mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
field can be final: assigned from lambda in constructor (IDEA-170073)
This commit is contained in:
+8
-2
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
|
||||
import com.intellij.codeInspection.reference.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -99,17 +100,22 @@ class CanBeFinalAnnotator extends RefGraphAnnotatorEx {
|
||||
RefElement refFrom,
|
||||
boolean referencedFromClassInitializer,
|
||||
boolean forReading,
|
||||
boolean forWriting) {
|
||||
boolean forWriting,
|
||||
PsiElement referenceElement) {
|
||||
if (!(refWhat instanceof RefField)) return;
|
||||
if (!(refFrom instanceof RefMethod) ||
|
||||
!((RefMethod)refFrom).isConstructor() ||
|
||||
((PsiField)refWhat.getElement()).hasInitializer() ||
|
||||
((RefMethod)refFrom).getOwnerClass() != ((RefField)refWhat).getOwnerClass() ||
|
||||
((RefField)refWhat).isStatic()) {
|
||||
if (!referencedFromClassInitializer && forWriting) {
|
||||
if (forWriting &&
|
||||
!(referencedFromClassInitializer && PsiTreeUtil.getParentOfType(referenceElement, PsiLambdaExpression.class, true) == null)) {
|
||||
((RefFieldImpl)refWhat).setFlag(false, CAN_BE_FINAL_MASK);
|
||||
}
|
||||
}
|
||||
else if (forWriting && PsiTreeUtil.getParentOfType(referenceElement, PsiLambdaExpression.class, true) != null) {
|
||||
((RefFieldImpl)refWhat).setFlag(false, CAN_BE_FINAL_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,7 +76,7 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField {
|
||||
}
|
||||
|
||||
setUsedQualifiedOutsidePackageFlag(refFrom, expressionFrom);
|
||||
getRefManager().fireNodeMarkedReferenced(this, refFrom, referencedFromClassInitializer, forReading, forWriting);
|
||||
getRefManager().fireNodeMarkedReferenced(this, refFrom, referencedFromClassInitializer, forReading, forWriting, expressionFrom);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -260,7 +260,7 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa
|
||||
protected void markReferenced(final RefElementImpl refFrom, PsiElement psiFrom, PsiElement psiWhat, final boolean forWriting, boolean forReading, PsiReferenceExpression expressionFrom) {
|
||||
addInReference(refFrom);
|
||||
setUsedQualifiedOutsidePackageFlag(refFrom, expressionFrom);
|
||||
getRefManager().fireNodeMarkedReferenced(this, refFrom, false, forReading, forWriting);
|
||||
getRefManager().fireNodeMarkedReferenced(this, refFrom, false, forReading, forWriting, expressionFrom);
|
||||
}
|
||||
|
||||
void setUsedQualifiedOutsidePackageFlag(RefElementImpl refFrom, PsiReferenceExpression expressionFrom) {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems />
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
abstract class Foo {
|
||||
private String foo;
|
||||
|
||||
public A(String foo) {
|
||||
this.foo = foo;
|
||||
Runnable r = () -> {this.foo = "";};
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems />
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
abstract class Foo {
|
||||
private String foo = "1";
|
||||
{
|
||||
Runnable r = () -> {this.foo = "";};
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,14 @@ public class CanBeFinalTest extends InspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testassignedFromLambda() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testassignedFromLambdaInClassInitializer() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testsimpleClassInheritance() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
+20
@@ -55,6 +55,26 @@ public abstract class RefGraphAnnotator {
|
||||
boolean referencedFromClassInitializer) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a reference to the specified element has been found.
|
||||
*
|
||||
* @param refWhat the referenced element.
|
||||
* @param refFrom the referencing element.
|
||||
* @param referencedFromClassInitializer if true, {@code refFrom} is a class and the reference
|
||||
* has been found in its initializer block.
|
||||
* @param forReading used for reading
|
||||
* @param forWriting used for writing
|
||||
* @param referenceElement reference element in refFrom
|
||||
*/
|
||||
public void onMarkReferenced(RefElement refWhat,
|
||||
RefElement refFrom,
|
||||
boolean referencedFromClassInitializer,
|
||||
boolean forReading,
|
||||
boolean forWriting,
|
||||
PsiElement referenceElement) {
|
||||
onMarkReferenced(refWhat, refFrom, referencedFromClassInitializer, forReading, forWriting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a reference to the specified element has been found.
|
||||
*
|
||||
|
||||
@@ -169,6 +169,17 @@ public class RefManagerImpl extends RefManager {
|
||||
annotator.onMarkReferenced(refWhat, refFrom, referencedFromClassInitializer, forReading, forWriting);
|
||||
}
|
||||
}
|
||||
|
||||
void fireNodeMarkedReferenced(RefElement refWhat,
|
||||
RefElement refFrom,
|
||||
boolean referencedFromClassInitializer,
|
||||
final boolean forReading,
|
||||
final boolean forWriting,
|
||||
PsiElement element) {
|
||||
for (RefGraphAnnotator annotator : myGraphAnnotators) {
|
||||
annotator.onMarkReferenced(refWhat, refFrom, referencedFromClassInitializer, forReading, forWriting, element);
|
||||
}
|
||||
}
|
||||
|
||||
public void fireNodeMarkedReferenced(PsiElement what, PsiElement from) {
|
||||
for (RefGraphAnnotator annotator : myGraphAnnotators) {
|
||||
|
||||
Reference in New Issue
Block a user