From acffc2bef987a2a5d0852e9b28a3804345239dfa Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 3 Jan 2020 18:47:23 +0700 Subject: [PATCH] PossibleHeapPollutionVarargsInspection: behavior changed according to new proposal: 1. Warn on compact/canonical constructor (and annotate it) when present 2. Create compact constructor and annotate it if not present Review ID: IDEA-CR-56682 GitOrigin-RevId: 9ace593c6ae32490dd37f684054a2e17d93e81a8 --- ...ossibleHeapPollutionVarargsInspection.java | 22 +++++++++++++------ .../quickFix/safeVarargs/afterRecord.java | 4 +++- .../safeVarargs/afterRecordCompact.java | 6 +++++ .../safeVarargs/afterRecordHasMembers.java | 11 ++++++++++ .../safeVarargs/beforeRecordCompact.java | 2 +- .../safeVarargs/beforeRecordHasMembers.java | 7 ++++++ 6 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordCompact.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordHasMembers.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordHasMembers.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java index e40087238f2b..abe00dbfaab0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/PossibleHeapPollutionVarargsInspection.java @@ -7,6 +7,7 @@ import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil; import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil; import com.intellij.codeInsight.intention.AddAnnotationPsiFix; import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; @@ -69,11 +70,19 @@ public class PossibleHeapPollutionVarargsInspection extends AbstractBaseJavaLoca @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiElement psiElement = descriptor.getPsiElement(); - if (psiElement instanceof PsiIdentifier) { - final PsiModifierListOwner psiMethod = (PsiModifierListOwner)psiElement.getParent(); - if (psiMethod != null) { - new AddAnnotationPsiFix(CommonClassNames.JAVA_LANG_SAFE_VARARGS, psiMethod, PsiNameValuePair.EMPTY_ARRAY).applyFix(project, descriptor); - } + if (!(psiElement instanceof PsiIdentifier)) return; + PsiModifierListOwner owner = (PsiModifierListOwner)psiElement.getParent(); + if (owner instanceof PsiClass) { + PsiClass rec = (PsiClass)owner; + if (!rec.isRecord()) return; + String compactCtorText = "public " + rec.getName() + " {}"; + PsiMethod ctor = JavaPsiFacade.getElementFactory(project).createMethodFromText(compactCtorText, owner); + PsiMethod firstMethod = ArrayUtil.getFirstElement(rec.getMethods()); + owner = (PsiMethod)WriteCommandAction.writeCommandAction(owner.getContainingFile()).withName(getFamilyName()) + .compute(() -> rec.addBefore(ctor, firstMethod)); + } + if (owner instanceof PsiMethod) { + new AddAnnotationPsiFix(CommonClassNames.JAVA_LANG_SAFE_VARARGS, owner, PsiNameValuePair.EMPTY_ARRAY).applyFix(project, descriptor); } } } @@ -120,7 +129,6 @@ public class PossibleHeapPollutionVarargsInspection extends AbstractBaseJavaLoca if (!PsiUtil.getLanguageLevel(method).isAtLeast(LanguageLevel.JDK_1_7)) return; if (AnnotationUtil.isAnnotated(method, CommonClassNames.JAVA_LANG_SAFE_VARARGS, 0)) return; if (!method.isVarArgs()) return; - if (JavaPsiRecordUtil.isCompactConstructor(method)) return; final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiParameter psiParameter = parameters[parameters.length - 1]; @@ -139,7 +147,7 @@ public class PossibleHeapPollutionVarargsInspection extends AbstractBaseJavaLoca PsiRecordComponent lastComponent = ArrayUtil.getLastElement(header.getRecordComponents()); if (lastComponent == null || !lastComponent.isVarArgs()) return; PsiMethod constructor = JavaPsiRecordUtil.findCanonicalConstructor(aClass); - if (constructor != null && JavaPsiRecordUtil.isExplicitCanonicalConstructor(constructor)) return; + if (constructor != null && constructor.isPhysical()) return; // will be reported on constructor instead final PsiType type = lastComponent.getType(); LOG.assertTrue(type instanceof PsiEllipsisType, "type: " + type.getCanonicalText() + "; param: " + lastComponent); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecord.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecord.java index 189564d9f1a0..1622a6a7ab37 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecord.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecord.java @@ -1,5 +1,7 @@ // "Annotate as @SafeVarargs" "true" -@SafeVarargs public record Test(java.util.List... args) { + @SafeVarargs + public Test { + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordCompact.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordCompact.java new file mode 100644 index 000000000000..45fb155c9327 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordCompact.java @@ -0,0 +1,6 @@ +// "Annotate as @SafeVarargs" "true" +record Rec(T... args) { + @SafeVarargs + public Rec { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordHasMembers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordHasMembers.java new file mode 100644 index 000000000000..fdf8cc9a34d9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/afterRecordHasMembers.java @@ -0,0 +1,11 @@ +// "Annotate as @SafeVarargs" "true" +public record Test(java.util.List... args) { + static final String FOO = "bar"; + + @SafeVarargs + public Test { + } + + void test() {} +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordCompact.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordCompact.java index b5619687d917..598df55d6873 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordCompact.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordCompact.java @@ -1,4 +1,4 @@ -// "Annotate as @SafeVarargs" "false" +// "Annotate as @SafeVarargs" "true" record Rec(T... args) { public Rec { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordHasMembers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordHasMembers.java new file mode 100644 index 000000000000..b0f855fe49f7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/beforeRecordHasMembers.java @@ -0,0 +1,7 @@ +// "Annotate as @SafeVarargs" "true" +public record Test(java.util.List... args) { + static final String FOO = "bar"; + + void test() {} +} +