Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1281 white between annotated declarations #1291

Merged
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).

### Fixed
- KtLint CLI 0.43 doesn't work with JDK 1.8 ([#1271](https://github.com/pinterest/ktlint/issues/1271))

- Fix false positive in rule spacing-between-declarations-with-annotations ([#1281] (https://github.com/pinterest/ktlint/issues/1281))
-
### Changed
- Update Kotlin version to `1.6.0` release

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST
import com.pinterest.ktlint.core.ast.children
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.PsiComment
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
import org.jetbrains.kotlin.psi.psiUtil.prevLeafs

/**
* @see https://youtrack.jetbrains.com/issue/KT-35106
Expand All @@ -24,20 +28,41 @@ class SpacingBetweenDeclarationsWithAnnotationsRule : Rule("spacing-between-decl
val declaration = node.psi.parent as? KtDeclaration
val prevDeclaration =
declaration?.getPrevSiblingIgnoringWhitespaceAndComments(withItself = false) as? KtDeclaration
val prevWhiteSpace = prevDeclaration?.nextSibling as? PsiWhiteSpace
if (declaration != null && prevDeclaration != null && prevWhiteSpace?.text?.count { it == '\n' } == 1) {
val whiteSpaceAfterPreviousDeclaration = prevDeclaration?.nextSibling as? PsiWhiteSpace
val startOfDeclarationIncludingLeadingComment = node.psi.parent.getPrevLeafIgnoringCommentAndWhitespaceExceptBlankLines()
if (whiteSpaceAfterPreviousDeclaration?.text != null &&
startOfDeclarationIncludingLeadingComment?.text?.count { it == '\n' } == 1
) {
emit(
node.startOffset,
"Declarations and declarations with annotations should have an empty space between.",
true
)
if (autoCorrect) {
val indent = prevWhiteSpace.text.substringAfter('\n')
(prevWhiteSpace.node as LeafPsiElement).rawReplaceWithText("\n\n$indent")
val indent = whiteSpaceAfterPreviousDeclaration.text.substringAfter('\n')
(whiteSpaceAfterPreviousDeclaration.node as LeafPsiElement).rawReplaceWithText("\n\n$indent")
}
}
}
}

/**
* Gets the previous element but ignores white whitespaces (excluding blank lines) and comments. Note the difference
* with method [PsiElement.getPrevSiblingIgnoringWhitespaceAndComments] which excludes blank lines as well.
*/
private fun PsiElement.getPrevLeafIgnoringCommentAndWhitespaceExceptBlankLines(): PsiElement? {
var prevLeaf: PsiElement? = this.prevLeaf()
val iterator = prevLeafs.iterator()
while (iterator.hasNext()) {
val psiElement = iterator.next()
if (psiElement is PsiComment || (psiElement is PsiWhiteSpace && psiElement.text?.count { it == '\n' } == 1)) {
prevLeaf = psiElement
} else {
break
}
}
return prevLeaf
}

private fun ASTNode.hasAnnotationsAsChildren(): Boolean = children().find { it.psi is KtAnnotationEntry } != null
}
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class SpacingBetweenDeclarationsWithAnnotationsRuleTest {
}

@Test
fun `missing space after comment with previous variable should do nothing`() {
fun `No blank line is required between comment and an annotated declaration`() {
Assertions.assertThat(
SpacingBetweenDeclarationsWithAnnotationsRule().lint(
"""
Expand All @@ -250,4 +250,27 @@ class SpacingBetweenDeclarationsWithAnnotationsRuleTest {
)
).isEmpty()
}

@Test
fun `Issue 1281 - No blank line is required between comment and an annotated declaration when previous declaration end with a comment`() {
Assertions.assertThat(
SpacingBetweenDeclarationsWithAnnotationsRule().lint(
"""
class KotlinPluginTest {
// tag::setUp[]
@BeforeEach
fun setUp() {
}
// end::setUp[]

// tag::testQuery[]
@Test
fun testFindById() {
}
// end::testQuery[]
}
""".trimIndent()
)
).isEmpty()
}
}