From d7a4c21bf15cf9e32307459a119008e4b0e1c904 Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Sun, 21 May 2023 17:55:05 +0530 Subject: [PATCH 1/7] Insert newline after `SEMICOLON` in `WrappingRule` --- .../standard/rules/NoSemicolonsRule.kt | 13 +- .../ruleset/standard/rules/WrappingRule.kt | 15 ++ .../standard/rules/WrappingRuleTest.kt | 141 ++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/NoSemicolonsRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/NoSemicolonsRule.kt index 1405c1d97e..8c399150ae 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/NoSemicolonsRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/NoSemicolonsRule.kt @@ -4,6 +4,7 @@ import com.pinterest.ktlint.rule.engine.core.api.ElementType.CLASS_BODY import com.pinterest.ktlint.rule.engine.core.api.ElementType.ENUM_ENTRY import com.pinterest.ktlint.rule.engine.core.api.ElementType.OBJECT_KEYWORD import com.pinterest.ktlint.rule.engine.core.api.ElementType.SEMICOLON +import com.pinterest.ktlint.rule.engine.core.api.Rule.VisitorModifier.RunAfterRule import com.pinterest.ktlint.rule.engine.core.api.RuleId import com.pinterest.ktlint.rule.engine.core.api.isWhiteSpace import com.pinterest.ktlint.rule.engine.core.api.lastChildLeafOrSelf @@ -24,7 +25,17 @@ import org.jetbrains.kotlin.psi.KtIfExpression import org.jetbrains.kotlin.psi.KtLoopExpression import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -public class NoSemicolonsRule : StandardRule("no-semi") { +public class NoSemicolonsRule : + StandardRule( + id = "no-semi", + visitorModifiers = + setOf( + RunAfterRule( + ruleId = WRAPPING_RULE_ID, + mode = RunAfterRule.Mode.REGARDLESS_WHETHER_RUN_AFTER_RULE_IS_LOADED_OR_DISABLED, + ), + ), + ) { override fun beforeVisitChildNodes( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt index ff1d22024d..93b27ae31a 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt @@ -26,6 +26,7 @@ import com.pinterest.ktlint.rule.engine.core.api.ElementType.OBJECT_LITERAL import com.pinterest.ktlint.rule.engine.core.api.ElementType.RBRACE import com.pinterest.ktlint.rule.engine.core.api.ElementType.RBRACKET import com.pinterest.ktlint.rule.engine.core.api.ElementType.RPAR +import com.pinterest.ktlint.rule.engine.core.api.ElementType.SEMICOLON import com.pinterest.ktlint.rule.engine.core.api.ElementType.STRING_TEMPLATE import com.pinterest.ktlint.rule.engine.core.api.ElementType.SUPER_TYPE_CALL_ENTRY import com.pinterest.ktlint.rule.engine.core.api.ElementType.SUPER_TYPE_ENTRY @@ -64,6 +65,7 @@ import com.pinterest.ktlint.rule.engine.core.api.nextCodeLeaf import com.pinterest.ktlint.rule.engine.core.api.nextCodeSibling import com.pinterest.ktlint.rule.engine.core.api.nextLeaf import com.pinterest.ktlint.rule.engine.core.api.nextSibling +import com.pinterest.ktlint.rule.engine.core.api.noNewLineInClosedRange import com.pinterest.ktlint.rule.engine.core.api.prevCodeLeaf import com.pinterest.ktlint.rule.engine.core.api.prevLeaf import com.pinterest.ktlint.rule.engine.core.api.prevSibling @@ -137,6 +139,7 @@ public class WrappingRule : ARROW -> rearrangeArrow(node, autoCorrect, emit) WHITE_SPACE -> line += node.text.count { it == '\n' } CLOSING_QUOTE -> rearrangeClosingQuote(node, autoCorrect, emit) + SEMICOLON -> insertNewLineBeforeSemi(node, autoCorrect, emit) } } @@ -529,6 +532,18 @@ public class WrappingRule : } } + private fun insertNewLineBeforeSemi( + node: ASTNode, + autoCorrect: Boolean, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, + ) { + val previousCodeLeaf = node.prevCodeLeaf()?.lastChildLeafOrSelf() ?: return + val nextCodeLeaf = node.nextCodeLeaf()?.firstChildLeafOrSelf() ?: return + if (noNewLineInClosedRange(previousCodeLeaf, nextCodeLeaf)) { + requireNewlineAfterLeaf(node, autoCorrect, emit, indent = previousCodeLeaf.indent()) + } + } + private fun requireNewlineBeforeLeaf( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt index 3194095698..a671dc7bdd 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt @@ -1871,6 +1871,147 @@ internal class WrappingRuleTest { .hasLintViolation(2, 10, "A newline was expected before 'Bar'") .isFormattedAs(formattedCode) } + + @Test + fun `Issue 1078 - Given a multiline semi separated var initialisation then wrap each expression to a new line`() { + val code = + """ + fun f1() { + val a = 3; val b = 2 + } + """.trimIndent() + val formattedCode = + """ + fun f1() { + val a = 3; + val b = 2 + } + """.trimIndent() + wrappingRuleAssertThat(code) + .isFormattedAs(formattedCode) + } + + @Test + fun `Issue 1078 - Given a multiline semi separated statements then wrap each expression to a new line`() { + val code = + """ + public fun f2() { + // no-op + }; public fun f3() { + // no-op + } + + public class A { + + }; public class B { + + } + + public class C; public class D + + class E { + init { + f1(); f2() + } + } + """.trimIndent() + val formattedCode = + """ + public fun f2() { + // no-op + }; + public fun f3() { + // no-op + } + + public class A { + + }; + public class B { + + } + + public class C; + public class D + + class E { + init { + f1(); + f2() + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .isFormattedAs(formattedCode) + } + + @Test + fun `Issue 1078 - Given a multiline semi separated control flow then wrap each expression to a new line`() { + val code = + """ + fun test() { + for (i in 0..10) { + println(i) + }; for (i in 0..100) { + println(i) + } + + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; while (Random(System.currentTimeMillis()).nextBoolean()) { + println(System.currentTimeMillis()) + } + + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; do { + println(System.currentTimeMillis()) + } while (System.currentTimeMillis() % 2 == 0L) + } + """.trimIndent() + val formattedCode = + """ + fun test() { + for (i in 0..10) { + println(i) + }; + for (i in 0..100) { + println(i) + } + + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; + while (Random(System.currentTimeMillis()).nextBoolean()) { + println(System.currentTimeMillis()) + } + + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; + do { + println(System.currentTimeMillis()) + } while (System.currentTimeMillis() % 2 == 0L) + } + """.trimIndent() + wrappingRuleAssertThat(code) + .isFormattedAs(formattedCode) + } + + @Test + fun `Issue 1078 - Given a multiline semi separated import statement then wrap each expression to a new line`() { + val code = + """ + import java.util.ArrayList; import java.util.HashMap + """.trimIndent() + val formattedCode = + """ + import java.util.ArrayList; + import java.util.HashMap + """.trimIndent() + wrappingRuleAssertThat(code) + .isFormattedAs(formattedCode) + } } // Replace the "$." placeholder with an actual "$" so that string "$.{expression}" is transformed to a String template From e89ebdcbd63dd76afda90472b6e915ff329a73aa Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Wed, 31 May 2023 23:04:33 +0530 Subject: [PATCH 2/7] Run the rule in the source code --- .../com/pinterest/ktlint/cli/internal/ReporterAggregator.kt | 3 ++- .../ktlint/ruleset/standard/rules/MaxLineLengthRule.kt | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ktlint-cli/src/main/kotlin/com/pinterest/ktlint/cli/internal/ReporterAggregator.kt b/ktlint-cli/src/main/kotlin/com/pinterest/ktlint/cli/internal/ReporterAggregator.kt index cb9cb5d7ee..8d26d44631 100644 --- a/ktlint-cli/src/main/kotlin/com/pinterest/ktlint/cli/internal/ReporterAggregator.kt +++ b/ktlint-cli/src/main/kotlin/com/pinterest/ktlint/cli/internal/ReporterAggregator.kt @@ -140,7 +140,8 @@ internal class ReporterAggregator( val stream = when { reporterConfiguration.output != null -> { - File(reporterConfiguration.output).parentFile?.mkdirsOrFail(); PrintStream(reporterConfiguration.output, "UTF-8") + File(reporterConfiguration.output).parentFile?.mkdirsOrFail() + PrintStream(reporterConfiguration.output, "UTF-8") } stdin -> { diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/MaxLineLengthRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/MaxLineLengthRule.kt index 6e8b520d27..25fd1092e9 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/MaxLineLengthRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/MaxLineLengthRule.kt @@ -177,7 +177,10 @@ internal class RangeTree(seq: List = emptyList()) { init { if (arr.isNotEmpty()) { - arr.reduce { p, n -> require(p <= n) { "Input must be sorted" }; n } + arr.reduce { p, n -> + require(p <= n) { "Input must be sorted" } + n + } } } From 72b636106766cdfd02dfa0a39deaa389914bdb20 Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Wed, 31 May 2023 23:26:04 +0530 Subject: [PATCH 3/7] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a3166d0e..9ee02fa02d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ At this point in time, it is not yet decided what the next steps will be. Ktlint * Extract rule `no-single-line-block-comment` from `comment-wrapping` rule. The `no-single-line-block-comment` rule is added as experimental rule to the `ktlint_official` code style, but it can be enabled explicitly for the other code styles as well. ([#1980](https://github.com/pinterest/ktlint/issues/1980)) * Clean-up unwanted logging dependencies ([#1998](https://github.com/pinterest/ktlint/issues/1998)) * Fix directory traversal for patterns referring to paths outside of current working directory or any of it child directories ([#2002](https://github.com/pinterest/ktlint/issues/2002)) +* Prevent multiple expression in same line separated by semicolon ([#1078](https://github.com/pinterest/ktlint/issues/1078)) ### Changed From ba9b023e11602a3af2f1e1053f2ee096f3618333 Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Thu, 1 Jun 2023 00:57:44 +0530 Subject: [PATCH 4/7] Handle enum entry with semicolon Add multiple entries, enums and assertions --- .../ruleset/standard/rules/WrappingRule.kt | 6 + .../standard/rules/WrappingRuleTest.kt | 156 ++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt index 93b27ae31a..dbce691461 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt @@ -11,6 +11,7 @@ import com.pinterest.ktlint.rule.engine.core.api.ElementType.COMMA import com.pinterest.ktlint.rule.engine.core.api.ElementType.CONDITION import com.pinterest.ktlint.rule.engine.core.api.ElementType.DESTRUCTURING_DECLARATION import com.pinterest.ktlint.rule.engine.core.api.ElementType.DOT +import com.pinterest.ktlint.rule.engine.core.api.ElementType.ENUM_ENTRY import com.pinterest.ktlint.rule.engine.core.api.ElementType.EOL_COMMENT import com.pinterest.ktlint.rule.engine.core.api.ElementType.FUN import com.pinterest.ktlint.rule.engine.core.api.ElementType.FUNCTION_LITERAL @@ -539,6 +540,11 @@ public class WrappingRule : ) { val previousCodeLeaf = node.prevCodeLeaf()?.lastChildLeafOrSelf() ?: return val nextCodeLeaf = node.nextCodeLeaf()?.firstChildLeafOrSelf() ?: return + if (previousCodeLeaf.treeParent.elementType == ENUM_ENTRY && nextCodeLeaf.elementType == RBRACE) { + // Allow + // enum class INDEX2 { ONE, TWO, THREE; } + return + } if (noNewLineInClosedRange(previousCodeLeaf, nextCodeLeaf)) { requireNewlineAfterLeaf(node, autoCorrect, emit, indent = previousCodeLeaf.indent()) } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt index a671dc7bdd..0dd56d3e13 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt @@ -1878,6 +1878,7 @@ internal class WrappingRuleTest { """ fun f1() { val a = 3; val b = 2 + val key: String = ""; val lambda: () -> Unit = { } } """.trimIndent() val formattedCode = @@ -1885,9 +1886,15 @@ internal class WrappingRuleTest { fun f1() { val a = 3; val b = 2 + val key: String = ""; + val lambda: () -> Unit = { } } """.trimIndent() wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 15, "Missing newline after \";\""), + LintViolation(3, 26, "Missing newline after \";\""), + ) .isFormattedAs(formattedCode) } @@ -1901,6 +1908,10 @@ internal class WrappingRuleTest { // no-op } + public fun f4() = 1; public fun f5() { + // no-op + } + public class A { }; public class B { @@ -1914,6 +1925,10 @@ internal class WrappingRuleTest { f1(); f2() } } + + enum class INDEX { + A, B, C; fun test() = 0 + } """.trimIndent() val formattedCode = """ @@ -1924,6 +1939,11 @@ internal class WrappingRuleTest { // no-op } + public fun f4() = 1; + public fun f5() { + // no-op + } + public class A { }; @@ -1940,8 +1960,21 @@ internal class WrappingRuleTest { f2() } } + + enum class INDEX { + A, B, C; + fun test() = 0 + } """.trimIndent() wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 3, "Missing newline after \";\""), + LintViolation(7, 21, "Missing newline after \";\""), + LintViolation(13, 3, "Missing newline after \";\""), + LintViolation(17, 16, "Missing newline after \";\""), + LintViolation(21, 14, "Missing newline after \";\""), + LintViolation(26, 13, "Missing newline after \";\""), + ) .isFormattedAs(formattedCode) } @@ -1995,6 +2028,37 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(4, 7, "Missing newline after \";\""), + LintViolation(10, 7, "Missing newline after \";\""), + LintViolation(16, 7, "Missing newline after \";\""), + ) + .isFormattedAs(formattedCode) + } + + @Test + fun `Issue 1078 - Given a multiline semi separated control flow with no body`() { + val code = + """ + fun test() { + for (i in 0..10); for (i in 0..100);while (System.currentTimeMillis() % 2 == 0L); while (Random(System.currentTimeMillis()).nextBoolean()); + } + """.trimIndent() + val formattedCode = + """ + fun test() { + for (i in 0..10); + for (i in 0..100); + while (System.currentTimeMillis() % 2 == 0L); + while (Random(System.currentTimeMillis()).nextBoolean()); + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 22, "Missing newline after \";\""), + LintViolation(2, 41, "Missing newline after \";\""), + LintViolation(2, 86, "Missing newline after \";\""), + ) .isFormattedAs(formattedCode) } @@ -2010,8 +2074,100 @@ internal class WrappingRuleTest { import java.util.HashMap """.trimIndent() wrappingRuleAssertThat(code) + .hasLintViolation(1, 28, "Missing newline after \";\"") .isFormattedAs(formattedCode) } + + @Test + fun `Issue 1078 - Given a multiline semi separated with multiple items`() { + val code = + """ + fun test() { + val a = 0; val b = 0; fun bar() { + // no-op + }; for(i in 0..10) { + println(i); println(i); a++; println(a) + } + } + """.trimIndent() + val formattedCode = + """ + fun test() { + val a = 0; + val b = 0; + fun bar() { + // no-op + }; + for(i in 0..10) { + println(i); + println(i); + a++; + println(a) + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 15, "Missing newline after \";\""), + LintViolation(2, 26, "Missing newline after \";\""), + LintViolation(4, 7, "Missing newline after \";\""), + LintViolation(5, 20, "Missing newline after \";\""), + LintViolation(5, 32, "Missing newline after \";\""), + LintViolation(5, 37, "Missing newline after \";\""), + ) + .isFormattedAs(formattedCode) + } + + @Test + fun `Issue 1078 - Given a enum with semicolon has not violation`() { + val code = + """ + enum class INDEX1 { ONE, TWO, THREE } + enum class INDEX2 { ONE, TWO, THREE; } + enum class INDEX3 { ONE, TWO, THREE; /* with comment */ } + enum class INDEX4 { + ONE, TWO, THREE; + } + enum class INDEX5 { + ONE, + TWO, + THREE; + } + enum class INDEX6 { + ONE, + TWO, + THREE, + ; + } + enum class INDEX7 { + ONE, + TWO, + THREE, + ; + fun foo() = "" + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasNoLintViolations() + } + + @Test + fun `Issue 1078 - Given a companion object with semicolon has not violation`() { + val code = + """ + class FirstClass(private val param: String) { + companion object; + private var toto: Boolean = false + } + + class SecondClass(private val param: String) { + companion object; // with comment + private var toto: Boolean = false + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasNoLintViolations() + } } // Replace the "$." placeholder with an actual "$" so that string "$.{expression}" is transformed to a String template From e518366134d44ddcbfebd98c9c93c8d810b98dfe Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Sat, 3 Jun 2023 03:39:25 +0530 Subject: [PATCH 5/7] Correct CHANGELOG.md messaging Split TCs into smaller ones Rename `insertNewLineBeforeSemi` to `insertNewLineAfterSemi` --- CHANGELOG.md | 2 +- .../ruleset/standard/rules/WrappingRule.kt | 4 +- .../standard/rules/WrappingRuleTest.kt | 828 ++++++++++++------ 3 files changed, 573 insertions(+), 261 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee02fa02d..a670c9ea4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,7 +67,7 @@ At this point in time, it is not yet decided what the next steps will be. Ktlint * Extract rule `no-single-line-block-comment` from `comment-wrapping` rule. The `no-single-line-block-comment` rule is added as experimental rule to the `ktlint_official` code style, but it can be enabled explicitly for the other code styles as well. ([#1980](https://github.com/pinterest/ktlint/issues/1980)) * Clean-up unwanted logging dependencies ([#1998](https://github.com/pinterest/ktlint/issues/1998)) * Fix directory traversal for patterns referring to paths outside of current working directory or any of it child directories ([#2002](https://github.com/pinterest/ktlint/issues/2002)) -* Prevent multiple expression in same line separated by semicolon ([#1078](https://github.com/pinterest/ktlint/issues/1078)) +* Prevent multiple expressions on same line separated by semicolon ([#1078](https://github.com/pinterest/ktlint/issues/1078)) ### Changed diff --git a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt index dbce691461..244ea97667 100644 --- a/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt +++ b/ktlint-ruleset-standard/src/main/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRule.kt @@ -140,7 +140,7 @@ public class WrappingRule : ARROW -> rearrangeArrow(node, autoCorrect, emit) WHITE_SPACE -> line += node.text.count { it == '\n' } CLOSING_QUOTE -> rearrangeClosingQuote(node, autoCorrect, emit) - SEMICOLON -> insertNewLineBeforeSemi(node, autoCorrect, emit) + SEMICOLON -> insertNewLineAfterSemi(node, autoCorrect, emit) } } @@ -533,7 +533,7 @@ public class WrappingRule : } } - private fun insertNewLineBeforeSemi( + private fun insertNewLineAfterSemi( node: ASTNode, autoCorrect: Boolean, emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt index 0dd56d3e13..84593db1d3 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt @@ -1872,301 +1872,613 @@ internal class WrappingRuleTest { .isFormattedAs(formattedCode) } - @Test - fun `Issue 1078 - Given a multiline semi separated var initialisation then wrap each expression to a new line`() { - val code = - """ - fun f1() { - val a = 3; val b = 2 - val key: String = ""; val lambda: () -> Unit = { } - } - """.trimIndent() - val formattedCode = - """ - fun f1() { - val a = 3; - val b = 2 - val key: String = ""; - val lambda: () -> Unit = { } + @Nested + inner class `Issue 1078 - Given multiple expression seperated with semi in a single line` { + @Nested + inner class `Given multiple variables` { + @Test + fun `Given two variables`() { + val code = + """ + fun foo() { + val bar1 = 3; val bar2 = 2 + val fooBar1: String = ""; val fooBar2: () -> Unit = { } + } + """.trimIndent() + val formattedCode = + """ + fun foo() { + val bar1 = 3; + val bar2 = 2 + val fooBar1: String = ""; + val fooBar2: () -> Unit = { } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 18, "Missing newline after \";\""), + LintViolation(3, 30, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given more than two variables`() { + val code = + """ + fun foo() { + val bar1 = 3; val bar2 = 2; val bar3 = 3; val bar4: () -> Unit = { }; val bar4: String = ""; + } + """.trimIndent() + val formattedCode = + """ + fun foo() { + val bar1 = 3; + val bar2 = 2; + val bar3 = 3; + val bar4: () -> Unit = { }; + val bar4: String = ""; + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 18, "Missing newline after \";\""), + LintViolation(2, 32, "Missing newline after \";\""), + LintViolation(2, 46, "Missing newline after \";\""), + LintViolation(2, 75, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given variables with comments`() { + val code = + """ + fun foo() { + val bar1 = 3; val bar2 = 2; // this is end comment + val bar1 = 3; /* block comment */ val bar2 = 2; + } + """.trimIndent() + val formattedCode = + """ + fun foo() { + val bar1 = 3; + val bar2 = 2; // this is end comment + val bar1 = 3; + /* block comment */ val bar2 = 2; + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 18, "Missing newline after \";\""), + LintViolation(3, 18, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasLintViolations( - LintViolation(2, 15, "Missing newline after \";\""), - LintViolation(3, 26, "Missing newline after \";\""), - ) - .isFormattedAs(formattedCode) - } + } - @Test - fun `Issue 1078 - Given a multiline semi separated statements then wrap each expression to a new line`() { - val code = - """ - public fun f2() { - // no-op - }; public fun f3() { - // no-op + @Nested + inner class `Given multiple classes, functions and init blocks` { + @Test + fun `Given multiple function declaration`() { + val code = + """ + public fun foo1() { + // no-op + }; public fun foo2() { + // no-op + }; fun foo3() = 0 + + public fun foo4() = 1; public fun foo5() { + // no-op + } + """.trimIndent() + val formattedCode = + """ + public fun foo1() { + // no-op + }; + public fun foo2() { + // no-op + }; + fun foo3() = 0 + + public fun foo4() = 1; + public fun foo5() { + // no-op + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 3, "Missing newline after \";\""), + LintViolation(5, 3, "Missing newline after \";\""), + LintViolation(7, 23, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given multiple function declaration with comments`() { + val code = + """ + public fun foo1() { + // no-op + }; /* block comment */ public fun foo2() { + // no-op + }; fun foo3() = 0 // single line comment + """.trimIndent() + val formattedCode = + """ + public fun foo1() { + // no-op + }; + /* block comment */ public fun foo2() { + // no-op + }; + fun foo3() = 0 // single line comment + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 3, "Missing newline after \";\""), + LintViolation(5, 3, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given multiple function invocations`() { + val code = + """ + class Bar { + public fun foo1() = 0 + fun foo2() = 0 + fun foo3(lambda: () -> Unit) = 0 + + init { + foo1(); foo3 { }; foo2() + } + } + """.trimIndent() + val formattedCode = + """ + class Bar { + public fun foo1() = 0 + fun foo2() = 0 + fun foo3(lambda: () -> Unit) = 0 + + init { + foo1(); + foo3 { }; + foo2() + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(7, 16, "Missing newline after \";\""), + LintViolation(7, 27, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) } - public fun f4() = 1; public fun f5() { - // no-op - } + @Test + fun `Given a multiline class declaration`() { + val code = + """ + public class FooBar1 { - public class A { + }; public class FooBar2 { - }; public class B { + } - } + public class FooBar3; public class FooBar4 + """.trimIndent() + val formattedCode = + """ + public class FooBar1 { - public class C; public class D + }; + public class FooBar2 { - class E { - init { - f1(); f2() - } - } + } - enum class INDEX { - A, B, C; fun test() = 0 - } - """.trimIndent() - val formattedCode = - """ - public fun f2() { - // no-op - }; - public fun f3() { - // no-op + public class FooBar3; + public class FooBar4 + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 3, "Missing newline after \";\""), + LintViolation(7, 22, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) } - public fun f4() = 1; - public fun f5() { - // no-op - } + @Test + fun `Given a multiline class declaration with comments`() { + val code = + """ + public class FooBar1 { - public class A { + }; /* block comment */ public class FooBar2 { - }; - public class B { + }; public class FooBar2 { - } + } // single line comment + """.trimIndent() + val formattedCode = + """ + public class FooBar1 { - public class C; - public class D + }; + /* block comment */ public class FooBar2 { - class E { - init { - f1(); - f2() - } - } + }; + public class FooBar2 { - enum class INDEX { - A, B, C; - fun test() = 0 + } // single line comment + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 3, "Missing newline after \";\""), + LintViolation(5, 3, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasLintViolations( - LintViolation(3, 3, "Missing newline after \";\""), - LintViolation(7, 21, "Missing newline after \";\""), - LintViolation(13, 3, "Missing newline after \";\""), - LintViolation(17, 16, "Missing newline after \";\""), - LintViolation(21, 14, "Missing newline after \";\""), - LintViolation(26, 13, "Missing newline after \";\""), - ) - .isFormattedAs(formattedCode) - } - @Test - fun `Issue 1078 - Given a multiline semi separated control flow then wrap each expression to a new line`() { - val code = - """ - fun test() { - for (i in 0..10) { - println(i) - }; for (i in 0..100) { - println(i) - } + @Test + fun `Given a multiple init block`() { + val code = + """ + public class Foo { + init { - while (System.currentTimeMillis() % 2 == 0L) { - println(System.currentTimeMillis()) - }; while (Random(System.currentTimeMillis()).nextBoolean()) { - println(System.currentTimeMillis()) - } + };init { - while (System.currentTimeMillis() % 2 == 0L) { - println(System.currentTimeMillis()) - }; do { - println(System.currentTimeMillis()) - } while (System.currentTimeMillis() % 2 == 0L) - } - """.trimIndent() - val formattedCode = - """ - fun test() { - for (i in 0..10) { - println(i) - }; - for (i in 0..100) { - println(i) - } + } + } + """.trimIndent() + val formattedCode = + """ + public class Foo { + init { - while (System.currentTimeMillis() % 2 == 0L) { - println(System.currentTimeMillis()) - }; - while (Random(System.currentTimeMillis()).nextBoolean()) { - println(System.currentTimeMillis()) - } + }; + init { - while (System.currentTimeMillis() % 2 == 0L) { - println(System.currentTimeMillis()) - }; - do { - println(System.currentTimeMillis()) - } while (System.currentTimeMillis() % 2 == 0L) + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolation(4, 7, "Missing newline after \";\"") + .isFormattedAs(formattedCode) + } + + @Test + fun `Given a multiple init block and variables with nested violations`() { + val code = + """ + public class Foo { + init { + val bar1 = 0; val bar2 = 0; + };init { + val bar3 = 0; val bar4 = 0; + } + } + """.trimIndent() + val formattedCode = + """ + public class Foo { + init { + val bar1 = 0; + val bar2 = 0; + }; + init { + val bar3 = 0; + val bar4 = 0; + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 22, "Missing newline after \";\""), + LintViolation(4, 7, "Missing newline after \";\""), + LintViolation(5, 22, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasLintViolations( - LintViolation(4, 7, "Missing newline after \";\""), - LintViolation(10, 7, "Missing newline after \";\""), - LintViolation(16, 7, "Missing newline after \";\""), - ) - .isFormattedAs(formattedCode) - } + } - @Test - fun `Issue 1078 - Given a multiline semi separated control flow with no body`() { - val code = - """ - fun test() { - for (i in 0..10); for (i in 0..100);while (System.currentTimeMillis() % 2 == 0L); while (Random(System.currentTimeMillis()).nextBoolean()); - } - """.trimIndent() - val formattedCode = - """ - fun test() { - for (i in 0..10); - for (i in 0..100); - while (System.currentTimeMillis() % 2 == 0L); - while (Random(System.currentTimeMillis()).nextBoolean()); + @Nested + inner class `Given flow control statements` { + @Test + fun `Given a multiple for statements`() { + val code = + """ + fun test() { + for (i in 0..10) { + println(i) + }; for (i in 0..100) { + println(i) + }; for (i in 0..1000) { + println(i) + } + } + """.trimIndent() + val formattedCode = + """ + fun test() { + for (i in 0..10) { + println(i) + }; + for (i in 0..100) { + println(i) + }; + for (i in 0..1000) { + println(i) + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(4, 7, "Missing newline after \";\""), + LintViolation(6, 7, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given a multiline while statements`() { + val code = + """ + fun test() { + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; while (Random(System.currentTimeMillis()).nextBoolean()) { + println(System.currentTimeMillis()) + } + } + """.trimIndent() + val formattedCode = + """ + fun test() { + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; + while (Random(System.currentTimeMillis()).nextBoolean()) { + println(System.currentTimeMillis()) + } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolation(4, 7, "Missing newline after \";\"") + .isFormattedAs(formattedCode) + } + + @Test + fun `Given a multiline do-while statements`() { + val code = + """ + fun test() { + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; do { + println(System.currentTimeMillis()) + } while (System.currentTimeMillis() % 2 == 0L); do { + println(System.currentTimeMillis()) + } while (System.currentTimeMillis() % 2 == 0L) + } + """.trimIndent() + val formattedCode = + """ + fun test() { + while (System.currentTimeMillis() % 2 == 0L) { + println(System.currentTimeMillis()) + }; + do { + println(System.currentTimeMillis()) + } while (System.currentTimeMillis() % 2 == 0L); + do { + println(System.currentTimeMillis()) + } while (System.currentTimeMillis() % 2 == 0L) + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(4, 7, "Missing newline after \";\""), + LintViolation(6, 52, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + + @Test + fun `Given a multiline semi separated control flow with no body`() { + val code = + """ + fun test() { + for (i in 0..10); for (i in 0..100);while (System.currentTimeMillis() % 2 == 0L); while (Random(System.currentTimeMillis()).nextBoolean()); + } + """.trimIndent() + val formattedCode = + """ + fun test() { + for (i in 0..10); + for (i in 0..100); + while (System.currentTimeMillis() % 2 == 0L); + while (Random(System.currentTimeMillis()).nextBoolean()); + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 22, "Missing newline after \";\""), + LintViolation(2, 41, "Missing newline after \";\""), + LintViolation(2, 86, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasLintViolations( - LintViolation(2, 22, "Missing newline after \";\""), - LintViolation(2, 41, "Missing newline after \";\""), - LintViolation(2, 86, "Missing newline after \";\""), - ) - .isFormattedAs(formattedCode) - } + } - @Test - fun `Issue 1078 - Given a multiline semi separated import statement then wrap each expression to a new line`() { - val code = - """ - import java.util.ArrayList; import java.util.HashMap - """.trimIndent() - val formattedCode = - """ - import java.util.ArrayList; - import java.util.HashMap - """.trimIndent() - wrappingRuleAssertThat(code) - .hasLintViolation(1, 28, "Missing newline after \";\"") - .isFormattedAs(formattedCode) - } + @Test + fun `Given a multiline semi separated import statement then wrap each expression to a new line`() { + val code = + """ + import java.util.ArrayList; import java.util.HashMap + """.trimIndent() + val formattedCode = + """ + import java.util.ArrayList; + import java.util.HashMap + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolation(1, 28, "Missing newline after \";\"") + .isFormattedAs(formattedCode) + } - @Test - fun `Issue 1078 - Given a multiline semi separated with multiple items`() { - val code = - """ - fun test() { - val a = 0; val b = 0; fun bar() { - // no-op - }; for(i in 0..10) { - println(i); println(i); a++; println(a) + @Test + fun `Given a multiline semi separated with variables, flow controls and method calls`() { + val code = + """ + fun test() { + val a = 0; val b = 0; fun bar() { + // no-op + }; for(i in 0..10) { + println(i); println(i); a++; println(a) + } } - } - """.trimIndent() - val formattedCode = - """ - fun test() { - val a = 0; - val b = 0; - fun bar() { - // no-op - }; - for(i in 0..10) { - println(i); - println(i); - a++; - println(a) + """.trimIndent() + val formattedCode = + """ + fun test() { + val a = 0; + val b = 0; + fun bar() { + // no-op + }; + for(i in 0..10) { + println(i); + println(i); + a++; + println(a) + } } - } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasLintViolations( - LintViolation(2, 15, "Missing newline after \";\""), - LintViolation(2, 26, "Missing newline after \";\""), - LintViolation(4, 7, "Missing newline after \";\""), - LintViolation(5, 20, "Missing newline after \";\""), - LintViolation(5, 32, "Missing newline after \";\""), - LintViolation(5, 37, "Missing newline after \";\""), - ) - .isFormattedAs(formattedCode) - } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 15, "Missing newline after \";\""), + LintViolation(2, 26, "Missing newline after \";\""), + LintViolation(4, 7, "Missing newline after \";\""), + LintViolation(5, 20, "Missing newline after \";\""), + LintViolation(5, 32, "Missing newline after \";\""), + LintViolation(5, 37, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } - @Test - fun `Issue 1078 - Given a enum with semicolon has not violation`() { - val code = - """ - enum class INDEX1 { ONE, TWO, THREE } - enum class INDEX2 { ONE, TWO, THREE; } - enum class INDEX3 { ONE, TWO, THREE; /* with comment */ } - enum class INDEX4 { - ONE, TWO, THREE; - } - enum class INDEX5 { - ONE, - TWO, - THREE; - } - enum class INDEX6 { - ONE, - TWO, - THREE, - ; - } - enum class INDEX7 { - ONE, - TWO, - THREE, - ; - fun foo() = "" + @Nested + inner class `Given enum class` { + @Test + fun `Given a enum without ending semi`() { + val code = + """ + enum class INDEX1 { ONE, TWO, THREE } + enum class INDEX5 { + ONE, + TWO, + THREE + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasNoLintViolations() + } + + @Test + fun `Given a enum with ending semi`() { + val code = + """ + enum class INDEX2 { ONE, TWO, THREE; } + enum class INDEX4 { + ONE, TWO, THREE; + } + enum class INDEX5 { + ONE, + TWO, + THREE; + } + enum class INDEX6 { + ONE, + TWO, + THREE, + ; + } + enum class INDEX7 { + ONE, + TWO, + THREE, + ; + fun foo() = "" + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasNoLintViolations() + } + + @Test + fun `Given a enum with ending semi with comment`() { + val code = + """ + enum class INDEX3 { ONE, TWO, THREE; /* with comment */ } + enum class INDEX6 { + ONE, + TWO, + THREE, // single line comment + ; // last single line comment + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasNoLintViolations() } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasNoLintViolations() - } - @Test - fun `Issue 1078 - Given a companion object with semicolon has not violation`() { - val code = - """ - class FirstClass(private val param: String) { - companion object; - private var toto: Boolean = false + @Test + fun `Given enum class with methods`() { + val code = + """ + enum class INDEX { + A, B, C; fun test() = 0 + } + """.trimIndent() + val formattedCode = + """ + enum class INDEX { + A, B, C; + fun test() = 0 + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolation(2, 13, "Missing newline after \";\"") + .isFormattedAs(formattedCode) } + } - class SecondClass(private val param: String) { - companion object; // with comment - private var toto: Boolean = false + @Nested + inner class `Given companion or object class` { + @Test + fun `Given a companion object with semicolon and variable`() { + val code = + """ + class Foo() { + companion object; private var toto: Boolean = false + } + """.trimIndent() + val formattedCode = + """ + class Foo() { + companion object; + private var toto: Boolean = false + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolation(2, 22, "Missing newline after \";\"") + .isFormattedAs(formattedCode) + } + + @Test + fun `Given a companion object with semicolon and comment has not violation`() { + val code = + """ + class Foo() { + companion object; // single-line comment + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasNoLintViolations() } - """.trimIndent() - wrappingRuleAssertThat(code) - .hasNoLintViolations() + } } } From 8c84e2a2dff46904aa72c1c3a4cb2ca0541094e8 Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Sat, 3 Jun 2023 03:52:38 +0530 Subject: [PATCH 6/7] Add `addAdditionalRuleProvider { NoSemicolonsRule() }` --- .../standard/rules/WrappingRuleTest.kt | 65 +++++++++++-------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt index 84593db1d3..67ff75c304 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt @@ -1888,13 +1888,14 @@ internal class WrappingRuleTest { val formattedCode = """ fun foo() { - val bar1 = 3; + val bar1 = 3 val bar2 = 2 - val fooBar1: String = ""; + val fooBar1: String = "" val fooBar2: () -> Unit = { } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(2, 18, "Missing newline after \";\""), LintViolation(3, 30, "Missing newline after \";\""), @@ -1912,14 +1913,15 @@ internal class WrappingRuleTest { val formattedCode = """ fun foo() { - val bar1 = 3; - val bar2 = 2; - val bar3 = 3; - val bar4: () -> Unit = { }; - val bar4: String = ""; + val bar1 = 3 + val bar2 = 2 + val bar3 = 3 + val bar4: () -> Unit = { } + val bar4: String = "" } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(2, 18, "Missing newline after \";\""), LintViolation(2, 32, "Missing newline after \";\""), @@ -1974,18 +1976,19 @@ internal class WrappingRuleTest { """ public fun foo1() { // no-op - }; + } public fun foo2() { // no-op - }; + } fun foo3() = 0 - public fun foo4() = 1; + public fun foo4() = 1 public fun foo5() { // no-op } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(3, 3, "Missing newline after \";\""), LintViolation(5, 3, "Missing newline after \";\""), @@ -2042,13 +2045,14 @@ internal class WrappingRuleTest { fun foo3(lambda: () -> Unit) = 0 init { - foo1(); - foo3 { }; + foo1() + foo3 { } foo2() } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(7, 16, "Missing newline after \";\""), LintViolation(7, 27, "Missing newline after \";\""), @@ -2071,15 +2075,16 @@ internal class WrappingRuleTest { """ public class FooBar1 { - }; + } public class FooBar2 { } - public class FooBar3; + public class FooBar3 public class FooBar4 """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(3, 3, "Missing newline after \";\""), LintViolation(7, 22, "Missing newline after \";\""), @@ -2134,13 +2139,14 @@ internal class WrappingRuleTest { public class Foo { init { - }; + } init { } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolation(4, 7, "Missing newline after \";\"") .isFormattedAs(formattedCode) } @@ -2161,16 +2167,17 @@ internal class WrappingRuleTest { """ public class Foo { init { - val bar1 = 0; - val bar2 = 0; - }; + val bar1 = 0 + val bar2 = 0 + } init { - val bar3 = 0; - val bar4 = 0; + val bar3 = 0 + val bar4 = 0 } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(3, 22, "Missing newline after \";\""), LintViolation(4, 7, "Missing newline after \";\""), @@ -2200,16 +2207,17 @@ internal class WrappingRuleTest { fun test() { for (i in 0..10) { println(i) - }; + } for (i in 0..100) { println(i) - }; + } for (i in 0..1000) { println(i) } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(4, 7, "Missing newline after \";\""), LintViolation(6, 7, "Missing newline after \";\""), @@ -2233,13 +2241,14 @@ internal class WrappingRuleTest { fun test() { while (System.currentTimeMillis() % 2 == 0L) { println(System.currentTimeMillis()) - }; + } while (Random(System.currentTimeMillis()).nextBoolean()) { println(System.currentTimeMillis()) } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolation(4, 7, "Missing newline after \";\"") .isFormattedAs(formattedCode) } @@ -2263,16 +2272,17 @@ internal class WrappingRuleTest { fun test() { while (System.currentTimeMillis() % 2 == 0L) { println(System.currentTimeMillis()) - }; + } do { println(System.currentTimeMillis()) - } while (System.currentTimeMillis() % 2 == 0L); + } while (System.currentTimeMillis() % 2 == 0L) do { println(System.currentTimeMillis()) } while (System.currentTimeMillis() % 2 == 0L) } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(4, 7, "Missing newline after \";\""), LintViolation(6, 52, "Missing newline after \";\""), @@ -2297,6 +2307,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(2, 22, "Missing newline after \";\""), LintViolation(2, 41, "Missing newline after \";\""), @@ -2313,10 +2324,11 @@ internal class WrappingRuleTest { """.trimIndent() val formattedCode = """ - import java.util.ArrayList; + import java.util.ArrayList import java.util.HashMap """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolation(1, 28, "Missing newline after \";\"") .isFormattedAs(formattedCode) } @@ -2463,6 +2475,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolation(2, 22, "Missing newline after \";\"") .isFormattedAs(formattedCode) } From 384e92e6916dfe35f05e9f14d442812db8c2e8b9 Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Sat, 3 Jun 2023 21:52:56 +0530 Subject: [PATCH 7/7] Add `addAdditionalRuleProvider` in every TC Create a TC w/o `addAdditionalRuleProvider` Rename `INDEX` enum to `FOO` enums --- .../standard/rules/WrappingRuleTest.kt | 78 +++++++++++++------ 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt index 67ff75c304..b1915d06b7 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/rules/WrappingRuleTest.kt @@ -1902,6 +1902,31 @@ internal class WrappingRuleTest { ).isFormattedAs(formattedCode) } + @Test + fun `Given two variables run without NoSemicolonsRule`() { + val code = + """ + fun foo() { + val bar1 = 3; val bar2 = 2 + val fooBar1: String = ""; val fooBar2: () -> Unit = { } + } + """.trimIndent() + val formattedCode = + """ + fun foo() { + val bar1 = 3; + val bar2 = 2 + val fooBar1: String = ""; + val fooBar2: () -> Unit = { } + } + """.trimIndent() + wrappingRuleAssertThat(code) + .hasLintViolations( + LintViolation(2, 18, "Missing newline after \";\""), + LintViolation(3, 30, "Missing newline after \";\""), + ).isFormattedAs(formattedCode) + } + @Test fun `Given more than two variables`() { val code = @@ -1942,13 +1967,14 @@ internal class WrappingRuleTest { val formattedCode = """ fun foo() { - val bar1 = 3; + val bar1 = 3 val bar2 = 2; // this is end comment - val bar1 = 3; - /* block comment */ val bar2 = 2; + val bar1 = 3 + /* block comment */ val bar2 = 2 } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(2, 18, "Missing newline after \";\""), LintViolation(3, 18, "Missing newline after \";\""), @@ -2010,13 +2036,14 @@ internal class WrappingRuleTest { """ public fun foo1() { // no-op - }; + } /* block comment */ public fun foo2() { // no-op - }; + } fun foo3() = 0 // single line comment """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(3, 3, "Missing newline after \";\""), LintViolation(5, 3, "Missing newline after \";\""), @@ -2107,15 +2134,16 @@ internal class WrappingRuleTest { """ public class FooBar1 { - }; + } /* block comment */ public class FooBar2 { - }; + } public class FooBar2 { } // single line comment """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(3, 3, "Missing newline after \";\""), LintViolation(5, 3, "Missing newline after \";\""), @@ -2348,20 +2376,21 @@ internal class WrappingRuleTest { val formattedCode = """ fun test() { - val a = 0; - val b = 0; + val a = 0 + val b = 0 fun bar() { // no-op - }; + } for(i in 0..10) { - println(i); - println(i); - a++; + println(i) + println(i) + a++ println(a) } } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolations( LintViolation(2, 15, "Missing newline after \";\""), LintViolation(2, 26, "Missing newline after \";\""), @@ -2378,8 +2407,8 @@ internal class WrappingRuleTest { fun `Given a enum without ending semi`() { val code = """ - enum class INDEX1 { ONE, TWO, THREE } - enum class INDEX5 { + enum class FOO1 { ONE, TWO, THREE } + enum class FOO2 { ONE, TWO, THREE @@ -2393,22 +2422,22 @@ internal class WrappingRuleTest { fun `Given a enum with ending semi`() { val code = """ - enum class INDEX2 { ONE, TWO, THREE; } - enum class INDEX4 { + enum class FOO1 { ONE, TWO, THREE; } + enum class FOO2 { ONE, TWO, THREE; } - enum class INDEX5 { + enum class FOO3 { ONE, TWO, THREE; } - enum class INDEX6 { + enum class FOO4 { ONE, TWO, THREE, ; } - enum class INDEX7 { + enum class FOO5 { ONE, TWO, THREE, @@ -2424,8 +2453,8 @@ internal class WrappingRuleTest { fun `Given a enum with ending semi with comment`() { val code = """ - enum class INDEX3 { ONE, TWO, THREE; /* with comment */ } - enum class INDEX6 { + enum class FOO1 { ONE, TWO, THREE; /* with comment */ } + enum class FOO2 { ONE, TWO, THREE, // single line comment @@ -2440,18 +2469,19 @@ internal class WrappingRuleTest { fun `Given enum class with methods`() { val code = """ - enum class INDEX { + enum class FOO { A, B, C; fun test() = 0 } """.trimIndent() val formattedCode = """ - enum class INDEX { + enum class FOO { A, B, C; fun test() = 0 } """.trimIndent() wrappingRuleAssertThat(code) + .addAdditionalRuleProvider { NoSemicolonsRule() } .hasLintViolation(2, 13, "Missing newline after \";\"") .isFormattedAs(formattedCode) }