diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MergeDuplicateAttributesFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MergeDuplicateAttributesFix.java index 9aebe4d8f428..fc912b7e5e35 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MergeDuplicateAttributesFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MergeDuplicateAttributesFix.java @@ -5,16 +5,16 @@ import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.Strings; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.siyeh.ig.psiutils.CommentTracker; -import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Objects; -import java.util.StringJoiner; +import java.util.ArrayList; +import java.util.List; public class MergeDuplicateAttributesFix extends LocalQuickFixAndIntentionActionOnPsiElement { public MergeDuplicateAttributesFix(PsiElement element) { @@ -27,42 +27,46 @@ public class MergeDuplicateAttributesFix extends LocalQuickFixAndIntentionAction @Nullable Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { - final PsiNameValuePair pair = (PsiNameValuePair)startElement; - final PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList)pair.getParent(); - final PsiNameValuePair[] attributes = parameterList.getAttributes(); - final StringJoiner joiner = new StringJoiner(", "); - final String name = pair.getName(); - final boolean[] isFirstValue = {true}; - StreamEx.of(attributes).filterBy(PsiNameValuePair::getName, name).map(attribute -> attribute.getValue()).filter(Objects::nonNull) - .forEach(value -> { - CommentTracker ct = new CommentTracker(); - if (value instanceof PsiArrayInitializerMemberValue) { - if (((PsiArrayInitializerMemberValue)value).getInitializers().length == 0 && !isFirstValue[0]) { - new CommentTracker().deleteAndRestoreComments(value.getParent()); - return; - } - else { - final PsiElement lBrace = value.getFirstChild(); - final PsiElement lastChild = value.getLastChild(); - PsiElement maybeTrailingComma = PsiTreeUtil.skipWhitespacesAndCommentsBackward(lastChild); - if (PsiUtil.isJavaToken(maybeTrailingComma, JavaTokenType.COMMA)) { - maybeTrailingComma = maybeTrailingComma.getPrevSibling(); - } - if (maybeTrailingComma == null) return; - joiner.add(ct.rangeText(lBrace.getNextSibling(), maybeTrailingComma)); - } + PsiNameValuePair pair = (PsiNameValuePair)startElement; + PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList)pair.getParent(); + PsiNameValuePair[] attributes = parameterList.getAttributes(); + List strings = new ArrayList<>(); + String name = pair.getName(); + if (name == null) return; + for (PsiNameValuePair attribute : attributes) { + String attributeName = attribute.getName(); + if (!name.equals(attributeName) && (attributeName != null || !PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name))) continue; + PsiAnnotationMemberValue value = attribute.getValue(); + if (value == null) continue; + CommentTracker ct = new CommentTracker(); + if (value instanceof PsiArrayInitializerMemberValue) { + if (((PsiArrayInitializerMemberValue)value).getInitializers().length != 0) { + PsiElement lBrace = value.getFirstChild(); + PsiElement rBrace = value.getLastChild(); + PsiElement maybeTrailingComma = PsiTreeUtil.skipWhitespacesAndCommentsBackward(rBrace); + // if there is a trailing comma in the array initializer, this allows you to copy comments between the last initializer and + // the trailing comma to the merged value + PsiElement to = (PsiUtil.isJavaToken(maybeTrailingComma, JavaTokenType.COMMA) ? maybeTrailingComma : rBrace).getPrevSibling(); + strings.add(ct.rangeText(lBrace.getNextSibling(), to)); } - else { - joiner.add(value.getText()); - } - if (!isFirstValue[0]) { - ct.deleteAndRestoreComments(value.getParent()); - } - isFirstValue[0] = false; - }); - final PsiAnnotation dummyAnnotation = JavaPsiFacade.getElementFactory(project).createAnnotationFromText("@A({" + joiner + "})", null); - final PsiAnnotationMemberValue mergedValue = dummyAnnotation.getParameterList().getAttributes()[0].getValue(); - final PsiAnnotation annotation = (PsiAnnotation)parameterList.getParent(); + } + else { + strings.add(value.getText()); + } + if (strings.size() != 1) { + // the check above allows you to get from + // @SuppressWarnings(value = "foo", value = "bar") + // to + // @SuppressWarnings(value = {"foo", "bar"}), + // but not to + // @SuppressWarnings({"foo", "bar"}) + ct.deleteAndRestoreComments(value.getParent()); + } + } + PsiAnnotation dummyAnnotation = + JavaPsiFacade.getElementFactory(project).createAnnotationFromText("@A({" + Strings.join(strings, ", ") + "})", null); + PsiAnnotationMemberValue mergedValue = dummyAnnotation.getParameterList().getAttributes()[0].getValue(); + PsiAnnotation annotation = (PsiAnnotation)parameterList.getParent(); annotation.setDeclaredAttributeValue(pair.getName(), mergedValue); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterArrays.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterArrays.java index 4a8a911a31c9..01c84da04a5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterArrays.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterArrays.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value= {"a", "b", "c"}) +@SuppressWarnings(value = {"a", "b", "c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterComments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterComments.java index 6f328d76fe75..edb6319b92db 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterComments.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterComments.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(/*1*/value/*2*/=/*3*/{"a", "b", /*12*/"c"/*13*/, /*14*/"d"/*15*/}/*4*/ /*5*//*6*//*7*//*8*/ /*9*//*10*//*11*//*16*//*17*/) +@SuppressWarnings(/*1*/value/*2*/ = /*3*/{"a", "b", /*12*/"c"/*13*/,/*14*/"d"/*15*/, /*18*/"e"/*19*/}/*4*//*5*//*6*//*7*//*8*//*9*//*10*//*11*//*16*//*17*/) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterEmptyArrays.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterEmptyArrays.java new file mode 100644 index 000000000000..4980f8bc494c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterEmptyArrays.java @@ -0,0 +1,3 @@ +// "Merge duplicate attributes" "true" +@SuppressWarnings(value = {"a", "b"}) +class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed1.java index 4a8a911a31c9..01c84da04a5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed1.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value= {"a", "b", "c"}) +@SuppressWarnings(value = {"a", "b", "c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed2.java index 4a8a911a31c9..01c84da04a5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterMixed2.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value= {"a", "b", "c"}) +@SuppressWarnings(value = {"a", "b", "c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterNotArrays.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterNotArrays.java index 4a8a911a31c9..01c84da04a5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterNotArrays.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterNotArrays.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value= {"a", "b", "c"}) +@SuppressWarnings(value = {"a", "b", "c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterShorthandForm1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterShorthandForm1.java new file mode 100644 index 000000000000..5a8073fee359 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterShorthandForm1.java @@ -0,0 +1,3 @@ +// "Merge duplicate attributes" "true" +@SuppressWarnings({"a", "b", "c"}) +class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterShorthandForm2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterShorthandForm2.java new file mode 100644 index 000000000000..01c84da04a5b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterShorthandForm2.java @@ -0,0 +1,3 @@ +// "Merge duplicate attributes" "true" +@SuppressWarnings(value = {"a", "b", "c"}) +class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterTrailingComma.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterTrailingComma.java index 4a8a911a31c9..01c84da04a5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterTrailingComma.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/afterTrailingComma.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value= {"a", "b", "c"}) +@SuppressWarnings(value = {"a", "b", "c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeArrays.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeArrays.java index 38fbd63e77d5..ef041b5d075f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeArrays.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeArrays.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value={"a"}, value={"b"}, value={"c"}) +@SuppressWarnings(value = {"a"}, value = {"b"}, value = {"c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeComments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeComments.java index cc698a795df7..ef8a9b2055a8 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeComments.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeComments.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(/*1*/value/*2*/=/*3*/"a"/*4*/, /*5*/value/*6*/=/*7*/"b"/*8*/, /*9*/value/*10*/=/*11*/{/*12*/"c"/*13*/, /*14*/"d"/*15*/, /*16*/}/*17*/) +@SuppressWarnings(/*1*/value/*2*/ = /*3*/"a"/*4*/,/*5*/value/*6*/ = /*7*/"b"/*8*/,/*9*/value/*10*/ = /*11*/{/*12*/"c"/*13*/,/*14*/"d"/*15*/, /*16*/}/*17*/, value = {/*18*/"e"/*19*/}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeEmptyArrays.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeEmptyArrays.java new file mode 100644 index 000000000000..c3376c02cc7b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeEmptyArrays.java @@ -0,0 +1,3 @@ +// "Merge duplicate attributes" "true" +@SuppressWarnings(value = {}, value = "a", value = {"b"}, value = {}) +class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed1.java index d4f8e58365ce..2f367f3f58dc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed1.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value={"a"}, value="b", value={"c"}) +@SuppressWarnings(value = {"a"}, value = "b", value = {"c"}) class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed2.java index df61d059956f..4b6e29f05931 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeMixed2.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value="a", value={"b"}, value="c") +@SuppressWarnings(value = "a", value = {"b"}, value = "c") class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeNotArrays.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeNotArrays.java index a983b150e80c..d834625cabef 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeNotArrays.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeNotArrays.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value="a", value="b", value="c") +@SuppressWarnings(value = "a", value = "b", value = "c") class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeShorthandForm1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeShorthandForm1.java new file mode 100644 index 000000000000..32fdc1315d4c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeShorthandForm1.java @@ -0,0 +1,3 @@ +// "Merge duplicate attributes" "true" +@SuppressWarnings("a", value = "b", value = "c") +class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeShorthandForm2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeShorthandForm2.java new file mode 100644 index 000000000000..e46fbe1526bb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeShorthandForm2.java @@ -0,0 +1,3 @@ +// "Merge duplicate attributes" "true" +@SuppressWarnings(value = "a", "b", value = "c") +class Main { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeTrailingComma.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeTrailingComma.java index 785ec6c12952..f0f5d09906d4 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeTrailingComma.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/mergeDuplicates/beforeTrailingComma.java @@ -1,3 +1,3 @@ // "Merge duplicate attributes" "true" -@SuppressWarnings(value={"a",}, value={"b", }, value={"c", }) +@SuppressWarnings(value = {"a",}, value = {"b", }, value = {"c", }) class Main { } \ No newline at end of file