diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterAnnotationUtil.kt b/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterAnnotationUtil.kt index 5ecd09c8cf59..694382fea14b 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterAnnotationUtil.kt +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterAnnotationUtil.kt @@ -2,11 +2,11 @@ package com.intellij.psi.formatter.java import com.intellij.lang.ASTNode -import com.intellij.lang.tree.util.children import com.intellij.openapi.roots.LanguageLevelProjectExtension import com.intellij.openapi.util.text.StringUtil import com.intellij.pom.java.LanguageLevel import com.intellij.psi.* +import com.intellij.psi.formatter.FormatterUtil import com.intellij.psi.impl.source.tree.JavaElementType import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager @@ -59,8 +59,8 @@ internal object JavaFormatterAnnotationUtil { val modifierList = node.firstChildNode ?: return false if (modifierList.elementType != JavaElementType.MODIFIER_LIST) return false - val annotations = modifierList.children().takeWhile { it.elementType == JavaElementType.ANNOTATION } - return annotations.any { !isTypeAnnotation(it) } + val annotationList = getAllAnnotationsOnPrefix(modifierList) + return annotationList.any { !isTypeAnnotation(it) } } /** @@ -71,6 +71,22 @@ internal object JavaFormatterAnnotationUtil { return isFieldWithAnnotations(field.node) } + /** + * Retrieves all annotation nodes within the given modifier list prefix, e.g. before all keywords. + * + * @param modifierList the ASTNode representing the modifier list. + * @return a list of ASTNode objects representing the annotations found in the modifier list. + */ + private fun getAllAnnotationsOnPrefix(modifierList: ASTNode): List { + val result = mutableListOf() + var currentNode = modifierList.firstChildNode + while (currentNode?.elementType == JavaElementType.ANNOTATION) { + result.add(currentNode) + currentNode = FormatterUtil.getNextNonWhitespaceSibling(currentNode) + } + return result + } + private fun getImportedTypeAnnotations(file: PsiJavaFile): Set = CachedValuesManager.getCachedValue(file) { val importList = file.importList ?: return@getCachedValue CachedValueProvider.Result(emptySet(), PsiModificationTracker.MODIFICATION_COUNT) diff --git a/java/java-tests/testData/psi/formatter/blankLinesAroundField/differentAnnotationLocation.java b/java/java-tests/testData/psi/formatter/blankLinesAroundField/differentAnnotationLocation.java deleted file mode 100644 index b81923949f48..000000000000 --- a/java/java-tests/testData/psi/formatter/blankLinesAroundField/differentAnnotationLocation.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.example; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class ClassWithAnnotations { - public final boolean simpleField1 = true; - private @Nullable - final Integer annotatedField1 = 10; - public Boolean simpleField2 = false; - public @NotNull Integer annotatedField2 = 1; - private Boolean simpleField3 = false; - @NotNull - private Integer getAnnotatedField3 = 2; -} diff --git a/java/java-tests/testData/psi/formatter/blankLinesAroundField/differentAnnotationLocation_after.java b/java/java-tests/testData/psi/formatter/blankLinesAroundField/differentAnnotationLocation_after.java deleted file mode 100644 index 8cb9ec0546bb..000000000000 --- a/java/java-tests/testData/psi/formatter/blankLinesAroundField/differentAnnotationLocation_after.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.example; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class ClassWithAnnotations { - public final boolean simpleField1 = true; - - - private @Nullable - final Integer annotatedField1 = 10; - public Boolean simpleField2 = false; - - - public @NotNull Integer annotatedField2 = 1; - private Boolean simpleField3 = false; - - - @NotNull - private Integer getAnnotatedField3 = 2; -} diff --git a/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement.java b/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement.java index 920af07443d0..eb005b507fab 100644 --- a/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement.java +++ b/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement.java @@ -4,8 +4,13 @@ import org.jetbrains.annotations.NotNull; public class ClassWithAnnotations { private static final Boolean SIMPLE_FIELD = false; - @NotNull public static final Boolean ANOTHER_ANNOTATED_FIELD = false; - @NotNull public static final Boolean ANNOTATED_FIELD = false; - private @NotNull Boolean annotatedField = false; + @FieldAnnotation public static final Boolean ANOTHER_ANNOTATED_FIELD = false; + @FieldAnnotation public static final Boolean ANNOTATED_FIELD = false; + @FieldAnnotation private @NotNull Boolean annotatedField = false; + private @NotNull Boolean secondAnnotatedField = false; + @NotNull Boolean nonPrivateAnnotatedField = false; + @NotNull @FieldAnnotation Boolean secondNonPrivateAnnotatedField = false; public Boolean simpleField = false; } + +interface @interface FieldAnnotation {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement_after.java b/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement_after.java index ccce472fb37e..831e2d21b33f 100644 --- a/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement_after.java +++ b/java/java-tests/testData/psi/formatter/blankLinesAroundField/rearrangement_after.java @@ -6,15 +6,30 @@ public class ClassWithAnnotations { private static final Boolean SIMPLE_FIELD = false; - @NotNull + @FieldAnnotation public static final Boolean ANOTHER_ANNOTATED_FIELD = false; - @NotNull + @FieldAnnotation public static final Boolean ANNOTATED_FIELD = false; + @FieldAnnotation private @NotNull Boolean annotatedField = false; + private @NotNull Boolean secondAnnotatedField = false; + + @NotNull Boolean nonPrivateAnnotatedField = false; + + + @NotNull + @FieldAnnotation + Boolean secondNonPrivateAnnotatedField = false; + public Boolean simpleField = false; } + +interface + +@interface FieldAnnotation { +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/formatter/blankLinesAroundField/typeAnnotation.java b/java/java-tests/testData/psi/formatter/blankLinesAroundField/typeAnnotation.java new file mode 100644 index 000000000000..fefa68e79c18 --- /dev/null +++ b/java/java-tests/testData/psi/formatter/blankLinesAroundField/typeAnnotation.java @@ -0,0 +1,20 @@ +package org.example; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ClassWithAnnotations { + public final boolean simpleField1 = true; + private @Nullable final Integer typeAnnotatedField1 = 10; + public Boolean simpleField2 = false; + public @NotNull Integer typeAnnotatedField2 = 1; + @NotNull Boolean typeAnnotatedField3 = true; + private Boolean simpleField3 = false; + @NotNull private Integer typeAnnotatedField4 = 2; + @FieldAnnotation private Boolean annotatedField4 = 4; + @FieldAnnotation @NotNull private Boolean annotatedField5 = 4; + @NotNull @FieldAnnotation private Boolean annotatedField6 = 4; + @FieldAnnotation private @NotNull Boolean annotatedField7 = 4; +} + +@interface FieldAnnotation {} \ No newline at end of file diff --git a/java/java-tests/testData/psi/formatter/blankLinesAroundField/typeAnnotation_after.java b/java/java-tests/testData/psi/formatter/blankLinesAroundField/typeAnnotation_after.java new file mode 100644 index 000000000000..2df902cc492f --- /dev/null +++ b/java/java-tests/testData/psi/formatter/blankLinesAroundField/typeAnnotation_after.java @@ -0,0 +1,39 @@ +package org.example; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ClassWithAnnotations { + public final boolean simpleField1 = true; + private @Nullable + final Integer typeAnnotatedField1 = 10; + public Boolean simpleField2 = false; + public @NotNull Integer typeAnnotatedField2 = 1; + @NotNull Boolean typeAnnotatedField3 = true; + private Boolean simpleField3 = false; + + + @NotNull + private Integer typeAnnotatedField4 = 2; + + + @FieldAnnotation + private Boolean annotatedField4 = 4; + + + @FieldAnnotation + @NotNull + private Boolean annotatedField5 = 4; + + + @NotNull + @FieldAnnotation + private Boolean annotatedField6 = 4; + + + @FieldAnnotation + private @NotNull Boolean annotatedField7 = 4; +} + +@interface FieldAnnotation { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterBlankLinesAroundFieldTest.kt b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterBlankLinesAroundFieldTest.kt index 721f74d93da4..1f7ce48c9d74 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterBlankLinesAroundFieldTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterBlankLinesAroundFieldTest.kt @@ -18,7 +18,7 @@ class JavaFormatterBlankLinesAroundFieldTest : JavaFormatterTestCase() { fun testMultipleAnnotatedFields() = doTest() - fun testDifferentAnnotationLocation() = doTest() + fun testTypeAnnotation() = doTest() fun testMixed() = doTest()