From 6fc9953a8270cef64e7df936d9df4622ce24f9a1 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Mon, 21 Mar 2016 20:42:44 +0100 Subject: [PATCH] show error if uninitialized field is referenced from lambda inside inner/anonymous class in another field initializer; disable anonymous -> lambda for such places --- .../analysis/HighlightControlFlowUtil.java | 1 + .../AnonymousCanBeLambdaInspection.java | 4 ++- ...ghtNotHaveBeenInitializedInsideLambda.java | 25 +++++++++++++++++++ ...eForwardReferenceFromNestedClassField.java | 19 ++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeForwardReferenceFromNestedClassField.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index 71b13ea68419..26cfaeef821e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -402,6 +402,7 @@ public class HighlightControlFlowUtil { private static boolean inInnerClass(@NotNull PsiElement psiElement, @Nullable PsiClass containingClass, @NotNull PsiFile containingFile) { PsiElement element = psiElement; while (element != null) { + if (element instanceof PsiLambdaExpression) return false; if (element instanceof PsiClass) return !containingFile.getManager().areElementsEquivalent(element, containingClass); element = element.getParent(); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index 64ff37a12f72..2ee90ae8ddd7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -500,8 +500,10 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection final PsiMember member = PsiTreeUtil.getParentOfType(myAnonymClass, PsiMember.class); if (member instanceof PsiField || member instanceof PsiClassInitializer) { final PsiElement resolved = expression.resolve(); + final PsiClass memberContainingClass = member.getContainingClass(); if (resolved instanceof PsiField && - ((PsiField)resolved).getContainingClass() == member.getContainingClass() && + memberContainingClass != null && + PsiTreeUtil.isAncestor(((PsiField)resolved).getContainingClass(), memberContainingClass, false) && expression.getQualifierExpression() == null) { final PsiExpression initializer = ((PsiField)resolved).getInitializer(); if (initializer == null || diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/FinalVariableMightNotHaveBeenInitializedInsideLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/FinalVariableMightNotHaveBeenInitializedInsideLambda.java index c8e80cc743c4..b924ad67598a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/FinalVariableMightNotHaveBeenInitializedInsideLambda.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/FinalVariableMightNotHaveBeenInitializedInsideLambda.java @@ -64,3 +64,28 @@ abstract class TestInnerAnonymous { } } +interface Fun { + B m(A a); +} + +class TestAnonymousWithRefToTheTopLevelUninitializedField { + private final int myId; + + private Runnable r = new Runnable() { + final int localId; + { + localId = 0; + } + + Fun ff = (a) -> myId; + Fun ffLocal = (a) -> localId; + public void run() { + } + }; + + public TestAnonymousWithRefToTheTopLevelUninitializedField(int id) { + myId = id; + } + +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeForwardReferenceFromNestedClassField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeForwardReferenceFromNestedClassField.java new file mode 100644 index 000000000000..759f02fcba62 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeForwardReferenceFromNestedClassField.java @@ -0,0 +1,19 @@ +// "Replace with lambda" "false" +class Test { + private final int myId; + + private final Runnable myModels = new Runnable() { + private Comparable myMapping = new Comparable() { + @Override + public String apply(final String s) { + return myId; + } + }; + + public void run() {} + }; + + public Test(final int i) { + myId = i; + } +} \ No newline at end of file