mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
lambda: effectively final
This commit is contained in:
+28
-6
@@ -695,18 +695,30 @@ public class HighlightControlFlowUtil {
|
||||
} else {
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(context, PsiLambdaExpression.class);
|
||||
if (lambdaExpression != null) {
|
||||
boolean effectivelyFinal;
|
||||
if (variable instanceof PsiParameter) {
|
||||
final PsiElement parent = variable.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
boolean effectivelyFinal = true;
|
||||
for (PsiReference reference : ReferencesSearch.search(variable)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element instanceof PsiExpression && PsiUtil.isOnAssignmentLeftHand((PsiExpression)element)) {
|
||||
effectivelyFinal = isAccessedForWriting(variable, new LocalSearchScope(((PsiParameter)variable).getDeclarationScope()));
|
||||
} else {
|
||||
final ControlFlow controlFlow;
|
||||
try {
|
||||
controlFlow = getControlFlow(PsiUtil.getVariableCodeBlock(variable, context));
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
|
||||
final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
|
||||
effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
|
||||
if (effectivelyFinal) {
|
||||
effectivelyFinal = isAccessedForWriting(variable, new LocalSearchScope(lambdaExpression));
|
||||
}
|
||||
} else {
|
||||
effectivelyFinal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!effectivelyFinal ) {
|
||||
@@ -717,6 +729,16 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isAccessedForWriting(PsiVariable variable, final LocalSearchScope searchScope) {
|
||||
for (PsiReference reference : ReferencesSearch.search(variable, searchScope)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClass getInnerClassVariableReferencedFrom(PsiVariable variable, PsiElement context) {
|
||||
final PsiElement[] scope;
|
||||
|
||||
@@ -200,7 +200,7 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
while (element != null) {
|
||||
// variable can be defined in for loop initializer
|
||||
PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof PsiExpression)) {
|
||||
if (!(parent instanceof PsiExpression) || parent instanceof PsiLambdaExpression) {
|
||||
if (element instanceof PsiCodeBlock || element instanceof PsiForStatement || element instanceof PsiForeachStatement) {
|
||||
blockSoFar = element;
|
||||
}
|
||||
|
||||
+50
@@ -1,6 +1,9 @@
|
||||
interface I {
|
||||
int m(int i);
|
||||
}
|
||||
interface J {
|
||||
int m();
|
||||
}
|
||||
|
||||
public class XXX {
|
||||
|
||||
@@ -19,4 +22,51 @@ public class XXX {
|
||||
final int L = 0;
|
||||
I i = (int h) -> { int k = 0; return h + k + <error descr="Variable used in lambda expression should be effectively final">j</error> + l + L; };
|
||||
}
|
||||
|
||||
void foo(J i) { }
|
||||
|
||||
void m1(int x) {
|
||||
int y = 1;
|
||||
foo(() -> x+y);
|
||||
}
|
||||
|
||||
void m2(int x) {
|
||||
int y;
|
||||
y = 1;
|
||||
foo(() -> x+y);
|
||||
}
|
||||
|
||||
void m3(int x, boolean cond) {
|
||||
int y;
|
||||
if (cond) y = 1;
|
||||
foo(() -> x+<error descr="Variable used in lambda expression should be effectively final">y</error>);
|
||||
}
|
||||
|
||||
void m4(int x, boolean cond) {
|
||||
int y;
|
||||
if (cond) y = 1;
|
||||
else y = 2;
|
||||
foo(() -> x+y);
|
||||
}
|
||||
|
||||
void m5(int x, boolean cond) {
|
||||
int y;
|
||||
if (cond) y = 1;
|
||||
y = 2;
|
||||
foo(() -> x+<error descr="Variable used in lambda expression should be effectively final">y</error>);
|
||||
}
|
||||
|
||||
void m6(int x) {
|
||||
foo(() -> <error descr="Variable used in lambda expression should be effectively final">x</error>+1);
|
||||
x++;
|
||||
}
|
||||
|
||||
void m7(int x) {
|
||||
foo(() -> <error descr="Variable used in lambda expression should be effectively final">x</error>=1);
|
||||
}
|
||||
|
||||
void m8() {
|
||||
int y;
|
||||
foo(() -> <error descr="Variable used in lambda expression should be effectively final">y</error>=1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user