"push condition inside call" intention replaced with "Conditional can be pushed inside branch" inspection

This commit is contained in:
Bas Leijdekkers
2017-04-04 17:42:19 +02:00
parent f96e053e52
commit 94fdc35577
16 changed files with 109 additions and 326 deletions

View File

@@ -1,184 +0,0 @@
/*
* Copyright 2000-2012 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.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class PushConditionInCallAction extends PsiElementBaseIntentionAction {
@Override
@NotNull
public String getFamilyName() {
return "Push condition inside call";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (element instanceof PsiCompiledElement) return false;
if (!element.getManager().isInProject(element)) return false;
// if (!(element instanceof PsiJavaToken && ((PsiJavaToken)element).getTokenType() == JavaTokenType.QUEST)) return false;
final PsiConditionalExpression conditionalExpression = PsiTreeUtil.getParentOfType(element, PsiConditionalExpression.class);
if (conditionalExpression == null) return false;
final String conditionText = conditionalExpression.getCondition().getText();
final PsiExpression thenExpression = conditionalExpression.getThenExpression();
final PsiExpression elseExpression = conditionalExpression.getElseExpression();
return isAvailable(conditionText, thenExpression, elseExpression, 0);
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
final PsiConditionalExpression conditionalExpression = PsiTreeUtil.getParentOfType(element, PsiConditionalExpression.class);
if (conditionalExpression == null) return;
PsiExpression thenExpression = conditionalExpression.getThenExpression();
if (thenExpression == null) return;
thenExpression = (PsiExpression)thenExpression.copy();
replaceRecursively(project, conditionalExpression, thenExpression, conditionalExpression.getElseExpression());
CodeStyleManager.getInstance(project).reformat(conditionalExpression.replace(thenExpression));
}
private boolean isAvailable(String conditionText, PsiExpression thenExpression, PsiExpression elseExpression, int level) {
if (!(thenExpression instanceof PsiCallExpression)) return false;
final PsiMethod thenMethod = ((PsiCallExpression)thenExpression).resolveMethod();
final PsiExpressionList thenArgsList = ((PsiCallExpression)thenExpression).getArgumentList();
if (thenArgsList == null) return false;
final PsiExpression[] thenExpressions = thenArgsList.getExpressions();
if (!(elseExpression instanceof PsiCallExpression)) return false;
final PsiMethod elseMethod = ((PsiCallExpression)elseExpression).resolveMethod();
final PsiExpressionList elseArgsList = ((PsiCallExpression)elseExpression).getArgumentList();
if (elseArgsList == null) return false;
final PsiExpression[] elseExpressions = elseArgsList.getExpressions();
if (thenMethod != elseMethod || thenMethod == null) return false;
if (thenExpressions.length != elseExpressions.length) return false;
final Pair<PsiExpression, PsiExpression> qualifiers = getQualifiers(thenExpression, elseExpression);
if (qualifiers != null) {
if (!isSameCall(thenExpressions, elseExpressions) && level == 0){
return false;
}
if (level > 0) {
setText("Push condition '" + conditionText + "' inside " + (thenMethod.isConstructor() ? "constructor" : "method") + " call");
return true;
}
return level > 0 || isAvailable(conditionText, qualifiers.first, qualifiers.second, level + 1);
}
PsiExpression tExpr = null;
for (int i = 0; i < thenExpressions.length; i++) {
PsiExpression lExpr = thenExpressions[i];
PsiExpression rExpr = elseExpressions[i];
if (!PsiEquivalenceUtil.areElementsEquivalent(lExpr, rExpr)) {
if (tExpr == null) {
tExpr = lExpr;
}
else {
return false;
}
}
}
setText("Push condition '" + conditionText + "' inside " + (thenMethod.isConstructor() ? "constructor" : "method") + " call");
return true;
}
private static boolean isSameCall(PsiExpression[] thenExpressions, PsiExpression[] elseExpressions) {
for (int i = 0; i < thenExpressions.length; i++) {
final PsiExpression lExpr = thenExpressions[i];
final PsiExpression rExpr = elseExpressions[i];
if (!PsiEquivalenceUtil.areElementsEquivalent(lExpr, rExpr)) {
return false;
}
}
return true;
}
private static Pair<PsiExpression, PsiExpression> getQualifiers(PsiExpression thenExpression, PsiExpression elseExpression) {
PsiExpression thenQualifier = null;
PsiExpression elseQualifier = null;
if (thenExpression instanceof PsiMethodCallExpression && elseExpression instanceof PsiMethodCallExpression) {
thenQualifier = ((PsiMethodCallExpression)thenExpression).getMethodExpression().getQualifierExpression();
elseQualifier = ((PsiMethodCallExpression)elseExpression).getMethodExpression().getQualifierExpression();
}
else if (thenExpression instanceof PsiNewExpression && elseExpression instanceof PsiNewExpression) {
thenQualifier = ((PsiNewExpression)thenExpression).getQualifier();
elseQualifier = ((PsiNewExpression)elseExpression).getQualifier();
}
if (thenQualifier == null ^ elseQualifier == null ||
thenQualifier != null && !PsiEquivalenceUtil.areElementsEquivalent(thenQualifier, elseQualifier)) {
return Pair.create(thenQualifier, elseQualifier);
}
return null;
}
private static void replaceRecursively(@NotNull Project project,
PsiConditionalExpression conditionalExpression,
PsiExpression thenExpression,
PsiExpression elseExpression) {
final PsiExpressionList thenArgsList = ((PsiCallExpression)thenExpression).getArgumentList();
if (thenArgsList == null) return;
final PsiExpression[] thenExpressions = thenArgsList.getExpressions();
final PsiExpressionList elseArgsList = ((PsiCallExpression)elseExpression).getArgumentList();
if (elseArgsList == null) return;
final PsiExpression[] elseExpressions = elseArgsList.getExpressions();
final Pair<PsiExpression, PsiExpression> qualifiers = getQualifiers(thenExpression, elseExpression);
if (qualifiers != null) {
if (isSameCall(thenExpressions, elseExpressions)) {
replaceRecursively(project, conditionalExpression, qualifiers.first, qualifiers.second);
}
else {
pushConditional(project, conditionalExpression, thenExpression, elseExpression);
}
}
else {
for (int i = 0; i < thenExpressions.length; i++) {
PsiExpression lExpr = thenExpressions[i];
PsiExpression rExpr = elseExpressions[i];
if (pushConditional(project, conditionalExpression, lExpr, rExpr)) {
break;
}
}
}
}
private static boolean pushConditional(@NotNull Project project,
PsiConditionalExpression conditionalExpression,
PsiExpression thenExpression,
PsiExpression elseExpression) {
if (!PsiEquivalenceUtil.areElementsEquivalent(thenExpression, elseExpression)) {
thenExpression.replace(JavaPsiFacade.getElementFactory(project).createExpressionFromText(
conditionalExpression.getCondition().getText() + "?" + thenExpression.getText() + ":" + elseExpression.getText(), thenExpression));
return true;
}
return false;
}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "true"
class Foo {
void bar(boolean b){
String s = foo(b ? "true" : "false");
}
String foo(String p) {return p;}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "true"
class Foo {
void bar(boolean b){
String s = foo(b ? "true" : "false", true).substring(0);
}
String foo(String p, boolean b) {return p;}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "true"
class Foo {
void bar(boolean b){
String s = foo("true", true).substring(b ? 1 : 2).substring(0);
}
String foo(String p, boolean b) {return p;}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "true"
class Foo {
void bar(boolean b){
String s = b <caret>? foo("true") : foo("false");
}
String foo(String p) {return p;}
}

View File

@@ -1,8 +0,0 @@
// "Push condition 'b' inside method call" "false"
class Foo {
void bar(boolean b){
String s = b <caret>? foo("true") : foo(false);
}
String foo(String p) {return p;}
String foo(boolean b) {return "false";}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "true"
class Foo {
void bar(boolean b){
String s = b <caret>? foo("true", true).substring(0) : foo("false", true).substring(0);
}
String foo(String p, boolean b) {return p;}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "false"
class Foo {
void bar(boolean b){
String s = b <caret>? foo("true", true).substring(0) : foo("false", true).substring(1);
}
String foo(String p, boolean b) {return p;}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "true"
class Foo {
void bar(boolean b){
String s = b <caret>? foo("true", true).substring(1).substring(0) : foo("true", true).substring(2).substring(0);
}
String foo(String p, boolean b) {return p;}
}

View File

@@ -1,7 +0,0 @@
// "Push condition 'b' inside method call" "false"
class Foo {
void bar(boolean b){
String s = b <caret>? foo("true", true) : foo("false", false);
}
String foo(String p, boolean b) {return p;}
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright 2000-2012 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.intellij.codeInsight.daemon.quickFix;
public class PushConditionInCallTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/pushConditionInCall";
}
}

View File

@@ -117,12 +117,12 @@ public class ConditionalCanBePushedInsideExpressionInspection extends BaseInspec
if (match.isExactMismatch() || match.isExactMatch()) {
return;
}
registerError(expression, ignoreSingleArgument && isOnlyArgumentOfMethodCall(match.getLeftDiff())
registerError(expression, ignoreSingleArgument && isOnlyArgumentOfMethodCall(match.getLeftDiff(), expression)
? ProblemHighlightType.INFORMATION
: ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
private boolean isOnlyArgumentOfMethodCall(PsiElement element) {
private boolean isOnlyArgumentOfMethodCall(PsiElement element, PsiConditionalExpression conditional) {
if (element == null) {
return false;
}
@@ -135,7 +135,11 @@ public class ConditionalCanBePushedInsideExpressionInspection extends BaseInspec
return false;
}
final PsiElement grandParent = expressionList.getParent();
return grandParent instanceof PsiMethodCallExpression;
if (!(grandParent instanceof PsiMethodCallExpression)) {
return false;
}
final PsiElement greatGrandParent = ParenthesesUtils.getParentSkipParentheses(grandParent);
return greatGrandParent == conditional;
}
}
}

View File

@@ -71,13 +71,23 @@ public class EquivalenceChecker {
return myExactlyMatches != null && !myExactlyMatches;
}
Match setConcreteIfExactMismatch(PsiElement left, PsiElement right) {
Match partialIfExactMismatch(PsiElement left, PsiElement right) {
return this == EXACT_MISMATCH ? new Match(left, right) : this;
}
static Match exact(boolean exactMatches) {
return exactMatches ? EXACT_MATCH : EXACT_MISMATCH;
}
Match combine(Match other) {
if (other.isExactMismatch() || isExactMatch()) {
return other;
}
if (isExactMismatch() || other.isExactMatch()) {
return this;
}
return EXACT_MISMATCH;
}
}
public boolean statementsAreEquivalent(@Nullable PsiStatement statement1, @Nullable PsiStatement statement2) {
@@ -208,7 +218,7 @@ public class EquivalenceChecker {
}
final PsiExpression initializer1 = localVariable1.getInitializer();
final PsiExpression initializer2 = localVariable2.getInitializer();
return expressionsMatch(initializer1, initializer2).setConcreteIfExactMismatch(initializer1, initializer2);
return expressionsMatch(initializer1, initializer2).partialIfExactMismatch(initializer1, initializer2);
}
protected Match tryStatementsMatch(@NotNull PsiTryStatement statement1, @NotNull PsiTryStatement statement2) {
@@ -333,7 +343,7 @@ public class EquivalenceChecker {
}
final PsiStatement body1 = statement1.getBody();
final PsiStatement body2 = statement2.getBody();
return statementsMatch(body1, body2).setConcreteIfExactMismatch(body1, body2);
return statementsMatch(body1, body2).partialIfExactMismatch(body1, body2);
}
protected Match forEachStatementsMatch(@NotNull PsiForeachStatement statement1, @NotNull PsiForeachStatement statement2) {
@@ -357,7 +367,7 @@ public class EquivalenceChecker {
}
final PsiStatement body1 = statement1.getBody();
final PsiStatement body2 = statement2.getBody();
return statementsMatch(body1, body2).setConcreteIfExactMismatch(body1, body2);
return statementsMatch(body1, body2).partialIfExactMismatch(body1, body2);
}
protected Match switchStatementsMatch(@NotNull PsiSwitchStatement statement1, @NotNull PsiSwitchStatement statement2) {
@@ -369,7 +379,7 @@ public class EquivalenceChecker {
if (bodyEq != EXACT_MATCH) {
return EXACT_MISMATCH;
}
return expressionsMatch(switchExpression1, switchExpression2).setConcreteIfExactMismatch(switchExpression1, switchExpression2);
return expressionsMatch(switchExpression1, switchExpression2).partialIfExactMismatch(switchExpression1, switchExpression2);
}
protected Match doWhileStatementsMatch(@NotNull PsiDoWhileStatement statement1, @NotNull PsiDoWhileStatement statement2) {
@@ -445,7 +455,7 @@ public class EquivalenceChecker {
}
final PsiExpression caseExpression1 = statement1.getCaseValue();
final PsiExpression caseExpression2 = statement2.getCaseValue();
return expressionsMatch(caseExpression1, caseExpression2).setConcreteIfExactMismatch(caseExpression1, caseExpression2);
return expressionsMatch(caseExpression1, caseExpression2).partialIfExactMismatch(caseExpression1, caseExpression2);
}
protected Match labeledStatementsMatch(@NotNull PsiLabeledStatement statement1, @NotNull PsiLabeledStatement statement2) {
@@ -525,7 +535,7 @@ public class EquivalenceChecker {
final PsiExpressionList expressionList2 =
statement2.getExpressionList();
final PsiExpression[] expressions2 = expressionList2.getExpressions();
return expressionListsAreEquivalent(expressions1, expressions2);
return expressionsAreEquivalent(expressions1, expressions2);
}
public boolean expressionsAreEquivalent(@Nullable PsiExpression expression1, @Nullable PsiExpression expression2) {
@@ -594,9 +604,57 @@ public class EquivalenceChecker {
if (expression1 instanceof PsiInstanceOfExpression) {
return instanceOfExpressionsMatch((PsiInstanceOfExpression)expression1, (PsiInstanceOfExpression)expression2);
}
if (expression1 instanceof PsiLambdaExpression) {
return lambdaExpressionsMatch((PsiLambdaExpression)expression1, (PsiLambdaExpression)expression2);
}
return EXACT_MISMATCH;
}
protected Match lambdaExpressionsMatch(PsiLambdaExpression expression1, PsiLambdaExpression expression2) {
final PsiParameterList parameterList1 = expression1.getParameterList();
final PsiParameterList parameterList2 = expression2.getParameterList();
final PsiParameter[] parameters1 = parameterList1.getParameters();
final PsiParameter[] parameters2 = parameterList2.getParameters();
if (parameters1.length != parameters2.length) {
return EXACT_MISMATCH;
}
for (int i = 0, length = parameters1.length; i < length; i++) {
if (!parametersAreEquivalent(parameters1[i], parameters2[i]).isExactMatch()) {
return EXACT_MISMATCH;
}
}
final PsiElement body1 = unwrapLambdaBody(expression1.getBody());
final PsiElement body2 = unwrapLambdaBody(expression2.getBody());
if (body1 instanceof PsiCodeBlock && body2 instanceof PsiCodeBlock) {
return codeBlocksMatch((PsiCodeBlock)body1, (PsiCodeBlock)body2);
}
else if (body1 instanceof PsiExpression && body2 instanceof PsiExpression) {
return expressionsMatch((PsiExpression)body1, (PsiExpression)body2);
}
return EXACT_MISMATCH;
}
private static PsiElement unwrapLambdaBody(PsiElement element) {
while (element instanceof PsiCodeBlock) {
final PsiCodeBlock codeBlock = (PsiCodeBlock)element;
final PsiStatement[] statements = codeBlock.getStatements();
if (statements.length != 1) {
break;
}
final PsiStatement statement = statements[0];
if (statement instanceof PsiReturnStatement) {
return ((PsiReturnStatement)statement).getReturnValue();
}
else if (statement instanceof PsiExpressionStatement) {
return ((PsiExpressionStatement)statement).getExpression();
}
else if (statement instanceof PsiBlockStatement) {
element = ((PsiBlockStatement)statement).getCodeBlock();
}
}
return element;
}
protected Match literalExpressionsMatch(PsiLiteralExpression expression1, PsiLiteralExpression expression2) {
final Object value1 = expression1.getValue();
final Object value2 = expression2.getValue();
@@ -679,20 +737,17 @@ public class EquivalenceChecker {
}
protected Match methodCallExpressionsMatch(@NotNull PsiMethodCallExpression methodCallExpression1, @NotNull PsiMethodCallExpression methodCallExpression2) {
final PsiReferenceExpression methodExpression1 =
methodCallExpression1.getMethodExpression();
final PsiReferenceExpression methodExpression2 =
methodCallExpression2.getMethodExpression();
if (!expressionsMatch(methodExpression1, methodExpression2).isExactMatch()) {
final PsiReferenceExpression methodExpression1 = methodCallExpression1.getMethodExpression();
final PsiReferenceExpression methodExpression2 = methodCallExpression2.getMethodExpression();
Match match = expressionsMatch(methodExpression1, methodExpression2);
if (match.isExactMismatch()) {
return EXACT_MISMATCH;
}
final PsiExpressionList argumentList1 =
methodCallExpression1.getArgumentList();
final PsiExpressionList argumentList1 = methodCallExpression1.getArgumentList();
final PsiExpression[] args1 = argumentList1.getExpressions();
final PsiExpressionList argumentList2 =
methodCallExpression2.getArgumentList();
final PsiExpressionList argumentList2 = methodCallExpression2.getArgumentList();
final PsiExpression[] args2 = argumentList2.getExpressions();
final Match match = expressionListsAreEquivalent(args1, args2);
match = match.combine(expressionsAreEquivalent(args1, args2));
if (match.isPartialMatch()) {
final PsiElement leftDiff = match.getLeftDiff();
@@ -732,7 +787,7 @@ public class EquivalenceChecker {
newExpression1.getArrayDimensions();
final PsiExpression[] arrayDimensions2 =
newExpression2.getArrayDimensions();
if (!expressionListsAreEquivalent(arrayDimensions1, arrayDimensions2).isExactMatch()) {
if (!expressionsAreEquivalent(arrayDimensions1, arrayDimensions2).isExactMatch()) {
return EXACT_MISMATCH;
}
final PsiArrayInitializerExpression arrayInitializer1 =
@@ -756,7 +811,7 @@ public class EquivalenceChecker {
final PsiExpression[] args1 = argumentList1 == null ? null : argumentList1.getExpressions();
final PsiExpressionList argumentList2 = newExpression2.getArgumentList();
final PsiExpression[] args2 = argumentList2 == null ? null : argumentList2.getExpressions();
return expressionListsAreEquivalent(args1, args2);
return expressionsAreEquivalent(args1, args2);
}
protected Match arrayInitializerExpressionsMatch(@NotNull PsiArrayInitializerExpression arrayInitializerExpression1, @NotNull PsiArrayInitializerExpression arrayInitializerExpression2) {
@@ -764,7 +819,7 @@ public class EquivalenceChecker {
arrayInitializerExpression1.getInitializers();
final PsiExpression[] initializers2 =
arrayInitializerExpression2.getInitializers();
return expressionListsAreEquivalent(initializers1, initializers2);
return expressionsAreEquivalent(initializers1, initializers2);
}
protected Match typeCastExpressionsMatch(@NotNull PsiTypeCastExpression typeCastExpression1, @NotNull PsiTypeCastExpression typeCastExpression2) {
@@ -778,7 +833,7 @@ public class EquivalenceChecker {
if (operand1 instanceof PsiFunctionalExpression || operand2 instanceof PsiFunctionalExpression) {
return EXACT_MISMATCH;
}
return expressionsMatch(operand1, operand2).setConcreteIfExactMismatch(operand1, operand2);
return expressionsMatch(operand1, operand2).partialIfExactMismatch(operand1, operand2);
}
protected Match arrayAccessExpressionsMatch(@NotNull PsiArrayAccessExpression arrayAccessExpression1, @NotNull PsiArrayAccessExpression arrayAccessExpression2) {
@@ -794,7 +849,7 @@ public class EquivalenceChecker {
if (arrayExpressionEq != EXACT_MATCH) {
return EXACT_MISMATCH;
}
return expressionsMatch(indexExpression1, indexExpression2).setConcreteIfExactMismatch(indexExpression1, indexExpression2);
return expressionsMatch(indexExpression1, indexExpression2).partialIfExactMismatch(indexExpression1, indexExpression2);
}
protected Match prefixExpressionsMatch(@NotNull PsiPrefixExpression prefixExpression1, @NotNull PsiPrefixExpression prefixExpression2) {
@@ -825,24 +880,7 @@ public class EquivalenceChecker {
}
final PsiExpression[] operands1 = polyadicExpression1.getOperands();
final PsiExpression[] operands2 = polyadicExpression2.getOperands();
if (operands1.length != operands2.length) {
return EXACT_MISMATCH;
}
Match incompleteMatch = null;
for (int i = 0; i < operands1.length; i++) {
final Match match = expressionsMatch(operands1[i], operands2[i]);
if (!match.isExactMatch()) {
if (incompleteMatch == null) {
incompleteMatch =
match.isExactMismatch() ? new Match(operands1[i], operands2[i]) : match;
}
else {
return EXACT_MISMATCH;
}
}
}
return incompleteMatch != null ? incompleteMatch : EXACT_MATCH;
return expressionsAreEquivalent(operands1, operands2);
}
protected Match assignmentExpressionsMatch(@NotNull PsiAssignmentExpression assignmentExpression1, @NotNull PsiAssignmentExpression assignmentExpression2) {
@@ -878,7 +916,7 @@ public class EquivalenceChecker {
return EXACT_MISMATCH;
}
protected Match expressionListsAreEquivalent(@Nullable PsiExpression[] expressions1, @Nullable PsiExpression[] expressions2) {
protected Match expressionsAreEquivalent(@Nullable PsiExpression[] expressions1, @Nullable PsiExpression[] expressions2) {
if (expressions1 == null && expressions2 == null) {
return EXACT_MATCH;
}
@@ -892,13 +930,14 @@ public class EquivalenceChecker {
Match incompleteMatch = null;
for (int i = 0; i < expressions1.length; i++) {
final Match match = expressionsMatch(expressions1[i], expressions2[i]);
if (!match.isExactMatch()) {
if (incompleteMatch == null) {
incompleteMatch = match.isExactMismatch() ? new Match(expressions1[i], expressions2[i]) : match;
}
else {
if (incompleteMatch == null && match.isPartialMatch()) {
incompleteMatch = match;
}
else if (!match.isExactMatch()) {
if (incompleteMatch != null) {
return EXACT_MISMATCH;
}
incompleteMatch = match.partialIfExactMismatch(expressions1[i], expressions2[i]);
}
}
return incompleteMatch == null ? EXACT_MATCH : incompleteMatch;

View File

@@ -53,4 +53,16 @@ class ConditionalCanBePushedInsideExpression {
}
}
void bar(boolean b){
String s = <warning descr="Conditional expression can be pushed inside branch">b ? foo(bar("true"), true).substring(1) : foo(bar("false"), true).substring(1)</warning>;
String t = <warning descr="Conditional expression can be pushed inside branch">b ? foo("true", true).substring(1).substring(0) : foo("true", true).substring(2).substring(0)</warning>;
String u = <warning descr="Conditional expression can be pushed inside branch">b ? foo("true", true).substring(0) : foo("false", true).substring(0)</warning>;
String v = <warning descr="Conditional expression can be pushed inside branch">b ? bar(bar("one")) : bar(bar("two"))</warning>;
}
String foo(String p, boolean b) {return p;}
String bar(String s) {
return s;
}
}

View File

@@ -35,6 +35,11 @@ class ConditionalExpressionWithIdenticalBranches {
static class WithFunctionalExpression {
private void foo(boolean b) {
Runnable r = b ? (Runnable) () -> {} : (Runnable) () -> {};
IntSupplier s = <warning descr="Conditional expression 'b ? () -> 1 : () -> { return 1; }' with identical branches">b ? () -> 1 : () -> { return 1; }</warning>;
}
}
interface IntSupplier {
int getAsInt();
}
}

View File

@@ -1064,10 +1064,6 @@
<className>com.intellij.codeInsight.intention.impl.JoinDeclarationAndAssignmentAction</className>
<category>Java/Declaration</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.PushConditionInCallAction</className>
<category>Java/Declaration</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.MoveInitializerToConstructorAction</className>
<category>Java/Declaration</category>