diff --git a/diktat-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt b/diktat-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt index 13b5be4c5f..f74bf92420 100644 --- a/diktat-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt +++ b/diktat-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt @@ -16,6 +16,20 @@ interface DiktatProcessor { */ fun fix(file: Path, callback: DiktatCallback): String + /** + * Run `diktat fix` on provided [code] using [callback] for detected errors and returned formatted code. + * + * @param code + * @param isScript + * @param callback + * @return result of `diktat fix` + */ + fun fix( + code: String, + isScript: Boolean, + callback: DiktatCallback, + ): String + /** * Run `diktat check` on provided [file] using [callback] for detected errors. * @@ -23,4 +37,17 @@ interface DiktatProcessor { * @param callback */ fun check(file: Path, callback: DiktatCallback) + + /** + * Run `diktat check` on provided [code] using [callback] for detected errors. + * + * @param code + * @param isScript + * @param callback + */ + fun check( + code: String, + isScript: Boolean, + callback: DiktatCallback, + ) } diff --git a/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/DiktatProcessorFactoryImpl.kt b/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/DiktatProcessorFactoryImpl.kt index bfabd5aa6f..c616077c6e 100644 --- a/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/DiktatProcessorFactoryImpl.kt +++ b/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/DiktatProcessorFactoryImpl.kt @@ -4,38 +4,86 @@ import org.cqfn.diktat.DiktatProcessor import org.cqfn.diktat.DiktatProcessorFactory import org.cqfn.diktat.api.DiktatCallback import org.cqfn.diktat.api.DiktatRuleSet +import org.cqfn.diktat.ktlint.DiktatErrorImpl.Companion.wrap import org.cqfn.diktat.ktlint.KtLintRuleSetWrapper.Companion.toKtLint import org.cqfn.diktat.util.isKotlinScript + import com.pinterest.ktlint.core.KtLint +import com.pinterest.ktlint.core.LintError import com.pinterest.ktlint.core.api.EditorConfigOverride + import java.nio.charset.StandardCharsets import java.nio.file.Path + import kotlin.io.path.absolutePathString import kotlin.io.path.readText +private typealias KtLintCallback = (LintError, Boolean) -> Unit + /** * A factory to create [DiktatProcessor] using [DiktatProcessorFactory] and `KtLint` as engine */ class DiktatProcessorFactoryImpl : DiktatProcessorFactory { override fun invoke(diktatRuleSet: DiktatRuleSet): DiktatProcessor = object : DiktatProcessor { - override fun fix(file: Path, callback: DiktatCallback): String = KtLint.format(ktLintParams(diktatRuleSet, file, callback.unwrap())) - override fun check(file: Path, callback: DiktatCallback) = KtLint.lint(ktLintParams(diktatRuleSet, file, callback.unwrap())) + override fun fix(file: Path, callback: DiktatCallback): String = KtLint.format(file.toKtLintParams(diktatRuleSet, callback)) + override fun fix( + code: String, + isScript: Boolean, + callback: DiktatCallback + ): String = KtLint.format(code.toKtLintParams(isScript, diktatRuleSet, callback)) + override fun check(file: Path, callback: DiktatCallback) = KtLint.lint(file.toKtLintParams(diktatRuleSet, callback)) + override fun check( + code: String, + isScript: Boolean, + callback: DiktatCallback + ) = KtLint.lint(code.toKtLintParams(isScript, diktatRuleSet, callback)) } - private fun ktLintParams( - diktatRuleSet: DiktatRuleSet, - file: Path, - callback: LintErrorCallback, - ): KtLint.ExperimentalParams = KtLint.ExperimentalParams( - fileName = file.absolutePathString(), - text = file.readText(StandardCharsets.UTF_8), - ruleSets = setOf(diktatRuleSet.toKtLint()), - userData = emptyMap(), - cb = callback, - script = file.isKotlinScript(), - editorConfigPath = null, - debug = false, // we do not use it - editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, - isInvokedFromCli = false - ) + companion object { + private fun Path.toKtLintParams( + diktatRuleSet: DiktatRuleSet, + callback: DiktatCallback, + ): KtLint.ExperimentalParams = ktLintParams( + fileName = absolutePathString(), + text = readText(StandardCharsets.UTF_8).replace("\r\n", "\n").replace("\r", "\n"), + isScript = isKotlinScript(), + diktatRuleSet = diktatRuleSet, + callback = callback, + ) + + private fun String.toKtLintParams( + isScript: Boolean, + diktatRuleSet: DiktatRuleSet, + callback: DiktatCallback, + ): KtLint.ExperimentalParams = ktLintParams( + fileName = if (isScript) "test.kts" else "test.kt", + text = this, + isScript = isScript, + diktatRuleSet = diktatRuleSet, + callback = callback, + ) + + private fun ktLintParams( + fileName: String, + text: String, + isScript: Boolean, + diktatRuleSet: DiktatRuleSet, + callback: DiktatCallback, + ): KtLint.ExperimentalParams = KtLint.ExperimentalParams( + fileName = fileName, + text = text, + ruleSets = setOf(diktatRuleSet.toKtLint()), + userData = emptyMap(), + cb = callback.toKtLint(), + script = isScript, + editorConfigPath = null, + debug = false, // we do not use it + editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, + isInvokedFromCli = false + ) + + private fun DiktatCallback.toKtLint(): KtLintCallback = { error, isCorrected -> + this(error.wrap(), isCorrected) + } + } } diff --git a/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/KtLintUtils.kt b/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/KtLintUtils.kt index 82e5a70e0d..9e554bdcd5 100644 --- a/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/KtLintUtils.kt +++ b/diktat-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/KtLintUtils.kt @@ -7,26 +7,12 @@ package org.cqfn.diktat.ktlint import org.cqfn.diktat.api.DiktatCallback import org.cqfn.diktat.api.DiktatRuleSet import org.cqfn.diktat.common.config.rules.DIKTAT_RULE_SET_ID -import org.cqfn.diktat.ktlint.DiktatErrorImpl.Companion.unwrap -import org.cqfn.diktat.ktlint.DiktatErrorImpl.Companion.wrap -import org.cqfn.diktat.ktlint.KtLintRuleSetWrapper.Companion.toKtLint -import com.pinterest.ktlint.core.KtLint -import com.pinterest.ktlint.core.KtLint.ExperimentalParams import com.pinterest.ktlint.core.LintError -import mu.KotlinLogging import org.intellij.lang.annotations.Language import java.nio.file.Path import kotlin.io.path.invariantSeparatorsPathString import kotlin.io.path.relativeTo -private val log = KotlinLogging.logger { } - -val defaultCallback = DiktatCallback { error, _ -> - log.warn { "Received linting error: $error" } -} - -typealias LintErrorCallback = (LintError, Boolean) -> Unit - /** * Makes sure this _rule id_ is qualified with a _rule set id_. * @@ -47,73 +33,62 @@ fun String.qualifiedWithRuleSetId(ruleSetId: String = DIKTAT_RULE_SET_ID): Strin */ fun Path.relativePathStringTo(sourceRootDir: Path): String = relativeTo(sourceRootDir).invariantSeparatorsPathString -/** - * @return [DiktatCallback] from KtLint [LintErrorCallback] - */ -fun LintErrorCallback.wrap(): DiktatCallback = DiktatCallback { error, isCorrected -> - this(error.unwrap(), isCorrected) -} - -/** - * @return KtLint [LintErrorCallback] from [DiktatCallback] or exception - */ -fun DiktatCallback.unwrap(): LintErrorCallback = { error, isCorrected -> - this(error.wrap(), isCorrected) -} - /** * Enables ignoring autocorrected errors when in "fix" mode (i.e. when - * [KtLint.format] is invoked). + * [com.pinterest.ktlint.core.KtLint.format] is invoked). * * Before version 0.47, _Ktlint_ only reported non-corrected errors in "fix" * mode. * Now, this has changed. * * @receiver the instance of _Ktlint_ parameters. - * @return the instance with the [callback][ExperimentalParams.cb] modified in - * such a way that it ignores corrected errors. - * @see KtLint.format - * @see ExperimentalParams.cb + * @return the instance [DiktatCallback] that ignores corrected errors. + * @see com.pinterest.ktlint.core.KtLint.format * @since 1.2.4 */ -private fun ExperimentalParams.ignoreCorrectedErrors(): ExperimentalParams = - copy(cb = { error: LintError, corrected: Boolean -> - if (!corrected) { - cb(error, false) - } - }) +private fun DiktatCallback.ignoreCorrectedErrors(): DiktatCallback = DiktatCallback { error, isCorrected -> + if (!isCorrected) { + this@ignoreCorrectedErrors(error, false) + } +} /** * @param ruleSetSupplier - * @param text - * @param fileName + * @param file * @param cb callback to be called on unhandled [LintError]s * @return formatted code */ @Suppress("LAMBDA_IS_NOT_LAST_PARAMETER") fun format( ruleSetSupplier: () -> DiktatRuleSet, - @Language("kotlin") text: String, - fileName: String, - cb: DiktatCallback = defaultCallback -): String { - val ruleSets = listOf(ruleSetSupplier().toKtLint()) - return KtLint.format( - ExperimentalParams( - text = text, - ruleSets = ruleSets, - fileName = fileName.removeSuffix("_copy"), - script = fileName.removeSuffix("_copy").endsWith("kts"), - cb = cb.unwrap(), - debug = true, - ).ignoreCorrectedErrors() + file: Path, + cb: DiktatCallback, +): String = DiktatProcessorFactoryImpl().invoke(ruleSetSupplier()) + .fix( + file = file, + callback = cb.ignoreCorrectedErrors(), + ) + +/** + * @param ruleSetSupplier + * @param file + * @param cb callback to be called on unhandled [LintError]s + * @return formatted code + */ +@Suppress("LAMBDA_IS_NOT_LAST_PARAMETER") +fun lint( + ruleSetSupplier: () -> DiktatRuleSet, + file: Path, + cb: DiktatCallback = DiktatCallback.empty +) = DiktatProcessorFactoryImpl().invoke(ruleSetSupplier()) + .check( + file = file, + callback = cb.ignoreCorrectedErrors(), ) -} /** * @param ruleSetSupplier * @param text - * @param fileName * @param cb callback to be called on unhandled [LintError]s * @return formatted code */ @@ -121,18 +96,10 @@ fun format( fun lint( ruleSetSupplier: () -> DiktatRuleSet, @Language("kotlin") text: String, - fileName: String = "test.ks", cb: DiktatCallback = DiktatCallback.empty -) { - val ruleSets = listOf(ruleSetSupplier().toKtLint()) - KtLint.lint( - ExperimentalParams( - text = text, - ruleSets = ruleSets, - fileName = fileName.removeSuffix("_copy"), - script = fileName.removeSuffix("_copy").endsWith("kts"), - cb = cb.unwrap(), - debug = true, - ).ignoreCorrectedErrors() +) = DiktatProcessorFactoryImpl().invoke(ruleSetSupplier()) + .check( + code = text, + isScript = false, + callback = cb.ignoreCorrectedErrors(), ) -} diff --git a/diktat-rules/build.gradle.kts b/diktat-rules/build.gradle.kts index e218cceece..066881e477 100644 --- a/diktat-rules/build.gradle.kts +++ b/diktat-rules/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(libs.kotlin.logging) testImplementation(projects.diktatTestFramework) testImplementation(projects.diktatKtlintEngine) + testImplementation(libs.log4j2.slf4j) testImplementation(libs.junit.jupiter) testImplementation(libs.junit.platform.suite) testImplementation(libs.assertj.core) diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/PackageNamingWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/PackageNamingWarnTest.kt index 60ddd1e26a..596325569b 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/PackageNamingWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/PackageNamingWarnTest.kt @@ -16,6 +16,8 @@ import com.pinterest.ktlint.core.LintError import generated.WarningNames import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path class PackageNamingWarnTest : LintTestBase(::PackageNaming) { private val ruleId: String = "$DIKTAT_RULE_SET_ID:${PackageNaming.NAME_ID}" @@ -35,8 +37,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_MISSING) - fun `missing package name (check)`() { - lintMethod( + fun `missing package name (check)`(@TempDir tempDir: Path) { + lintMethodWithFile( """ import org.cqfn.diktat.a.b.c @@ -46,6 +48,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), + tempDir = tempDir, + fileName = TEST_FILE_NAME, LintError(1, 1, ruleId, "${PACKAGE_NAME_MISSING.warnText()} $TEST_FILE_NAME", true), rulesConfigList = rulesConfigList ) @@ -53,8 +57,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_MISSING) - fun `missing package name with annotation (check)`() { - lintMethod( + fun `missing package name with annotation (check)`(@TempDir tempDir: Path) { + lintMethodWithFile( """ @file:Suppress("CONSTANT_UPPERCASE") @@ -66,6 +70,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), + tempDir = tempDir, + fileName = TEST_FILE_NAME, LintError(1, 37, ruleId, "${PACKAGE_NAME_MISSING.warnText()} $TEST_FILE_NAME", true), rulesConfigList = rulesConfigList ) @@ -73,8 +79,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_MISSING) - fun `don't add the package name to the file in buildSrc path`() { - lintMethod( + fun `don't add the package name to the file in buildSrc path`(@TempDir tempDir: Path) { + lintMethodWithFile( """ import org.cqfn.diktat.a.b.c @@ -84,7 +90,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), - fileName = "~/diktat/buildSrc/src/main/kotlin/Version.kt", + tempDir = tempDir, + fileName = "diktat/buildSrc/src/main/kotlin/Version.kt", rulesConfigList = rulesConfigList ) } @@ -93,7 +100,6 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Tag(WarningNames.PACKAGE_NAME_INCORRECT_CASE) fun `package name should be in a lower case (check)`() { lintMethod( - """ package /* AAA */ org.cqfn.diktat.SPECIALTEST.test @@ -195,8 +201,8 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_SYMBOLS) - fun `test source config`() { - lintMethod( + fun `test source config`(@TempDir tempDir: Path) { + lintMethodWithFile( """ package org.cqfn.diktat.domain @@ -209,11 +215,12 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), - fileName = "~/diktat/diktat-rules/src/nativeMain/kotlin/org/cqfn/diktat/domain/BlaBla.kt", + tempDir = tempDir, + fileName = "diktat/diktat-rules/src/nativeMain/kotlin/org/cqfn/diktat/domain/BlaBla.kt", rulesConfigList = rulesConfigSourceDirectories ) - lintMethod( + lintMethodWithFile( """ package org.cqfn.diktat.domain @@ -226,16 +233,17 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), + tempDir = tempDir, + fileName = "diktat/diktat-rules/src/main/kotlin/org/cqfn/diktat/domain/BlaBla.kt", LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PATH.warnText()} org.cqfn.diktat.main.kotlin.org.cqfn.diktat.domain", true), - fileName = "~/diktat/diktat-rules/src/main/kotlin/org/cqfn/diktat/domain/BlaBla.kt", rulesConfigList = rulesConfigSourceDirectories ) } @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_SYMBOLS) - fun `test directories for test config`() { - lintMethod( + fun `test directories for test config`(@TempDir tempDir: Path) { + lintMethodWithFile( """ package org.cqfn.diktat.domain @@ -248,11 +256,12 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), - fileName = "~/diktat/diktat-rules/src/nativeTest/kotlin/org/cqfn/diktat/domain/BlaBla.kt", + tempDir = tempDir, + fileName = "diktat/diktat-rules/src/nativeTest/kotlin/org/cqfn/diktat/domain/BlaBla.kt", rulesConfigList = rulesConfigSourceDirectories ) - lintMethod( + lintMethodWithFile( """ package org.cqfn.diktat.domain @@ -265,49 +274,54 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { class TestPackageName { } """.trimIndent(), + tempDir = tempDir, + fileName = "diktat/diktat-rules/src/test/kotlin/org/cqfn/diktat/domain/BlaBla.kt", LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PATH.warnText()} org.cqfn.diktat.test.kotlin.org.cqfn.diktat.domain", true), - fileName = "~/diktat/diktat-rules/src/test/kotlin/org/cqfn/diktat/domain/BlaBla.kt", rulesConfigList = rulesConfigSourceDirectories ) } @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `regression - incorrect warning on file under test directory`() { - lintMethod( + fun `regression - incorrect warning on file under test directory`(@TempDir tempDir: Path) { + lintMethodWithFile( """ package org.cqfn.diktat.ruleset.chapter1 """.trimIndent(), - fileName = "~/diktat/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/EnumValueCaseTest.kt", + tempDir = tempDir, + fileName = "diktat/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/EnumValueCaseTest.kt", rulesConfigList = rulesConfigList ) - lintMethod( + lintMethodWithFile( """ package org.cqfn.diktat.chapter1 """.trimIndent(), + tempDir = tempDir, + fileName = "diktat/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/EnumValueCaseTest.kt", LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PATH.warnText()} org.cqfn.diktat.ruleset.chapter1", true), - fileName = "~/diktat/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter1/EnumValueCaseTest.kt", rulesConfigList = rulesConfigList ) } @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `regression - should not remove special words from file path`() { - lintMethod( + fun `regression - should not remove special words from file path`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |package org.cqfn.diktat.test.processing """.trimMargin(), - fileName = "/home/testu/project/module/src/test/kotlin/org/cqfn/diktat/test/processing/SpecialPackageNaming.kt", + tempDir = tempDir, + fileName = "project/module/src/test/kotlin/org/cqfn/diktat/test/processing/SpecialPackageNaming.kt", rulesConfigList = rulesConfigList ) - lintMethod( + lintMethodWithFile( """ |package kotlin.collections """.trimMargin(), - fileName = "/home/testu/project/module/src/main/kotlin/kotlin/collections/Collections.kt", + tempDir = tempDir, + fileName = "project/module/src/main/kotlin/kotlin/collections/Collections.kt", rulesConfigList = listOf( RulesConfig("DIKTAT_COMMON", true, mapOf("domainName" to "kotlin")) ) @@ -316,13 +330,14 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `should respect KMP project structure - positive example`() { + fun `should respect KMP project structure - positive example`(@TempDir tempDir: Path) { listOf("main", "test", "jvmMain", "jvmTest", "androidMain", "androidTest", "iosMain", "iosTest", "jsMain", "jsTest", "commonMain", "commonTest").forEach { - lintMethod( + lintMethodWithFile( """ |package org.cqfn.diktat """.trimMargin(), - fileName = "/home/testu/project/src/$it/kotlin/org/cqfn/diktat/Example.kt", + tempDir = tempDir, + fileName = "project/src/$it/kotlin/org/cqfn/diktat/Example.kt", rulesConfigList = rulesConfigList ) } @@ -330,14 +345,15 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `should respect KMP project structure`() { + fun `should respect KMP project structure`(@TempDir tempDir: Path) { listOf("main", "test", "jvmMain", "jvmTest", "androidMain", "androidTest", "iosMain", "iosTest", "jsMain", "jsTest", "commonMain", "commonTest").forEach { - lintMethod( + lintMethodWithFile( """ |package org.cqfn.diktat """.trimMargin(), + tempDir = tempDir, + fileName = "project/src/$it/kotlin/org/cqfn/diktat/example/Example.kt", LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PATH.warnText()} org.cqfn.diktat.example", true), - fileName = "/home/testu/project/src/$it/kotlin/org/cqfn/diktat/example/Example.kt", rulesConfigList = rulesConfigList ) } @@ -345,50 +361,54 @@ class PackageNamingWarnTest : LintTestBase(::PackageNaming) { @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `should respect KMP project structure - illegal source set name`() { - lintMethod( + fun `should respect KMP project structure - illegal source set name`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |package org.cqfn.diktat """.trimMargin(), + tempDir = tempDir, + fileName = "project/src/myProjectMain/kotlin/org/cqfn/diktat/example/Example.kt", LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PATH.warnText()} org.cqfn.diktat.myProjectMain.kotlin.org.cqfn.diktat.example", true), - fileName = "/home/testu/project/src/myProjectMain/kotlin/org/cqfn/diktat/example/Example.kt", rulesConfigList = rulesConfigList ) } @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `should warn if there is empty domain name`() { - lintMethod( + fun `should warn if there is empty domain name`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |package org.cqfn.diktat """.trimMargin(), + tempDir = tempDir, + fileName = "project/src/main/kotlin/org/cqfn/diktat/example/Example.kt", LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PREFIX.warnText()} ", true), LintError(1, 9, ruleId, "${PACKAGE_NAME_INCORRECT_PATH.warnText()} org.cqfn.diktat.example", true), - fileName = "/home/testu/project/src/main/kotlin/org/cqfn/diktat/example/Example.kt", rulesConfigList = rulesConfigListEmptyDomainName ) } @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `shouldn't trigger if path contains dot`() { - lintMethod( + fun `shouldn't trigger if path contains dot`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |package org.cqfn.diktat.test.utils """.trimMargin(), - fileName = "/home/testu/project/src/main/kotlin/org/cqfn/diktat/test.utils/Example.kt", + tempDir = tempDir, + fileName = "project/src/main/kotlin/org/cqfn/diktat/test.utils/Example.kt", ) } @Test @Tag(WarningNames.PACKAGE_NAME_INCORRECT_PATH) - fun `shouldn't trigger for gradle script`() { - lintMethod( + fun `shouldn't trigger for gradle script`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |import org.cqfn.diktat.generation.docs.generateAvailableRules """.trimMargin(), - fileName = "/home/testu/project/build.gradle.kts", + tempDir = tempDir, + fileName = "project/build.gradle.kts", ) } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt index 4d8ce6e028..649d4c9bf0 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt @@ -4,6 +4,7 @@ import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.ruleset.constants.Warnings.HEADER_MISSING_OR_WRONG_COPYRIGHT import org.cqfn.diktat.ruleset.constants.Warnings.HEADER_WRONG_FORMAT import org.cqfn.diktat.ruleset.rules.chapter2.comments.HeaderCommentRule +import org.cqfn.diktat.test.framework.processing.ResourceReader import org.cqfn.diktat.util.FixTestBase import generated.WarningNames @@ -11,6 +12,8 @@ import generated.WarningNames.WRONG_COPYRIGHT_YEAR import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path import java.time.LocalDate class HeaderCommentRuleFixTest : FixTestBase( @@ -27,19 +30,19 @@ class HeaderCommentRuleFixTest : FixTestBase( ) { @Test @Tag(WarningNames.HEADER_WRONG_FORMAT) - fun `new line should be inserted after header KDoc`() { - fixAndCompare("NewlineAfterHeaderKdocExpected.kt", "NewlineAfterHeaderKdocTest.kt", replacements = currentYearReplacement) + fun `new line should be inserted after header KDoc`(@TempDir tempDir: Path) { + fixAndCompare("NewlineAfterHeaderKdocExpected.kt", "NewlineAfterHeaderKdocTest.kt", resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement)) } @Test @Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT) - fun `if no copyright is present and mandatoryCopyright=true, it is added`() { - fixAndCompare("AutoCopyrightExpected.kt", "AutoCopyrightTest.kt", replacements = currentYearReplacement) + fun `if no copyright is present and mandatoryCopyright=true, it is added`(@TempDir tempDir: Path) { + fixAndCompare("AutoCopyrightExpected.kt", "AutoCopyrightTest.kt", resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement)) } @Test @Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT) - fun `if no copyright is present, added it and apply pattern for current year`() { + fun `if no copyright is present, added it and apply pattern for current year`(@TempDir tempDir: Path) { fixAndCompare("AutoCopyrightApplyPatternExpected.kt", "AutoCopyrightApplyPatternTest.kt", listOf( RulesConfig( @@ -51,7 +54,7 @@ class HeaderCommentRuleFixTest : FixTestBase( ), RulesConfig(HEADER_WRONG_FORMAT.name, true, emptyMap()) ), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @@ -60,88 +63,92 @@ class HeaderCommentRuleFixTest : FixTestBase( */ @Test @Tag(WarningNames.HEADER_NOT_BEFORE_PACKAGE) - fun `header KDoc should be moved before package`() { - fixAndCompare("MisplacedHeaderKdocExpected.kt", "MisplacedHeaderKdocTest.kt", replacements = currentYearReplacement) + fun `header KDoc should be moved before package`(@TempDir tempDir: Path) { + fixAndCompare("MisplacedHeaderKdocExpected.kt", "MisplacedHeaderKdocTest.kt", resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement)) } @Test @Tags(Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT), Tag(WarningNames.HEADER_WRONG_FORMAT)) - fun `header KDoc should be moved before package - no copyright`() { + fun `header KDoc should be moved before package - no copyright`(@TempDir tempDir: Path) { fixAndCompare("MisplacedHeaderKdocNoCopyrightExpected.kt", "MisplacedHeaderKdocNoCopyrightTest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, false, emptyMap()), RulesConfig(HEADER_WRONG_FORMAT.name, true, emptyMap())), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tags(Tag(WarningNames.HEADER_NOT_BEFORE_PACKAGE), Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT)) - fun `header KDoc should be moved before package - appended copyright`() { - fixAndCompare("MisplacedHeaderKdocAppendedCopyrightExpected.kt", "MisplacedHeaderKdocAppendedCopyrightTest.kt", replacements = currentYearReplacement) + fun `header KDoc should be moved before package - appended copyright`(@TempDir tempDir: Path) { + fixAndCompare( + "MisplacedHeaderKdocAppendedCopyrightExpected.kt", + "MisplacedHeaderKdocAppendedCopyrightTest.kt", + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), + ) } @Test @Tag(WRONG_COPYRIGHT_YEAR) - fun `copyright invalid year should be auto-corrected`() { + fun `copyright invalid year should be auto-corrected`(@TempDir tempDir: Path) { fixAndCompare("CopyrightDifferentYearExpected.kt", "CopyrightDifferentYearTest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", "copyrightText" to "Copyright (c) My Company., Ltd. 2012-2019. All rights reserved." ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tag(WRONG_COPYRIGHT_YEAR) - fun `copyright invalid year should be auto-corrected 2`() { + fun `copyright invalid year should be auto-corrected 2`(@TempDir tempDir: Path) { fixAndCompare("CopyrightDifferentYearExpected2.kt", "CopyrightDifferentYearTest2.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", "copyrightText" to "Copyright (c) My Company., Ltd. 2021. All rights reserved." ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tag(WRONG_COPYRIGHT_YEAR) - fun `copyright invalid pattern, but valid in code`() { + fun `copyright invalid pattern, but valid in code`(@TempDir tempDir: Path) { fixAndCompare("CopyrightInvalidPatternValidCodeExpected.kt", "CopyrightInvalidPatternValidCodeTest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", "copyrightText" to "Copyright (c) My Company., Ltd. 2012-2019. All rights reserved." ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tag(WRONG_COPYRIGHT_YEAR) - fun `copyright invalid pattern, update actual year in it and auto-correct`() { + fun `copyright invalid pattern, update actual year in it and auto-correct`(@TempDir tempDir: Path) { fixAndCompare("CopyrightAbsentInvalidPatternExpected.kt", "CopyrightAbsentInvalidPatternTest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", "copyrightText" to "Copyright (c) My Company., Ltd. 2012-2019. All rights reserved." ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tag(WRONG_COPYRIGHT_YEAR) - fun `should not raise npe`() { + fun `should not raise npe`(@TempDir tempDir: Path) { fixAndCompare("CopyrightShouldNotTriggerNPEExpected.kt", "CopyrightShouldNotTriggerNPETest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", "copyrightText" to "Copyright (c) My Company., Ltd. 2012-2021. All rights reserved." ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT) - fun `copyright multiline`() { + fun `copyright multiline`(@TempDir tempDir: Path) { fixAndCompare("MultilineCopyrightExample.kt", "MultilineCopyrightTest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", @@ -161,13 +168,13 @@ class HeaderCommentRuleFixTest : FixTestBase( | limitations under the License. """.trimMargin() ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } @Test @Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT) - fun `should not trigger if copyright text have different indents`() { + fun `should not trigger if copyright text have different indents`(@TempDir tempDir: Path) { fixAndCompare("MultilineCopyrightNotTriggerExample.kt", "MultilineCopyrightNotTriggerTest.kt", listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true, mapOf( "isCopyrightMandatory" to "true", @@ -179,7 +186,7 @@ class HeaderCommentRuleFixTest : FixTestBase( | You may obtain a copy of the License at """.trimMargin() ))), - replacements = currentYearReplacement, + resourceReader = ResourceReader.withReplacements(tempDir, currentYearReplacement), ) } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt index 4c57aa6cee..779da8d1aa 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt @@ -14,6 +14,8 @@ import com.pinterest.ktlint.core.LintError import generated.WarningNames import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path import java.time.LocalDate @@ -476,28 +478,28 @@ class HeaderCommentRuleTest : LintTestBase(::HeaderCommentRule) { @Test @Tag(WarningNames.HEADER_NOT_BEFORE_PACKAGE) - fun `header KDoc in gradle script`() { - lintMethod( + fun `header KDoc in gradle script`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |version = "0.1.0-SNAPSHOT" | """.trimMargin(), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/builds.gradle.kts" - ) } @Test @Tag(WarningNames.HEADER_NOT_BEFORE_PACKAGE) - fun `header KDoc in kts script`() { - lintMethod( + fun `header KDoc in kts script`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |val version = "0.1.0-SNAPSHOT" | """.trimMargin(), - LintError(1, 1, ruleId, "${HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE.warnText()} there are 0 declared classes and/or objects"), - fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" - + tempDir = tempDir, + fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts", + LintError(1, 1, ruleId, "${HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE.warnText()} there are 0 declared classes and/or objects") ) } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/KdocMethodsTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/KdocMethodsTest.kt index d4166a1965..40e04a547a 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/KdocMethodsTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/KdocMethodsTest.kt @@ -16,6 +16,8 @@ import generated.WarningNames import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path class KdocMethodsTest : LintTestBase(::KdocMethods) { private val ruleId: String = "$DIKTAT_RULE_SET_ID:${KdocMethods.NAME_ID}" @@ -77,24 +79,28 @@ class KdocMethodsTest : LintTestBase(::KdocMethods) { Tag(WarningNames.KDOC_WITHOUT_THROWS_TAG), Tag(WarningNames.MISSING_KDOC_ON_FUNCTION) ) - fun `Warning should not be triggered for functions in tests`() { + fun `Warning should not be triggered for functions in tests`(@TempDir tempDir: Path) { val validCode = "@Test $funCode" val complexAnnotationCode = "@Anno(test = [\"args\"]) $funCode" // do not force KDoc on annotated function - lintMethod(validCode, fileName = "src/main/kotlin/org/cqfn/diktat/Example.kt") + lintMethodWithFile(validCode, tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/Example.kt") // no false positive triggers on annotations - lintMethod(complexAnnotationCode, - LintError(1, 1, ruleId, "${MISSING_KDOC_ON_FUNCTION.warnText()} doubleInt", true), - fileName = "src/main/kotlin/org/cqfn/diktat/Example.kt" + lintMethodWithFile(complexAnnotationCode, + tempDir = tempDir, + fileName = "src/main/kotlin/org/cqfn/diktat/Example.kt", + LintError(1, 1, ruleId, "${MISSING_KDOC_ON_FUNCTION.warnText()} doubleInt", true) ) // should check all .kt files unless both conditions on location and name are true - lintMethod(funCode, - LintError(1, 1, ruleId, "${MISSING_KDOC_ON_FUNCTION.warnText()} doubleInt", true), - fileName = "src/test/kotlin/org/cqfn/diktat/Example.kt" + lintMethodWithFile(funCode, + tempDir = tempDir, + fileName = "src/test/kotlin/org/cqfn/diktat/Example.kt", + LintError(1, 1, ruleId, "${MISSING_KDOC_ON_FUNCTION.warnText()} doubleInt", true) ) // should allow to set custom test dirs - lintMethod(funCode, fileName = "src/jvmTest/kotlin/org/cqfn/diktat/ExampleTest.kt", + lintMethodWithFile(funCode, + tempDir = tempDir, + fileName = "src/jvmTest/kotlin/org/cqfn/diktat/ExampleTest.kt", rulesConfigList = listOf(RulesConfig(DIKTAT_COMMON, true, mapOf("testDirs" to "test,jvmTest"))) ) } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileSizeWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileSizeWarnTest.kt index cd578e1b8e..507e3f45c9 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileSizeWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileSizeWarnTest.kt @@ -33,7 +33,7 @@ class FileSizeWarnTest : LintTestBase(::FileSize) { fun `file smaller then max`() { val path = javaClass.classLoader.getResource("test/paragraph3/src/main/FileSizeLarger.kt") val file = File(path!!.file) - lintMethod(file.readText(), fileName = file.absolutePath, rulesConfigList = rulesConfigListSmall) + lintMethodWithFile(file.toPath(), rulesConfigList = rulesConfigListSmall) } @Test @@ -45,10 +45,9 @@ class FileSizeWarnTest : LintTestBase(::FileSize) { .readText() .split("\n") .size - lintMethod(file.readText(), + lintMethodWithFile(file.toPath(), LintError(1, 1, ruleId, "${Warnings.FILE_IS_TOO_LONG.warnText()} $size", false), - fileName = file.absolutePath, rulesConfigList = rulesConfigListLarge) } @@ -57,7 +56,7 @@ class FileSizeWarnTest : LintTestBase(::FileSize) { fun `use default values`() { val path = javaClass.classLoader.getResource("test/paragraph3/src/main/FileSizeLarger.kt") val file = File(path!!.file) - lintMethod(file.readText(), fileName = file.absolutePath, rulesConfigList = rulesConfigListEmpty) + lintMethodWithFile(file.toPath(), rulesConfigList = rulesConfigListEmpty) } @Test @@ -66,10 +65,10 @@ class FileSizeWarnTest : LintTestBase(::FileSize) { val path = javaClass.classLoader.getResource("test/paragraph3/src/main/A/FileSize2000.kt") val file = File(path!!.file) val size = generate2000lines() + 1 - lintMethod(file.readText(), + lintMethodWithFile(file.toPath(), LintError(1, 1, ruleId, "${Warnings.FILE_IS_TOO_LONG.warnText()} $size", false), - fileName = file.absolutePath, rulesConfigList = rulesConfigListLarge) + rulesConfigList = rulesConfigListLarge) } private fun generate2000lines(): Int { diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt index e3ecd45387..57ebef6829 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/FileStructureRuleTest.kt @@ -16,6 +16,8 @@ import generated.WarningNames import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path class FileStructureRuleTest : LintTestBase(::FileStructureRule) { private val ruleId = "$DIKTAT_RULE_SET_ID:${FileStructureRule.NAME_ID}" @@ -564,8 +566,8 @@ class FileStructureRuleTest : LintTestBase(::FileStructureRule) { @Test @Tag(WarningNames.FILE_INCORRECT_BLOCKS_ORDER) - fun `error in moving blocking at the first place`() { - lintMethod( + fun `error in moving blocking at the first place`(@TempDir tempDir: Path) { + lintMethodWithFile( """ // Without suppressing these, version catalog usage in `plugins` is marked as an error in IntelliJ: // https://youtrack.jetbrains.com/issue/KTIJ-19369 @@ -574,8 +576,9 @@ class FileStructureRuleTest : LintTestBase(::FileStructureRule) { id(libs.plugins.kotlinJvm.get().pluginId) } """.trimIndent(), - expectedLintErrors = arrayOf(LintError(3, 1, ruleId, "${Warnings.FILE_INCORRECT_BLOCKS_ORDER.warnText()} @file:Suppress(\"DSL_SCOPE_VIOLATION\")", true)), fileName = "build.gradle.kts", + tempDir = tempDir, + expectedLintErrors = arrayOf(LintError(3, 1, ruleId, "${Warnings.FILE_INCORRECT_BLOCKS_ORDER.warnText()} @file:Suppress(\"DSL_SCOPE_VIOLATION\")", true)), ) } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/MagicNumberRuleWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/MagicNumberRuleWarnTest.kt index ec73e59b55..165968ba3e 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/MagicNumberRuleWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/MagicNumberRuleWarnTest.kt @@ -10,6 +10,8 @@ import com.pinterest.ktlint.core.LintError import generated.WarningNames import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path class MagicNumberRuleWarnTest : LintTestBase(::MagicNumberRule) { private val ruleId = "$DIKTAT_RULE_SET_ID:${MagicNumberRule.NAME_ID}" @@ -186,8 +188,8 @@ class MagicNumberRuleWarnTest : LintTestBase(::MagicNumberRule) { @Test @Tag(WarningNames.MAGIC_NUMBER) - fun `check ignore numbers in test`() { - lintMethod( + fun `check ignore numbers in test`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |fun f1oo() { | val m = -1 @@ -205,6 +207,7 @@ class MagicNumberRuleWarnTest : LintTestBase(::MagicNumberRule) { | return 32 |} """.trimMargin(), + tempDir = tempDir, fileName = "src/test/kotlin/org/cqfn/diktat/test/hehe/MagicNumberTest.kt", rulesConfigList = rulesConfigIgnoreNumbersMagicNumber, ) diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt index 6df9da27dd..e22062f4b4 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt @@ -14,6 +14,8 @@ import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tags import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path @Suppress("LargeClass") class NewlinesRuleWarnTest : LintTestBase(::NewlinesRule) { @@ -1168,13 +1170,14 @@ class NewlinesRuleWarnTest : LintTestBase(::NewlinesRule) { @Test @Tag(WarningNames.COMPLEX_EXPRESSION) - fun `COMPLEX_EXPRESSION shouldn't trigger for declarations in kts`() { - lintMethod( + fun `COMPLEX_EXPRESSION shouldn't trigger for declarations in kts`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |dependencies { | implementation(libs.spring.cloud.starter.gateway) |} """.trimMargin(), + tempDir = tempDir, fileName = "build.gradle.kts" ) } 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 79adc34eb8..aef5f8ff75 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 @@ -12,12 +12,15 @@ import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXT import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.EXTENDED_INDENT_OF_PARAMETERS import org.cqfn.diktat.ruleset.utils.indentation.IndentationConfig.Companion.INDENTATION_SIZE import org.cqfn.diktat.util.LintTestBase +import org.cqfn.diktat.util.TEST_FILE_NAME import com.pinterest.ktlint.core.LintError import generated.WarningNames 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 java.nio.file.Path /** * Legacy indentation tests. @@ -85,34 +88,38 @@ class IndentationRuleWarnTest : LintTestBase(::IndentationRule) { @Test @Tag(WarningNames.WRONG_INDENTATION) - fun `should warn if no new line at the end of file`() { - lintMethod( + fun `should warn if no new line at the end of file`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |class Example { | val zero = 0 |} """.trimMargin(), - LintError(3, 1, ruleId, "${WRONG_INDENTATION.warnText()} no newline at the end of file TestFileName.kt", true) + tempDir = tempDir, + fileName = TEST_FILE_NAME, + LintError(3, 1, ruleId, "${WRONG_INDENTATION.warnText()} no newline at the end of file $TEST_FILE_NAME", true) ) } @Test @Tag(WarningNames.WRONG_INDENTATION) - fun `should warn if no new line at the end of file, last child whitespace`() { - lintMethod( + fun `should warn if no new line at the end of file, last child whitespace`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |class Example { | val zero = 0 |} """.trimMargin(), - LintError(3, 1, ruleId, "${WRONG_INDENTATION.warnText()} no newline at the end of file TestFileName.kt", true) + tempDir = tempDir, + fileName = TEST_FILE_NAME, + LintError(3, 1, ruleId, "${WRONG_INDENTATION.warnText()} no newline at the end of file $TEST_FILE_NAME", true) ) } @Test @Tag(WarningNames.WRONG_INDENTATION) - fun `should warn if too many blank lines at the end of file`() { - lintMethod( + fun `should warn if too many blank lines at the end of file`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |class Example { | val zero = 0 @@ -120,7 +127,9 @@ class IndentationRuleWarnTest : LintTestBase(::IndentationRule) { | | """.trimMargin(), - LintError(5, 1, ruleId, "${WRONG_INDENTATION.warnText()} too many blank lines at the end of file TestFileName.kt", true) + tempDir = tempDir, + fileName = TEST_FILE_NAME, + LintError(5, 1, ruleId, "${WRONG_INDENTATION.warnText()} too many blank lines at the end of file $TEST_FILE_NAME", true) ) } @@ -693,24 +702,26 @@ class IndentationRuleWarnTest : LintTestBase(::IndentationRule) { @Test @Tag(WarningNames.WRONG_INDENTATION) - fun `check script`() { - lintMethod( + fun `check script`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |val q = 1 | """.trimMargin(), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" ) } @Test @Tag(WarningNames.WRONG_INDENTATION) - fun `check gradle script`() { - lintMethod( + fun `check gradle script`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |projectName = "diKTat" | """.trimMargin(), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/build.gradle.kts" ) } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AvoidUtilityClassWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AvoidUtilityClassWarnTest.kt index 0f18e6312e..f50843b43c 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AvoidUtilityClassWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AvoidUtilityClassWarnTest.kt @@ -9,6 +9,8 @@ import com.pinterest.ktlint.core.LintError import generated.WarningNames import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path class AvoidUtilityClassWarnTest : LintTestBase(::AvoidUtilityClass) { private val ruleId = "$DIKTAT_RULE_SET_ID:${AvoidUtilityClass.NAME_ID}" @@ -99,8 +101,8 @@ class AvoidUtilityClassWarnTest : LintTestBase(::AvoidUtilityClass) { @Test @Tag(WarningNames.AVOID_USING_UTILITY_CLASS) - fun `check test-class`() { - lintMethod( + fun `check test-class`(@TempDir tempDir: Path) { + lintMethodWithFile( """ |class StringUtils { | fun goo(tex: String): Int { @@ -108,10 +110,11 @@ class AvoidUtilityClassWarnTest : LintTestBase(::AvoidUtilityClass) { | } |} """.trimMargin(), - LintError(1, 1, ruleId, "${AVOID_USING_UTILITY_CLASS.warnText()} StringUtils"), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/Example.kt", + LintError(1, 1, ruleId, "${AVOID_USING_UTILITY_CLASS.warnText()} StringUtils"), ) - lintMethod( + lintMethodWithFile( """ |@Test |class StringUtils1 { @@ -120,9 +123,10 @@ class AvoidUtilityClassWarnTest : LintTestBase(::AvoidUtilityClass) { | } |} """.trimMargin(), + tempDir = tempDir, fileName = "src/test/kotlin/org/cqfn/diktat/Example.kt" ) - lintMethod( + lintMethodWithFile( """ |class StringUtils2 { | fun goo(tex: String): Int { @@ -130,6 +134,7 @@ class AvoidUtilityClassWarnTest : LintTestBase(::AvoidUtilityClass) { | } |} """.trimMargin(), + tempDir = tempDir, fileName = "src/test/kotlin/org/cqfn/diktat/UtilTest.kt" ) } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/RunInScriptWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/RunInScriptWarnTest.kt index 440dbdf3dd..320062465d 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/RunInScriptWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/RunInScriptWarnTest.kt @@ -9,14 +9,16 @@ import com.pinterest.ktlint.core.LintError import generated.WarningNames import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path class RunInScriptWarnTest : LintTestBase(::RunInScript) { private val ruleId: String = "$DIKTAT_RULE_SET_ID:${RunInScript.NAME_ID}" @Test @Tag(WarningNames.RUN_IN_SCRIPT) - fun `check simple example`() { - lintMethod( + fun `check simple example`(@TempDir tempDir: Path) { + lintMethodWithFile( """ class A {} @@ -44,19 +46,20 @@ class RunInScriptWarnTest : LintTestBase(::RunInScript) { } """.trimMargin(), + tempDir = tempDir, + fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts", LintError(10, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} foo/*df*/()", true), LintError(12, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} foo( //dfdg...", true), LintError(15, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} println(\"hello\")", true), LintError(17, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} w.map { it -> it }", true), - LintError(19, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} tasks.register(\"a\") {...", true), - fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" + LintError(19, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} tasks.register(\"a\") {...", true) ) } @Test @Tag(WarningNames.RUN_IN_SCRIPT) - fun `check correct examples`() { - lintMethod( + fun `check correct examples`(@TempDir tempDir: Path) { + lintMethodWithFile( """ run { println("hello") @@ -68,14 +71,15 @@ class RunInScriptWarnTest : LintTestBase(::RunInScript) { } """.trimMargin(), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" ) } @Test @Tag(WarningNames.RUN_IN_SCRIPT) - fun `check correct with custom wrapper`() { - lintMethod( + fun `check correct with custom wrapper`(@TempDir tempDir: Path) { + lintMethodWithFile( """ custom { println("hello") @@ -87,14 +91,15 @@ class RunInScriptWarnTest : LintTestBase(::RunInScript) { println("hello") } """.trimMargin(), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" ) } @Test @Tag(WarningNames.RUN_IN_SCRIPT) - fun `check gradle file`() { - lintMethod( + fun `check gradle file`(@TempDir tempDir: Path) { + lintMethodWithFile( """ class A {} @@ -126,15 +131,16 @@ class RunInScriptWarnTest : LintTestBase(::RunInScript) { }) """.trimMargin(), - LintError(6, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} if(true) {...", true), - fileName = "src/main/kotlin/org/cqfn/diktat/builds.gradle.kts" + tempDir = tempDir, + fileName = "src/main/kotlin/org/cqfn/diktat/builds.gradle.kts", + LintError(6, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} if(true) {...", true) ) } @Test @Tag(WarningNames.RUN_IN_SCRIPT) - fun `check gradle script with eq expression`() { - lintMethod( + fun `check gradle script with eq expression`(@TempDir tempDir: Path) { + lintMethodWithFile( """ version = "0.1.0-SNAPSHOT" @@ -146,14 +152,15 @@ class RunInScriptWarnTest : LintTestBase(::RunInScript) { foo().goo() """.trimMargin(), + tempDir = tempDir, fileName = "src/main/kotlin/org/cqfn/diktat/builds.gradle.kts" ) } @Test @Tag(WarningNames.RUN_IN_SCRIPT) - fun `check kts script with eq expression`() { - lintMethod( + fun `check kts script with eq expression`(@TempDir tempDir: Path) { + lintMethodWithFile( """ version = "0.1.0-SNAPSHOT" @@ -163,9 +170,10 @@ class RunInScriptWarnTest : LintTestBase(::RunInScript) { foo/*df*/() """.trimMargin(), + tempDir = tempDir, + fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts", LintError(1, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} version = \"0.1.0-SNAPSHOT\"", true), - LintError(7, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} foo/*df*/()", true), - fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" + LintError(7, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} foo/*df*/()", true) ) } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProviderTest.kt similarity index 72% rename from diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt rename to diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProviderTest.kt index 49cc2f81b6..2ea069c128 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProvider4Test.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/DiktatRuleSetProviderTest.kt @@ -5,7 +5,6 @@ package org.cqfn.diktat.util import org.cqfn.diktat.api.DiktatRuleSet -import org.cqfn.diktat.api.DiktatRuleSetFactory import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.common.config.rules.RulesConfigReader import org.cqfn.diktat.ruleset.rules.DiktatRule @@ -22,20 +21,6 @@ import kotlin.io.path.isRegularFile import kotlin.io.path.nameWithoutExtension import kotlin.io.path.walk -/** - * simple class for emulating RuleSetProvider to inject .yml rule configuration and mock this part of code - */ -class DiktatRuleSetProvider4Test( - private val ruleSupplier: (rulesConfigList: List) -> DiktatRule, - rulesConfigList: List?, -) : DiktatRuleSetFactory { - private val rulesConfigList: List? = rulesConfigList ?: RulesConfigReader(javaClass.classLoader).readResource("diktat-analysis.yml") - - override fun invoke(): DiktatRuleSet = DiktatRuleSet(listOf(ruleSupplier.invoke(rulesConfigList ?: emptyList()))) - - override fun create(configFile: String): DiktatRuleSet = throw IllegalStateException("Method is not supported for testing") -} - class DiktatRuleSetProviderTest { @OptIn(ExperimentalPathApi::class) @Suppress("UnsafeCallOnNullableType") @@ -70,5 +55,21 @@ class DiktatRuleSetProviderTest { private val ignoredRuleNames = listOf( "DummyWarning", ) + + /** + * Simple method to emulate [DiktatRuleSet] to inject `.yml` rule configuration and mock this part of code. + */ + internal fun diktatRuleSetForTest( + ruleSupplier: (rulesConfigList: List) -> DiktatRule, + rulesConfigList: List?, + ): DiktatRuleSet = run { + rulesConfigList ?: RulesConfigReader(Companion::class.java.classLoader) + .readResource("diktat-analysis.yml") + .orEmpty() + } + .let(ruleSupplier) + .let { + DiktatRuleSet(listOf(it)) + } } } diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt index c90af420a8..177e5d6095 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/util/FixTestBase.kt @@ -2,11 +2,13 @@ package org.cqfn.diktat.util import org.cqfn.diktat.api.DiktatCallback import org.cqfn.diktat.common.config.rules.RulesConfig -import org.cqfn.diktat.ktlint.defaultCallback import org.cqfn.diktat.ktlint.format import org.cqfn.diktat.ruleset.rules.DiktatRule import org.cqfn.diktat.test.framework.processing.FileComparisonResult +import org.cqfn.diktat.test.framework.processing.ResourceReader import org.cqfn.diktat.test.framework.processing.TestComparatorUnit +import org.cqfn.diktat.util.DiktatRuleSetProviderTest.Companion.diktatRuleSetForTest +import mu.KotlinLogging import org.intellij.lang.annotations.Language import org.junit.jupiter.api.Assertions import java.nio.file.Path @@ -28,11 +30,10 @@ open class FixTestBase( private val testComparatorUnitSupplier = { overrideRulesConfigList: List? -> TestComparatorUnit( resourceFilePath = resourceFilePath, - function = { expectedText, testFilePath -> + function = { testFile -> format( - ruleSetSupplier = { DiktatRuleSetProvider4Test(ruleSupplier, overrideRulesConfigList ?: defaultRulesConfigList).invoke() }, - text = expectedText, - fileName = testFilePath, + ruleSetSupplier = { diktatRuleSetForTest(ruleSupplier, overrideRulesConfigList ?: defaultRulesConfigList) }, + file = testFile, cb = cb, ) }, @@ -43,21 +44,18 @@ open class FixTestBase( * @param expectedPath path to file with expected result, relative to [resourceFilePath] * @param testPath path to file with code that will be transformed by formatter, relative to [resourceFilePath] * @param overrideRulesConfigList optional override to [defaultRulesConfigList] - * @param trimLastEmptyLine whether the last (empty) line should be - * discarded when reading the content of [testPath]. - * @param replacements a map of replacements which will be applied to [expectedPath] and [testPath] before comparing. + * @param resourceReader [ResourceReader] to read resource content. * @see fixAndCompareContent */ protected fun fixAndCompare( expectedPath: String, testPath: String, overrideRulesConfigList: List? = null, - trimLastEmptyLine: Boolean = false, - replacements: Map = emptyMap(), + resourceReader: ResourceReader = ResourceReader.default, ) { val testComparatorUnit = testComparatorUnitSupplier(overrideRulesConfigList) val result = testComparatorUnit - .compareFilesFromResources(expectedPath, testPath, trimLastEmptyLine, replacements) + .compareFilesFromResources(expectedPath, testPath, resourceReader) Assertions.assertTrue( result.isSuccessful ) { @@ -97,6 +95,14 @@ open class FixTestBase( val testComparatorUnit = testComparatorUnitSupplier(overrideRulesConfigList) return testComparatorUnit - .compareFilesFromFileSystem(expected, actual, false) + .compareFilesFromFileSystem(expected, actual) + } + + companion object { + private val log = KotlinLogging.logger { } + + private val defaultCallback = DiktatCallback { error, _ -> + log.warn { "Received linting error: $error" } + } } } 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 b08c16f47f..91ea91d3a4 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 @@ -1,14 +1,20 @@ package org.cqfn.diktat.util +import org.cqfn.diktat.api.DiktatCallback import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.ktlint.DiktatErrorImpl.Companion.unwrap import org.cqfn.diktat.ktlint.lint import org.cqfn.diktat.ruleset.rules.DiktatRule -import com.pinterest.ktlint.core.KtLint +import org.cqfn.diktat.util.DiktatRuleSetProviderTest.Companion.diktatRuleSetForTest 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 +import java.nio.file.Path +import java.nio.file.StandardOpenOption +import kotlin.io.path.createDirectories +import kotlin.io.path.readText +import kotlin.io.path.writeText /** * Base class for testing rules without fixing code. @@ -23,18 +29,68 @@ open class LintTestBase(private val ruleSupplier: (rulesConfigList: List? = null, - fileName: String? = null + ) = doAssert( + actualLintErrors = lintResult(code, rulesConfigList), + description = "lint result for \"$code\"", + expectedLintErrors = expectedLintErrors + ) + + /** + * Perform linting of [code] by creating a file in [tempDir] with [fileName], collect errors and compare with [expectedLintErrors] + * + * @param code code to check + * @param tempDir a path to temporary folder + * @param fileName relative path to file which needs to be checked + * @param expectedLintErrors expected errors + * @param rulesConfigList optional override for `this.rulesConfigList` + * @see lintResult + */ + fun lintMethodWithFile( + @Language("kotlin") code: String, + tempDir: Path, + fileName: String, + vararg expectedLintErrors: LintError, + rulesConfigList: List? = null, ) { - val actualLintErrors = lintResult(code, rulesConfigList, fileName) + val file = tempDir.resolve(fileName).also { + it.parent.createDirectories() + it.writeText(code) + } + lintMethodWithFile( + file = file, + expectedLintErrors = expectedLintErrors, + rulesConfigList = rulesConfigList, + ) + } - val description = "lint result for \"$code\"" + /** + * Perform linting of [file], collect errors and compare with [expectedLintErrors] + * + * @param file a path to file to check + * @param expectedLintErrors expected errors + * @param rulesConfigList optional override for `this.rulesConfigList` + * @see lintResult + */ + fun lintMethodWithFile( + file: Path, + vararg expectedLintErrors: LintError, + rulesConfigList: List? = null, + ) = doAssert( + actualLintErrors = lintResult(file, rulesConfigList), + description = "lint result for \"${file.readText()}\"", + expectedLintErrors = expectedLintErrors + ) + private fun doAssert( + actualLintErrors: List, + description: String, + vararg expectedLintErrors: LintError, + ) { when { expectedLintErrors.size == 1 && actualLintErrors.size == 1 -> { val actual = actualLintErrors[0] @@ -59,32 +115,59 @@ open class LintTestBase(private val ruleSupplier: (rulesConfigList: List? = null, + ): List { + val lintErrors: MutableList = mutableListOf() + + lint( + ruleSetSupplier = { rulesConfigList.toDiktatRuleSet() }, + file = file, + cb = lintErrors.collector(), + ) + + return lintErrors + } + /** * Lints the [code] and returns the errors collected, but (unlike - * [lintMethod]) doesn't make any assertions. + * [lintMethodWithFile]) doesn't make any assertions. * * @param code the code to check. * @param rulesConfigList an optional override for `this.rulesConfigList`. - * @param fileName an optional override for the file name. * @return the list of lint errors. - * @see lintMethod + * @see lintMethodWithFile */ protected fun lintResult( @Language("kotlin") code: String, rulesConfigList: List? = null, - fileName: String? = null ): List { - val actualFileName = fileName ?: TEST_FILE_NAME val lintErrors: MutableList = mutableListOf() lint( - ruleSetSupplier = { DiktatRuleSetProvider4Test(ruleSupplier, - rulesConfigList ?: this.rulesConfigList).invoke() }, + ruleSetSupplier = { rulesConfigList.toDiktatRuleSet() }, text = code, - fileName = actualFileName, - cb = { lintError, _ -> lintErrors += lintError.unwrap() }, + cb = lintErrors.collector(), ) return lintErrors } + + private fun List?.toDiktatRuleSet() = diktatRuleSetForTest(ruleSupplier, this ?: rulesConfigList) + + companion object { + private fun MutableList.collector(): DiktatCallback = DiktatCallback { error, _ -> + this += error.unwrap() + } + } } diff --git a/diktat-rules/src/test/resources/test/chapter6/abstract_classes/ShouldReplaceAbstractKeywordTest.kt b/diktat-rules/src/test/resources/test/chapter6/abstract_classes/ShouldReplaceAbstractKeywordTest.kt index 0e26c4a8d5..a89ce689bb 100644 --- a/diktat-rules/src/test/resources/test/chapter6/abstract_classes/ShouldReplaceAbstractKeywordTest.kt +++ b/diktat-rules/src/test/resources/test/chapter6/abstract_classes/ShouldReplaceAbstractKeywordTest.kt @@ -26,4 +26,4 @@ abstract class Another { abstract fun absFunc() fun someFunc(){} -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/chapter6/script/SimpleRunInScriptExpected.kts b/diktat-rules/src/test/resources/test/chapter6/script/SimpleRunInScriptExpected.kts index 7c0b81a2a1..e78b6c119e 100644 --- a/diktat-rules/src/test/resources/test/chapter6/script/SimpleRunInScriptExpected.kts +++ b/diktat-rules/src/test/resources/test/chapter6/script/SimpleRunInScriptExpected.kts @@ -15,4 +15,4 @@ run { also { println("a") -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/LambdaArgExpected.kt b/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/LambdaArgExpected.kt index 47e1b4f5b5..f490d6511f 100644 --- a/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/LambdaArgExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/LambdaArgExpected.kt @@ -7,4 +7,4 @@ private fun checkCommentedCode(node: ASTNode) { .map { (strangecase, text) -> "" } -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/VariableNamingExpected.kt b/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/VariableNamingExpected.kt index a3f5eae19d..1acd15253a 100644 --- a/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/VariableNamingExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph1/naming/identifiers/VariableNamingExpected.kt @@ -45,4 +45,4 @@ class B { val qwe = QQ } } -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/paragraph2/kdoc/OrderedTagsAssertionExpected.kt b/diktat-rules/src/test/resources/test/paragraph2/kdoc/OrderedTagsAssertionExpected.kt index fe4d7db474..425444742c 100644 --- a/diktat-rules/src/test/resources/test/paragraph2/kdoc/OrderedTagsAssertionExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph2/kdoc/OrderedTagsAssertionExpected.kt @@ -9,4 +9,4 @@ package com.saveourtool.save.reporter.json class JsonReporter( override val out: BufferedSink, builder: PolymorphicModuleBuilder.() -> Unit = {} -) : Reporter \ No newline at end of file +) : Reporter diff --git a/diktat-rules/src/test/resources/test/paragraph3/annotations/AnnotationCommentTest.kt b/diktat-rules/src/test/resources/test/paragraph3/annotations/AnnotationCommentTest.kt index f6b5e30cfb..8a53ec40f1 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/annotations/AnnotationCommentTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/annotations/AnnotationCommentTest.kt @@ -3,4 +3,4 @@ class A { } @Foo /* */ @Goo /* */ @Qwe class AA {} -/** */ @Foo /** */ @Gg class Bb {} \ No newline at end of file +/** */ @Foo /** */ @Gg class Bb {} diff --git a/diktat-rules/src/test/resources/test/paragraph3/enum_separated/LastElementCommentTest.kt b/diktat-rules/src/test/resources/test/paragraph3/enum_separated/LastElementCommentTest.kt index 0705384cdd..8cb04d2817 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/enum_separated/LastElementCommentTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/enum_separated/LastElementCommentTest.kt @@ -76,4 +76,4 @@ enum class Foo34 { A, B, C; /** some comment 34 */ -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/paragraph3/indentation/ConstructorExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/indentation/ConstructorExpected.kt index 2453c2c1ac..bd1170d20a 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/indentation/ConstructorExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/indentation/ConstructorExpected.kt @@ -13,4 +13,3 @@ sealed class SealedExample { class Subclass(val property1: Type1, val property2: Type2, val property3: Type3, val property4: Type4) : SealedExample() } - diff --git a/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentFullExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentFullExpected.kt index e6cb579d99..77aaa10b57 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentFullExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentFullExpected.kt @@ -90,4 +90,3 @@ enum class Enumeration { fun veryLongExpressionBodyMethod() = "abc" - diff --git a/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationFull1Expected.kt b/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationFull1Expected.kt index 890053ba1f..6e515cc863 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationFull1Expected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationFull1Expected.kt @@ -65,4 +65,3 @@ data class Example(val field1: Type1, some text $foo $bar another text """.trimIndent() } - diff --git a/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationParametersExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationParametersExpected.kt index de75ebd1f1..b2ee6fa420 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationParametersExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/indentation/IndentationParametersExpected.kt @@ -10,4 +10,3 @@ fun test( val test = Test(param1, param2, param3) } - diff --git a/diktat-rules/src/test/resources/test/paragraph3/newlines/ColonExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/newlines/ColonExpected.kt index 81edec3196..b86656df67 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/newlines/ColonExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/newlines/ColonExpected.kt @@ -1,4 +1,4 @@ package test.paragraph3.newlines fun foo(a: Int, - b: Int) { } \ No newline at end of file + b: Int) { } diff --git a/diktat-rules/src/test/resources/test/paragraph3/nullable/NullPrimitiveExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/nullable/NullPrimitiveExpected.kt index fe5f9aaa14..f1c2b40979 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/nullable/NullPrimitiveExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/nullable/NullPrimitiveExpected.kt @@ -8,4 +8,4 @@ class A { val f: Byte = 0 val g: Long = 0L val h: Char = '' -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/paragraph3/spaces/LBraceAfterKeywordExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/spaces/LBraceAfterKeywordExpected.kt index 7f974682c6..9e3bcc86e7 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/spaces/LBraceAfterKeywordExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/spaces/LBraceAfterKeywordExpected.kt @@ -14,4 +14,4 @@ class Example { try { } finally { } } -} \ No newline at end of file +} diff --git a/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt index bd80f5e585..3663988509 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt @@ -33,4 +33,4 @@ val myTest22 = "string${foo()}" val myTest23 = x.toString() + foo() val myTest24 = foo() + "string" val myTest25 = "String ${valueStr?.value}" -val myTest26 = "my string ${if (true) "1" else "2"}" \ No newline at end of file +val myTest26 = "my string ${if (true) "1" else "2"}" diff --git a/diktat-rules/src/test/resources/test/paragraph3/top_level/TopLevelWithCommentExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/top_level/TopLevelWithCommentExpected.kt index 58968da89d..0437700af0 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/top_level/TopLevelWithCommentExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/top_level/TopLevelWithCommentExpected.kt @@ -21,4 +21,4 @@ fun foo() {} /* text here - */ \ No newline at end of file + */ diff --git a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt index 34455f5a8c..bc8e445b07 100644 --- a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt +++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt @@ -8,6 +8,7 @@ import org.cqfn.diktat.test.framework.util.deleteIfExistsSilently import org.cqfn.diktat.test.framework.util.inheritJavaHome import org.cqfn.diktat.test.framework.util.isWindows import org.cqfn.diktat.test.framework.util.temporaryDirectory +import generated.KTLINT_VERSION import mu.KotlinLogging import org.assertj.core.api.Assertions.fail @@ -34,7 +35,6 @@ class DiktatSaveSmokeTest : DiktatSmokeTestBase() { config: Path, expected: String, test: String, - trimLastEmptyLine: Boolean, ) { saveSmokeTest(config, test) } diff --git a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt index d7db0408d6..b70d814bb0 100644 --- a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt +++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTest.kt @@ -21,11 +21,10 @@ class DiktatSmokeTest : DiktatSmokeTestBase() { config: Path, expected: String, test: String, - trimLastEmptyLine: Boolean, ) { Assertions.assertTrue( getTestComparatorUnit(config) - .compareFilesFromResources(expected, test, trimLastEmptyLine) + .compareFilesFromResources(expected, test) .isSuccessful ) } @@ -41,11 +40,10 @@ class DiktatSmokeTest : DiktatSmokeTestBase() { private fun getTestComparatorUnit(config: Path) = TestComparatorUnit( resourceFilePath = RESOURCE_FILE_PATH, - function = { expectedText, testFilePath -> + function = { testFile -> format( ruleSetSupplier = { DiktatRuleSetProvider(config.absolutePathString()).invoke() }, - text = expectedText, - fileName = testFilePath, + file = testFile, cb = { lintError, _ -> unfixedLintErrors.add(lintError) }, ) }, diff --git a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt index b26871f538..b71a3baa5a 100644 --- a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt +++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestBase.kt @@ -315,9 +315,9 @@ abstract class DiktatSmokeTestBase { ) // so that trailing newline isn't checked, because it's incorrectly read in tests and we are comparing file with itself // file name is `gradle_` so that IDE doesn't suggest to import gradle project val tmpFilePath = "../../../build.gradle.kts" - fixAndCompare(configFilePath, tmpFilePath, tmpFilePath, false) + fixAndCompare(configFilePath, tmpFilePath, tmpFilePath) assertUnfixedLintErrors { unfixedLintErrors -> - Assertions.assertTrue(unfixedLintErrors.isEmpty()) + assertThat(unfixedLintErrors).isEmpty() } } @@ -367,7 +367,6 @@ abstract class DiktatSmokeTestBase { config: Path, expected: String, test: String, - trimLastEmptyLine: Boolean = true, ) abstract fun doAssertUnfixedLintErrors(diktatErrorConsumer: (List) -> Unit) diff --git a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestUtils.kt b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestUtils.kt index 12807c7390..f0aa07d2a5 100644 --- a/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestUtils.kt +++ b/diktat-ruleset/src/test/kotlin/org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestUtils.kt @@ -15,7 +15,6 @@ internal const val BUILD_DIRECTORY = "build/libs" internal const val DIKTAT_FAT_JAR = "diktat.jar" internal const val DIKTAT_FAT_JAR_GLOB = "diktat-*.jar" internal const val KTLINT_FAT_JAR = "ktlint" -internal const val KTLINT_VERSION = "0.46.1" private val logger = KotlinLogging.logger {} diff --git a/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt index ba55d3661d..e18b8bb078 100644 --- a/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt +++ b/diktat-ruleset/src/test/resources/test/smoke/src/main/kotlin/Example1-2Expected.kt @@ -45,3 +45,4 @@ fun foo(x : Int ) } } + diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/FileComparator.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/FileComparator.kt index 8d93ee66ec..fed34e997e 100644 --- a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/FileComparator.kt +++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/FileComparator.kt @@ -1,23 +1,20 @@ package org.cqfn.diktat.test.framework.processing +import org.cqfn.diktat.test.framework.util.readTextOrNull import io.github.petertrr.diffutils.diff import io.github.petertrr.diffutils.patch.ChangeDelta import io.github.petertrr.diffutils.text.DiffRowGenerator import mu.KotlinLogging import java.io.File -import java.io.IOException -import java.nio.file.Path -import kotlin.io.path.readLines /** * A class that is capable of comparing files content */ class FileComparator( - private val expectedResultFileName: String, - private val expectedResultList: List, - private val actualResultFileName: String, - private val actualResultList: List, + private val fileName: String, + private val expectedResult: String, + private val actualResult: String, ) { private val diffGenerator = DiffRowGenerator( columnWidth = Int.MAX_VALUE, @@ -32,14 +29,17 @@ class FileComparator( * delta in files */ val delta: String? by lazy { - if (expectedResultList.isEmpty()) { + if (expectedResult.isEmpty()) { return@lazy null } val regex = (".*// ;warn:?(.*):(\\d*): (.+)").toRegex() - val expectWithoutWarn = expectedResultList.filterNot { line -> - line.contains(regex) - } - val patch = diff(expectWithoutWarn, actualResultList) + val expectWithoutWarn = expectedResult + .split("\n") + .filterNot { line -> + line.contains(regex) + } + .joinToString("\n") + val patch = diff(expectWithoutWarn, actualResult, null) if (patch.deltas.isEmpty()) { return@lazy null @@ -62,22 +62,20 @@ class FileComparator( constructor( expectedResultFile: File, - actualResultList: List + actualResult: String ) : this( - expectedResultFileName = expectedResultFile.name, - expectedResultList = readFile(expectedResultFile.toPath()), - actualResultFileName = "No file name.kt", - actualResultList = actualResultList, + fileName = expectedResultFile.name, + expectedResult = expectedResultFile.toPath().readTextOrNull().orEmpty(), + actualResult = actualResult, ) constructor( expectedResultFile: File, actualResultFile: File ) : this( - expectedResultFileName = expectedResultFile.name, - expectedResultList = readFile(expectedResultFile.toPath()), - actualResultFileName = actualResultFile.name, - actualResultList = readFile(actualResultFile.toPath()), + fileName = expectedResultFile.name, + expectedResult = expectedResultFile.toPath().readTextOrNull().orEmpty(), + actualResult = actualResultFile.toPath().readTextOrNull().orEmpty(), ) /** @@ -91,37 +89,24 @@ class FileComparator( ) fun compareFilesEqual(): Boolean { try { - if (expectedResultList.isEmpty()) { + if (expectedResult.isEmpty()) { return false } val joinedDeltas = delta ?: return true log.error(""" - |Expected result from <$expectedResultFileName> and <$actualResultFileName> formatted are different. + |Expected result for <$fileName> formatted are different. |See difference below: |$joinedDeltas """.trimMargin() ) return false } catch (e: IllegalArgumentException) { - log.error("Not able to prepare diffs between <$expectedResultFileName> and <$actualResultFileName>", e) + log.error("Not able to prepare diffs for <$fileName>", e) return false } } companion object { private val log = KotlinLogging.logger {} - - /** - * @param file file where to write these list to, separated with newlines. - * @return a list of lines from the file, or an empty list if an I/O error - * has occurred. - */ - private fun readFile(file: Path): List = - try { - file.readLines() - } catch (e: IOException) { - log.error("Not able to read file: $file") - emptyList() - } } } diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/ResourceReader.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/ResourceReader.kt new file mode 100644 index 0000000000..b118ce5ff0 --- /dev/null +++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/ResourceReader.kt @@ -0,0 +1,65 @@ +package org.cqfn.diktat.test.framework.processing + +import org.cqfn.diktat.test.framework.util.readTextOrNull +import mu.KotlinLogging +import java.nio.file.Path +import kotlin.io.path.createDirectories +import kotlin.io.path.isRegularFile +import kotlin.io.path.toPath +import kotlin.io.path.writeText + +/** + * A base interface to read resources for testing purposes + */ +interface ResourceReader : Function1 { + /** + * @param resourceName + * @return [Path] for provider [resourceName] + */ + override fun invoke(resourceName: String): Path? + + companion object { + private val log = KotlinLogging.logger {} + + /** + * Default implementation of [ResourceReader] + */ + val default: ResourceReader = object : ResourceReader { + override fun invoke(resourceName: String): Path? = javaClass.classLoader.getResource(resourceName) + ?.toURI() + ?.toPath() + .also { + if (it == null || !it.isRegularFile()) { + log.error { "Not able to find file for running test: $resourceName" } + } + } + } + + /** + * @param tempDir the temporary directory (usually injected by _JUnit_). + * @param replacements a map of replacements which will be applied to actual and expected content before comparing. + * @return Instance of [ResourceReader] with replacements of content + */ + fun withReplacements( + tempDir: Path, + replacements: Map, + ): ResourceReader = object : ResourceReader { + override fun invoke(resourceName: String): Path? = default.invoke(resourceName) + ?.let { originalFile -> + tempDir.resolve(resourceName) + .also { resultFile -> + originalFile.readTextOrNull()?.replaceAll(replacements) + ?.let { + resultFile.parent.createDirectories() + resultFile.writeText(it) + } + } + } + } + + private fun String.replaceAll(replacements: Map): String = replacements.entries + .fold(this) { result, replacement -> + result.replace(replacement.key, replacement.value) + } + } +} diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt index 49fb848025..077a809850 100644 --- a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt +++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestComparatorUnit.kt @@ -1,15 +1,10 @@ package org.cqfn.diktat.test.framework.processing +import org.cqfn.diktat.test.framework.util.readTextOrNull import mu.KotlinLogging -import java.io.IOException import java.nio.file.Path -import java.nio.file.Paths -import kotlin.io.path.Path -import kotlin.io.path.absolutePathString -import kotlin.io.path.copyTo import kotlin.io.path.isRegularFile import kotlin.io.path.name -import kotlin.io.path.readLines /** * Class that can apply transformation to an input file and then compare with expected result and output difference. @@ -21,7 +16,7 @@ import kotlin.io.path.readLines @Suppress("ForbiddenComment", "TYPE_ALIAS") class TestComparatorUnit( private val resourceFilePath: String, - private val function: (expectedText: String, testFilePath: String) -> String, + private val function: (testFile: Path) -> String, ) { /** * @param expectedResult the name of the resource which has the expected @@ -31,9 +26,7 @@ class TestComparatorUnit( * `newlineAtEnd` is `true`), then the file should end with **two** * consecutive linebreaks. * @param testFileStr the name of the resource which has the original content. - * @param trimLastEmptyLine whether the last (empty) line should be - * discarded when reading the content of [testFileStr]. - * @param replacements a map of replacements which will be applied to [expectedResult] and [testFileStr] before comparing. + * @param resourceReader [ResourceReader] to read resource content * @return the result of file comparison by their content. * @see compareFilesFromFileSystem */ @@ -41,11 +34,10 @@ class TestComparatorUnit( fun compareFilesFromResources( expectedResult: String, testFileStr: String, - trimLastEmptyLine: Boolean = false, - replacements: Map = emptyMap(), + resourceReader: ResourceReader = ResourceReader.default, ): FileComparisonResult { - val expectedPath = javaClass.classLoader.getResource("$resourceFilePath/$expectedResult") - val testPath = javaClass.classLoader.getResource("$resourceFilePath/$testFileStr") + val expectedPath = resourceReader("$resourceFilePath/$expectedResult") + val testPath = resourceReader("$resourceFilePath/$testFileStr") if (testPath == null || expectedPath == null) { log.error("Not able to find files for running test: $expectedResult and $testFileStr") return FileComparisonResult( @@ -56,10 +48,8 @@ class TestComparatorUnit( } return compareFilesFromFileSystem( - Paths.get(expectedPath.toURI()), - Paths.get(testPath.toURI()), - trimLastEmptyLine, - replacements, + expectedPath, + testPath, ) } @@ -70,9 +60,6 @@ class TestComparatorUnit( * an empty string (which is the case if `newlineAtEnd` is `true`), then * the file should end with **two** consecutive linebreaks. * @param testFile the file which has the original content. - * @param trimLastEmptyLine whether the last (empty) line should be - * discarded when reading the content of [testFile]. - * @param replacements a map of replacements which will be applied to [expectedFile] and [testFile] before comparing. * @return the result of file comparison by their content. * @see compareFilesFromResources */ @@ -80,8 +67,6 @@ class TestComparatorUnit( fun compareFilesFromFileSystem( expectedFile: Path, testFile: Path, - trimLastEmptyLine: Boolean = false, - replacements: Map = emptyMap(), ): FileComparisonResult { if (!testFile.isRegularFile() || !expectedFile.isRegularFile()) { log.error("Not able to find files for running test: $expectedFile and $testFile") @@ -92,58 +77,23 @@ class TestComparatorUnit( expectedContent = "// $expectedFile is a regular file: ${expectedFile.isRegularFile()}") } - val copyTestFile = Path("${testFile.absolutePathString()}_copy") - testFile.copyTo(copyTestFile, overwrite = true) - - val actualResult = function( - readFile(copyTestFile).replaceAll(replacements).joinToString("\n"), - copyTestFile.absolutePathString() - ) - - val actualFileContent = if (trimLastEmptyLine) { - actualResult.split("\n").dropLast(1) - } else { - // fixme: actualResult is separated by KtLint#determineLneSeparator, should be split by it here too - actualResult.split("\n") - } - - val expectedFileContent = readFile(expectedFile).replaceAll(replacements) + val actualFileContent = function(testFile) + val expectedFileContent = expectedFile.readTextOrNull().orEmpty() val comparator = FileComparator( expectedFile.name, expectedFileContent, - testFile.name, actualFileContent, ) return FileComparisonResult( comparator.compareFilesEqual(), comparator.delta, - actualFileContent.joinToString("\n"), - expectedFileContent.joinToString("\n")) + actualFileContent, + expectedFileContent) } private companion object { private val log = KotlinLogging.logger {} - - /** - * @param file the file whose content is to be read. - * @return file content as a list of lines, or an empty list if an I/O error - * has occurred. - */ - private fun readFile(file: Path): List = - try { - file.readLines() - } catch (e: IOException) { - log.error("Not able to read file: $file") - emptyList() - } - - private fun List.replaceAll(replacements: Map): List = map { line -> - replacements.entries - .fold(line) { result, replacement -> - result.replace(replacement.key, replacement.value) - } - } } } diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestCompare.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestCompare.kt index 9723b17cbb..d86f01d83c 100644 --- a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestCompare.kt +++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/processing/TestCompare.kt @@ -78,7 +78,7 @@ open class TestCompare : TestBase { private fun processToStdOut(): Boolean { this.testResult = executeCommand("cmd /c ${testConfig.executionCommand} $testFile") - return FileComparator(expectedResult, getExecutionResult()).compareFilesEqual() + return FileComparator(expectedResult, getExecutionResult().joinToString("\n")).compareFilesEqual() } private fun buildFullPathToResource(resourceFile: String, resourceAbsolutePath: String): File { diff --git a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt index 589dcfaea3..5f8b1d31a0 100644 --- a/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt +++ b/diktat-test-framework/src/main/kotlin/org/cqfn/diktat/test/framework/util/TestUtils.kt @@ -8,6 +8,7 @@ import mu.KotlinLogging import java.io.File import java.io.IOException +import java.nio.charset.StandardCharsets import java.nio.file.FileVisitResult import java.nio.file.FileVisitResult.CONTINUE import java.nio.file.Files @@ -29,6 +30,7 @@ import kotlin.io.path.deleteIfExists import kotlin.io.path.div import kotlin.io.path.isDirectory import kotlin.io.path.isSameFileAs +import kotlin.io.path.readText private val logger = KotlinLogging.logger {} @@ -272,6 +274,18 @@ fun String?.isWindows(): Boolean { return this != null && startsWith("Windows") } +/** + * @receiver the file whose content is to be read. + * @return file content as a single [String], or null if an I/O error + * has occurred. + */ +fun Path.readTextOrNull(): String? = try { + readText(StandardCharsets.UTF_8).replace("\r\n", "\n").replace("\r", "\n") +} catch (e: IOException) { + logger.error(e) { "Not able to read file: $this" } + null +} + /** * Retries the execution of the [block]. *