mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
don't flush fields for pure method and getter calls (IDEA-117449)
This commit is contained in:
@@ -1602,6 +1602,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiAnnotation findContractAnnotation(PsiMethod method) {
|
||||
return AnnotationUtil.findAnnotation(method, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
|
||||
}
|
||||
@@ -1741,6 +1742,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
if (psiVariable != null) {
|
||||
DfaVariableValue dfaVariable = myFactory.getVarFactory().createVariableValue(psiVariable, false);
|
||||
addInstruction(new FlushVariableInstruction(dfaVariable));
|
||||
if (psiVariable instanceof PsiField) {
|
||||
addInstruction(new FlushVariableInstruction(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1774,6 +1778,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
if (psiVariable != null) {
|
||||
DfaVariableValue dfaVariable = myFactory.getVarFactory().createVariableValue(psiVariable, false);
|
||||
addInstruction(new FlushVariableInstruction(dfaVariable));
|
||||
if (psiVariable instanceof PsiField) {
|
||||
addInstruction(new FlushVariableInstruction(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.dataFlow.instructions;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.DataFlowRunner;
|
||||
import com.intellij.codeInspection.dataFlow.DfaInstructionState;
|
||||
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
|
||||
import com.intellij.codeInspection.dataFlow.InstructionVisitor;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -56,17 +55,26 @@ public class MethodCallInstruction extends Instruction {
|
||||
myPrecalculatedReturnValue = null;
|
||||
}
|
||||
|
||||
public MethodCallInstruction(@NotNull PsiCallExpression context, @Nullable DfaValue precalculatedReturnValue) {
|
||||
myContext = context;
|
||||
public MethodCallInstruction(@NotNull PsiCallExpression call, @Nullable DfaValue precalculatedReturnValue) {
|
||||
myContext = call;
|
||||
myMethodType = MethodType.REGULAR_METHOD_CALL;
|
||||
myCall = context;
|
||||
final PsiExpressionList argList = context.getArgumentList();
|
||||
myCall = call;
|
||||
final PsiExpressionList argList = call.getArgumentList();
|
||||
myArgs = argList != null ? argList.getExpressions() : PsiExpression.EMPTY_ARRAY;
|
||||
myType = myCall.getType();
|
||||
myShouldFlushFields = !(myCall instanceof PsiNewExpression && myType != null && myType.getArrayDimensions() > 0);
|
||||
|
||||
myShouldFlushFields = !(myCall instanceof PsiNewExpression && myType != null && myType.getArrayDimensions() > 0) && !isPureCall(call);
|
||||
myPrecalculatedReturnValue = precalculatedReturnValue;
|
||||
}
|
||||
|
||||
private static boolean isPureCall(PsiCallExpression call) {
|
||||
PsiMethod method = call.resolveMethod();
|
||||
if (method == null) return false;
|
||||
PsiAnnotation anno = ControlFlowAnalyzer.findContractAnnotation(method);
|
||||
if (anno != null && Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(anno, "pure"))) return true;
|
||||
return PropertyUtil.isSimplePropertyGetter(method);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiType getResultType() {
|
||||
return myType;
|
||||
|
||||
@@ -436,13 +436,13 @@ public class AnnotationUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getStringAttributeValue(PsiAnnotation anno, @Nullable final String attributeName) {
|
||||
public static String getStringAttributeValue(@NotNull PsiAnnotation anno, @Nullable final String attributeName) {
|
||||
PsiAnnotationMemberValue attrValue = anno.findAttributeValue(attributeName);
|
||||
Object constValue = JavaPsiFacade.getInstance(anno.getProject()).getConstantEvaluationHelper().computeConstantExpression(attrValue);
|
||||
return constValue instanceof String ? (String)constValue : null;
|
||||
}
|
||||
@Nullable
|
||||
public static Boolean getBooleanAttributeValue(PsiAnnotation anno, @Nullable final String attributeName) {
|
||||
public static Boolean getBooleanAttributeValue(@NotNull PsiAnnotation anno, @Nullable final String attributeName) {
|
||||
PsiAnnotationMemberValue attrValue = anno.findAttributeValue(attributeName);
|
||||
Object constValue = JavaPsiFacade.getInstance(anno.getProject()).getConstantEvaluationHelper().computeConstantExpression(attrValue);
|
||||
return constValue instanceof Boolean ? (Boolean)constValue : null;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class PropertyUtil {
|
||||
private PropertyUtil() {
|
||||
}
|
||||
|
||||
public static boolean isSimplePropertyGetter(PsiMethod method) {
|
||||
public static boolean isSimplePropertyGetter(@NotNull PsiMethod method) {
|
||||
return hasGetterName(method) && method.getParameterList().getParametersCount() == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class Doo {
|
||||
|
||||
@Nullable
|
||||
Object getMethod() {return null;}
|
||||
|
||||
boolean isSomething() { return false;}
|
||||
|
||||
@Contract(pure=true)
|
||||
boolean pureSomething() { return false;}
|
||||
|
||||
public void main2() {
|
||||
if (getMethod() == null && !isSomething()) {
|
||||
return;
|
||||
} else {
|
||||
System.out.println(<warning descr="Method invocation 'getMethod().hashCode()' may produce 'java.lang.NullPointerException'">getMethod().hashCode()</warning>);
|
||||
}
|
||||
}
|
||||
|
||||
public void main3() {
|
||||
if (getMethod() == null && !pureSomething()) {
|
||||
return;
|
||||
} else {
|
||||
System.out.println(<warning descr="Method invocation 'getMethod().hashCode()' may produce 'java.lang.NullPointerException'">getMethod().hashCode()</warning>);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -306,6 +306,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testAndEquals() { doTest(); }
|
||||
|
||||
public void testUnusedCallDoesNotMakeUnknown() { doTest(); }
|
||||
public void testGettersAndPureNoFlushing() { doTest(); }
|
||||
|
||||
public void testParametersAreNonnullByDefault() {
|
||||
myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
|
||||
|
||||
Reference in New Issue
Block a user