diff --git a/diktat-analysis.yml b/diktat-analysis.yml index 5ffd63d5e0..d91b1f999d 100644 --- a/diktat-analysis.yml +++ b/diktat-analysis.yml @@ -282,6 +282,9 @@ # Checks that backticks (``) are not used in the identifier name, except the case when it is test method (marked with @Test annotation) - name: BACKTICKS_PROHIBITED enabled: true + # all code blocks annotated with @Nested, @ParameterizedTest (JUnit 5) will + # be ignored and not checked. + ignoreAnnotated: [ Nested, ParameterizedTest ] # Checks that a single line concatenation of strings is not used - name: STRING_CONCATENATION enabled: true diff --git a/diktat-rules/pom.xml b/diktat-rules/pom.xml index 20788abcd9..c19b5e5505 100644 --- a/diktat-rules/pom.xml +++ b/diktat-rules/pom.xml @@ -69,6 +69,11 @@ junit-jupiter test + + org.junit.platform + junit-platform-suite-engine + test + org.assertj assertj-core diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt index 13dd478017..671b12d262 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleFixTest.kt @@ -1,6 +1,18 @@ package org.cqfn.diktat.ruleset.chapter3.spaces import org.cqfn.diktat.common.config.rules.RulesConfig +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.IndentationConfig +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.asRulesConfigList +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.asSequenceWithConcatenation +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.describe +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.extendedIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.withCustomParameters +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionBodyFunctionsContinuationIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionBodyFunctionsSingleIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionsWrappedAfterOperatorContinuationIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionsWrappedAfterOperatorSingleIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.whitespaceInStringLiteralsContinuationIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.whitespaceInStringLiteralsSingleIndent import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationRule import org.cqfn.diktat.util.FixTestBase @@ -8,15 +20,18 @@ import org.cqfn.diktat.util.FixTestBase import generated.WarningNames import org.assertj.core.api.SoftAssertions.assertSoftly import org.intellij.lang.annotations.Language -import org.junit.jupiter.api.MethodOrderer.MethodName +import org.junit.jupiter.api.MethodOrderer.DisplayName +import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestMethodOrder import org.junit.jupiter.api.io.TempDir +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource import java.nio.file.Path -@TestMethodOrder(MethodName::class) +@TestMethodOrder(DisplayName::class) class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", ::IndentationRule, listOf( @@ -30,7 +45,7 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", ) ) ) -), IndentationRuleTestMixin { +) { @Test @Tag(WarningNames.WRONG_INDENTATION) fun `parameters should be properly aligned`() { @@ -61,138 +76,6 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", fixAndCompare("MultilionStringExpected.kt", "MultilionStringTest.kt") } - /** - * This test has a counterpart under [IndentationRuleWarnTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should remain unchanged if properly indented (extendedIndentAfterOperators = true)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to true) - - lintMultipleMethods( - expressionBodyFunctionsContinuationIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * This test has a counterpart under [IndentationRuleWarnTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should remain unchanged if properly indented (extendedIndentAfterOperators = false)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to false) - - lintMultipleMethods( - expressionBodyFunctionsSingleIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * This test has a counterpart under [IndentationRuleWarnTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should be reformatted if mis-indented (extendedIndentAfterOperators = true)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to true) - - lintMultipleMethods( - actualContent = expressionBodyFunctionsSingleIndent, - expectedContent = expressionBodyFunctionsContinuationIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * This test has a counterpart under [IndentationRuleWarnTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should be reformatted if mis-indented (extendedIndentAfterOperators = false)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to false) - - lintMultipleMethods( - actualContent = expressionBodyFunctionsContinuationIndent, - expectedContent = expressionBodyFunctionsSingleIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * See [#1347](https://github.com/saveourtool/diktat/issues/1347). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `no whitespace should be injected into multi-line string literals (code matches settings, extendedIndent = true)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters(*extendedIndent(enabled = true)) - - lintMultipleMethods( - whitespaceInStringLiteralsContinuationIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * See [#1347](https://github.com/saveourtool/diktat/issues/1347). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `no whitespace should be injected into multi-line string literals (code matches settings, extendedIndent = false)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters(*extendedIndent(enabled = false)) - - lintMultipleMethods( - whitespaceInStringLiteralsSingleIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * See [#1347](https://github.com/saveourtool/diktat/issues/1347). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `no whitespace should be injected into multi-line string literals (mis-indented code reformatted, extendedIndent = true)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters(*extendedIndent(enabled = true)) - - lintMultipleMethods( - actualContent = whitespaceInStringLiteralsSingleIndent, - expectedContent = whitespaceInStringLiteralsContinuationIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - - /** - * See [#1347](https://github.com/saveourtool/diktat/issues/1347). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `no whitespace should be injected into multi-line string literals (mis-indented code reformatted, extendedIndent = false)`(@TempDir tempDir: Path) { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters(*extendedIndent(enabled = false)) - - lintMultipleMethods( - actualContent = whitespaceInStringLiteralsContinuationIndent, - expectedContent = whitespaceInStringLiteralsSingleIndent, - tempDir = tempDir, - rulesConfigList = customConfig.asRulesConfigList()) - } - /** * @param actualContent the original file content (may well be modified as * fixes are applied). @@ -230,4 +113,148 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation", } } } + + /** + * See [#1330](https://github.com/saveourtool/diktat/issues/1330). + */ + @Nested + @TestMethodOrder(DisplayName::class) + inner class `Expression body functions` { + @ParameterizedTest(name = "extendedIndentAfterOperators = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `should remain unchanged if properly indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators) + + val expressionBodyFunctions = when { + extendedIndentAfterOperators -> expressionBodyFunctionsContinuationIndent + else -> expressionBodyFunctionsSingleIndent + } + + lintMultipleMethods( + expressionBodyFunctions, + tempDir = tempDir, + rulesConfigList = customConfig.asRulesConfigList()) + } + + @ParameterizedTest(name = "extendedIndentAfterOperators = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `should be reformatted if mis-indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators) + + val expressionBodyFunctionsActual = when { + extendedIndentAfterOperators -> expressionBodyFunctionsSingleIndent + else -> expressionBodyFunctionsContinuationIndent + } + val expressionBodyFunctionsExpected = when { + extendedIndentAfterOperators -> expressionBodyFunctionsContinuationIndent + else -> expressionBodyFunctionsSingleIndent + } + + lintMultipleMethods( + actualContent = expressionBodyFunctionsActual, + expectedContent = expressionBodyFunctionsExpected, + tempDir = tempDir, + rulesConfigList = customConfig.asRulesConfigList()) + } + } + + /** + * See [#1347](https://github.com/saveourtool/diktat/issues/1347). + */ + @Nested + @TestMethodOrder(DisplayName::class) + inner class `Multi-line string literals` { + @ParameterizedTest(name = "extendedIndent = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `no whitespace should be injected (code matches settings)`(extendedIndent: Boolean, @TempDir tempDir: Path) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters(*extendedIndent(enabled = extendedIndent)) + + val whitespaceInStringLiterals = when { + extendedIndent -> whitespaceInStringLiteralsContinuationIndent + else -> whitespaceInStringLiteralsSingleIndent + } + + lintMultipleMethods( + whitespaceInStringLiterals, + tempDir = tempDir, + rulesConfigList = customConfig.asRulesConfigList()) + } + + @ParameterizedTest(name = "extendedIndent = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `no whitespace should be injected (mis-indented code reformatted)`(extendedIndent: Boolean, @TempDir tempDir: Path) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters(*extendedIndent(enabled = extendedIndent)) + + val whitespaceInStringLiteralsActual = when { + extendedIndent -> whitespaceInStringLiteralsSingleIndent + else -> whitespaceInStringLiteralsContinuationIndent + } + val whitespaceInStringLiteralsExpected = when { + extendedIndent -> whitespaceInStringLiteralsContinuationIndent + else -> whitespaceInStringLiteralsSingleIndent + } + + lintMultipleMethods( + actualContent = whitespaceInStringLiteralsActual, + expectedContent = whitespaceInStringLiteralsExpected, + tempDir = tempDir, + rulesConfigList = customConfig.asRulesConfigList()) + } + } + + /** + * See [#1340](https://github.com/saveourtool/diktat/issues/1340). + */ + @Nested + @TestMethodOrder(DisplayName::class) + inner class `Expressions wrapped after operator` { + @ParameterizedTest(name = "extendedIndentAfterOperators = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `should be properly indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators) + + val expressionsWrappedAfterOperator = when { + extendedIndentAfterOperators -> expressionsWrappedAfterOperatorContinuationIndent + else -> expressionsWrappedAfterOperatorSingleIndent + } + + lintMultipleMethods( + expressionsWrappedAfterOperator, + tempDir = tempDir, + rulesConfigList = customConfig.asRulesConfigList()) + } + + @ParameterizedTest(name = "extendedIndentAfterOperators = {0}") + @ValueSource(booleans = [false, true]) + @Tag(WarningNames.WRONG_INDENTATION) + fun `should be reformatted if mis-indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) { + val defaultConfig = IndentationConfig("newlineAtEnd" to false) + val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators) + + val expressionsWrappedAfterOperatorActual = when { + extendedIndentAfterOperators -> expressionsWrappedAfterOperatorSingleIndent + else -> expressionsWrappedAfterOperatorContinuationIndent + } + val expressionsWrappedAfterOperatorExpected = when { + extendedIndentAfterOperators -> expressionsWrappedAfterOperatorContinuationIndent + else -> expressionsWrappedAfterOperatorSingleIndent + } + + lintMultipleMethods( + actualContent = expressionsWrappedAfterOperatorActual, + expectedContent = expressionsWrappedAfterOperatorExpected, + tempDir = tempDir, + rulesConfigList = customConfig.asRulesConfigList()) + } + } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTest.kt new file mode 100644 index 0000000000..55a1d92ded --- /dev/null +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTest.kt @@ -0,0 +1,10 @@ +package org.cqfn.diktat.ruleset.chapter3.spaces + +import org.junit.platform.suite.api.SelectClasses +import org.junit.platform.suite.api.Suite + +@Suite +@SelectClasses( + IndentationRuleWarnTest::class, + IndentationRuleFixTest::class) +class IndentationRuleTest diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestMixin.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestMixin.kt index ff4263716f..81fcb2df33 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestMixin.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestMixin.kt @@ -3,9 +3,6 @@ package org.cqfn.diktat.ruleset.chapter3.spaces import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig -import org.intellij.lang.annotations.Language - -import java.lang.Boolean.getBoolean as getBooleanProperty /** * Code shared by [IndentationRuleWarnTest] and [IndentationRuleFixTest]. @@ -13,333 +10,7 @@ import java.lang.Boolean.getBoolean as getBooleanProperty * @see IndentationRuleWarnTest * @see IndentationRuleFixTest */ -internal interface IndentationRuleTestMixin { - /** - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - * - * @see expressionBodyFunctionsContinuationIndent - */ - @Suppress("CUSTOM_GETTERS_SETTERS") - val expressionBodyFunctionsSingleIndent: Array - @Language("kotlin") - get() = - arrayOf( - """ - |@Test - |fun `checking that suppression with ignore everything works`() { - | val code = - | ""${'"'} - | @Suppress("diktat") - | fun foo() { - | val a = 1 - | } - | ""${'"'}.trimIndent() - | lintMethod(code) - |} - """.trimMargin(), - - """ - |val currentTime: Time - | get() = - | with(currentDateTime) { - | Time(hour = hour, minute = minute, second = second) - | } - """.trimMargin(), - - """ - |fun formatDateByPattern(date: String, pattern: String = "ddMMyy"): String = - | DateTimeFormatter.ofPattern(pattern).format(LocalDate.parse(date)) - """.trimMargin(), - - """ - |private fun createLayoutParams(): WindowManager.LayoutParams = - | WindowManager.LayoutParams().apply { /* ... */ } - """.trimMargin(), - - """ - |private fun createLayoutParams(): WindowManager.LayoutParams = - | WindowManager.LayoutParams().apply { - | type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL - | token = composeView.applicationWindowToken - | width = WindowManager.LayoutParams.MATCH_PARENT - | height = WindowManager.LayoutParams.MATCH_PARENT - | format = PixelFormat.TRANSLUCENT - | - | // TODO make composable configurable - | - | // see https://stackoverflow.com/questions/43511326/android-making-activity-full-screen-with-status-bar-on-top-of-it - | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - | windowInsetsController?.hide(WindowInsets.Type.statusBars()) - | } else { - | @Suppress("DEPRECATION") - | systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE or - | View.SYSTEM_UI_FLAG_FULLSCREEN or - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) - | } - | } - """.trimMargin(), - - """ - |val offsetDelta = - | if (shimmerAnimationType != ShimmerAnimationType.FADE) translateAnim.dp - | else 2000.dp - """.trimMargin(), - - """ - |private fun lerp(start: Float, stop: Float, fraction: Float): Float = - | (1 - fraction) * start + fraction * stop - """.trimMargin(), - - """ - |fun foo() = - | println() - """.trimMargin(), - ) - - /** - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - * - * @see expressionBodyFunctionsSingleIndent - */ - @Suppress("CUSTOM_GETTERS_SETTERS") - val expressionBodyFunctionsContinuationIndent: Array - @Language("kotlin") - get() = - arrayOf( - """ - |@Test - |fun `checking that suppression with ignore everything works`() { - | val code = - | ""${'"'} - | @Suppress("diktat") - | fun foo() { - | val a = 1 - | } - | ""${'"'}.trimIndent() - | lintMethod(code) - |} - """.trimMargin(), - - """ - |val currentTime: Time - | get() = - | with(currentDateTime) { - | Time(hour = hour, minute = minute, second = second) - | } - """.trimMargin(), - - """ - |fun formatDateByPattern(date: String, pattern: String = "ddMMyy"): String = - | DateTimeFormatter.ofPattern(pattern).format(LocalDate.parse(date)) - """.trimMargin(), - - """ - |private fun createLayoutParams(): WindowManager.LayoutParams = - | WindowManager.LayoutParams().apply { /* ... */ } - """.trimMargin(), - - """ - |private fun createLayoutParams(): WindowManager.LayoutParams = - | WindowManager.LayoutParams().apply { - | type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL - | token = composeView.applicationWindowToken - | width = WindowManager.LayoutParams.MATCH_PARENT - | height = WindowManager.LayoutParams.MATCH_PARENT - | format = PixelFormat.TRANSLUCENT - | - | // TODO make composable configurable - | - | // see https://stackoverflow.com/questions/43511326/android-making-activity-full-screen-with-status-bar-on-top-of-it - | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - | windowInsetsController?.hide(WindowInsets.Type.statusBars()) - | } else { - | @Suppress("DEPRECATION") - | systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE or - | View.SYSTEM_UI_FLAG_FULLSCREEN or - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) - | } - | } - """.trimMargin(), - - """ - |val offsetDelta = - | if (shimmerAnimationType != ShimmerAnimationType.FADE) translateAnim.dp - | else 2000.dp - """.trimMargin(), - - """ - |private fun lerp(start: Float, stop: Float, fraction: Float): Float = - | (1 - fraction) * start + fraction * stop - """.trimMargin(), - - """ - |fun foo() = - | println() - """.trimMargin(), - ) - - /** - * See [#1347](https://github.com/saveourtool/diktat/issues/1347). - * - * @see whitespaceInStringLiteralsContinuationIndent - */ - @Suppress("CUSTOM_GETTERS_SETTERS") - val whitespaceInStringLiteralsSingleIndent: Array - @Language("kotlin") - get() = - arrayOf( - """ - |@Test - |fun `test method name`() { - | @Language("kotlin") - | val code = - | ""${'"'} - | @Suppress("diktat") - | fun foo() { - | val a = 1 - | } - | ""${'"'}.trimIndent() - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun f0() { - | @Language("kotlin") - | val code = - | ""${'"'} - | |@Suppress("diktat") - | |fun foo() { - | | val a = 1 - | |} - | ""${'"'}.trimMargin() - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun f1() { - | @Language("kotlin") - | val code = - | ""${'"'} - | |@Suppress("diktat") - | |fun foo() { - | | val a = 1 - | |} - | ""${'"'}.trimMargin("|") - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun f2() { - | @Language("kotlin") - | val code = - | ""${'"'} - | >@Suppress("diktat") - | >fun foo() { - | > val a = 1 - | >} - | ""${'"'} . trimMargin ( marginPrefix = ">" ) - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun checkScript() { - | lintMethod( - | ""${'"'} - | |val A = "aa" - | ""${'"'}.trimMargin(), - | ) - |} - """.trimMargin(), - ) - - /** - * See [#1347](https://github.com/saveourtool/diktat/issues/1347). - * - * @see whitespaceInStringLiteralsSingleIndent - */ - @Suppress("CUSTOM_GETTERS_SETTERS") - val whitespaceInStringLiteralsContinuationIndent: Array - @Language("kotlin") - get() = - arrayOf( - """ - |@Test - |fun `test method name`() { - | @Language("kotlin") - | val code = - | ""${'"'} - | @Suppress("diktat") - | fun foo() { - | val a = 1 - | } - | ""${'"'}.trimIndent() - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun f0() { - | @Language("kotlin") - | val code = - | ""${'"'} - | |@Suppress("diktat") - | |fun foo() { - | | val a = 1 - | |} - | ""${'"'}.trimMargin() - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun f1() { - | @Language("kotlin") - | val code = - | ""${'"'} - | |@Suppress("diktat") - | |fun foo() { - | | val a = 1 - | |} - | ""${'"'}.trimMargin("|") - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun f2() { - | @Language("kotlin") - | val code = - | ""${'"'} - | >@Suppress("diktat") - | >fun foo() { - | > val a = 1 - | >} - | ""${'"'} . trimMargin ( marginPrefix = ">" ) - | lintMethod(code) - |} - """.trimMargin(), - - """ - |fun checkScript() { - | lintMethod( - | ""${'"'} - | |val A = "aa" - | ""${'"'}.trimMargin(), - | ) - |} - """.trimMargin(), - ) - +internal object IndentationRuleTestMixin { /** * Creates an `IndentationConfig` from zero or more * [config entries][configEntries]. Invoke without arguments to create a @@ -439,11 +110,4 @@ internal interface IndentationRuleTestMixin { else -> "\"$first\u2026\" ($count line(s))" } } - - /** - * @return `true` if known-to-fail unit tests can be muted on the CI server. - */ - @Suppress("FUNCTION_BOOLEAN_PREFIX") - fun testsCanBeMuted(): Boolean = - getBooleanProperty("tests.can.be.muted") } 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 new file mode 100644 index 0000000000..a4b9005deb --- /dev/null +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/spaces/IndentationRuleTestResources.kt @@ -0,0 +1,789 @@ +package org.cqfn.diktat.ruleset.chapter3.spaces + +import org.intellij.lang.annotations.Language + +/** + * Test resources shared by [IndentationRuleWarnTest] and + * [IndentationRuleFixTest]. + * + * @see IndentationRuleWarnTest + * @see IndentationRuleFixTest + */ +@Suppress("LargeClass") +internal object IndentationRuleTestResources { + /** + * See [#1330](https://github.com/saveourtool/diktat/issues/1330). + * + * @see expressionBodyFunctionsContinuationIndent + */ + @Language("kotlin") + val expressionBodyFunctionsSingleIndent: Array = arrayOf( + """ + |@Test + |fun `checking that suppression with ignore everything works`() { + | val code = + | ""${'"'} + | @Suppress("diktat") + | fun foo() { + | val a = 1 + | } + | ""${'"'}.trimIndent() + | lintMethod(code) + |} + """.trimMargin(), + + """ + |val currentTime: Time + | get() = + | with(currentDateTime) { + | Time(hour = hour, minute = minute, second = second) + | } + """.trimMargin(), + + """ + |fun formatDateByPattern(date: String, pattern: String = "ddMMyy"): String = + | DateTimeFormatter.ofPattern(pattern).format(LocalDate.parse(date)) + """.trimMargin(), + + """ + |private fun createLayoutParams(): WindowManager.LayoutParams = + | WindowManager.LayoutParams().apply { /* ... */ } + """.trimMargin(), + + """ + |private fun createLayoutParams(): WindowManager.LayoutParams = + | WindowManager.LayoutParams().apply { + | type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL + | token = composeView.applicationWindowToken + | width = WindowManager.LayoutParams.MATCH_PARENT + | height = WindowManager.LayoutParams.MATCH_PARENT + | format = PixelFormat.TRANSLUCENT + | + | // TODO make composable configurable + | + | // see https://stackoverflow.com/questions/43511326/android-making-activity-full-screen-with-status-bar-on-top-of-it + | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + | windowInsetsController?.hide(WindowInsets.Type.statusBars()) + | } else { + | @Suppress("DEPRECATION") + | systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE or + | View.SYSTEM_UI_FLAG_FULLSCREEN or + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) + | } + | } + """.trimMargin(), + + """ + |val offsetDelta = + | if (shimmerAnimationType != ShimmerAnimationType.FADE) translateAnim.dp + | else 2000.dp + """.trimMargin(), + + """ + |private fun lerp(start: Float, stop: Float, fraction: Float): Float = + | (1 - fraction) * start + fraction * stop + """.trimMargin(), + + """ + |fun foo() = + | println() + """.trimMargin(), + ) + + /** + * See [#1330](https://github.com/saveourtool/diktat/issues/1330). + * + * @see expressionBodyFunctionsSingleIndent + */ + @Language("kotlin") + val expressionBodyFunctionsContinuationIndent: Array = arrayOf( + """ + |@Test + |fun `checking that suppression with ignore everything works`() { + | val code = + | ""${'"'} + | @Suppress("diktat") + | fun foo() { + | val a = 1 + | } + | ""${'"'}.trimIndent() + | lintMethod(code) + |} + """.trimMargin(), + + """ + |val currentTime: Time + | get() = + | with(currentDateTime) { + | Time(hour = hour, minute = minute, second = second) + | } + """.trimMargin(), + + """ + |fun formatDateByPattern(date: String, pattern: String = "ddMMyy"): String = + | DateTimeFormatter.ofPattern(pattern).format(LocalDate.parse(date)) + """.trimMargin(), + + """ + |private fun createLayoutParams(): WindowManager.LayoutParams = + | WindowManager.LayoutParams().apply { /* ... */ } + """.trimMargin(), + + """ + |private fun createLayoutParams(): WindowManager.LayoutParams = + | WindowManager.LayoutParams().apply { + | type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL + | token = composeView.applicationWindowToken + | width = WindowManager.LayoutParams.MATCH_PARENT + | height = WindowManager.LayoutParams.MATCH_PARENT + | format = PixelFormat.TRANSLUCENT + | + | // TODO make composable configurable + | + | // see https://stackoverflow.com/questions/43511326/android-making-activity-full-screen-with-status-bar-on-top-of-it + | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + | windowInsetsController?.hide(WindowInsets.Type.statusBars()) + | } else { + | @Suppress("DEPRECATION") + | systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE or + | View.SYSTEM_UI_FLAG_FULLSCREEN or + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) + | } + | } + """.trimMargin(), + + """ + |val offsetDelta = + | if (shimmerAnimationType != ShimmerAnimationType.FADE) translateAnim.dp + | else 2000.dp + """.trimMargin(), + + """ + |private fun lerp(start: Float, stop: Float, fraction: Float): Float = + | (1 - fraction) * start + fraction * stop + """.trimMargin(), + + """ + |fun foo() = + | println() + """.trimMargin(), + ) + + /** + * See [#1347](https://github.com/saveourtool/diktat/issues/1347). + * + * @see whitespaceInStringLiteralsContinuationIndent + */ + @Language("kotlin") + val whitespaceInStringLiteralsSingleIndent: Array = arrayOf( + """ + |@Test + |fun `test method name`() { + | @Language("kotlin") + | val code = + | ""${'"'} + | @Suppress("diktat") + | fun foo() { + | val a = 1 + | } + | ""${'"'}.trimIndent() + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun f0() { + | @Language("kotlin") + | val code = + | ""${'"'} + | |@Suppress("diktat") + | |fun foo() { + | | val a = 1 + | |} + | ""${'"'}.trimMargin() + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun f1() { + | @Language("kotlin") + | val code = + | ""${'"'} + | |@Suppress("diktat") + | |fun foo() { + | | val a = 1 + | |} + | ""${'"'}.trimMargin("|") + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun f2() { + | @Language("kotlin") + | val code = + | ""${'"'} + | >@Suppress("diktat") + | >fun foo() { + | > val a = 1 + | >} + | ""${'"'} . trimMargin ( marginPrefix = ">" ) + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun checkScript() { + | lintMethod( + | ""${'"'} + | |val A = "aa" + | ""${'"'}.trimMargin(), + | ) + |} + """.trimMargin(), + ) + + /** + * See [#1347](https://github.com/saveourtool/diktat/issues/1347). + * + * @see whitespaceInStringLiteralsSingleIndent + */ + @Language("kotlin") + val whitespaceInStringLiteralsContinuationIndent: Array = arrayOf( + """ + |@Test + |fun `test method name`() { + | @Language("kotlin") + | val code = + | ""${'"'} + | @Suppress("diktat") + | fun foo() { + | val a = 1 + | } + | ""${'"'}.trimIndent() + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun f0() { + | @Language("kotlin") + | val code = + | ""${'"'} + | |@Suppress("diktat") + | |fun foo() { + | | val a = 1 + | |} + | ""${'"'}.trimMargin() + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun f1() { + | @Language("kotlin") + | val code = + | ""${'"'} + | |@Suppress("diktat") + | |fun foo() { + | | val a = 1 + | |} + | ""${'"'}.trimMargin("|") + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun f2() { + | @Language("kotlin") + | val code = + | ""${'"'} + | >@Suppress("diktat") + | >fun foo() { + | > val a = 1 + | >} + | ""${'"'} . trimMargin ( marginPrefix = ">" ) + | lintMethod(code) + |} + """.trimMargin(), + + """ + |fun checkScript() { + | lintMethod( + | ""${'"'} + | |val A = "aa" + | ""${'"'}.trimMargin(), + | ) + |} + """.trimMargin(), + ) + + /** + * Expressions wrapped on an operator or an infix function, single indent + * (`extendedIndentAfterOperators` is **off**). + * + * When adding new code fragments to this list, be sure to also add their + * counterparts (preserving order) to [expressionsWrappedAfterOperatorContinuationIndent]. + * + * See [#1340](https://github.com/saveourtool/diktat/issues/1340). + * + * @see expressionsWrappedAfterOperatorContinuationIndent + */ + @Language("kotlin") + val expressionsWrappedAfterOperatorSingleIndent: Array = arrayOf( + """ + |fun f() { + | systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE or + | View.SYSTEM_UI_FLAG_FULLSCREEN or + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + |} + """.trimMargin(), + + """ + |val systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE or + | View.SYSTEM_UI_FLAG_FULLSCREEN or + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + """.trimMargin(), + + """ + |const val FOO = 1 + | + |const val BAR = 2 + | + |const val BAZ = 4 + | + |fun acceptInteger(arg: Int) = Unit + | + |fun main() { + | acceptInteger(FOO or BAR or BAZ or FOO or BAR or BAZ or + | FOO or BAR or BAZ or FOO or BAR or BAZ or FOO or BAR or BAZ or + | FOO or BAR or BAZ) + |} + """.trimMargin(), + + """ + |const val TRUE = true + | + |const val FALSE = false + | + |fun acceptBoolean(arg: Boolean) = Unit + | + |fun f() { + | acceptBoolean(TRUE || + | FALSE || + | TRUE) + |} + """.trimMargin(), + + """ + |val c = 3 + + | 2 + """.trimMargin(), + + """ + |infix fun Int.combineWith(that: Int) = this + that + | + |fun f() { + | val x = 1 combineWith + | 2 combineWith + | 3 combineWith + | 4 combineWith + | 5 combineWith + | 6 + |} + """.trimMargin(), + + """ + |fun f(i1: Int, i2: Int, i3: Int): Int { + | if (i2 > 0 && + | i3 < 0) { + | return 2 + | } + | return 0 + |} + """.trimMargin(), + + """ + |val value1 = 1 to + | 2 to + | 3 + """.trimMargin(), + + """ + |val value2 = + | 1 to + | 2 to + | 3 + """.trimMargin(), + + """ + |val value3 = + | (1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value4 = identity(1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value5 = identity( + | 1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value6 = + | identity(1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |/** + | * Line breaks: + | * + | * 1. before the expression body (`=`), + | * 2. before the effective function arguments, and + | * 3. on each infix function call ([to]). + | */ + |val value7 = + | identity( + | 1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value8 = identity(identity(1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value9 = identity(identity( + | 1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value10 = + | identity(identity(1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value11 = + | identity(identity( + | 1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value12 + | get() = + | 1 to + | 2 to + | 3 + """.trimMargin(), + + """ + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value13 + | get() = + | (1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value14 + | get() = + | identity(1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value15 + | get() = + | identity(identity(1 to + | 2 to + | 3)) + """.trimMargin(), + ) + + /** + * Expressions wrapped on an operator or an infix function, continuation + * indent (`extendedIndentAfterOperators` is **on**). + * + * When adding new code fragments to this list, be sure to also add their + * counterparts (preserving order) to [expressionsWrappedAfterOperatorSingleIndent]. + * + * See [#1340](https://github.com/saveourtool/diktat/issues/1340). + * + * @see expressionsWrappedAfterOperatorSingleIndent + */ + @Language("kotlin") + val expressionsWrappedAfterOperatorContinuationIndent: Array = arrayOf( + """ + |fun f() { + | systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE or + | View.SYSTEM_UI_FLAG_FULLSCREEN or + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + |} + """.trimMargin(), + + """ + |val systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE or + | View.SYSTEM_UI_FLAG_FULLSCREEN or + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE or + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + """.trimMargin(), + + """ + |const val FOO = 1 + | + |const val BAR = 2 + | + |const val BAZ = 4 + | + |fun acceptInteger(arg: Int) = Unit + | + |fun main() { + | acceptInteger(FOO or BAR or BAZ or FOO or BAR or BAZ or + | FOO or BAR or BAZ or FOO or BAR or BAZ or FOO or BAR or BAZ or + | FOO or BAR or BAZ) + |} + """.trimMargin(), + + """ + |const val TRUE = true + | + |const val FALSE = false + | + |fun acceptBoolean(arg: Boolean) = Unit + | + |fun f() { + | acceptBoolean(TRUE || + | FALSE || + | TRUE) + |} + """.trimMargin(), + + """ + |val c = 3 + + | 2 + """.trimMargin(), + + """ + |infix fun Int.combineWith(that: Int) = this + that + | + |fun f() { + | val x = 1 combineWith + | 2 combineWith + | 3 combineWith + | 4 combineWith + | 5 combineWith + | 6 + |} + """.trimMargin(), + + """ + |fun f(i1: Int, i2: Int, i3: Int): Int { + | if (i2 > 0 && + | i3 < 0) { + | return 2 + | } + | return 0 + |} + """.trimMargin(), + + """ + |val value1 = 1 to + | 2 to + | 3 + """.trimMargin(), + + """ + |val value2 = + | 1 to + | 2 to + | 3 + """.trimMargin(), + + """ + |val value3 = + | (1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value4 = identity(1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value5 = identity( + | 1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value6 = + | identity(1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |/** + | * Line breaks: + | * + | * 1. before the expression body (`=`), + | * 2. before the effective function arguments, and + | * 3. on each infix function call ([to]). + | */ + |val value7 = + | identity( + | 1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value8 = identity(identity(1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value9 = identity(identity( + | 1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value10 = + | identity(identity(1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |val value11 = + | identity(identity( + | 1 to + | 2 to + | 3)) + """.trimMargin(), + + """ + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value12 + | get() = + | 1 to + | 2 to + | 3 + """.trimMargin(), + + """ + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value13 + | get() = + | (1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value14 + | get() = + | identity(1 to + | 2 to + | 3) + """.trimMargin(), + + """ + |fun identity(t: T): T = t + | + |// Same as above, but using a custom getter instead of an explicit initializer. + |val value15 + | get() = + | identity(identity(1 to + | 2 to + | 3)) + """.trimMargin(), + ) +} 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 1db8e0ffbe..9885a29254 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 @@ -2,6 +2,15 @@ package org.cqfn.diktat.ruleset.chapter3.spaces import org.cqfn.diktat.common.config.rules.DIKTAT_RULE_SET_ID import org.cqfn.diktat.common.config.rules.RulesConfig +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.IndentationConfig +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.asRulesConfigList +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.asSequenceWithConcatenation +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.expressionBodyFunctionsContinuationIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionBodyFunctionsSingleIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionsWrappedAfterOperatorContinuationIndent +import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestResources.expressionsWrappedAfterOperatorSingleIndent import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationRule import org.cqfn.diktat.util.LintTestBase @@ -12,17 +21,20 @@ import org.assertj.core.api.AbstractSoftAssertions import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.SoftAssertions.assertSoftly import org.intellij.lang.annotations.Language -import org.junit.jupiter.api.MethodOrderer.MethodName +import org.junit.jupiter.api.MethodOrderer.DisplayName +import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test 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") -@TestMethodOrder(MethodName::class) -class IndentationRuleWarnTest : LintTestBase(::IndentationRule), IndentationRuleTestMixin { +@TestMethodOrder(DisplayName::class) +class IndentationRuleWarnTest : LintTestBase(::IndentationRule) { private val ruleId = "$DIKTAT_RULE_SET_ID:${IndentationRule.NAME_ID}" private val rulesConfigList = listOf( RulesConfig(WRONG_INDENTATION.name, true, @@ -707,92 +719,6 @@ class IndentationRuleWarnTest : LintTestBase(::IndentationRule), IndentationRule ) } - /** - * This test has a counterpart under [IndentationRuleFixTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should be properly indented (extendedIndentAfterOperators = true)`() { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to true) - - lintMultipleMethods( - expressionBodyFunctionsContinuationIndent, - lintErrors = emptyArray(), - customConfig.asRulesConfigList() - ) - } - - /** - * This test has a counterpart under [IndentationRuleFixTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should be properly indented (extendedIndentAfterOperators = false)`() { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to false) - - lintMultipleMethods( - expressionBodyFunctionsSingleIndent, - lintErrors = emptyArray(), - customConfig.asRulesConfigList() - ) - } - - /** - * This test has a counterpart under [IndentationRuleFixTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should be reported if mis-indented (extendedIndentAfterOperators = true)`() { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to true) - - assertSoftly { softly -> - expressionBodyFunctionsSingleIndent.forEach { code -> - softly.assertThat(lintResult(code, customConfig.asRulesConfigList())) - .describedAs("lint result for ${code.describe()}") - .isNotEmpty - .hasSizeBetween(1, 20).allSatisfy(Consumer { lintError -> - assertThat(lintError.ruleId).describedAs("ruleId").isEqualTo(ruleId) - assertThat(lintError.canBeAutoCorrected).describedAs("canBeAutoCorrected").isTrue - assertThat(lintError.detail).matches(warnTextRegex) - }) - } - } - } - - /** - * This test has a counterpart under [IndentationRuleFixTest]. - * - * See [#1330](https://github.com/saveourtool/diktat/issues/1330). - */ - @Test - @Tag(WarningNames.WRONG_INDENTATION) - fun `expression body functions should be reported if mis-indented (extendedIndentAfterOperators = false)`() { - val defaultConfig = IndentationConfig("newlineAtEnd" to false) - val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to false) - - assertSoftly { softly -> - expressionBodyFunctionsContinuationIndent.forEach { code -> - softly.assertThat(lintResult(code, customConfig.asRulesConfigList())) - .describedAs("lint result for ${code.describe()}") - .isNotEmpty - .hasSizeBetween(1, 20).allSatisfy(Consumer { lintError -> - assertThat(lintError.ruleId).describedAs("ruleId").isEqualTo(ruleId) - assertThat(lintError.canBeAutoCorrected).describedAs("canBeAutoCorrected").isTrue - assertThat(lintError.detail).matches(warnTextRegex) - }) - } - } - } - /** * @see warnTextRegex */ @@ -885,4 +811,108 @@ class IndentationRuleWarnTest : LintTestBase(::IndentationRule), IndentationRule @Language("RegExp") private val warnTextRegex = "^\\Q${WRONG_INDENTATION.warnText()}\\E expected \\d+ but was \\d+$" } + + /** + * See [#1330](https://github.com/saveourtool/diktat/issues/1330). + */ + @Nested + @TestMethodOrder(DisplayName::class) + inner class `Expression body functions` { + @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) + + val expressionBodyFunctions = when { + extendedIndentAfterOperators -> expressionBodyFunctionsContinuationIndent + else -> expressionBodyFunctionsSingleIndent + } + + lintMultipleMethods( + expressionBodyFunctions, + 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) + + val expressionBodyFunctions = when { + extendedIndentAfterOperators -> expressionBodyFunctionsSingleIndent + else -> expressionBodyFunctionsContinuationIndent + } + + assertSoftly { softly -> + expressionBodyFunctions.forEach { code -> + softly.assertThat(lintResult(code, customConfig.asRulesConfigList())) + .describedAs("lint result for ${code.describe()}") + .isNotEmpty + .hasSizeBetween(1, 20).allSatisfy(Consumer { lintError -> + assertThat(lintError.ruleId).describedAs("ruleId").isEqualTo(ruleId) + assertThat(lintError.canBeAutoCorrected).describedAs("canBeAutoCorrected").isTrue + assertThat(lintError.detail).matches(warnTextRegex) + }) + } + } + } + } + + /** + * See [#1340](https://github.com/saveourtool/diktat/issues/1340). + */ + @Nested + @TestMethodOrder(DisplayName::class) + inner class `Expressions wrapped after operator` { + @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) + + val expressionsWrappedAfterOperator = when { + extendedIndentAfterOperators -> expressionsWrappedAfterOperatorContinuationIndent + else -> expressionsWrappedAfterOperatorSingleIndent + } + + lintMultipleMethods( + expressionsWrappedAfterOperator, + 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) + + val expressionsWrappedAfterOperator = when { + extendedIndentAfterOperators -> expressionsWrappedAfterOperatorSingleIndent + else -> expressionsWrappedAfterOperatorContinuationIndent + } + + assertSoftly { softly -> + expressionsWrappedAfterOperator.forEach { code -> + softly.assertThat(lintResult(code, customConfig.asRulesConfigList())) + .describedAs("lint result for ${code.describe()}") + .isNotEmpty + .hasSizeBetween(1, 5).allSatisfy(Consumer { lintError -> + assertThat(lintError.ruleId).describedAs("ruleId").isEqualTo(ruleId) + assertThat(lintError.canBeAutoCorrected).describedAs("canBeAutoCorrected").isTrue + assertThat(lintError.detail).matches(warnTextRegex) + }) + } + } + } + } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/LintTestBase.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/LintTestBase.kt index 8c0d888083..3c9575b5ed 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/LintTestBase.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/LintTestBase.kt @@ -5,6 +5,7 @@ import org.cqfn.diktat.common.config.rules.RulesConfig import com.pinterest.ktlint.core.KtLint import com.pinterest.ktlint.core.LintError import com.pinterest.ktlint.core.Rule +import org.assertj.core.api.Assertions.assertThat import org.intellij.lang.annotations.Language /** @@ -28,8 +29,9 @@ open class LintTestBase(private val ruleSupplier: (rulesConfigList: List? = null, fileName: String? = null ) { - lintResult(code, rulesConfigList, fileName) - .assertEquals(*lintErrors) + assertThat(lintResult(code, rulesConfigList, fileName)) + .describedAs("lint result for \"$code\"") + .containsExactly(*lintErrors) } /** diff --git a/pom.xml b/pom.xml index 1eda7c1ee6..24ca422df3 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,7 @@ 1.3.3 0.46.1 5.8.2 + 1.8.2 31.1-jre 1.7.36 1.5.0 @@ -196,6 +197,11 @@ junit-jupiter ${junit.version} + + org.junit.platform + junit-platform-suite-engine + ${junit.platform.version} + org.assertj assertj-core