mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
lambda: do not suggest to replace with lambda when refs to final fields exist in body (IDEA-111026); final initializer
This commit is contained in:
@@ -1723,7 +1723,7 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
if (expression.getTextRange().getStartOffset() >= referencedField.getTextRange().getEndOffset()) return null;
|
||||
// only simple reference can be illegal
|
||||
if (expression.getQualifierExpression() != null) return null;
|
||||
PsiField initField = findEnclosingFieldInitializer(expression);
|
||||
PsiField initField = findEnclosingFieldInitializer(expression, true);
|
||||
PsiClassInitializer classInitializer = findParentClassInitializer(expression);
|
||||
if (initField == null && classInitializer == null) return null;
|
||||
// instance initializers may access static fields
|
||||
@@ -1743,7 +1743,12 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
* @return field that has initializer with this element as subexpression or null if not found
|
||||
*/
|
||||
@Nullable
|
||||
static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element) {
|
||||
public static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element) {
|
||||
return findEnclosingFieldInitializer(element, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element, boolean stopAtLambda) {
|
||||
while (element != null) {
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiField) {
|
||||
@@ -1751,7 +1756,7 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
if (element == field.getInitializer()) return field;
|
||||
if (field instanceof PsiEnumConstant && element == ((PsiEnumConstant)field).getArgumentList()) return field;
|
||||
}
|
||||
if (element instanceof PsiClass || element instanceof PsiMethod || parent instanceof PsiLambdaExpression) return null;
|
||||
if (element instanceof PsiClass || element instanceof PsiMethod || (stopAtLambda && parent instanceof PsiLambdaExpression)) return null;
|
||||
element = parent;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.ChangeContextUtil;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -84,6 +85,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
body.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression methodCallExpression) {
|
||||
if (bodyContainsForbiddenRefs[0]) return;
|
||||
super.visitMethodCallExpression(methodCallExpression);
|
||||
final PsiMethod psiMethod = methodCallExpression.resolveMethod();
|
||||
if (psiMethod == methods[0] ||
|
||||
@@ -97,6 +99,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
|
||||
@Override
|
||||
public void visitThisExpression(PsiThisExpression expression) {
|
||||
if (bodyContainsForbiddenRefs[0]) return;
|
||||
if (expression.getQualifier() == null) {
|
||||
bodyContainsForbiddenRefs[0] = true;
|
||||
}
|
||||
@@ -104,6 +107,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
|
||||
@Override
|
||||
public void visitSuperExpression(PsiSuperExpression expression) {
|
||||
if (bodyContainsForbiddenRefs[0]) return;
|
||||
if (expression.getQualifier() == null) {
|
||||
bodyContainsForbiddenRefs[0] = true;
|
||||
}
|
||||
@@ -111,9 +115,28 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(PsiLocalVariable variable) {
|
||||
if (bodyContainsForbiddenRefs[0]) return;
|
||||
super.visitLocalVariable(variable);
|
||||
locals.add(variable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
if (bodyContainsForbiddenRefs[0]) return;
|
||||
super.visitReferenceExpression(expression);
|
||||
if (!(expression.getParent() instanceof PsiMethodCallExpression)) {
|
||||
PsiField field = HighlightUtil.findEnclosingFieldInitializer(expression);
|
||||
if (field != null) {
|
||||
final PsiElement resolved = expression.resolve();
|
||||
if (resolved instanceof PsiField &&
|
||||
((PsiField)resolved).hasModifierProperty(PsiModifier.FINAL) &&
|
||||
!((PsiField)resolved).hasInitializer() &&
|
||||
((PsiField)resolved).getContainingClass() == field.getContainingClass()) {
|
||||
bodyContainsForbiddenRefs[0] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!bodyContainsForbiddenRefs[0]) {
|
||||
PsiResolveHelper helper = PsiResolveHelper.SERVICE.getInstance(body.getProject());
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class MyTest {
|
||||
final Runnable lambdaRunnable = () -> {
|
||||
System.out.println(<error descr="Variable 'o' might not have been initialized">o</error>);
|
||||
};
|
||||
|
||||
final Object o;
|
||||
|
||||
MyTest(Object o) {
|
||||
this.o = o;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// "Replace with lambda" "false"
|
||||
class MyTest {
|
||||
final Runnable anonymRunnable = new Run<caret>nable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println(o);
|
||||
}
|
||||
};
|
||||
|
||||
final Object o;
|
||||
|
||||
MyTest(Object o) {
|
||||
this.o = o;
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testUnderscores() { doTest(true);}
|
||||
public void testReturnTypeAmbiguity() { doTest();}
|
||||
public void testWildcardsAndFormalLambdaParams() {doTest();}
|
||||
public void testFinalInitializer() {doTest();}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
|
||||
Reference in New Issue
Block a user