diff --git a/java/java-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java b/java/java-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java index 8cb271a89d80..767b932079e2 100644 --- a/java/java-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java @@ -19,20 +19,24 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil; import com.intellij.codeInsight.intention.AddAnnotationFix; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import sun.util.LocaleServiceProviderPool; /** * User: anna * Date: 1/28/11 */ public class PossibleHeapPollutionVarargsInspection extends BaseJavaLocalInspectionTool { + public static final Logger LOG = Logger.getInstance("#" + PossibleHeapPollutionVarargsInspection.class.getName()); @Nls @NotNull @Override @@ -70,11 +74,21 @@ public class PossibleHeapPollutionVarargsInspection extends BaseJavaLocalInspect return new HeapPollutionVisitor() { @Override protected void registerProblem(PsiMethod method, PsiIdentifier nameIdentifier) { - holder.registerProblem(nameIdentifier, "Possible heap pollution from parameterized vararg type #loc", - //todo check if can be final or static - method.hasModifierProperty(PsiModifier.FINAL) || - method.hasModifierProperty(PsiModifier.STATIC) || - method.isConstructor() ? new AnnotateAsSafeVarargsQuickFix() : null); + final LocalQuickFix quickFix; + if (method.hasModifierProperty(PsiModifier.FINAL) || + method.hasModifierProperty(PsiModifier.STATIC) || + method.isConstructor()) { + quickFix = new AnnotateAsSafeVarargsQuickFix(); + } + else { + final PsiClass containingClass = method.getContainingClass(); + LOG.assertTrue(containingClass != null); + boolean canBeFinal = !method.hasModifierProperty(PsiModifier.ABSTRACT) && + !containingClass.isInterface() && + OverridingMethodsSearch.search(method).findFirst() == null; + quickFix = canBeFinal ? new MakeFinalAndAnnotateQuickFix() : null; + } + holder.registerProblem(nameIdentifier, "Possible heap pollution from parameterized vararg type #loc", quickFix); } }; } @@ -102,6 +116,30 @@ public class PossibleHeapPollutionVarargsInspection extends BaseJavaLocalInspect } } + private static class MakeFinalAndAnnotateQuickFix implements LocalQuickFix { + @NotNull + @Override + public String getName() { + return "Make final and annotate as @SafeVarargs"; + } + + @NotNull + @Override + public String getFamilyName() { + return getName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement psiElement = descriptor.getPsiElement(); + if (psiElement instanceof PsiIdentifier) { + final PsiMethod psiMethod = (PsiMethod)psiElement.getParent(); + psiMethod.getModifierList().setModifierProperty(PsiModifier.FINAL, true); + new AddAnnotationFix("java.lang.SafeVarargs", psiMethod).applyFix(project, descriptor); + } + } + } + public static abstract class HeapPollutionVisitor extends JavaElementVisitor { @Override diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/after9.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/after9.java new file mode 100644 index 000000000000..a0bb3e718767 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/after9.java @@ -0,0 +1,8 @@ +// "Make final and annotate as @SafeVarargs" "true" +public class Test { + @SafeVarargs + public final void main(T... args) { + + } +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before10.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before10.java new file mode 100644 index 000000000000..c50569deb122 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before10.java @@ -0,0 +1,5 @@ +// "Make final and annotate as @SafeVarargs" "false" +public interface Test { + void main(T... args); +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before11.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before11.java new file mode 100644 index 000000000000..3d17e6970a54 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before11.java @@ -0,0 +1,5 @@ +// "Make final and annotate as @SafeVarargs" "false" +public abstract class Test { + abstract void main(T... args); +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before9.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before9.java new file mode 100644 index 000000000000..d78a3cd1ace8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before9.java @@ -0,0 +1,7 @@ +// "Make final and annotate as @SafeVarargs" "true" +public class Test { + public void main(T... args) { + + } +} +