Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ This project adheres to [Semantic Versioning](https://semver.org/).
### Removed

### Fixed
* Fix with array-syntax annotations on the same line as other annotations `annotation` ([#1765](https://github.com/pinterest/ktlint/issues/1765))
* Do not enable the experimental rules by default when `.editorconfig` properties `disabled_rules` or `ktlint_disabled_rules` are set. ([#1771](https://github.com/pinterest/ktlint/issues/1771))
* A function signature not having any parameters which exceeds the `max-line-length` should be ignored by rule `function-signature` ([#1773](https://github.com/pinterest/ktlint/issues/1773))
*

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,4 +548,46 @@ class AnnotationRuleTest {
""".trimIndent()
annotationRuleAssertThat(code).hasNoLintViolations()
}

@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 =
"""
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)
}

@Test
fun `annotation followed by array syntax annotation`() {
val code =
"""
@Foo3 @[Foo1 Foo2]
fun foo() {}
""".trimIndent()
val formattedCode =
"""
@Foo3
@[Foo1 Foo2]
fun foo() {}
""".trimIndent()
annotationRuleAssertThat(code)
.hasLintViolation(1, 7, "@[...] style annotations should be on a separate line from other annotations.")
.isFormattedAs(formattedCode)
}
}
}