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

Fix indent parenthesized expression #2127

Merged
merged 7 commits into from
Jul 15, 2023
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 @@ -12,7 +12,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).

* Allow to disable ktlint in `.editorconfig` for a glob ([#2100](https://github.com/pinterest/ktlint/issues/2100))
* Fix wrapping of nested function literals `wrapping` ([#2106](https://github.com/pinterest/ktlint/issues/2106))
* Do not indent class body for classes having a long super type list in code style `ktlint_official` as it is inconsistent compared to other class bodies `indent` [#2115](https://github.com/pinterest/ktlint/issues/2115)
* Do not indent class body for classes having a long super type list in code style `ktlint_official` as it is inconsistent compared to other class bodies `indent` [#2115](https://github.com/pinterest/ktlint/issues/2115)
* In code style `ktlint_official` do not indent the closing parenthesis of a PARENTHESIZED expression `indent` [#920](https://github.com/pinterest/ktlint/issues/920)
* Log message `Format was not able to resolve all violations which (theoretically) can be autocorrected in file ... in 3 consecutive runs of format` is now only displayed in case a new ktlint rule is actually needed. [#2129](https://github.com/pinterest/ktlint/issues/2129)
* Fix wrapping of function signature in case the opening brace of the function body block exceeds the maximum line length. Fix upsert of whitespace into composite nodes. `function-signature` [#2130](https://github.com/pinterest/ktlint/issues/2130)
* Fix spacing around colon in annotations `spacing-around-colon` ([#2093](https://github.com/pinterest/ktlint/issues/2093))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,16 @@ public class IndentationRule :
node.elementType == SECONDARY_CONSTRUCTOR ->
visitSecondaryConstructor(node)

node.elementType == PARENTHESIZED &&
node.treeParent.treeParent.elementType != IF ->
startIndentContext(node)
node.elementType == PARENTHESIZED ->
if (codeStyle == ktlint_official) {
// Contrary to the IntelliJ IDEA default formatter, do not indent the closing RPAR
startIndentContext(
fromAstNode = node,
lastChildIndent = "",
)
} else if (node.treeParent.treeParent.elementType != IF) {
startIndentContext(node)
}

node.elementType == BINARY_WITH_TYPE ||
node.elementType == SUPER_TYPE_ENTRY ||
Expand Down Expand Up @@ -1366,7 +1373,7 @@ private class StringTemplateIndenter(
it.isLiteralStringTemplateEntry() ||
it.isVariableStringTemplateEntry() ||
it.isClosingQuote()
)
)
) {
val (actualIndent, actualContent) =
if (it.isIndentBeforeClosingQuote()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,25 @@ public class NoSemicolonsRule :
}
}

private fun ASTNode?.doesNotRequirePreSemi(): Boolean {
if (this == null) {
return true
}
if (this is PsiWhiteSpace) {
val nextLeaf =
private fun ASTNode?.doesNotRequirePreSemi() =
when {
this == null -> true

this is PsiWhiteSpace -> {
nextLeaf {
val psi = it.psi
it !is PsiWhiteSpace &&
it !is PsiComment &&
psi.getStrictParentOfType<KDoc>() == null &&
psi.getStrictParentOfType<KtAnnotationEntry>() == null
}.let { nextLeaf ->
nextLeaf == null || // \s+ and then eof
(textContains('\n') && nextLeaf.elementType != KtTokens.LBRACE)
}
return (
nextLeaf == null || // \s+ and then eof
textContains('\n') && nextLeaf.elementType != KtTokens.LBRACE
)
}

else -> false
}
return false
}

private fun isNoSemicolonRequiredAfter(node: ASTNode): Boolean {
val prevCodeLeaf =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class SpacingAroundCurlyRule : StandardRule("curly-spacing") {
(
prevLeaf?.elementType == LPAR &&
((node as LeafPsiElement).parent is KtLambdaExpression || node.parent.parent is KtLambdaExpression)
)
)
spacingAfter = nextLeaf is PsiWhiteSpace || nextLeaf?.elementType == RBRACE
if (prevLeaf is PsiWhiteSpace &&
!prevLeaf.textContains('\n') &&
Expand All @@ -69,7 +69,7 @@ public class SpacingAroundCurlyRule : StandardRule("curly-spacing") {
prevLeaf.prevLeaf()?.let { it.elementType == RPAR || KtTokens.KEYWORDS.contains(it.elementType) } == true ||
node.treeParent.elementType == CLASS_BODY ||
(prevLeaf.treeParent.elementType == FUN && prevLeaf.treeNext.elementType != LAMBDA_EXPRESSION)
) // allow newline for lambda return type
) // allow newline for lambda return type
) {
emit(node.startOffset, "Unexpected newline before \"${node.text}\"", true)
if (autoCorrect) {
Expand Down Expand Up @@ -141,7 +141,7 @@ public class SpacingAroundCurlyRule : StandardRule("curly-spacing") {
nextElementType == LBRACKET ||
nextElementType == LPAR ||
nextElementType == COLONCOLON
)
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public class SpacingAroundParensRule : StandardRule("paren-spacing") {
// Super keyword needs special-casing
prevLeaf.prevLeaf()?.elementType == SUPER_KEYWORD ||
prevLeaf.prevLeaf()?.treeParent?.elementType == PRIMARY_CONSTRUCTOR
) &&
) &&
(
node.treeParent?.elementType == VALUE_PARAMETER_LIST ||
node.treeParent?.elementType == VALUE_ARGUMENT_LIST
)
)
} else {
prevLeaf is PsiWhiteSpace && !prevLeaf.textContains('\n') &&
prevLeaf.prevLeaf()?.elementType != LPAR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public class StringTemplateRule : StandardRule("string-template") {
(
nextSibling.elementType == LITERAL_STRING_TEMPLATE_ENTRY &&
!nextSibling.text.substring(0, 1).isPartOfIdentifier()
)
)
}
) {
emit(node.treePrev.startOffset + 2, "Redundant curly braces", true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public class WrappingRule :
numberOfArgs == 1 &&
firstArg?.firstChildNode?.elementType
?.let { it == OBJECT_LITERAL || it == LAMBDA_EXPRESSION } == true
)
)
) {
return
}
Expand Down Expand Up @@ -308,7 +308,7 @@ public class WrappingRule :
!(
entries.dropLast(1).all { it.elementType == SUPER_TYPE_ENTRY } &&
entries.last().elementType == SUPER_TYPE_CALL_ENTRY
)
)
) {
// put space after :
if (!node.prevLeaf().isWhiteSpaceWithNewline()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5322,6 +5322,24 @@ internal class IndentationRuleTest {
.isFormattedAs(formattedCode)
}

@Test
fun `Issue 920 - Given ktlint_official codestyle and a PARENTHESIZED expression`() {
val code =
"""
val foobar =
if (true) {
(
foo()
)
} else {
bar()
}
""".trimIndent()
indentationRuleAssertThat(code)
.withEditorConfigOverride(CODE_STYLE_PROPERTY to ktlint_official)
.hasNoLintViolations()
}

private companion object {
val INDENT_STYLE_TAB =
INDENT_STYLE_PROPERTY to PropertyType.IndentStyleValue.tab
Expand Down