From 9b8a2cfd54c0324ef1e4fcad55d72e01588508fb Mon Sep 17 00:00:00 2001 From: Sha Sha Chu Date: Wed, 4 Jan 2023 15:26:12 -0800 Subject: [PATCH 1/3] Fixing issue #1765 It seemed simplest to always force `@[...]` annotations onto separate lines. --- CHANGELOG.md | 1 + .../ktlint/ruleset/standard/AnnotationRule.kt | 29 ++++++++++++++ .../ruleset/standard/AnnotationRuleTest.kt | 39 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55496d30b6..6670ab5261 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Removed ### Fixed +* Issue with array-syntax annotations on the same line as other annotations. ([#1765](https://github.com/pinterest/ktlint/issues/1765)). ### Changed diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRule.kt index 7fdfdd8891..0d942fde35 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRule.kt @@ -20,6 +20,7 @@ import com.pinterest.ktlint.core.ast.lastChildLeafOrSelf import com.pinterest.ktlint.core.ast.nextCodeLeaf import com.pinterest.ktlint.core.ast.nextLeaf import com.pinterest.ktlint.core.ast.prevLeaf +import com.pinterest.ktlint.core.ast.upsertWhitespaceAfterMe import com.pinterest.ktlint.core.ast.upsertWhitespaceBeforeMe import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace @@ -49,6 +50,9 @@ public class AnnotationRule : Rule("annotation") { FILE_ANNOTATION_LIST -> { visitFileAnnotationList(node, emit, autoCorrect) } + ANNOTATION -> { + visitAnnotation(node, emit, autoCorrect) + } ANNOTATION_ENTRY -> visitAnnotationEntry(node, emit, autoCorrect) } @@ -259,6 +263,31 @@ public class AnnotationRule : Rule("annotation") { } } + private fun visitAnnotation( + node: ASTNode, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, + autoCorrect: Boolean, + ) { + require(node.elementType == ANNOTATION) + + if ((node.isFollowedByOtherAnnotationEntry() && node.isOnSameLineAsNextAnnotationEntry()) || + (node.isPrecededByOtherAnnotationEntry() && node.isOnSameLineAsPreviousAnnotationEntry()) + ) { + emit( + node.startOffset, + "@[...] style annotations should be on a separate line from other annotations.", + true, + ) + if (autoCorrect) { + if (node.isFollowedByOtherAnnotationEntry()) { + node.upsertWhitespaceAfterMe(getNewlineWithIndent(node.treeParent)) + } else if (node.isPrecededByOtherAnnotationEntry()) { + node.upsertWhitespaceBeforeMe(getNewlineWithIndent(node.treeParent)) + } + } + } + } + private fun getNewlineWithIndent(modifierListRoot: ASTNode): String { val nodeBeforeAnnotations = modifierListRoot.treeParent.treePrev as? PsiWhiteSpace // If there is no whitespace before the annotation, the annotation is the first diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt index e1f4dc9ae8..026c3e4ce1 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt @@ -548,4 +548,43 @@ class AnnotationRuleTest { """.trimIndent() annotationRuleAssertThat(code).hasNoLintViolations() } + + @Test + fun `Array syntax annotations on the same line as other annotations, Issue #1765`() { + val code = + """ + class Main { + @[Foo1 Foo2] @Foo3 + fun foo() {} + } + """.trimIndent() + val formattedCode = + """ + class Main { + @[Foo1 Foo2] + @Foo3 + fun foo() {} + } + """.trimIndent() + annotationRuleAssertThat(code) + .asKotlinScript() + .hasLintViolation(2, 5, "@[...] style annotations should be on a separate line from other annotations.") + .isFormattedAs(formattedCode) + + val code2 = + """ + @Foo3 @[Foo1 Foo2] + fun foo() {} + """.trimIndent() + val formattedCode2 = + """ + @Foo3 + @[Foo1 Foo2] + fun foo() {} + """.trimIndent() + annotationRuleAssertThat(code2) + .asKotlinScript() + .hasLintViolation(1, 7, "@[...] style annotations should be on a separate line from other annotations.") + .isFormattedAs(formattedCode2) + } } From 677b268cd9c4a55d960f3bacda3cd3915a5c8a70 Mon Sep 17 00:00:00 2001 From: Sha Sha Chu Date: Mon, 9 Jan 2023 10:26:53 -0800 Subject: [PATCH 2/3] review feedback --- .../ruleset/standard/AnnotationRuleTest.kt | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt index 026c3e4ce1..703367ee7f 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt @@ -549,42 +549,45 @@ class AnnotationRuleTest { annotationRuleAssertThat(code).hasNoLintViolations() } - @Test - fun `Array syntax annotations on the same line as other annotations, Issue #1765`() { - val code = - """ + @Nested inner class `Array syntax annotations, Issue #1765` { + @Test + fun `annotation preceded by array syntax annotation`() { + val code = + """ class Main { @[Foo1 Foo2] @Foo3 fun foo() {} } """.trimIndent() - val formattedCode = - """ + val formattedCode = + """ class Main { @[Foo1 Foo2] @Foo3 fun foo() {} } """.trimIndent() - annotationRuleAssertThat(code) - .asKotlinScript() - .hasLintViolation(2, 5, "@[...] style annotations should be on a separate line from other annotations.") - .isFormattedAs(formattedCode) + annotationRuleAssertThat(code) + .hasLintViolation(2, 5, "@[...] style annotations should be on a separate line from other annotations.") + .isFormattedAs(formattedCode) + } - val code2 = - """ + @Test + fun `annotation followed by array syntax annotation`() { + val code = + """ @Foo3 @[Foo1 Foo2] fun foo() {} """.trimIndent() - val formattedCode2 = - """ + val formattedCode = + """ @Foo3 @[Foo1 Foo2] fun foo() {} """.trimIndent() - annotationRuleAssertThat(code2) - .asKotlinScript() - .hasLintViolation(1, 7, "@[...] style annotations should be on a separate line from other annotations.") - .isFormattedAs(formattedCode2) + annotationRuleAssertThat(code) + .hasLintViolation(1, 7, "@[...] style annotations should be on a separate line from other annotations.") + .isFormattedAs(formattedCode) + } } } From 7d537dffcecfa98203090ef43e189f348d78f9e5 Mon Sep 17 00:00:00 2001 From: paul-dingemans Date: Sun, 15 Jan 2023 19:58:09 +0100 Subject: [PATCH 3/3] Fix lint violations. Update changelog. Closes #1766 --- CHANGELOG.md | 2 +- .../ruleset/standard/AnnotationRuleTest.kt | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6670ab5261..eabb565755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Removed ### Fixed -* Issue with array-syntax annotations on the same line as other annotations. ([#1765](https://github.com/pinterest/ktlint/issues/1765)). +* Fix with array-syntax annotations on the same line as other annotations `annotation` ([#1765](https://github.com/pinterest/ktlint/issues/1765)) ### Changed diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt index 703367ee7f..af14897739 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/AnnotationRuleTest.kt @@ -554,19 +554,19 @@ class AnnotationRuleTest { fun `annotation preceded by array syntax annotation`() { val code = """ - class Main { - @[Foo1 Foo2] @Foo3 - fun foo() {} - } - """.trimIndent() + class Main { + @[Foo1 Foo2] @Foo3 + fun foo() {} + } + """.trimIndent() val formattedCode = """ - class Main { - @[Foo1 Foo2] - @Foo3 - fun foo() {} - } - """.trimIndent() + class Main { + @[Foo1 Foo2] + @Foo3 + fun foo() {} + } + """.trimIndent() annotationRuleAssertThat(code) .hasLintViolation(2, 5, "@[...] style annotations should be on a separate line from other annotations.") .isFormattedAs(formattedCode) @@ -576,15 +576,15 @@ class AnnotationRuleTest { fun `annotation followed by array syntax annotation`() { val code = """ - @Foo3 @[Foo1 Foo2] - fun foo() {} - """.trimIndent() + @Foo3 @[Foo1 Foo2] + fun foo() {} + """.trimIndent() val formattedCode = """ - @Foo3 - @[Foo1 Foo2] - fun foo() {} - """.trimIndent() + @Foo3 + @[Foo1 Foo2] + fun foo() {} + """.trimIndent() annotationRuleAssertThat(code) .hasLintViolation(1, 7, "@[...] style annotations should be on a separate line from other annotations.") .isFormattedAs(formattedCode)