diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java index bc503c0eb6d8..96bf56509231 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java @@ -17,9 +17,13 @@ package com.intellij.psi.impl; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Function; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -96,4 +100,49 @@ public class PsiDiamondTypeUtil { } return psiElement; } + + public static PsiElement replaceDiamondWithExplicitTypes(PsiElement element) { + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiJavaCodeReferenceElement)) { + return parent; + } + final PsiJavaCodeReferenceElement javaCodeReferenceElement = + (PsiJavaCodeReferenceElement) parent; + final PsiReferenceParameterList referenceParameterList = + (PsiReferenceParameterList) element; + final StringBuilder text = new StringBuilder(); + text.append(javaCodeReferenceElement.getQualifiedName()); + text.append('<'); + final PsiTypeElement[] typeElements = referenceParameterList.getTypeParameterElements(); + final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(typeElements[0], PsiNewExpression.class); + final PsiDiamondType.DiamondInferenceResult result = PsiDiamondType.resolveInferredTypesNoCheck(newExpression, newExpression); + text.append(StringUtil.join(result.getInferredTypes(), new Function() { + @Override + public String fun(PsiType psiType) { + return psiType.getCanonicalText(); + } + }, ",")); + text.append('>'); + final PsiElementFactory elementFactory = + JavaPsiFacade.getElementFactory(element.getProject()); + final PsiJavaCodeReferenceElement newReference = + elementFactory.createReferenceFromText(text.toString(), element); + return CodeStyleManager.getInstance(javaCodeReferenceElement.getProject()).reformat(javaCodeReferenceElement.replace(newReference)); + } + + public static PsiExpression expandTopLevelDiamondsInside(PsiExpression expr) { + if (expr instanceof PsiNewExpression) { + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)expr).getClassReference(); + if (classReference != null) { + final PsiReferenceParameterList parameterList = classReference.getParameterList(); + if (parameterList != null) { + final PsiTypeElement[] typeParameterElements = parameterList.getTypeParameterElements(); + if (typeParameterElements.length == 1 && typeParameterElements[0].getType() instanceof PsiDiamondType) { + return (PsiExpression)replaceDiamondWithExplicitTypes(parameterList).getParent(); + } + } + } + } + return expr; + } } diff --git a/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml b/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml index 59f6a0ce7098..cbc20212f075 100644 --- a/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml +++ b/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml @@ -16,6 +16,7 @@ + diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java index 0a1eee49d99f..7959869d1819 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java @@ -16,6 +16,7 @@ package com.siyeh.ipp.trivialif; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiDiamondTypeUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.ipp.base.Intention; @@ -148,11 +149,11 @@ public class ReplaceIfWithConditionalIntention extends Intention { PsiExpression elseValue, PsiType requiredType) { condition = ParenthesesUtils.stripParentheses(condition); - thenValue = ParenthesesUtils.stripParentheses(thenValue); + thenValue = PsiDiamondTypeUtil.expandTopLevelDiamondsInside(ParenthesesUtils.stripParentheses(thenValue)); if (thenValue == null) { return null; } - elseValue = ParenthesesUtils.stripParentheses(elseValue); + elseValue = PsiDiamondTypeUtil.expandTopLevelDiamondsInside(ParenthesesUtils.stripParentheses(elseValue)); if (elseValue == null) { return null; } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceDiamondWithExplicitTypeArgumentsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceDiamondWithExplicitTypeArgumentsIntention.java index 1e701098d06f..9d9a0323bb84 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceDiamondWithExplicitTypeArgumentsIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceDiamondWithExplicitTypeArgumentsIntention.java @@ -16,15 +16,12 @@ package com.siyeh.ipp.types; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.impl.PsiDiamondTypeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; - public class ReplaceDiamondWithExplicitTypeArgumentsIntention extends Intention { @NotNull @@ -36,34 +33,6 @@ public class ReplaceDiamondWithExplicitTypeArgumentsIntention extends Intention @Override protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { - final PsiElement parent = element.getParent(); - if (!(parent instanceof PsiJavaCodeReferenceElement)) { - return; - } - final PsiJavaCodeReferenceElement javaCodeReferenceElement = - (PsiJavaCodeReferenceElement) parent; - final PsiReferenceParameterList referenceParameterList = - (PsiReferenceParameterList) element; - final StringBuilder text = new StringBuilder(); - text.append(javaCodeReferenceElement.getQualifiedName()); - text.append('<'); - final PsiTypeElement[] typeElements = referenceParameterList.getTypeParameterElements(); - final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(typeElements[0], PsiNewExpression.class); - final PsiDiamondType.DiamondInferenceResult result = PsiDiamondType.resolveInferredTypesNoCheck(newExpression, newExpression); - boolean first = true; - for (PsiType typeArgument : result.getInferredTypes()) { - if (first) { - first = false; - } else { - text.append(','); - } - text.append(typeArgument.getCanonicalText()); - } - text.append('>'); - final PsiElementFactory elementFactory = - JavaPsiFacade.getElementFactory(element.getProject()); - final PsiJavaCodeReferenceElement newReference = - elementFactory.createReferenceFromText(text.toString(), element); - CodeStyleManager.getInstance(javaCodeReferenceElement.getProject()).reformat(javaCodeReferenceElement.replace(newReference)); + PsiDiamondTypeUtil.replaceDiamondWithExplicitTypes(element); } } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReplaceableAssignmentsWithDiamonds.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReplaceableAssignmentsWithDiamonds.java new file mode 100644 index 000000000000..a9066666d5df --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReplaceableAssignmentsWithDiamonds.java @@ -0,0 +1,10 @@ +import java.util.*; + +class Test { + public void multiAssignment(boolean b) { + List l; + if (b) { + l = new ArrayList<>(1); + } else l = new ArrayList<>(3); + } +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReplaceableAssignmentsWithDiamonds_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReplaceableAssignmentsWithDiamonds_after.java new file mode 100644 index 000000000000..bd163278d020 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReplaceableAssignmentsWithDiamonds_after.java @@ -0,0 +1,8 @@ +import java.util.*; + +class Test { + public void multiAssignment(boolean b) { + List l; + l = b ? new ArrayList(1) : new ArrayList(3); + } +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReturnValueWithDiamonds.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReturnValueWithDiamonds.java new file mode 100644 index 000000000000..83c7f46c4c1c --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReturnValueWithDiamonds.java @@ -0,0 +1,10 @@ +import java.util.*; + +class Test { + public List multiReturn(boolean b) { + if (b) { + return new ArrayList<>(1); + } + else return new ArrayList<>(3); + } +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReturnValueWithDiamonds_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReturnValueWithDiamonds_after.java new file mode 100644 index 000000000000..d913c7a43dc8 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ReturnValueWithDiamonds_after.java @@ -0,0 +1,7 @@ +import java.util.*; + +class Test { + public List multiReturn(boolean b) { + return b ? new ArrayList(1) : new ArrayList(3); + } +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java new file mode 100644 index 000000000000..f4a51a62f53e --- /dev/null +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ipp.trivialif; + +import com.siyeh.IntentionPowerPackBundle; +import com.siyeh.ipp.IPPTestCase; + +public class ReplaceIfWithConditionalIntentionTest extends IPPTestCase { + + public void testReturnValueWithDiamonds() { + doTest(); + } + + public void testReplaceableAssignmentsWithDiamonds() { + doTest(); + } + + @Override + protected String getIntentionName() { + return IntentionPowerPackBundle.message("replace.if.with.conditional.intention.name"); + } + + @Override + protected String getRelativePath() { + return "trivialif/replaceIfWithConditional"; + } +}