mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: Update variable nullability only when DFA is completed successfully (IDEA-188416)
This commit is contained in:
@@ -60,22 +60,25 @@ public class DfaUtil {
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public static Nullness checkNullness(@Nullable final PsiVariable variable, @Nullable final PsiElement context) {
|
||||
return checkNullness(variable, context, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/**
|
||||
* @return {@code null} means "can't get results of DFA"
|
||||
*/
|
||||
@Nullable
|
||||
public static Nullness checkNullness(@Nullable final PsiVariable variable,
|
||||
@Nullable final PsiElement context,
|
||||
@Nullable final PsiElement outerBlock) {
|
||||
if (variable == null || context == null) return Nullness.UNKNOWN;
|
||||
if (variable == null || context == null) return null;
|
||||
|
||||
final PsiElement codeBlock = outerBlock == null ? DfaPsiUtil.getEnclosingCodeBlock(variable, context) : outerBlock;
|
||||
Map<PsiElement, ValuableInstructionVisitor.PlaceResult> results = codeBlock == null ? null : getCachedPlaceResults(codeBlock);
|
||||
ValuableInstructionVisitor.PlaceResult placeResult = results == null ? null : results.get(context);
|
||||
if (placeResult == null) {
|
||||
return Nullness.UNKNOWN;
|
||||
return null;
|
||||
}
|
||||
if (placeResult.myNulls.contains(variable) && !placeResult.myNotNulls.contains(variable)) return Nullness.NULLABLE;
|
||||
if (placeResult.myNotNulls.contains(variable) && !placeResult.myNulls.contains(variable)) return Nullness.NOT_NULL;
|
||||
|
||||
@@ -1720,6 +1720,9 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
PsiExpression initializer = ((PsiVariable)declaredElements[0]).getInitializer();
|
||||
|
||||
Nullness nullness = DfaUtil.checkNullness(variableCopy, initializer, bodyCopy);
|
||||
if (nullness == null) {
|
||||
return null;
|
||||
}
|
||||
return nullness == Nullness.NOT_NULL;
|
||||
}
|
||||
catch (IncorrectOperationException ignore) {
|
||||
|
||||
@@ -67,7 +67,7 @@ public class JavaSliceNullnessAnalyzer extends SliceNullnessAnalyzerBase {
|
||||
|
||||
if (value instanceof PsiLocalVariable || value instanceof PsiParameter) {
|
||||
Nullness result = DfaUtil.checkNullness((PsiVariable)value, context);
|
||||
if (result != Nullness.UNKNOWN) {
|
||||
if (result != null && result != Nullness.UNKNOWN) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class TooComplexCode {
|
||||
static class X { @NotNull X get() { return this; }}
|
||||
static class A extends X { @NotNull X get() { return new B(); }}
|
||||
static class B extends X { @NotNull X get() { return new C(); }}
|
||||
static class C extends X { @NotNull X get() { return new A(); }}
|
||||
|
||||
void tooComplex(@NotNull X x) {
|
||||
if (x instanceof A) {
|
||||
<selection>X y = x.get();</selection>
|
||||
if (y instanceof A) {
|
||||
System.out.println("A A "+x+' '+y);
|
||||
}
|
||||
if (y instanceof B) {
|
||||
System.out.println("A B "+x+' '+y);
|
||||
}
|
||||
}
|
||||
if (x instanceof B) {
|
||||
X y = x.get();
|
||||
if (y instanceof A) {
|
||||
System.out.println("B A "+x+' '+y);
|
||||
}
|
||||
if (y instanceof B) {
|
||||
System.out.println("B B "+x+' '+y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class TooComplexCode {
|
||||
static class X { @NotNull X get() { return this; }}
|
||||
static class A extends X { @NotNull X get() { return new B(); }}
|
||||
static class B extends X { @NotNull X get() { return new C(); }}
|
||||
static class C extends X { @NotNull X get() { return new A(); }}
|
||||
|
||||
void tooComplex(@NotNull X x) {
|
||||
if (x instanceof A) {
|
||||
X y = newMethod(x);
|
||||
if (y instanceof A) {
|
||||
System.out.println("A A "+x+' '+y);
|
||||
}
|
||||
if (y instanceof B) {
|
||||
System.out.println("A B "+x+' '+y);
|
||||
}
|
||||
}
|
||||
if (x instanceof B) {
|
||||
X y = newMethod(x);
|
||||
if (y instanceof A) {
|
||||
System.out.println("B A "+x+' '+y);
|
||||
}
|
||||
if (y instanceof B) {
|
||||
System.out.println("B B "+x+' '+y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private X newMethod(@NotNull X x) {
|
||||
return x.get();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
@@ -1093,6 +1095,17 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNotNullArgumentTooComplexCode() throws Exception {
|
||||
RegistryValue value = Registry.get("ide.dfa.state.limit");
|
||||
int oldValue = value.asInteger();
|
||||
try {
|
||||
value.setValue(50);
|
||||
doTest();
|
||||
}finally {
|
||||
value.setValue(oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void testVariableInLoopWithConditionalBreak() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user