mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
turn off contract inference for overrideable methods; hopefully, not forever (IDEA-127518)
This commit is contained in:
@@ -17,17 +17,20 @@ package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis;
|
||||
import com.intellij.codeInspection.dataFlow.ContractInference;
|
||||
import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer;
|
||||
import com.intellij.codeInspection.dataFlow.MethodContract;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer.ORG_JETBRAINS_ANNOTATIONS_CONTRACT;
|
||||
|
||||
public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -37,7 +40,7 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
|
||||
return fromBytecode;
|
||||
}
|
||||
|
||||
if (listOwner instanceof PsiMethod && ControlFlowAnalyzer.ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN)) {
|
||||
if (listOwner instanceof PsiMethod && ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && !PsiUtil.canBeOverriden((PsiMethod)listOwner)) {
|
||||
List<MethodContract> contracts = ContractInference.inferContracts((PsiMethod)listOwner);
|
||||
if (!contracts.isEmpty()) {
|
||||
return ProjectBytecodeAnalysis.getInstance(listOwner.getProject()).createContractAnnotation("\"" + StringUtil.join(contracts, "; ") + "\"");
|
||||
@@ -50,19 +53,25 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiAnnotation[] findInferredAnnotations(@NotNull PsiModifierListOwner listOwner) {
|
||||
List<PsiAnnotation> result = ContainerUtil.newArrayList();
|
||||
PsiAnnotation[] fromBytecode = ProjectBytecodeAnalysis.getInstance(listOwner.getProject()).findInferredAnnotations(listOwner);
|
||||
if (fromBytecode.length > 0) {
|
||||
return fromBytecode;
|
||||
}
|
||||
|
||||
if (listOwner instanceof PsiMethod) {
|
||||
List<MethodContract> contracts = ContractInference.inferContracts((PsiMethod)listOwner);
|
||||
if (!contracts.isEmpty()) {
|
||||
return new PsiAnnotation[]{ProjectBytecodeAnalysis.getInstance(listOwner.getProject()).createContractAnnotation("\"" + StringUtil.join(contracts, "; ") + "\"")};
|
||||
for (PsiAnnotation annotation : fromBytecode) {
|
||||
if (!ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotation.getQualifiedName()) ||
|
||||
!(listOwner instanceof PsiMethod) ||
|
||||
!PsiUtil.canBeOverriden((PsiMethod)listOwner)) {
|
||||
result.add(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
return PsiAnnotation.EMPTY_ARRAY;
|
||||
if (listOwner instanceof PsiMethod && !PsiUtil.canBeOverriden((PsiMethod)listOwner)) {
|
||||
List<MethodContract> contracts = ContractInference.inferContracts((PsiMethod)listOwner);
|
||||
if (!contracts.isEmpty()) {
|
||||
result.add(ProjectBytecodeAnalysis.getInstance(listOwner.getProject())
|
||||
.createContractAnnotation("\"" + StringUtil.join(contracts, "; ") + "\""));
|
||||
}
|
||||
}
|
||||
|
||||
return result.isEmpty() ? PsiAnnotation.EMPTY_ARRAY : result.toArray(new PsiAnnotation[result.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class Doo {
|
||||
|
||||
boolean isMaybeNotNull(@Nullable Object o) {
|
||||
return o != null;
|
||||
}
|
||||
|
||||
void foo(@Nullable String s) {
|
||||
if (isMaybeNotNull(s)) {
|
||||
System.out.println(<warning descr="Method invocation 's.length()' may produce 'java.lang.NullPointerException'">s.length()</warning>);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DooImpl extends Doo {
|
||||
boolean isMaybeNotNull(@Nullable Object o) {
|
||||
return hashCode() == 42;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class Doo {
|
||||
|
||||
boolean isNotNull(@Nullable Object o) {
|
||||
static boolean isNotNull(@Nullable Object o) {
|
||||
return o != null;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -277,7 +277,7 @@ class ContractInferenceFromSourceTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
|
||||
private List<String> inferContracts(String method) {
|
||||
def clazz = myFixture.addClass("class Foo { $method }")
|
||||
def clazz = myFixture.addClass("final class Foo { $method }")
|
||||
return ContractInference.inferContracts(clazz.methods[0]).collect { it as String }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testRootThrowableCause() { doTest(); }
|
||||
|
||||
public void testUseInferredContracts() { doTest(); }
|
||||
public void testContractInferenceBewareOverriding() { doTest(); }
|
||||
|
||||
public void testNumberComparisonsWhenValueIsKnown() { doTest(); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user