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 1c5a0f38a921..b7e4bf4fe5ab 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 @@ -649,14 +649,8 @@ public class HighlightControlFlowUtil { @NotNull PsiField field, @NotNull PsiReferenceExpression reference, @NotNull PsiFile containingFile) { - if (!containingFile.getManager().areElementsEquivalent(enclosingCtrOrInitializer.getContainingClass(), field.getContainingClass())) return false; - PsiExpression qualifierExpression = reference.getQualifierExpression(); - // JLS 16: "Such an assignment is defined to occur if and only if either the simple name of the variable - // (or, for a field, its simple name qualified by this) occurs on the left hand side of an assignment operator" - // Qualified this is not allowed by spec - return qualifierExpression == null || (qualifierExpression instanceof PsiThisExpression && - ((PsiThisExpression)qualifierExpression).getQualifier() == null); + return LocalsOrMyInstanceFieldsControlFlowPolicy.isLocalOrMyInstanceReference(reference); } diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsOrMyInstanceFieldsControlFlowPolicy.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsOrMyInstanceFieldsControlFlowPolicy.java index 25521743ad54..86b82a0bc4ec 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsOrMyInstanceFieldsControlFlowPolicy.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/LocalsOrMyInstanceFieldsControlFlowPolicy.java @@ -17,7 +17,7 @@ package com.intellij.psi.controlFlow; import com.intellij.psi.*; -import com.intellij.psi.util.PsiUtil; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; public class LocalsOrMyInstanceFieldsControlFlowPolicy implements ControlFlowPolicy { @@ -28,13 +28,9 @@ public class LocalsOrMyInstanceFieldsControlFlowPolicy implements ControlFlowPol @Override public PsiVariable getUsedVariable(@NotNull PsiReferenceExpression refExpr) { - PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(refExpr.getQualifierExpression()); - if (qualifier == null || (qualifier instanceof PsiThisExpression && ((PsiThisExpression)qualifier).getQualifier() == null)) { - PsiElement resolved = refExpr.resolve(); - if (!(resolved instanceof PsiVariable)) return null; - return (PsiVariable)resolved; + if (isLocalOrMyInstanceReference(refExpr)) { + return ObjectUtils.tryCast(refExpr.resolve(), PsiVariable.class); } - return null; } @@ -51,4 +47,19 @@ public class LocalsOrMyInstanceFieldsControlFlowPolicy implements ControlFlowPol public static LocalsOrMyInstanceFieldsControlFlowPolicy getInstance() { return INSTANCE; } + + /** + * @param variableReference variable reference to check + * @return true if given variable reference refers to local variable or the field which participates in + * definitive assignment analysis, as specified in JLS, chapter 16. The method does not check whether + * the reference actually resolves to variable. + */ + public static boolean isLocalOrMyInstanceReference(PsiReferenceExpression variableReference) { + PsiExpression qualifierExpression = variableReference.getQualifierExpression(); + // JLS 16: "Such an assignment is defined to occur if and only if either the simple name of the variable + // (or, for a field, its simple name qualified by this) occurs on the left hand side of an assignment operator" + // Qualified this is not allowed by spec + return qualifierExpression == null || (qualifierExpression instanceof PsiThisExpression && + ((PsiThisExpression)qualifierExpression).getQualifier() == null); + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java index 60d0a0f233fc..c648224d9818 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java @@ -251,4 +251,14 @@ class QualifiedThis { QualifiedThis.this.x = 5; this.x = 5; } +} + +class ParenthesizedThis { + final int x; + final int y = (this).x + 1; // allowed as qualifier is not naked 'this'! + + ParenthesizedThis() { + (this).x = 5; + this.x = 6; + } } \ No newline at end of file