Skip to content

Commit

Permalink
Fix KDOC indentation for tab indentation style (#1263)
Browse files Browse the repository at this point in the history
* Remove unused variables

* Fix KDOC indentation for tab indentation style

Closes #850

* Add changelog message for fix of issue #850

Co-authored-by: Paul Dingemans <pdingemans@bol.com>
  • Loading branch information
paul-dingemans and Paul Dingemans authored Nov 2, 2021
1 parent a941af8 commit d3a58fe
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Remove spaces before primary constructor (`paren-spacing`) ([#1207](https://github.com/pinterest/ktlint/issues/1207))
- Fix false positive for delegated properties with a lambda argument (`indent`) ([#1210](https://github.com/pinterest/ktlint/issues/1210))
- Remove unnecessary wildcard imports (`no-unused-imports`) ([#1256](https://github.com/pinterest/ktlint/issues/1256))
- Fix indentation of KDoc comment when using tab indentation style (`indent`) ([#850](https://github.com/pinterest/ktlint/issues/850))
### Changed
- Support absolute paths for globs ([#1131](https://github.com/pinterest/ktlint/issues/1131))
- Fix regression from 0.41 with argument list wrapping after dot qualified expression (`argument-list-wrapping`)([#1159](https://github.com/pinterest/ktlint/issues/1159))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import com.pinterest.ktlint.core.ast.ElementType.FUN
import com.pinterest.ktlint.core.ast.ElementType.FUNCTION_LITERAL
import com.pinterest.ktlint.core.ast.ElementType.GT
import com.pinterest.ktlint.core.ast.ElementType.KDOC
import com.pinterest.ktlint.core.ast.ElementType.KDOC_END
import com.pinterest.ktlint.core.ast.ElementType.KDOC_LEADING_ASTERISK
import com.pinterest.ktlint.core.ast.ElementType.KDOC_START
import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.LBRACE
Expand All @@ -44,7 +46,6 @@ import com.pinterest.ktlint.core.ast.ElementType.RBRACE
import com.pinterest.ktlint.core.ast.ElementType.RBRACKET
import com.pinterest.ktlint.core.ast.ElementType.REGULAR_STRING_PART
import com.pinterest.ktlint.core.ast.ElementType.RPAR
import com.pinterest.ktlint.core.ast.ElementType.SAFE_ACCESS
import com.pinterest.ktlint.core.ast.ElementType.SAFE_ACCESS_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.SHORT_STRING_TEMPLATE_ENTRY
import com.pinterest.ktlint.core.ast.ElementType.STRING_TEMPLATE
Expand Down Expand Up @@ -673,16 +674,6 @@ class IndentationRule : Rule("indent"), Rule.Modifier.RestrictToRootLast {
if (!ctx.ignored.contains(p) && nextSibling != null) {
expectedIndent++
debug { "++inside(${p.elementType}) -> $expectedIndent" }
val siblingType = nextSibling.elementType
val e = if (
siblingType == DOT ||
siblingType == SAFE_ACCESS ||
siblingType == ELVIS
) {
nextSibling.treeNext
} else {
nextSibling
}
ctx.ignored.add(p)
ctx.exitAdjBy(p, -1)
}
Expand Down Expand Up @@ -999,7 +990,14 @@ class IndentationRule : Rule("indent"), Rule.Modifier.RestrictToRootLast {
}
}
IndentStyle.TAB -> {
if (' ' in nodeIndent) {
val isKdocIndent = node.isKDocIndent()
val indentWithoutKdocIndent =
if (isKdocIndent) {
nodeIndent.removeSuffix(" ")
} else {
nodeIndent
}
if (' ' in indentWithoutKdocIndent) {
emit(
node.startOffset + text.length - nodeIndent.length,
"Unexpected space character(s)",
Expand All @@ -1008,7 +1006,13 @@ class IndentationRule : Rule("indent"), Rule.Modifier.RestrictToRootLast {
// First normalize the indent to spaces using the tab width.
val asSpaces = nodeIndent.replace("\t", " ".repeat(editorConfig.tabWidth))
// Then divide that space-based indent into tabs.
"\t".repeat(asSpaces.length / editorConfig.tabWidth)
"\t".repeat(asSpaces.length / editorConfig.tabWidth) +
// Re-add the kdoc indent when it was present before
if (isKdocIndent) {
" "
} else {
""
}
} else {
nodeIndent
}
Expand Down Expand Up @@ -1127,6 +1131,15 @@ class IndentationRule : Rule("indent"), Rule.Modifier.RestrictToRootLast {
}
}

private fun ASTNode.isKDocIndent() =
if (text.lastOrNull() == ' ') {
// The indentation of a KDoc comment contains a space as the last character regardless of the indentation style
// (tabs or spaces) except for the starting line of the KDoc comment
nextLeaf()?.elementType == KDOC_LEADING_ASTERISK || nextLeaf()?.elementType == KDOC_END
} else {
false
}

private fun ASTNode.isIndentBeforeClosingQuote() =
elementType == CLOSING_QUOTE || (text.isBlank() && nextCodeSibling()?.elementType == CLOSING_QUOTE)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,53 @@ internal class IndentationRuleTest {
assertThat(IndentationRule().format(code)).isEqualTo(code)
}

@Test
fun `format kdoc`() {
@Suppress("RemoveCurlyBracesFromTemplate")
val code =
"""
/**
* some function1
*/
fun someFunction1() {
return Unit
}
class SomeClass {
/**
* some function2
*/
fun someFunction2() {
return Unit
}
}
""".trimIndent()
@Suppress("RemoveCurlyBracesFromTemplate")
val codeTabs =
"""
/**
* some function1
*/
fun someFunction1() {
${TAB}return Unit
}
class SomeClass {
${TAB}/**
${TAB} * some function2
${TAB} */
${TAB}fun someFunction2() {
${TAB}${TAB}return Unit
${TAB}}
}
""".trimIndent()
assertThat(IndentationRule().lint(code)).isEmpty()
assertThat(IndentationRule().format(code)).isEqualTo(code)

assertThat(IndentationRule().lint(codeTabs, INDENT_STYLE_TABS)).isEmpty()
assertThat(IndentationRule().format(codeTabs, INDENT_STYLE_TABS)).isEqualTo(codeTabs)
}

private companion object {
const val MULTILINE_STRING_QUOTE = "${'"'}${'"'}${'"'}"
const val TAB = "${'\t'}"
Expand Down

0 comments on commit d3a58fe

Please # to comment.