diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestResources.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestResources.kt index d1f97b6a74..9cacd40b54 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestResources.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestResources.kt @@ -978,4 +978,103 @@ internal object IndentationRuleTestResources { val parenthesesSurroundedInfixExpressions = mapOf( false to parenthesesSurroundedInfixExpressionsSingleIndent, true to parenthesesSurroundedInfixExpressionsContinuationIndent) + + @Language("kotlin") + @Suppress("COMMENT_WHITE_SPACE") + private val ifExpressionsSingleIndent = arrayOf( + /*- + * #1351, case 1. + * + * Boolean operator priority (`&&` has higher priority than `||`). + * + * Currently, this is an incorrectly formatted code kept to detect the + * contract breakage. It will be re-formatted once the issue is fixed. + */ + """ + |fun f1() { + | if (valueParameterNode.parents().none { it.elementType == PRIMARY_CONSTRUCTOR } || + | !valueParameterNode.hasChildOfType(VAL_KEYWORD) && + | !valueParameterNode.hasChildOfType(VAR_KEYWORD) + | ) { + | return + | } + |} + """.trimMargin(), + + /*- + * #1351, case 2. + * + * IDEA combines the values of `CONTINUATION_INDENT_IN_IF_CONDITIONS` + * and `CONTINUATION_INDENT_FOR_CHAINED_CALLS`, so the resulting indent + * can be anything between 8 (2x) and 16 (4x). + * + * Currently, this is an incorrectly formatted code kept to detect the + * contract breakage. It will be re-formatted once the issue is fixed. + */ + """ + |fun f2() { + | val prevComment = if (valueParameterNode.siblings(forward = false) + | .takeWhile { it.elementType != EOL_COMMENT && it.elementType != BLOCK_COMMENT } + | .all { it.elementType == WHITE_SPACE } + | ) { + | 0 + | } else { + | 1 + | } + |} + """.trimMargin(), + ) + + @Language("kotlin") + @Suppress("COMMENT_WHITE_SPACE") + private val ifExpressionsContinuationIndent = arrayOf( + /*- + * #1351, case 1. + * + * Boolean operator priority (`&&` has higher priority than `||`). + * + * Currently, this is an incorrectly formatted code kept to detect the + * contract breakage. It will be re-formatted once the issue is fixed. + */ + """ + |fun f1() { + | if (valueParameterNode.parents().none { it.elementType == PRIMARY_CONSTRUCTOR } || + | !valueParameterNode.hasChildOfType(VAL_KEYWORD) && + | !valueParameterNode.hasChildOfType(VAR_KEYWORD) + | ) { + | return + | } + |} + """.trimMargin(), + + /*- + * #1351, case 2. + * + * IDEA combines the values of `CONTINUATION_INDENT_IN_IF_CONDITIONS` + * and `CONTINUATION_INDENT_FOR_CHAINED_CALLS`, so the resulting indent + * can be anything between 8 (2x) and 16 (4x). + * + * Currently, this is an incorrectly formatted code kept to detect the + * contract breakage. It will be re-formatted once the issue is fixed. + */ + """ + |fun f2() { + | val prevComment = if (valueParameterNode.siblings(forward = false) + | .takeWhile { it.elementType != EOL_COMMENT && it.elementType != BLOCK_COMMENT } + | .all { it.elementType == WHITE_SPACE } + | ) { + | 0 + | } else { + | 1 + | } + |} + """.trimMargin(), + ) + + /** + * `if`-expression examples. + */ + val ifExpressions = mapOf( + false to ifExpressionsSingleIndent, + true to ifExpressionsContinuationIndent) } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleWarnTest.kt index f5037e4f57..2892cfde57 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleWarnTest.kt @@ -10,11 +10,11 @@ import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.describe import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.withCustomParameters import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionBodyFunctions import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionsWrappedAfterOperator +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.ifExpressions import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.parenthesesSurroundedInfixExpressions import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationRule import org.cqfn.diktat.util.LintTestBase - import com.pinterest.ktlint.core.LintError import generated.WarningNames import org.assertj.core.api.AbstractSoftAssertions @@ -29,7 +29,6 @@ import org.junit.jupiter.api.TestMethodOrder import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource import org.opentest4j.MultipleFailuresError - import java.util.function.Consumer @Suppress("LargeClass") @@ -936,4 +935,42 @@ class IndentationRuleWarnTest : LintTestBase(::IndentationRule) { } } } + + @Nested + @TestMethodOrder(DisplayName::class) + inner class `If expressions` { + @ParameterizedTest(name = "extendedIndentAfterOperators = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `should be properly indented`(extendedIndentAfterOperators: Boolean) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators) + + lintMultipleMethods( + ifExpressions[extendedIndentAfterOperators].assertNotNull(), + lintErrors = emptyArray(), + customConfig.asRulesConfigList() + ) + } + + @ParameterizedTest(name = "extendedIndentAfterOperators = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `should be reported if mis-indented`(extendedIndentAfterOperators: Boolean) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators) + + assertSoftly { softly -> + ifExpressions[!extendedIndentAfterOperators].assertNotNull().forEach { code -> + softly.assertThat(lintResult(code, customConfig.asRulesConfigList())) + .describedAs("lint result for ${code.describe()}") + .hasSizeBetween(0, 3).allSatisfy(Consumer { lintError -> + assertThat(lintError.ruleId).describedAs("ruleId").isEqualTo(ruleId) + assertThat(lintError.canBeAutoCorrected).describedAs("canBeAutoCorrected").isTrue + assertThat(lintError.detail).matches(warnTextRegex) + }) + } + } + } + } }