From 6ee2ce046e7184dffd4f4b5535cbb2f40843c431 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 6 Jul 2016 16:31:45 +0200 Subject: [PATCH] can be final: don't suggest final modifiers for implicitly write fields (IDEA-148069) --- .../canBeFinal/CanBeFinalAnnotator.java | 6 +++++ .../reference/RefFieldImpl.java | 2 +- .../fieldImplicitWrite/expected.xml | 9 +++++++ .../fieldImplicitWrite/src/Test.java | 9 +++++++ .../codeInspection/CanBeFinalTest.java | 27 +++++++++++++++++++ .../codeInspection/reference/RefUtil.java | 2 +- 6 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/expected.xml create mode 100644 java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/src/Test.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java b/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java index c0aa08dab227..90a51eba9547 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalAnnotator.java @@ -89,6 +89,12 @@ class CanBeFinalAnnotator extends RefGraphAnnotatorEx { } } } + else if (refElement instanceof RefField) { + final PsiElement element = refElement.getElement(); + if (element != null && RefUtil.isImplicitWrite(element)) { + ((RefElementImpl)refElement).setFlag(false, CAN_BE_FINAL_MASK); + } + } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java index a70f700bad2b..29611b3648ba 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java @@ -121,7 +121,7 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField { refUtil.addReferences(psiField, this, psiField); } - if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant || RefUtil.isWriteImplicitly(psiField)) { + if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant || RefUtil.isImplicitWrite(psiField)) { if (!checkFlag(USED_FOR_WRITING_MASK)) { setFlag(true, ASSIGNED_ONLY_IN_INITIALIZER_MASK); setFlag(true, USED_FOR_WRITING_MASK); diff --git a/java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/expected.xml b/java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/expected.xml new file mode 100644 index 000000000000..93b56fb7e0e4 --- /dev/null +++ b/java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/expected.xml @@ -0,0 +1,9 @@ + + + + Test.java + 3 + Declaration can have final modifier + + + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/src/Test.java b/java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/src/Test.java new file mode 100644 index 000000000000..a991d4c63053 --- /dev/null +++ b/java/java-tests/testData/inspection/canBeFinal/fieldImplicitWrite/src/Test.java @@ -0,0 +1,9 @@ +final class G { + private Object implicitWrite; + private Object foo; + + void fooBar() { + System.out.println(implicitWrite); + System.out.println(foo); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/CanBeFinalTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/CanBeFinalTest.java index afaf50f49f23..d48fd3263215 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/CanBeFinalTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/CanBeFinalTest.java @@ -9,8 +9,14 @@ package com.intellij.codeInspection; import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.codeInspection.canBeFinal.CanBeFinalInspection; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiNamedElement; import com.intellij.testFramework.InspectionTestCase; +import com.intellij.testFramework.PlatformTestUtil; public class CanBeFinalTest extends InspectionTestCase { @Override @@ -120,4 +126,25 @@ public class CanBeFinalTest extends InspectionTestCase { doTest(tool); } + + public void testfieldImplicitWrite() throws Exception { + PlatformTestUtil.registerExtension(ImplicitUsageProvider.EP_NAME, new ImplicitUsageProvider() { + @Override + public boolean isImplicitUsage(PsiElement element) { + return isImplicitWrite(element); + } + + @Override + public boolean isImplicitRead(PsiElement element) { + return false; + } + + @Override + public boolean isImplicitWrite(PsiElement element) { + return element instanceof PsiField && "implicitWrite".equals(((PsiNamedElement)element).getName()); + } + }, myTestRootDisposable); + + doTest(); + } } diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefUtil.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefUtil.java index 017836dddb94..80b40880fa79 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefUtil.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefUtil.java @@ -58,7 +58,7 @@ public class RefUtil { return false; } - public static boolean isWriteImplicitly(PsiElement element) { + public static boolean isImplicitWrite(PsiElement element) { final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME); for (ImplicitUsageProvider provider : implicitUsageProviders) { if (provider.isImplicitWrite(element)) return true;