From 9a42e17b169a576f4ad2f20751ef4af4a96a743b Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 19 May 2022 20:24:19 +0200 Subject: [PATCH] Run rules during unit tests in correct order With KtLintAssertThat an AssertJ style `assertThat` is created for a specific rule. In addition to that rule, it is possible to run additional rules. In case the rule which is to be tested has defined a VisitorModifier which requires one or more additional rules to be loaded and to be enabled, it is mandatory that those rules are added to the unit test. The goal is to execute the rules during unit tests in the same order as when running the CLI version of KtLint. During each unit test a dynamic RuleSet is being created for a limited set of rules (e.g. the rule for which the `assertThat` is created plus the additional rules specified in the unit tests). The rules in this minimized ruleSet are executed in the order as defined by the VisitorModifier as defined in the rules. In order to achieve above, following is changed as well: * Split naming policy of rule id and rule set id. The naming policy of the latter is not changed. The naming policy of the ruleId is changed so that the ruleSetId prefix can be specified optionally. If the ruleId is not prefixed with a ruleSetId then it is assumed to be equal to "standard". For all experimental rules, the ruleSetId has been added. * Remove obsolete parameter "isUnitTestContext" from VisitorProvider * As the VisitorModifiers are now also used and checked during unit tests, it is required to run the additional rules during the lint phase as well. Some code examples in tests in which the IndentationRule is added as additional rule are changed to comply with that rule. Closes #1457 --- .../kotlin/com/pinterest/ktlint/core/Rule.kt | 4 +- .../com/pinterest/ktlint/core/RuleSet.kt | 2 +- .../pinterest/ktlint/core/VisitorProvider.kt | 24 ++-- .../ktlint/core/internal/IdNamingPolicy.kt | 21 ++- .../ktlint/core/VisitorProviderTest.kt | 5 +- .../ruleset/experimental/AnnotationRule.kt | 2 +- .../experimental/AnnotationSpacingRule.kt | 2 +- .../experimental/ArgumentListWrappingRule.kt | 2 +- .../BlockCommentInitialStarAlignmentRule.kt | 2 +- .../experimental/CommentWrappingRule.kt | 2 +- .../DiscouragedCommentLocationRule.kt | 2 +- .../experimental/EnumEntryNameCaseRule.kt | 3 +- .../ExperimentalRuleSetProvider.kt | 5 +- .../experimental/FunKeywordSpacingRule.kt | 2 +- .../FunctionReturnTypeSpacingRule.kt | 2 +- .../FunctionStartOfBodySpacingRule.kt | 2 +- .../FunctionTypeReferenceSpacingRule.kt | 2 +- .../ruleset/experimental/KdocWrappingRule.kt | 2 +- .../experimental/ModifierListSpacingRule.kt | 2 +- .../experimental/MultiLineIfElseRule.kt | 2 +- .../NoEmptyFirstLineInMethodBlockRule.kt | 3 +- .../experimental/NullableTypeSpacingRule.kt | 2 +- .../ruleset/experimental/PackageNameRule.kt | 3 +- .../experimental/ParameterListSpacingRule.kt | 2 +- .../SpacingAroundAngleBracketsRule.kt | 2 +- .../SpacingAroundDoubleColonRule.kt | 3 +- .../SpacingAroundUnaryOperatorRule.kt | 3 +- ...gBetweenDeclarationsWithAnnotationsRule.kt | 3 +- ...cingBetweenDeclarationsWithCommentsRule.kt | 3 +- ...enFunctionNameAndOpeningParenthesisRule.kt | 2 +- .../TypeArgumentListSpacingRule.kt | 2 +- .../TypeParameterListSpacingRule.kt | 2 +- ...saryParenthesesBeforeTrailingLambdaRule.kt | 2 +- .../trailingcomma/TrailingCommaRule.kt | 3 +- .../ArgumentListWrappingRuleTest.kt | 4 +- .../experimental/FunctionSignatureRuleTest.kt | 10 +- .../experimental/MultiLineIfElseRuleTest.kt | 4 +- .../NullableTypeSpacingRuleTest.kt | 11 +- .../SpacingAroundAngleBracketRuleTest.kt | 4 +- .../experimental/TrailingCommaRuleTest.kt | 123 +++++++++--------- .../ruleset/standard/IndentationRuleTest.kt | 40 +++++- .../standard/ParameterListWrappingRuleTest.kt | 36 ++--- .../standard/StringTemplateRuleTest.kt | 2 +- .../ruleset/standard/WrappingRuleTest.kt | 14 +- .../pinterest/ktlint/test/KtLintAssertThat.kt | 99 +++++++------- .../pinterest/ktlint/test/RuleExtension.kt | 24 +--- 46 files changed, 259 insertions(+), 237 deletions(-) diff --git a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/Rule.kt b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/Rule.kt index 58d0242553..b8b9c98911 100644 --- a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/Rule.kt +++ b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/Rule.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode * Implementation **doesn't** have to be thread-safe or stateless * (provided [RuleSetProvider] creates a new instance on each `get()` call). * - * @param id must be unique within the ruleset + * @param id: For non-standard rules, it is expected that this id consist of the ruleSetId and ruleId, e.g. "some-rule-set-id:some-rule-id" * @param visitorModifiers: set of modifiers of the visitor. Preferably a rule has no modifiers at all, meaning that it * is completely independent of all other rules. * @@ -20,7 +20,7 @@ abstract class Rule( public val visitorModifiers: Set = emptySet() ) { init { - IdNamingPolicy.enforceNaming(id) + IdNamingPolicy.enforceRuleIdNaming(id) } /** diff --git a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/RuleSet.kt b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/RuleSet.kt index 168ac3f121..bee3736f1c 100644 --- a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/RuleSet.kt +++ b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/RuleSet.kt @@ -12,7 +12,7 @@ open class RuleSet( ) : Iterable { init { - IdNamingPolicy.enforceNaming(id) + IdNamingPolicy.enforceRuleSetIdNaming(id) require(rules.isNotEmpty()) { "At least one rule must be provided" } } diff --git a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/VisitorProvider.kt b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/VisitorProvider.kt index a9dfdc2d29..5102096f48 100644 --- a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/VisitorProvider.kt +++ b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/VisitorProvider.kt @@ -6,11 +6,10 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode public class VisitorProvider( ruleSets: Iterable, - private val debug: Boolean, - isUnitTestContext: Boolean = false + private val debug: Boolean ) { private val ruleReferences: List = - VisitorProviderInitializer(ruleSets, debug, isUnitTestContext).getRulePreferences() + VisitorProviderInitializer(ruleSets, debug).getRulePreferences() internal fun visitor( ruleSets: Iterable, @@ -27,7 +26,7 @@ public class VisitorProvider( .rules .filter { rule -> toQualifiedRuleId(ruleSet.id, rule.id) in enabledQualifiedRuleIds } .filter { rule -> isNotDisabled(rootNode, toQualifiedRuleId(ruleSet.id, rule.id)) } - .map { rule -> "${ruleSet.id}:${rule.id}" to rule } + .map { rule -> "${toQualifiedRuleId(ruleSet.id, rule.id)}" to rule } }.toMap() if (debug && enabledRules.isEmpty()) { println( @@ -130,7 +129,11 @@ private fun toQualifiedRuleId( ruleSetId: String, ruleId: String ) = - "$ruleSetId:$ruleId" + if (ruleId.startsWith("$ruleSetId:")) { + ruleId + } else { + "$ruleSetId:$ruleId" + } private fun String.toQualifiedRuleId() = if (contains(":")) { @@ -141,8 +144,7 @@ private fun String.toQualifiedRuleId() = private class VisitorProviderInitializer( val ruleSets: Iterable, - val debug: Boolean, - val isUnitTestContext: Boolean = false + val debug: Boolean ) { fun getRulePreferences(): List { return ruleSets @@ -275,13 +277,7 @@ private class VisitorProviderInitializer( while (ruleReferencesIterator.hasNext()) { val ruleReference = ruleReferencesIterator.next() - if (ruleReference.runAfterRule != null && isUnitTestContext) { - // When running unit tests,the RunAfterRule annotation is ignored. The code provided in the unit should - // be formatted as if the rule on which it depends was already applied. In this way the unit test can be - // restricted to one single rule instead of having to take into account all other rules on which it - // might depend. - newRuleReferences.add(ruleReference.copy(runAfterRule = null)) - } else if (ruleReference.runAfterRule != null && newRuleReferences.none { rule -> rule.runsAfter(ruleReference) }) { + if (ruleReference.runAfterRule != null && newRuleReferences.none { rule -> rule.runsAfter(ruleReference) }) { // The RunAfterRule refers to a rule which is not yet added to the new list of rule references. if (this.none { it.runsAfter(ruleReference) }) { // The RunAfterRule refers to a rule which is not loaded at all. diff --git a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/internal/IdNamingPolicy.kt b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/internal/IdNamingPolicy.kt index a687e35fcf..27c6a5f0e4 100644 --- a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/internal/IdNamingPolicy.kt +++ b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/internal/IdNamingPolicy.kt @@ -4,14 +4,23 @@ package com.pinterest.ktlint.core.internal * Provides policy to have consistent and restricted `id` field naming style. */ internal object IdNamingPolicy { - private const val ID_REGEX = "[a-z]+([-][a-z]+)*" - private val idRegex = ID_REGEX.toRegex() + private const val SIMPLE_ID_REGEX = "[a-z]+([-][a-z]+)*" + private val ruleIdRegex = "($SIMPLE_ID_REGEX:)?($SIMPLE_ID_REGEX)".toRegex() + private val ruleSetIdRegex = "($SIMPLE_ID_REGEX)".toRegex() /** - * Checks provided [id] is valid. + * Checks provided [ruleId] is valid. * - * Will throw [IllegalArgumentException] on invalid [id] name. + * Will throw [IllegalArgumentException] on invalid [ruleId] name. */ - internal fun enforceNaming(id: String) = - require(id.matches(idRegex)) { "id $id must match $ID_REGEX" } + internal fun enforceRuleIdNaming(ruleId: String) = + require(ruleId.matches(ruleIdRegex)) { "Rule id '$ruleId' must match '${ruleIdRegex.pattern}'" } + + /** + * Checks provided [ruleSetId] is valid. + * + * Will throw [IllegalArgumentException] on invalid [ruleSetId] name. + */ + internal fun enforceRuleSetIdNaming(ruleSetId: String) = + require(ruleSetId.matches(ruleSetIdRegex)) { "RuleSet id '$ruleSetId' must match '${ruleSetIdRegex.pattern}'" } } diff --git a/ktlint-core/src/test/kotlin/com/pinterest/ktlint/core/VisitorProviderTest.kt b/ktlint-core/src/test/kotlin/com/pinterest/ktlint/core/VisitorProviderTest.kt index 8fb609083c..7f049d1d27 100644 --- a/ktlint-core/src/test/kotlin/com/pinterest/ktlint/core/VisitorProviderTest.kt +++ b/ktlint-core/src/test/kotlin/com/pinterest/ktlint/core/VisitorProviderTest.kt @@ -580,10 +580,7 @@ class VisitorProviderTest { return VisitorProvider( ruleSets = ruleSetList, // Enable debug mode as it is helpful when a test fails - debug = true, - // Although this is a unit test, the isUnitTestContext is disabled by default so that rules marked with - // RunAfterRule can be tested as well. - isUnitTestContext = isUnitTestContext ?: false + debug = true ).run { var visits: MutableList? = null visitor(ruleSetList, SOME_ROOT_AST_NODE, concurrent ?: false) diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationRule.kt index 5458260ab9..aea0a98473 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationRule.kt @@ -34,7 +34,7 @@ import org.jetbrains.kotlin.psi.psiUtil.nextLeaf * * @see [AnnotationSpacingRule] for white space rules. Moved since */ -class AnnotationRule : Rule("annotation") { +class AnnotationRule : Rule("$experimentalRulesetId:annotation") { companion object { const val multipleAnnotationsOnSameLineAsAnnotatedConstructErrorMessage = diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationSpacingRule.kt index c7a988540c..dc0e96302d 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/AnnotationSpacingRule.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.psi.psiUtil.leaves * * https://kotlinlang.org/docs/reference/coding-conventions.html#annotation-formatting */ -class AnnotationSpacingRule : Rule("annotation-spacing") { +class AnnotationSpacingRule : Rule("$experimentalRulesetId:annotation-spacing") { companion object { const val ERROR_MESSAGE = "Annotations should occur immediately before the annotated construct" diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRule.kt index 554774be0d..48c52adbf8 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRule.kt @@ -41,7 +41,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType */ @OptIn(FeatureInAlphaState::class) class ArgumentListWrappingRule : - Rule("argument-list-wrapping"), + Rule("$experimentalRulesetId:argument-list-wrapping"), UsesEditorConfigProperties { private var editorConfigIndent = IndentConfig.DEFAULT_INDENT_CONFIG private var maxLineLength = -1 diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/BlockCommentInitialStarAlignmentRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/BlockCommentInitialStarAlignmentRule.kt index 18321fd11d..c6bed583b7 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/BlockCommentInitialStarAlignmentRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/BlockCommentInitialStarAlignmentRule.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafElement */ class BlockCommentInitialStarAlignmentRule : Rule( - "block-comment-initial-star-alignment", + "$experimentalRulesetId:block-comment-initial-star-alignment", visitorModifiers = setOf( // The block comment is a node which can contain multiple lines. The indent of the second and later line // should be determined based on the indent of the block comment node. This indent is determined by the diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/CommentWrappingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/CommentWrappingRule.kt index 2f3f822431..dfa80efd97 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/CommentWrappingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/CommentWrappingRule.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiCommentImpl */ @OptIn(FeatureInAlphaState::class) public class CommentWrappingRule : - Rule("comment-wrapping"), + Rule("$experimentalRulesetId:comment-wrapping"), UsesEditorConfigProperties { override val editorConfigProperties: List> = listOf( diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/DiscouragedCommentLocationRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/DiscouragedCommentLocationRule.kt index 6979a11a3d..3e17a4e685 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/DiscouragedCommentLocationRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/DiscouragedCommentLocationRule.kt @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode * foo(t: T) = "some-result" * ``` */ -public class DiscouragedCommentLocationRule : Rule("discouraged-comment-location") { +public class DiscouragedCommentLocationRule : Rule("$experimentalRulesetId:discouraged-comment-location") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/EnumEntryNameCaseRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/EnumEntryNameCaseRule.kt index 14f1f28009..abb65991fb 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/EnumEntryNameCaseRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/EnumEntryNameCaseRule.kt @@ -5,8 +5,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement import org.jetbrains.kotlin.psi.KtEnumEntry -public class EnumEntryNameCaseRule : Rule("enum-entry-name-case") { - +public class EnumEntryNameCaseRule : Rule("$experimentalRulesetId:enum-entry-name-case") { internal companion object { val regex = Regex("[A-Z]([A-Za-z\\d]*|[A-Z_\\d]*)") } diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ExperimentalRuleSetProvider.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ExperimentalRuleSetProvider.kt index af15095de0..523ac73b74 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ExperimentalRuleSetProvider.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ExperimentalRuleSetProvider.kt @@ -4,10 +4,11 @@ import com.pinterest.ktlint.core.RuleSet import com.pinterest.ktlint.core.RuleSetProvider import com.pinterest.ktlint.ruleset.experimental.trailingcomma.TrailingCommaRule -public class ExperimentalRuleSetProvider : RuleSetProvider { +public const val experimentalRulesetId = "experimental" +public class ExperimentalRuleSetProvider : RuleSetProvider { override fun get(): RuleSet = RuleSet( - "experimental", + experimentalRulesetId, AnnotationRule(), ArgumentListWrappingRule(), MultiLineIfElseRule(), diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunKeywordSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunKeywordSpacingRule.kt index 638a1befc2..c62ba33fa3 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunKeywordSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunKeywordSpacingRule.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement /** * Lints and formats the spacing after the fun keyword */ -public class FunKeywordSpacingRule : Rule("fun-keyword-spacing") { +public class FunKeywordSpacingRule : Rule("$experimentalRulesetId:fun-keyword-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionReturnTypeSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionReturnTypeSpacingRule.kt index c98d45d615..2518f99a53 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionReturnTypeSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionReturnTypeSpacingRule.kt @@ -10,7 +10,7 @@ import com.pinterest.ktlint.core.ast.upsertWhitespaceAfterMe import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafElement -public class FunctionReturnTypeSpacingRule : Rule("function-return-type-spacing") { +public class FunctionReturnTypeSpacingRule : Rule("$experimentalRulesetId:function-return-type-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionStartOfBodySpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionStartOfBodySpacingRule.kt index f826b35ebf..afd8871eab 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionStartOfBodySpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionStartOfBodySpacingRule.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement /** * Lints and formats the spacing after the fun keyword */ -public class FunctionStartOfBodySpacingRule : Rule("function-start-of-body-spacing") { +public class FunctionStartOfBodySpacingRule : Rule("$experimentalRulesetId:function-start-of-body-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionTypeReferenceSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionTypeReferenceSpacingRule.kt index ce7bacb00b..6aa8656b8d 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionTypeReferenceSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionTypeReferenceSpacingRule.kt @@ -9,7 +9,7 @@ import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE import com.pinterest.ktlint.core.ast.nextSibling import org.jetbrains.kotlin.com.intellij.lang.ASTNode -public class FunctionTypeReferenceSpacingRule : Rule("function-type-reference-spacing") { +public class FunctionTypeReferenceSpacingRule : Rule("$experimentalRulesetId:function-type-reference-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/KdocWrappingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/KdocWrappingRule.kt index 480390dc80..6d429594d2 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/KdocWrappingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/KdocWrappingRule.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement */ @OptIn(FeatureInAlphaState::class) public class KdocWrappingRule : - Rule("kdoc-wrapping"), + Rule("$experimentalRulesetId:kdoc-wrapping"), UsesEditorConfigProperties { override val editorConfigProperties: List> = listOf( diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ModifierListSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ModifierListSpacingRule.kt index 4ffc5624fa..cedf3d124d 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ModifierListSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ModifierListSpacingRule.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement /** * Lint and format the spacing between the modifiers in and after the last modifier in a modifier list. */ -public class ModifierListSpacingRule : Rule("modifier-list-spacing") { +public class ModifierListSpacingRule : Rule("$experimentalRulesetId:modifier-list-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRule.kt index 9e11d82dd1..3dd50d83dc 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRule.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.psiUtil.leaves * * TODO: if, for, when branch, do, while */ -class MultiLineIfElseRule : Rule("multiline-if-else") { +class MultiLineIfElseRule : Rule("$experimentalRulesetId:multiline-if-else") { override fun visit( node: ASTNode, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NoEmptyFirstLineInMethodBlockRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NoEmptyFirstLineInMethodBlockRule.kt index 345980399f..0f24ef368f 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NoEmptyFirstLineInMethodBlockRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NoEmptyFirstLineInMethodBlockRule.kt @@ -10,8 +10,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement -class NoEmptyFirstLineInMethodBlockRule : Rule("no-empty-first-line-in-method-block") { - +class NoEmptyFirstLineInMethodBlockRule : Rule("$experimentalRulesetId:no-empty-first-line-in-method-block") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRule.kt index 2ed271aabe..2a460d649d 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRule.kt @@ -7,7 +7,7 @@ import com.pinterest.ktlint.core.ast.prevLeaf import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement -public class NullableTypeSpacingRule : Rule("nullable-type-spacing") { +public class NullableTypeSpacingRule : Rule("$experimentalRulesetId:nullable-type-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/PackageNameRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/PackageNameRule.kt index 6d85bc87c8..74ad5efbae 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/PackageNameRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/PackageNameRule.kt @@ -5,8 +5,7 @@ import com.pinterest.ktlint.core.ast.ElementType.PACKAGE_DIRECTIVE import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.psi.KtPackageDirective -class PackageNameRule : Rule("package-name") { - +class PackageNameRule : Rule("$experimentalRulesetId:package-name") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ParameterListSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ParameterListSpacingRule.kt index 72caf43100..fbe41916cf 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ParameterListSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/ParameterListSpacingRule.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement * comma's and colons. However, it does have a more complete view on the higher concept of the parameter-list without * interfering of the parameter-list-wrapping rule. */ -public class ParameterListSpacingRule : Rule("parameter-list-spacing") { +public class ParameterListSpacingRule : Rule("$experimentalRulesetId:parameter-list-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketsRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketsRule.kt index 6278285d19..1a86564d9d 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketsRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketsRule.kt @@ -13,7 +13,7 @@ import com.pinterest.ktlint.core.ast.prevLeaf import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafElement -class SpacingAroundAngleBracketsRule : Rule("spacing-around-angle-brackets") { +class SpacingAroundAngleBracketsRule : Rule("$experimentalRulesetId:spacing-around-angle-brackets") { private fun String.trimBeforeLastLine() = this.substring(this.lastIndexOf('\n')) override fun visit( diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundDoubleColonRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundDoubleColonRule.kt index 9f1fa1ef12..a96dbf9d8f 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundDoubleColonRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundDoubleColonRule.kt @@ -11,8 +11,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement -class SpacingAroundDoubleColonRule : Rule("double-colon-spacing") { - +class SpacingAroundDoubleColonRule : Rule("$experimentalRulesetId:double-colon-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundUnaryOperatorRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundUnaryOperatorRule.kt index 0c4195e959..dbd11654d9 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundUnaryOperatorRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundUnaryOperatorRule.kt @@ -12,8 +12,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode * * @see [Kotlin Style Guide](https://kotlinlang.org/docs/reference/coding-conventions.html#horizontal-whitespace) */ -class SpacingAroundUnaryOperatorRule : Rule("unary-op-spacing") { - +class SpacingAroundUnaryOperatorRule : Rule("$experimentalRulesetId:unary-op-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithAnnotationsRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithAnnotationsRule.kt index cc903893da..ebd2c6c7b8 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithAnnotationsRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithAnnotationsRule.kt @@ -17,8 +17,7 @@ import org.jetbrains.kotlin.psi.psiUtil.prevLeafs /** * @see https://youtrack.jetbrains.com/issue/KT-35106 */ -class SpacingBetweenDeclarationsWithAnnotationsRule : Rule("spacing-between-declarations-with-annotations") { - +class SpacingBetweenDeclarationsWithAnnotationsRule : Rule("$experimentalRulesetId:spacing-between-declarations-with-annotations") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithCommentsRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithCommentsRule.kt index 0513223141..cf8e60df18 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithCommentsRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenDeclarationsWithCommentsRule.kt @@ -16,8 +16,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset /** * @see https://youtrack.jetbrains.com/issue/KT-35088 */ -class SpacingBetweenDeclarationsWithCommentsRule : Rule("spacing-between-declarations-with-comments") { - +class SpacingBetweenDeclarationsWithCommentsRule : Rule("$experimentalRulesetId:spacing-between-declarations-with-comments") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenFunctionNameAndOpeningParenthesisRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenFunctionNameAndOpeningParenthesisRule.kt index ab5dbe71b8..6802b88072 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenFunctionNameAndOpeningParenthesisRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingBetweenFunctionNameAndOpeningParenthesisRule.kt @@ -6,7 +6,7 @@ import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE import com.pinterest.ktlint.core.ast.nextSibling import org.jetbrains.kotlin.com.intellij.lang.ASTNode -public class SpacingBetweenFunctionNameAndOpeningParenthesisRule : Rule("spacing-between-function-name-and-opening-parenthesis") { +public class SpacingBetweenFunctionNameAndOpeningParenthesisRule : Rule("$experimentalRulesetId:spacing-between-function-name-and-opening-parenthesis") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeArgumentListSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeArgumentListSpacingRule.kt index 01d1747688..26d190102d 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeArgumentListSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeArgumentListSpacingRule.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode /** * Lints and formats the spacing before and after the angle brackets of a type argument list. */ -public class TypeArgumentListSpacingRule : Rule("type-argument-list-spacing") { +public class TypeArgumentListSpacingRule : Rule("$experimentalRulesetId:type-argument-list-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeParameterListSpacingRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeParameterListSpacingRule.kt index 47f9502ecf..2ebe62bf18 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeParameterListSpacingRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/TypeParameterListSpacingRule.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement /** * Lints and formats the spacing before and after the angle brackets of a type parameter list. */ -public class TypeParameterListSpacingRule : Rule("type-parameter-list-spacing") { +public class TypeParameterListSpacingRule : Rule("$experimentalRulesetId:type-parameter-list-spacing") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/UnnecessaryParenthesesBeforeTrailingLambdaRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/UnnecessaryParenthesesBeforeTrailingLambdaRule.kt index ab0e0e2bd6..a5d71eb8ba 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/UnnecessaryParenthesesBeforeTrailingLambdaRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/UnnecessaryParenthesesBeforeTrailingLambdaRule.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode /** * Ensures there are no unnecessary parentheses before a trailing lambda. */ -class UnnecessaryParenthesesBeforeTrailingLambdaRule : Rule("unnecessary-parentheses-before-trailing-lambda") { +class UnnecessaryParenthesesBeforeTrailingLambdaRule : Rule("$experimentalRulesetId:unnecessary-parentheses-before-trailing-lambda") { override fun visit( node: ASTNode, autoCorrect: Boolean, diff --git a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/trailingcomma/TrailingCommaRule.kt b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/trailingcomma/TrailingCommaRule.kt index 8c2d1b31b0..7c80610c65 100644 --- a/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/trailingcomma/TrailingCommaRule.kt +++ b/ktlint-ruleset-experimental/src/main/kotlin/com/pinterest/ktlint/ruleset/experimental/trailingcomma/TrailingCommaRule.kt @@ -10,6 +10,7 @@ import com.pinterest.ktlint.core.ast.containsLineBreakInRange import com.pinterest.ktlint.core.ast.isRoot import com.pinterest.ktlint.core.ast.prevCodeLeaf import com.pinterest.ktlint.core.ast.prevLeaf +import com.pinterest.ktlint.ruleset.experimental.experimentalRulesetId import kotlin.properties.Delegates import org.ec4j.core.model.PropertyType import org.ec4j.core.model.PropertyType.PropertyValueParser @@ -33,7 +34,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast @OptIn(FeatureInAlphaState::class) public class TrailingCommaRule : Rule( - id = "trailing-comma", + id = "$experimentalRulesetId:trailing-comma", visitorModifiers = setOf( VisitorModifier.RunAfterRule( ruleId = "standard:indent", diff --git a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRuleTest.kt b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRuleTest.kt index 48e22eab37..3464ad3ff5 100644 --- a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRuleTest.kt +++ b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/ArgumentListWrappingRuleTest.kt @@ -61,7 +61,7 @@ class ArgumentListWrappingRuleTest { ) """.trimIndent() argumentListWrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 9, "Argument should be on a separate line (unless all arguments can fit a single line)"), LintViolation(2, 14, "Argument should be on a separate line (unless all arguments can fit a single line)"), @@ -281,7 +281,7 @@ class ArgumentListWrappingRuleTest { } """.trimIndent() argumentListWrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 10, "Argument should be on a separate line (unless all arguments can fit a single line)"), LintViolation(2, 19, "Argument should be on a separate line (unless all arguments can fit a single line)"), diff --git a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionSignatureRuleTest.kt b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionSignatureRuleTest.kt index f25a1e6aa3..56847ac75e 100644 --- a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionSignatureRuleTest.kt +++ b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/FunctionSignatureRuleTest.kt @@ -56,7 +56,7 @@ class FunctionSignatureRuleTest { """.trimIndent() functionSignatureWrappingRuleAssertThat(code) .setMaxLineLength() - .addAdditionalFormattingRule(FunctionStartOfBodySpacingRule()) + .addAdditionalRules(FunctionStartOfBodySpacingRule()) .hasLintViolation(2, 38, "Expected a single space before body block") .isFormattedAs(formattedCode) } @@ -481,8 +481,8 @@ class FunctionSignatureRuleTest { fun f7(): List? = null """.trimIndent() functionSignatureWrappingRuleAssertThat(code) - .addAdditionalFormattingRule(NullableTypeSpacingRule()) - .hasNoLintViolationsExceptInAdditionalFormattingRules() + .addAdditionalRules(NullableTypeSpacingRule()) + .hasNoLintViolationsExceptInAdditionalRules() .isFormattedAs(formattedCode) } @@ -553,7 +553,7 @@ class FunctionSignatureRuleTest { fun f29(block: (T) -> String) = "some-result" """.trimIndent() functionSignatureWrappingRuleAssertThat(code) - .addAdditionalFormattingRule( + .addAdditionalRules( NoMultipleSpacesRule(), SpacingAroundAngleBracketsRule(), SpacingAroundParensRule(), @@ -603,7 +603,7 @@ class FunctionSignatureRuleTest { fun f11(block: (T) -> String) = "some-result" """.trimIndent() functionSignatureWrappingRuleAssertThat(code) - .addAdditionalFormattingRule( + .addAdditionalRules( TypeParameterListSpacingRule(), FunctionStartOfBodySpacingRule(), FunctionTypeReferenceSpacingRule(), diff --git a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRuleTest.kt b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRuleTest.kt index c9300d7285..9360a17e55 100644 --- a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRuleTest.kt +++ b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/MultiLineIfElseRuleTest.kt @@ -425,7 +425,7 @@ class MultiLineIfElseRuleTest { } """.trimIndent() multiLineIfElseRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(4, 9, "Missing { ... }"), LintViolation(7, 9, "Missing { ... }") @@ -454,7 +454,7 @@ class MultiLineIfElseRuleTest { } """.trimIndent() multiLineIfElseRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(3, 9, "Missing { ... }"), LintViolation(5, 9, "Missing { ... }") diff --git a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRuleTest.kt b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRuleTest.kt index fc70587050..4bd0c99188 100644 --- a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRuleTest.kt +++ b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/NullableTypeSpacingRuleTest.kt @@ -1,10 +1,6 @@ package com.pinterest.ktlint.ruleset.experimental -import com.pinterest.ktlint.core.LintError import com.pinterest.ktlint.test.KtLintAssertThat.Companion.assertThat -import com.pinterest.ktlint.test.format -import com.pinterest.ktlint.test.lint -import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test class NullableTypeSpacingRuleTest { @@ -20,10 +16,9 @@ class NullableTypeSpacingRuleTest { """ val foo : String? = null """.trimIndent() - Assertions.assertThat(NullableTypeSpacingRule().lint(code)).containsExactly( - LintError(1, 17, "nullable-type-spacing", "Unexpected whitespace") - ) - Assertions.assertThat(NullableTypeSpacingRule().format(code)).isEqualTo(formattedCode) + nullableTypeSpacingRuleAssertThat(code) + .hasLintViolation(1, 17, "Unexpected whitespace") + .isFormattedAs(formattedCode) } @Test diff --git a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketRuleTest.kt b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketRuleTest.kt index de4cc3c8b1..750fab5261 100644 --- a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketRuleTest.kt +++ b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/SpacingAroundAngleBracketRuleTest.kt @@ -60,7 +60,7 @@ class SpacingAroundAngleBracketRuleTest { > = mapOf() """.trimIndent() spacingAroundAngleBracketsRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(1, 12, "Unexpected spacing after \"<\""), LintViolation(2, 23, "Unexpected spacing before \">\""), @@ -110,7 +110,7 @@ class SpacingAroundAngleBracketRuleTest { > {} """.trimIndent() spacingAroundAngleBracketsRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 19, "Unexpected spacing after \"<\""), LintViolation(3, 31, "Unexpected spacing before \">\""), diff --git a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/TrailingCommaRuleTest.kt b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/TrailingCommaRuleTest.kt index a3e58597be..327b28de87 100644 --- a/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/TrailingCommaRuleTest.kt +++ b/ktlint-ruleset-experimental/src/test/kotlin/com/pinterest/ktlint/ruleset/experimental/TrailingCommaRuleTest.kt @@ -4,6 +4,7 @@ import com.pinterest.ktlint.core.api.FeatureInAlphaState import com.pinterest.ktlint.ruleset.experimental.trailingcomma.TrailingCommaRule import com.pinterest.ktlint.ruleset.experimental.trailingcomma.TrailingCommaRule.Companion.allowTrailingCommaOnCallSiteProperty import com.pinterest.ktlint.ruleset.experimental.trailingcomma.TrailingCommaRule.Companion.allowTrailingCommaProperty +import com.pinterest.ktlint.ruleset.standard.IndentationRule import com.pinterest.ktlint.ruleset.standard.NoUnusedImportsRule import com.pinterest.ktlint.test.KtLintAssertThat.Companion.assertThat import com.pinterest.ktlint.test.LintViolation @@ -11,7 +12,13 @@ import org.junit.jupiter.api.Test @OptIn(FeatureInAlphaState::class) class TrailingCommaRuleTest { - private val trailingCommaRuleAssertThat = TrailingCommaRule().assertThat() + private val trailingCommaRuleAssertThat = + TrailingCommaRule() + .assertThat( + // Apply the IndentationRule always as additional rule, so that the formattedCode in the unit test looks + // correct. + IndentationRule() + ) @Test fun `Given property allow trailing comma on call site is not set then remove trailing comma's`() { @@ -124,8 +131,8 @@ class TrailingCommaRuleTest { ) -> Int = when (x) { 1, 2 -> { - foo, - bar /* The comma should be inserted before the comment */ + foo, + bar /* The comma should be inserted before the comment */ -> block( foo * bar, @@ -146,8 +153,8 @@ class TrailingCommaRuleTest { ) -> Int = when (x) { 1, 2, -> { - foo, - bar, /* The comma should be inserted before the comment */ + foo, + bar, /* The comma should be inserted before the comment */ -> block( foo * bar, @@ -164,7 +171,7 @@ class TrailingCommaRuleTest { LintViolation(4, 29, "Missing trailing comma before \")\""), LintViolation(6, 13, "Missing trailing comma before \")\""), LintViolation(8, 9, "Missing trailing comma before \"->\""), - LintViolation(11, 12, "Missing trailing comma before \"->\""), + LintViolation(11, 16, "Missing trailing comma before \"->\""), LintViolation(15, 22, "Missing trailing comma before \")\"") ).isFormattedAs(formattedCode) } @@ -244,28 +251,28 @@ class TrailingCommaRuleTest { """ data class Foo1(val bar: Int,) data class Foo2( - val bar: Int, // The comma before the comment should be removed without removing the comment itself + val bar: Int, // The comma before the comment should be removed without removing the comment itself ) data class Foo3( - val bar: Int, /* The comma before the comment should be removed without removing the comment itself */ + val bar: Int, /* The comma before the comment should be removed without removing the comment itself */ ) """.trimIndent() val formattedCode = """ data class Foo1(val bar: Int) data class Foo2( - val bar: Int // The comma before the comment should be removed without removing the comment itself + val bar: Int // The comma before the comment should be removed without removing the comment itself ) data class Foo3( - val bar: Int /* The comma before the comment should be removed without removing the comment itself */ + val bar: Int /* The comma before the comment should be removed without removing the comment itself */ ) """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaProperty to false) .hasLintViolations( LintViolation(1, 29, "Unnecessary trailing comma before \")\""), - LintViolation(3, 16, "Unnecessary trailing comma before \")\""), - LintViolation(6, 16, "Unnecessary trailing comma before \")\"") + LintViolation(3, 17, "Unnecessary trailing comma before \")\""), + LintViolation(6, 17, "Unnecessary trailing comma before \")\"") ).isFormattedAs(formattedCode) } @@ -275,27 +282,27 @@ class TrailingCommaRuleTest { """ data class Foo1(val bar: Int) data class Foo2( - val bar: Int // The comma should be inserted before the comment + val bar: Int // The comma should be inserted before the comment ) data class Foo3( - val bar: Int /* The comma should be inserted before the comment */ + val bar: Int /* The comma should be inserted before the comment */ ) """.trimIndent() val formattedCode = """ data class Foo1(val bar: Int) data class Foo2( - val bar: Int, // The comma should be inserted before the comment + val bar: Int, // The comma should be inserted before the comment ) data class Foo3( - val bar: Int, /* The comma should be inserted before the comment */ + val bar: Int, /* The comma should be inserted before the comment */ ) """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaProperty to true) .hasLintViolations( - LintViolation(3, 16, "Missing trailing comma before \")\""), - LintViolation(6, 16, "Missing trailing comma before \")\"") + LintViolation(3, 17, "Missing trailing comma before \")\""), + LintViolation(6, 17, "Missing trailing comma before \")\"") ).isFormattedAs(formattedCode) } @@ -307,11 +314,11 @@ class TrailingCommaRuleTest { class Foo2< A, B, // The comma before the comment should be removed without removing the comment itself - > {} + > {} class Foo3< A, B, /* The comma before the comment should be removed without removing the comment itself */ - > {} + > {} """.trimIndent() val formattedCode = """ @@ -319,11 +326,11 @@ class TrailingCommaRuleTest { class Foo2< A, B // The comma before the comment should be removed without removing the comment itself - > {} + > {} class Foo3< A, B /* The comma before the comment should be removed without removing the comment itself */ - > {} + > {} """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaProperty to false) @@ -342,11 +349,11 @@ class TrailingCommaRuleTest { class Foo2< A, B // The comma should be inserted before the comment - > {} + > {} class Foo3< A, B /* The comma should be inserted before the comment */ - > {} + > {} """.trimIndent() val formattedCode = """ @@ -354,11 +361,11 @@ class TrailingCommaRuleTest { class Foo2< A, B, // The comma should be inserted before the comment - > {} + > {} class Foo3< A, B, /* The comma should be inserted before the comment */ - > {} + > {} """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaProperty to true) @@ -528,13 +535,13 @@ class TrailingCommaRuleTest { """ val fooBar1: (Int, Int) -> Int = { foo, bar, -> foo * bar } val fooBar2: (Int, Int) -> Int = { - foo, - bar, // The comma before the comment should be removed without removing the comment itself + foo, + bar, // The comma before the comment should be removed without removing the comment itself -> foo * bar } val fooBar3: (Int, Int) -> Int = { - foo, - bar, /* The comma before the comment should be removed without removing the comment itself */ + foo, + bar, /* The comma before the comment should be removed without removing the comment itself */ -> foo * bar } """.trimIndent() @@ -542,13 +549,13 @@ class TrailingCommaRuleTest { """ val fooBar1: (Int, Int) -> Int = { foo, bar -> foo * bar } val fooBar2: (Int, Int) -> Int = { - foo, - bar // The comma before the comment should be removed without removing the comment itself + foo, + bar // The comma before the comment should be removed without removing the comment itself -> foo * bar } val fooBar3: (Int, Int) -> Int = { - foo, - bar /* The comma before the comment should be removed without removing the comment itself */ + foo, + bar /* The comma before the comment should be removed without removing the comment itself */ -> foo * bar } """.trimIndent() @@ -556,8 +563,8 @@ class TrailingCommaRuleTest { .withEditorConfigOverride(allowTrailingCommaProperty to false) .hasLintViolations( LintViolation(1, 44, "Unnecessary trailing comma before \"->\""), - LintViolation(4, 8, "Unnecessary trailing comma before \"->\""), - LintViolation(9, 8, "Unnecessary trailing comma before \"->\"") + LintViolation(4, 12, "Unnecessary trailing comma before \"->\""), + LintViolation(9, 12, "Unnecessary trailing comma before \"->\"") ).isFormattedAs(formattedCode) } @@ -567,13 +574,13 @@ class TrailingCommaRuleTest { """ val fooBar1: (Int, Int) -> Int = { foo, bar -> foo * bar } val fooBar2: (Int, Int) -> Int = { - foo, - bar // The comma should be inserted before the comment + foo, + bar // The comma should be inserted before the comment -> foo * bar } val fooBar3: (Int, Int) -> Int = { - foo, - bar /* The comma should be inserted before the comment */ + foo, + bar /* The comma should be inserted before the comment */ -> foo * bar } """.trimIndent() @@ -581,21 +588,21 @@ class TrailingCommaRuleTest { """ val fooBar1: (Int, Int) -> Int = { foo, bar -> foo * bar } val fooBar2: (Int, Int) -> Int = { - foo, - bar, // The comma should be inserted before the comment + foo, + bar, // The comma should be inserted before the comment -> foo * bar } val fooBar3: (Int, Int) -> Int = { - foo, - bar, /* The comma should be inserted before the comment */ + foo, + bar, /* The comma should be inserted before the comment */ -> foo * bar } """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaProperty to true) .hasLintViolations( - LintViolation(4, 8, "Missing trailing comma before \"->\""), - LintViolation(9, 8, "Missing trailing comma before \"->\"") + LintViolation(4, 12, "Missing trailing comma before \"->\""), + LintViolation(9, 12, "Missing trailing comma before \"->\"") ).isFormattedAs(formattedCode) } @@ -606,20 +613,20 @@ class TrailingCommaRuleTest { val list1: List = emptyList() val list2: List< String, // The comma before the comment should be removed without removing the comment itself - > = emptyList() + > = emptyList() val list3: List< String, /* The comma before the comment should be removed without removing the comment itself */ - > = emptyList() + > = emptyList() """.trimIndent() val formattedCode = """ val list1: List = emptyList() val list2: List< String // The comma before the comment should be removed without removing the comment itself - > = emptyList() + > = emptyList() val list3: List< String /* The comma before the comment should be removed without removing the comment itself */ - > = emptyList() + > = emptyList() """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaOnCallSiteProperty to false) @@ -637,20 +644,20 @@ class TrailingCommaRuleTest { val list1: List = emptyList() val list2: List< String // The comma should be inserted before the comment - > = emptyList() + > = emptyList() val list3: List< String /* The comma should be inserted before the comment */ - > = emptyList() + > = emptyList() """.trimIndent() val formattedCode = """ val list1: List = emptyList() val list2: List< String, // The comma should be inserted before the comment - > = emptyList() + > = emptyList() val list3: List< String, /* The comma should be inserted before the comment */ - > = emptyList() + > = emptyList() """.trimIndent() trailingCommaRuleAssertThat(code) .withEditorConfigOverride(allowTrailingCommaOnCallSiteProperty to true) @@ -898,9 +905,9 @@ class TrailingCommaRuleTest { val code = """ class Test { - var foo = Bar() - set(value) { - } + var foo = Bar() + set(value) { + } } """.trimIndent() trailingCommaRuleAssertThat(code) @@ -979,7 +986,7 @@ class TrailingCommaRuleTest { // was incorrectly seen as part of the type of variable "bar3" and a reference "EnumThree," (with the // trailing comma was added) which in turn resulted in not recognizing that the import of EnumThree actually // was used. - .addAdditionalFormattingRule(NoUnusedImportsRule()) + .addAdditionalRules(NoUnusedImportsRule()) .withEditorConfigOverride(allowTrailingCommaProperty to true) .hasLintViolation(9, 24, "Missing trailing comma before \")\"") .isFormattedAs(formattedCode) diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/IndentationRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/IndentationRuleTest.kt index 7149f5d146..a9a9e8e669 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/IndentationRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/IndentationRuleTest.kt @@ -2010,7 +2010,7 @@ internal class IndentationRuleTest { """.trimIndent() .replacePlaceholderWithStringTemplate() indentationRuleAssertThat(code) - .addAdditionalFormattingRule(WrappingRule()) + .addAdditionalRules(WrappingRule()) .hasLintViolations( LintViolation(3, 1, "Unexpected indentation (4) (should be 8)"), LintViolation(4, 1, "Unexpected indentation (4) (should be 8)") @@ -2048,7 +2048,7 @@ internal class IndentationRuleTest { } """.trimIndent() indentationRuleAssertThat(code) - .addAdditionalFormattingRule(WrappingRule()) + .addAdditionalRules(WrappingRule()) .hasLintViolations( LintViolation(5, 1, "Unexpected indent of multiline string closing quotes"), LintViolation(7, 1, "Unexpected indent of multiline string closing quotes") @@ -2088,7 +2088,7 @@ internal class IndentationRuleTest { """.trimIndent() .replacePlaceholderWithStringTemplate() indentationRuleAssertThat(code) - .addAdditionalFormattingRule(WrappingRule()) + .addAdditionalRules(WrappingRule()) .hasLintViolations( LintViolation(3, 1, "Unexpected indentation (0) (should be 8)"), LintViolation(4, 1, "Unexpected indentation (4) (should be 8)"), @@ -2669,7 +2669,7 @@ internal class IndentationRuleTest { } """.trimIndent() indentationRuleAssertThat(code) - .addAdditionalFormattingRule(WrappingRule()) + .addAdditionalRules(WrappingRule()) .hasLintViolations( LintViolation(2, 1, "Unexpected indentation (0) (should be 4)"), LintViolation(6, 1, "Unexpected indent of multiline string closing quotes") @@ -2730,7 +2730,7 @@ internal class IndentationRuleTest { } """.trimIndent() indentationRuleAssertThat(code) - .addAdditionalFormattingRule(WrappingRule()) + .addAdditionalRules(WrappingRule()) .hasLintViolation(6, 1, "Unexpected indent of multiline string closing quotes") .isFormattedAs(formattedCode) } @@ -2900,7 +2900,7 @@ internal class IndentationRuleTest { } """.trimIndent() indentationRuleAssertThat(code) - .addAdditionalFormattingRule(WrappingRule()) + .addAdditionalRules(WrappingRule()) .hasLintViolation(6, 1, "Unexpected indent of multiline string closing quotes") .isFormattedAs(formattedCode) } @@ -3720,6 +3720,34 @@ internal class IndentationRuleTest { indentationRuleAssertThat(code).hasNoLintViolations() } + @Disabled("To be fixed as code as lambda with parameters on multiple line") + @Test + fun `Given a function with lambda parameters on multiple lines then align the parameters`() { + val code = + """ + val fieldExample = + LongNameClass { paramA, + paramB, + paramC -> + ClassB(paramA, paramB, paramC) + } + """.trimIndent() + val formattedCode = + """ + val fieldExample = + LongNameClass { paramA, + paramB, + paramC -> + ClassB(paramA, paramB, paramC) + } + """.trimIndent() + indentationRuleAssertThat(code) + .hasLintViolations( + LintViolation(3, 1, "Unexpected indentation (12) (should be 20)"), + LintViolation(4, 1, "Unexpected indentation (12) (should be 20)") + ).isFormattedAs(formattedCode) + } + private companion object { val INDENT_STYLE_TAB = indentStyleProperty to PropertyType.IndentStyleValue.tab } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/ParameterListWrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/ParameterListWrappingRuleTest.kt index a85cc165aa..71b5c245a8 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/ParameterListWrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/ParameterListWrappingRuleTest.kt @@ -11,13 +11,9 @@ class ParameterListWrappingRuleTest { private val parameterListWrappingRuleAssertThat = ParameterListWrappingRule() .assertThat( - additionalFormattingRules = listOf( - // In case a parameter is wrapped to a separate line by the ParameterListWrappingRule() then its - // indentation might still be incorrect until the IndentationRule has fixed it. Apply the - // IndentationRule format after the ParameterListWrappingRule(), so that the formattedCode in the - /* unit test looks correct. Note that the Lint Violations of the rule are suppressed!.*/ - IndentationRule() - ) + // Apply the IndentationRule always as additional rule, so that the formattedCode in the unit test looks + // correct. + IndentationRule() ) @Test @@ -182,13 +178,17 @@ class ParameterListWrappingRuleTest { val code = """ val fieldExample = - LongNameClass { paramA, - paramB, - paramC -> - ClassB(paramA, paramB, paramC) - } + LongNameClass { paramA, + paramB, + paramC -> + ClassB(paramA, paramB, paramC) + } """.trimIndent() - parameterListWrappingRuleAssertThat(code).hasNoLintViolations() + val parameterListWrappingRuleWithoutIndentationRule = ParameterListWrappingRule().assertThat() + parameterListWrappingRuleWithoutIndentationRule(code).hasNoLintViolations() + // IndentationRule does alter the code while the code is accepted by the Default IDEA formatter. So statement + // below would fail! + // parameterListWrappingRuleAssertThat(code).hasNoLintViolations() } @Test @@ -340,11 +340,11 @@ class ParameterListWrappingRuleTest { val code = """ data class A( - /* - * comment - */ - // - var v: String + /* + * comment + */ + // + var v: String ) """.trimIndent() parameterListWrappingRuleAssertThat(code).hasNoLintViolations() diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt index 5c700673f2..30b512430a 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/StringTemplateRuleTest.kt @@ -350,7 +350,7 @@ class StringTemplateRuleTest { } """.trimIndent() stringTemplateRuleAssertThat(code) - .addAdditionalFormattingRule(NoUnusedImportsRule()) + .addAdditionalRules(NoUnusedImportsRule()) .hasLintViolation(3, 21, "Redundant \"toString()\" call in string template") .isFormattedAs(formattedCode) } diff --git a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/WrappingRuleTest.kt b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/WrappingRuleTest.kt index f707770346..982c87dba6 100644 --- a/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/WrappingRuleTest.kt +++ b/ktlint-ruleset-standard/src/test/kotlin/com/pinterest/ktlint/ruleset/standard/WrappingRuleTest.kt @@ -42,7 +42,7 @@ internal class WrappingRuleTest { """.trimIndent() .replacePlaceholderWithStringTemplate() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 13, "Missing newline after \"(\""), LintViolation(4, 6, "Missing newline before \")\"") @@ -80,7 +80,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 13, "Missing newline after \"(\""), LintViolation(3, 7, "Missing newline before \")\""), @@ -124,7 +124,7 @@ internal class WrappingRuleTest { """.trimIndent() .replacePlaceholderWithStringTemplate() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 10, "Missing newline after \"(\""), LintViolation(8, 6, "Missing newline before \"\"\""), @@ -158,7 +158,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 9, "Missing newline after \"(\""), LintViolation(6, 30, "Missing newline before \")\"") @@ -191,7 +191,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(2, 11, "Missing newline after \"(\""), LintViolation(2, 49, "Missing newline after \",\""), @@ -230,7 +230,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(1, 10, "Missing newline after \"(\""), LintViolation(1, 33, "Missing newline after \",\""), @@ -272,7 +272,7 @@ internal class WrappingRuleTest { } """.trimIndent() wrappingRuleAssertThat(code) - .addAdditionalFormattingRule(IndentationRule()) + .addAdditionalRules(IndentationRule()) .hasLintViolations( LintViolation(6, 8, "Missing newline after \"(\""), LintViolation(8, 8, "Missing newline before \")\"") diff --git a/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/KtLintAssertThat.kt b/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/KtLintAssertThat.kt index 35e7af06dc..4a2c5d6a99 100644 --- a/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/KtLintAssertThat.kt +++ b/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/KtLintAssertThat.kt @@ -31,9 +31,19 @@ import org.assertj.core.api.Assertions.assertThat @OptIn(FeatureInAlphaState::class) @Suppress("MemberVisibilityCanBePrivate") public class KtLintAssertThat( + /** + * The rule which is the subject of the test, e.g. the rule for which the AssertThat is created. + */ private val rule: Rule, + /** + * The code which is to be linted and formatted. + */ private val code: String, - private val additionalFormattingRules: MutableSet + /** + * The rules which have to be executed in addition to the main rule when linting/formatting the code. Note that + * lint errors for those rules are suppressed. + */ + private val additionalRules: MutableSet ) { private var filePath: String? = null private var kotlinScript = false @@ -99,11 +109,12 @@ public class KtLintAssertThat( } /** - * Adds a rule to be executed when formatting the code. This can to be used to unit test rules which are best to be - * tested in conjunction, for example wrapping and indenting. This method can be called multiple times if needed. + * Adds a rule to be executed when linting/formatting the code. This can to be used to unit test rules which are + * best to be tested in conjunction, for example wrapping and indenting. This method can be called multiple times if + * needed. */ - public fun addAdditionalFormattingRule(vararg rules: Rule): KtLintAssertThat { - additionalFormattingRules.addAll(rules) + public fun addAdditionalRules(vararg rules: Rule): KtLintAssertThat { + additionalRules.addAll(rules) return this } @@ -120,8 +131,8 @@ public class KtLintAssertThat( * * Note: When linting succeeds without errors, formatting is also checked. */ - public fun hasNoLintViolationsExceptInAdditionalFormattingRules(): KtLintAssertThatAssertable = - ktLintAssertThatAssertable().hasNoLintViolationsExceptInAdditionalFormattingRules() + public fun hasNoLintViolationsExceptInAdditionalRules(): KtLintAssertThatAssertable = + ktLintAssertThatAssertable().hasNoLintViolationsExceptInAdditionalRules() /** * Asserts that the code does contain given [LintViolation] which automatically can be corrected. This is a sugar @@ -172,7 +183,7 @@ public class KtLintAssertThat( filePath = filePath, kotlinScript = kotlinScript, editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, - additionalFormattingRules = additionalFormattingRules.toList() + additionalRules = additionalRules.toList() ) } else { KtLintAssertThatAssertable( @@ -181,20 +192,20 @@ public class KtLintAssertThat( filePath = filePath, kotlinScript = kotlinScript, editorConfigOverride = EditorConfigOverride.from(*editorConfigProperties.toTypedArray()), - additionalFormattingRules = additionalFormattingRules.toList() + additionalRules = additionalRules.toList() ) } public companion object { /** * Creates an assertThat assertion function for a given rule. This assertion function has extensions - * specifically for testing KtLint rules. The [additionalFormattingRules] are only executed during the format + * specifically for testing KtLint rules. The [additionalRules] are only executed during the format * phase of the test. This means that the unit test only has to check the lint violations thrown by the rule for * which the assertThat is created. But the code is formatted by both the rule and the - * [additionalFormattingRules] in the order as defined by the rule definitions. + * [additionalRules] in the order as defined by the rule definitions. */ - public fun Rule.assertThat(additionalFormattingRules: List = emptyList()): (String) -> KtLintAssertThat = - { code -> KtLintAssertThat(this, code, additionalFormattingRules.toMutableSet()) } + public fun Rule.assertThat(vararg additionalRules: Rule): (String) -> KtLintAssertThat = + { code -> KtLintAssertThat(this, code, additionalRules.toMutableSet()) } /** * See [setMaxLineLength] for intended usage. @@ -215,14 +226,17 @@ public class KtLintAssertThat( */ @OptIn(FeatureInAlphaState::class) public class KtLintAssertThatAssertable( - /** The rule for which the AssertThat is created. */ + /** The rule which is the subject of the test, e.g. the rule for which the AssertThat is created. */ private val rule: Rule, private val code: String, private val filePath: String?, private val kotlinScript: Boolean, private val editorConfigOverride: EditorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, - /** The rules which have to be executed in addition to the main rule when formatting the code. */ - private val additionalFormattingRules: List + /** + * The rules which have to be executed in addition to the main rule when linting/formatting the code. Note that + * lint errors for those rules are suppressed. + */ + private val additionalRules: List ) : AbstractAssert(code, KtLintAssertThatAssertable::class.java) { /** @@ -234,7 +248,7 @@ public class KtLintAssertThatAssertable( assertThat(lint()).isEmpty() // Also format the code to be absolutely sure that codes does not get changed - val actualFormattedCode = format(ignoreAdditionalRules = true) + val actualFormattedCode = format() assertThat(actualFormattedCode) .describedAs("Code is changed by format while no lint errors were found") @@ -252,9 +266,9 @@ public class KtLintAssertThatAssertable( * other, a unit test cal still verify that code is formatted correctly even when the rule under test is not * violated. */ - public fun hasNoLintViolationsExceptInAdditionalFormattingRules(): KtLintAssertThatAssertable { - check(additionalFormattingRules.isNotEmpty()) { - "hasNoLintViolationsExceptInAdditionalFormattingRules can only be used when additional formatting rules have been added" + public fun hasNoLintViolationsExceptInAdditionalRules(): KtLintAssertThatAssertable { + check(additionalRules.isNotEmpty()) { + "hasNoLintViolationsExceptInAdditionalRules can only be used when additional rules have been added" } assertThat(lint()).isEmpty() @@ -300,7 +314,7 @@ public class KtLintAssertThatAssertable( "Use '.hasNoLintErrors()' instead of '.isFormattedAs()'" } - val actualFormattedCode = format(false) + val actualFormattedCode = format() assertThat(actualFormattedCode) .describedAs("Code is formatted as") @@ -332,7 +346,7 @@ public class KtLintAssertThatAssertable( public fun hasLintViolationsWithoutAutocorrect(vararg expectedLintViolations: LintViolation) { check(expectedLintViolations.isNotEmpty()) - val actualLintViolationFields = lint(runFormatBeforeLint = true).toLintViolationsFieldsForCurrentRuleOnly() + val actualLintViolationFields = lint().toLintViolationsFieldsForCurrentRuleOnly() assertThat(actualLintViolationFields) .describedAs("Lint errors which can not be automatically corrected") @@ -361,38 +375,31 @@ public class KtLintAssertThatAssertable( ) }.toTypedArray() - private fun lint(runFormatBeforeLint: Boolean = false): List { - // Lint is only done with the rule for which the assertThat is created. In that way the unit test only has to - // check for violations caused by that rule. + private fun lint(): List { return listOf(rule) + // Also run the additional rules as the main rule might have a VisitorModifier which requires one or more of + // the additional rules to be loaded and enabled as well. + .plus(additionalRules) .lint( lintedFilePath = filePath, script = kotlinScript, - text = if (runFormatBeforeLint) { - format(false) - } else { - code - }, + text = code, editorConfigOverride = editorConfigOverride ) + // Remove all lint errors caused by the additional rule so that the unit test is only able to verify the + // lint errors caused by the main rule. + .filter { it.ruleId == rule.id } } - private fun format(ignoreAdditionalRules: Boolean): String { - val formattingRules = - if (ignoreAdditionalRules) { - listOf(rule) - } else { - // Formatting is done on the rule for which the assertThat is created plus the additional rules. In this way it - // is easier to test code which is formatted by closely related rules (for example wrapping and indent). - listOf(rule) + additionalFormattingRules - } - return formattingRules.format( - lintedFilePath = filePath, - script = kotlinScript, - text = code, - editorConfigOverride = editorConfigOverride - ) - } + private fun format(): String = + listOf(rule) + .plus(additionalRules) + .format( + lintedFilePath = filePath, + script = kotlinScript, + text = code, + editorConfigOverride = editorConfigOverride + ) /* Representation of the field of the [LintError] that should be identical. Note that no comparison can be made * against the original [LintError] as the [canBeAutoCorrected] flag is excluded from the hashcode. diff --git a/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/RuleExtension.kt b/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/RuleExtension.kt index 99d1694d9e..d7c0daf397 100644 --- a/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/RuleExtension.kt +++ b/ktlint-test/src/main/kotlin/com/pinterest/ktlint/test/RuleExtension.kt @@ -61,16 +61,10 @@ private fun List.toRuleSets(): List { ) ) } - return listOfNotNull( - dumpAstRuleSet, - RuleSet( - // RuleSet id is always set to "standard" as this has the side effect that the ruleset id will - // be excluded from the ruleId in the LintError which makes the unit tests of the experimental - // rules easier to maintain as they will not contain the reference to the ruleset id. - "standard", - *toTypedArray() - ) - ) + return this + .groupBy { it.id.substringBefore(":", "standard") } + .map { (ruleSetId, rules) -> RuleSet(ruleSetId, *rules.toTypedArray()) } + .plus(listOfNotNull(dumpAstRuleSet)) } /** @@ -233,10 +227,7 @@ public fun List.lint( experimentalParams, VisitorProvider( ruleSets = experimentalParams.ruleSets, - debug = experimentalParams.debug, - // When running unit tests, some VisitorModifiers have to be ignored. For example the RunAfterRule modifier - // should not be checked, if other that rule can only be tested together with the rule on which it depends. - isUnitTestContext = true + debug = experimentalParams.debug ) ) return res @@ -399,10 +390,7 @@ public fun List.format( experimentalParams, VisitorProvider( ruleSets = experimentalParams.ruleSets, - debug = experimentalParams.debug, - // When running unit tests, some VisitorModifiers have to be ignored. For example the RunAfterRule modifier - // should not be checked, if other that rule can only be tested together with the rule on which it depends. - isUnitTestContext = true + debug = experimentalParams.debug ) ) }