From a8e4cd8462cd81bc82d782917ae32d492106027c Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Sun, 22 Dec 2019 15:24:17 +0700 Subject: [PATCH] Contract inference: avoid inference of "_ -> param1" contract when primitive conversion takes place GitOrigin-RevId: 45d14c16892297858e33d6bf1dd4822a373577ff --- .../dataFlow/TypeConstraints.java | 5 +++-- .../ContractInferenceInterpreter.java | 2 +- .../psi/impl/source/JavaLightTreeUtil.java | 18 +++++++++++++++++- .../ContractInferenceFromSourceTest.groovy | 5 +++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraints.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraints.java index 95cf1ddaaf16..4c9636560e54 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraints.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraints.java @@ -352,12 +352,13 @@ public class TypeConstraints { @Override public boolean equals(Object obj) { - return obj == this || obj instanceof ExactClass && myClass.equals(((ExactClass)obj).myClass); + return obj == this || obj instanceof ExactClass && + myClass.getManager().areElementsEquivalent(myClass, ((ExactClass)obj).myClass); } @Override public int hashCode() { - return myClass.hashCode(); + return Objects.hashCode(myClass.getQualifiedName()); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inference/ContractInferenceInterpreter.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inference/ContractInferenceInterpreter.java index 2fd565d84340..d2f66cf967d2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inference/ContractInferenceInterpreter.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inference/ContractInferenceInterpreter.java @@ -209,7 +209,7 @@ class ContractInferenceInterpreter { if (type == PARENTH_EXPRESSION) { return visitExpression(states, findExpressionChild(myTree, expr)); } - if (type == TYPE_CAST_EXPRESSION) { + if (type == TYPE_CAST_EXPRESSION && !isPrimitiveCast(myTree, expr)) { return visitExpression(states, findExpressionChild(myTree, expr)); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightTreeUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightTreeUtil.java index 13172856645e..c2ae3a4d51c6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightTreeUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightTreeUtil.java @@ -22,6 +22,8 @@ import com.intellij.psi.impl.cache.RecordUtil; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.LightTreeUtil; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.java.IKeywordElementType; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,12 +63,26 @@ public class JavaLightTreeUtil { @Nullable public static LighterASTNode skipParenthesesCastsDown(@NotNull LighterAST tree, @Nullable LighterASTNode node) { - while (node != null && (node.getTokenType() == PARENTH_EXPRESSION || node.getTokenType() == TYPE_CAST_EXPRESSION)) { + while (node != null) { + IElementType type = node.getTokenType(); + if (type != PARENTH_EXPRESSION && type != TYPE_CAST_EXPRESSION) break; + if (type == TYPE_CAST_EXPRESSION && isPrimitiveCast(tree, node)) break; node = findExpressionChild(tree, node); } return node; } + public static boolean isPrimitiveCast(@NotNull LighterAST tree, @NotNull LighterASTNode node) { + LighterASTNode typeElement = LightTreeUtil.firstChildOfType(tree, node, TYPE); + if (typeElement != null) { + LighterASTNode item = ContainerUtil.getOnlyItem(tree.getChildren(typeElement)); + if (item.getTokenType() instanceof IKeywordElementType) { + return true; + } + } + return false; + } + @Nullable public static LighterASTNode skipParenthesesDown(@NotNull LighterAST tree, @Nullable LighterASTNode expression) { while (expression != null && expression.getTokenType() == PARENTH_EXPRESSION) { diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/ContractInferenceFromSourceTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInspection/ContractInferenceFromSourceTest.groovy index 709bba75fdf9..0aa0b9cca403 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/ContractInferenceFromSourceTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/ContractInferenceFromSourceTest.groovy @@ -705,6 +705,11 @@ static String test(String a, String b) { """) assert c == ['_, null -> null', 'null, !null -> null'] } + + void "test primitive cast ignored"() { + def c = inferContracts("""static int test(long x) {return (int)x;}""") + assert c == [] + } private String inferContract(String method) { return assertOneElement(inferContracts(method))