From 74126a5f80a4da430d5364448a64af3d11e821bd Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Tue, 28 Mar 2023 18:33:40 +0300 Subject: [PATCH 01/18] Diktat command ### What's done: - added DiktatProcessor - added DiktatProcessCommand - reused it in maven-plugin - reused it in gradle-plugin --- diktat-gradle-plugin/build.gradle.kts | 17 +- .../plugin/gradle/DiktatGradlePlugin.kt | 40 +-- .../plugin/gradle/DiktatJavaExecTaskBase.kt | 250 ------------------ .../org/cqfn/diktat/plugin/gradle/Utils.kt | 14 +- .../plugin/gradle/tasks/DiktatCheckTask.kt | 38 +++ .../plugin/gradle/tasks/DiktatFixTask.kt | 39 +++ .../plugin/gradle/tasks/DiktatTaskBase.kt | 212 +++++++++++++++ .../gradle/tasks/SarifReportMergeTask.kt | 9 +- .../plugin/gradle/DiktatGradlePluginTest.kt | 5 +- .../plugin/gradle/DiktatJavaExecTaskTest.kt | 138 +++++----- .../plugin/gradle/ReporterSelectionTest.kt | 2 +- diktat-maven-plugin/build.gradle.kts | 2 +- .../diktat/plugin/maven/DiktatBaseMojo.kt | 78 +++--- .../cqfn/diktat/plugin/maven/DiktatMojo.kt | 26 +- .../ruleset/rules/DiktatRuleSetProvider.kt | 6 +- diktat-ruleset/build.gradle.kts | 5 - .../org/cqfn/diktat/DiktatProcessCommand.kt | 128 +++++++++ .../kotlin/org/cqfn/diktat/DiktatProcessor.kt | 68 +++++ .../org/cqfn/diktat/api/DiktatCallback.kt | 15 ++ .../kotlin/org/cqfn/diktat/api/DiktatError.kt | 31 +++ .../org/cqfn/diktat/api/DiktatLogLevel.kt | 10 + .../diktat/ktlint/LintErrorCallbackWrapper.kt | 22 ++ .../cqfn/diktat/ktlint/LintErrorWrapper.kt | 34 +++ 23 files changed, 737 insertions(+), 452 deletions(-) delete mode 100644 diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt create mode 100644 diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt create mode 100644 diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatFixTask.kt create mode 100644 diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt diff --git a/diktat-gradle-plugin/build.gradle.kts b/diktat-gradle-plugin/build.gradle.kts index 2fc6a6626e..13aa895d28 100644 --- a/diktat-gradle-plugin/build.gradle.kts +++ b/diktat-gradle-plugin/build.gradle.kts @@ -13,17 +13,14 @@ plugins { dependencies { implementation(kotlin("gradle-plugin-api")) + implementation(projects.diktatRuleset) implementation(libs.sarif4k.jvm) - - api(projects.diktatCommon) { - exclude("org.jetbrains.kotlin", "kotlin-compiler-embeddable") - exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk8") - exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk7") - exclude("org.jetbrains.kotlin", "kotlin-stdlib") - exclude("org.jetbrains.kotlin", "kotlin-stdlib-common") - exclude("org.slf4j", "slf4j-log4j12") - } - + implementation(libs.ktlint.core) + implementation(libs.ktlint.reporter.plain) + implementation(libs.ktlint.reporter.sarif) + implementation(libs.ktlint.reporter.json) + implementation(libs.ktlint.reporter.html) + implementation(libs.ktlint.reporter.baseline) testImplementation(libs.junit.jupiter.api) testRuntimeOnly(libs.junit.jupiter.engine) } diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePlugin.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePlugin.kt index e444c458b6..7980e01e92 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePlugin.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePlugin.kt @@ -1,12 +1,10 @@ package org.cqfn.diktat.plugin.gradle +import org.cqfn.diktat.plugin.gradle.tasks.DiktatCheckTask.Companion.registerDiktatCheckTask +import org.cqfn.diktat.plugin.gradle.tasks.DiktatFixTask.Companion.registerDiktatFixTask import org.cqfn.diktat.plugin.gradle.tasks.configureMergeReportsTask -import generated.DIKTAT_VERSION -import generated.KTLINT_VERSION import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.artifacts.ExternalModuleDependency -import org.gradle.api.attributes.Bundling import org.gradle.api.tasks.util.PatternSet /** @@ -28,38 +26,8 @@ class DiktatGradlePlugin : Plugin { diktatConfigFile = project.rootProject.file("diktat-analysis.yml") } - // Configuration that will be used as classpath for JavaExec task. - val diktatConfiguration = project.configurations.create(DIKTAT_CONFIGURATION) { configuration -> - configuration.isVisible = false - configuration.dependencies.add(project.dependencies.create("com.pinterest:ktlint:$KTLINT_VERSION", closureOf { - /* - * Prevent the discovery of standard rules by excluding them as - * dependencies. - */ - val ktlintRuleSets = sequenceOf( - "standard", - "experimental", - "test", - "template" - ) - ktlintRuleSets.forEach { ktlintRuleSet -> - exclude( - mutableMapOf( - "group" to "com.pinterest.ktlint", - "module" to "ktlint-ruleset-$ktlintRuleSet" - ) - ) - } - - attributes { - it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.EXTERNAL)) - } - })) - configuration.dependencies.add(project.dependencies.create("org.cqfn.diktat:diktat-rules:$DIKTAT_VERSION")) - } - - project.registerDiktatCheckTask(diktatExtension, diktatConfiguration, patternSet) - project.registerDiktatFixTask(diktatExtension, diktatConfiguration, patternSet) + project.registerDiktatCheckTask(diktatExtension, patternSet) + project.registerDiktatFixTask(diktatExtension, patternSet) project.configureMergeReportsTask(diktatExtension) } diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt deleted file mode 100644 index 94f1690088..0000000000 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt +++ /dev/null @@ -1,250 +0,0 @@ -package org.cqfn.diktat.plugin.gradle - -import org.cqfn.diktat.common.config.rules.DIKTAT_CONF_PROPERTY -import org.cqfn.diktat.common.ktlint.ktlintDisabledRulesArgument -import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.DIKTAT_CHECK_TASK -import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.DIKTAT_FIX_TASK -import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.MIN_JVM_REQUIRES_ADD_OPENS - -import generated.DIKTAT_VERSION -import generated.KTLINT_VERSION -import org.gradle.api.JavaVersion -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.FileCollection -import org.gradle.api.provider.Property -import org.gradle.api.tasks.IgnoreEmptyDirectories -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.JavaExec -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity -import org.gradle.api.tasks.SkipWhenEmpty -import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.TaskProvider -import org.gradle.api.tasks.VerificationTask -import org.gradle.api.tasks.util.PatternFilterable -import org.gradle.api.tasks.util.PatternSet -import org.gradle.util.GradleVersion - -import java.io.File -import javax.inject.Inject - -/** - * A base diktat task for gradle <6.8, which wraps [JavaExec]. - * - * Note: class being `open` is required for gradle to create a task. - */ -open class DiktatJavaExecTaskBase @Inject constructor( - private val gradleVersionString: String, - diktatExtension: DiktatExtension, - diktatConfiguration: Configuration, - private val inputs: PatternFilterable, - additionalFlags: Iterable = emptyList() -) : JavaExec(), VerificationTask { - /** - * A backing [Property] for [getIgnoreFailures] and [setIgnoreFailures] - */ - @get:Internal - internal val ignoreFailuresProp: Property = project.objects.property(Boolean::class.javaObjectType) - - /** - * Whether diktat should be executed via JavaExec or not. - */ - @get:Internal - internal var shouldRun = true - - /** - * Files that will be analyzed by diktat - */ - @get:IgnoreEmptyDirectories - @get:SkipWhenEmpty - @get:PathSensitive(PathSensitivity.RELATIVE) - @get:InputFiles - val actualInputs: FileCollection by lazy { - if (inputs.includes.isEmpty() && inputs.excludes.isEmpty()) { - inputs.include("src/**/*.kt") - } - project.objects.fileCollection().from( - project.fileTree("${project.projectDir}").apply { - exclude("${project.buildDir}") - } - .matching(inputs) - ) - } - - init { - group = "verification" - if (isMainClassPropertySupported(gradleVersionString)) { - // `main` is deprecated and replaced with `mainClass` since gradle 6.4 - mainClass.set("com.pinterest.ktlint.Main") - } else { - @Suppress("Deprecation") - main = "com.pinterest.ktlint.Main" - } - - classpath = diktatConfiguration - project.logger.debug("Setting diktatCheck classpath to ${diktatConfiguration.dependencies.toSet()}") - if (diktatExtension.debug) { - project.logger.lifecycle("Running diktat $DIKTAT_VERSION with ktlint $KTLINT_VERSION") - } - ignoreFailures = diktatExtension.ignoreFailures - isIgnoreExitValue = ignoreFailures // ignore returned value of JavaExec started process if lint errors shouldn't fail the build - systemProperty(DIKTAT_CONF_PROPERTY, resolveConfigFile(diktatExtension.diktatConfigFile).also { - project.logger.info("Setting system property for diktat config to $it") - }) - args = additionalFlags.toMutableList().apply { - /* - * Disable the standard rules via the command line. - * - * Classpath exclusion (see `DiktatGradlePlugin`) is enough, but - * this is better left enabled as a safety net. - */ - add(ktlintDisabledRulesArgument) - - if (diktatExtension.debug) { - add("--debug") - } - diktatExtension.baseline?.let { - add("--baseline=${diktatExtension.baseline}") - } - actualInputs.also { - if (it.isEmpty) { - /* - If ktlint receives empty patterns, it implicitly uses **/*.kt, **/*.kts instead. - This can lead to diktat analyzing gradle buildscripts and so on. We want to prevent it. - */ - project.logger.warn("Inputs for $name do not exist, will not run diktat") - shouldRun = false - } - } - .files - .also { files -> - project.logger.info("Analyzing ${files.size} files with diktat in project ${project.name}") - project.logger.debug("Analyzing $files") - } - .forEach { - addInput(it) - } - - add(reporterFlag(diktatExtension)) - } - project.logger.debug("Setting JavaExec args to $args") - } - - /** - * Function to execute diKTat - */ - @TaskAction - override fun exec() { - fixForNewJpms() - if (shouldRun) { - super.exec() - } else { - project.logger.info("Skipping diktat execution") - } - } - - /** - * @param ignoreFailures whether failure in this plugin should be ignored by a build - */ - override fun setIgnoreFailures(ignoreFailures: Boolean) = ignoreFailuresProp.set(ignoreFailures) - - /** - * @return whether failure in this plugin should be ignored by a build - */ - @Suppress("FUNCTION_BOOLEAN_PREFIX") - override fun getIgnoreFailures(): Boolean = ignoreFailuresProp.getOrElse(false) - - @Suppress("AVOID_NULL_CHECKS") - private fun reporterFlag(diktatExtension: DiktatExtension): String = buildString { - val reporterFlag = project.createReporterFlag(diktatExtension) - append(reporterFlag) - if (isSarifReporterActive(reporterFlag)) { - // need to set user.home specially for ktlint, so it will be able to put a relative path URI in SARIF - systemProperty("user.home", project.rootDir.toString()) - } - - val outputFile = project.getOutputFile(diktatExtension) - if (outputFile != null) { - outputs.file(outputFile) - val outFlag = ",output=$outputFile" - append(outFlag) - } - } - - @Suppress("MagicNumber") - private fun isMainClassPropertySupported(gradleVersionString: String) = - GradleVersion.version(gradleVersionString) >= GradleVersion.version("6.4") - - private fun MutableList.addInput(file: File) { - add(file.toRelativeString(project.projectDir)) - } - - private fun resolveConfigFile(file: File): String { - if (file.toPath().startsWith(project.rootDir.toPath())) { - // In gradle, project.files() returns File relative to project.projectDir. - // There is no need to resolve file further if it has been passed via gradle files API. - return file.absolutePath - } - - // otherwise, e.g. if file is passed as java.io.File with relative path, we try to find it - return generateSequence(project.projectDir) { it.parentFile } - .map { it.resolve(file) } - .run { - firstOrNull { it.exists() } ?: first() - } - .absolutePath - } - - private fun fixForNewJpms() { - val javaVersion = getJavaExecJvmVersion() - project.logger.debug("For diktat execution jvm version $javaVersion will be used") - if (javaVersion.majorVersion.toInt() >= MIN_JVM_REQUIRES_ADD_OPENS) { - // https://github.com/saveourtool/diktat/issues/1182#issuecomment-1023099713 - project.logger.debug("Adding `--add-opens` flag for JVM version >=$MIN_JVM_REQUIRES_ADD_OPENS compatibility") - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") - } - } - - private fun getJavaExecJvmVersion(): JavaVersion = if (GradleVersion.version(gradleVersionString) >= GradleVersion.version("6.7") && - javaLauncher.isPresent - ) { - // Java Launchers are available since 6.7, but may not always be configured - javaLauncher.map { it.metadata.jvmVersion }.map(JavaVersion::toVersion).get() - } else { - // `javaVersion` property is available since 5.2 and is simply derived from path to JVM executable, - // which may be explicitly set or be the same as current Gradle JVM. - javaVersion - } -} - -/** - * @param diktatExtension [DiktatExtension] with some values for task configuration - * @param diktatConfiguration dependencies of diktat run - * @param patternSet [PatternSet] to discover files for diktat check - * @return a [TaskProvider] - */ -fun Project.registerDiktatCheckTask(diktatExtension: DiktatExtension, - diktatConfiguration: Configuration, - patternSet: PatternSet -): TaskProvider = - tasks.register( - DIKTAT_CHECK_TASK, DiktatJavaExecTaskBase::class.java, gradle.gradleVersion, - diktatExtension, diktatConfiguration, patternSet - ) - -/** - * @param diktatExtension [DiktatExtension] with some values for task configuration - * @param diktatConfiguration dependencies of diktat run - * @param patternSet [PatternSet] to discover files for diktat fix - * @return a [TaskProvider] - */ -fun Project.registerDiktatFixTask(diktatExtension: DiktatExtension, - diktatConfiguration: Configuration, - patternSet: PatternSet -): TaskProvider = - tasks.register( - DIKTAT_FIX_TASK, DiktatJavaExecTaskBase::class.java, gradle.gradleVersion, - diktatExtension, diktatConfiguration, patternSet, listOf("-F ") - ) diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt index 9181043b48..ab84448c43 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt @@ -47,28 +47,28 @@ fun Any.closureOf(action: T.() -> Unit): Closure = * @param diktatExtension extension of type [DiktatExtension] * @return CLI flag as string */ -fun Project.createReporterFlag(diktatExtension: DiktatExtension): String { +fun Project.getReporterType(diktatExtension: DiktatExtension): String { val name = diktatExtension.reporter.trim() val validReporters = listOf("sarif", "plain", "json", "html") - val reporterFlag = when { + val reporterType = when { diktatExtension.githubActions -> { if (diktatExtension.reporter.isNotEmpty()) { logger.warn("`diktat.githubActions` is set to true, so custom reporter [$name] will be ignored and SARIF reporter will be used") } - "--reporter=sarif" + "sarif" } name.isEmpty() -> { logger.info("Reporter name was not set. Using 'plain' reporter") - "--reporter=plain" + "plain" } name !in validReporters -> { logger.warn("Reporter name is invalid (provided value: [$name]). Falling back to 'plain' reporter") - "--reporter=plain" + "plain" } - else -> "--reporter=$name" + else -> name } - return reporterFlag + return reporterType } /** diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt new file mode 100644 index 0000000000..ba817089af --- /dev/null +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt @@ -0,0 +1,38 @@ +package org.cqfn.diktat.plugin.gradle.tasks + +import org.cqfn.diktat.DiktatProcessCommand +import org.cqfn.diktat.plugin.gradle.DiktatExtension +import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin +import org.gradle.api.Project +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.util.PatternFilterable +import org.gradle.api.tasks.util.PatternSet +import javax.inject.Inject + +/** + * A task to check source code by diktat + */ +abstract class DiktatCheckTask @Inject constructor( + extension: DiktatExtension, + inputs: PatternFilterable +) : DiktatTaskBase(extension, inputs) { + override fun doRun(diktatCommand: DiktatProcessCommand, formattedContentConsumer: (String) -> Unit) { + diktatCommand.check() + } + + companion object { + /** + * @param diktatExtension [DiktatExtension] with some values for task configuration + * @param patternSet [PatternSet] to discover files for diktat check + * @return a [TaskProvider] + */ + fun Project.registerDiktatCheckTask( + diktatExtension: DiktatExtension, + patternSet: PatternSet + ): TaskProvider = + tasks.register( + DiktatGradlePlugin.DIKTAT_CHECK_TASK, DiktatCheckTask::class.java, + diktatExtension, patternSet + ) + } +} diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatFixTask.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatFixTask.kt new file mode 100644 index 0000000000..c705fb22fe --- /dev/null +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatFixTask.kt @@ -0,0 +1,39 @@ +package org.cqfn.diktat.plugin.gradle.tasks + +import org.cqfn.diktat.DiktatProcessCommand +import org.cqfn.diktat.plugin.gradle.DiktatExtension +import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin +import org.gradle.api.Project +import org.gradle.api.tasks.TaskProvider +import org.gradle.api.tasks.util.PatternFilterable +import org.gradle.api.tasks.util.PatternSet +import javax.inject.Inject + +/** + * A task to check source code by diktat + */ +abstract class DiktatFixTask @Inject constructor( + extension: DiktatExtension, + inputs: PatternFilterable +) : DiktatTaskBase(extension, inputs) { + override fun doRun(diktatCommand: DiktatProcessCommand, formattedContentConsumer: (String) -> Unit) { + val formattedText = diktatCommand.fix() + formattedContentConsumer(formattedText) + } + + companion object { + /** + * @param diktatExtension [DiktatExtension] with some values for task configuration + * @param patternSet [PatternSet] to discover files for diktat fix + * @return a [TaskProvider] + */ + fun Project.registerDiktatFixTask( + diktatExtension: DiktatExtension, + patternSet: PatternSet + ): TaskProvider = + tasks.register( + DiktatGradlePlugin.DIKTAT_FIX_TASK, DiktatFixTask::class.java, + diktatExtension, patternSet + ) + } +} diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt new file mode 100644 index 0000000000..7082dc864e --- /dev/null +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -0,0 +1,212 @@ +package org.cqfn.diktat.plugin.gradle.tasks + +import org.cqfn.diktat.DiktatProcessCommand +import org.cqfn.diktat.DiktatProcessor +import org.cqfn.diktat.api.DiktatCallback +import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.unwrap +import org.cqfn.diktat.plugin.gradle.DiktatExtension +import org.cqfn.diktat.plugin.gradle.getReporterType +import org.cqfn.diktat.plugin.gradle.getOutputFile +import org.cqfn.diktat.plugin.gradle.isSarifReporterActive +import com.pinterest.ktlint.core.LintError +import com.pinterest.ktlint.core.Reporter +import com.pinterest.ktlint.core.internal.CurrentBaseline +import com.pinterest.ktlint.core.internal.containsLintError +import com.pinterest.ktlint.core.internal.loadBaseline +import com.pinterest.ktlint.reporter.baseline.BaselineReporter +import com.pinterest.ktlint.reporter.sarif.SarifReporter +import com.pinterest.ktlint.reporter.html.HtmlReporter +import com.pinterest.ktlint.reporter.json.JsonReporter +import com.pinterest.ktlint.reporter.plain.PlainReporter +import generated.DIKTAT_VERSION +import generated.KTLINT_VERSION +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.IgnoreEmptyDirectories +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.SkipWhenEmpty +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.VerificationTask +import org.gradle.api.tasks.util.PatternFilterable +import java.io.File +import java.io.FileOutputStream +import java.io.PrintStream + +/** + * A base task to run `diktat` + */ +abstract class DiktatTaskBase( + @get:Internal internal val extension: DiktatExtension, + private val inputs: PatternFilterable +) : DefaultTask(), VerificationTask { + /** + * Files that will be analyzed by diktat + */ + @get:IgnoreEmptyDirectories + @get:SkipWhenEmpty + @get:PathSensitive(PathSensitivity.RELATIVE) + @get:InputFiles + val actualInputs: FileCollection by lazy { + if (inputs.includes.isEmpty() && inputs.excludes.isEmpty()) { + inputs.include("src/**/*.kt") + } + project.objects.fileCollection().from( + project.fileTree("${project.projectDir}").apply { + exclude("${project.buildDir}") + } + .matching(inputs) + ) + } + + /** + * Whether diktat should be executed + */ + @get:Internal + internal val shouldRun: Boolean by lazy { + !actualInputs.isEmpty + } + + /** + * A baseline loaded from provided file or empty + */ + @get:Internal + internal val baseline: CurrentBaseline by lazy { + extension.baseline?.let { loadBaseline(it) } + ?: CurrentBaseline(emptyMap(), false) + } + + /** + * A reporter created based on configuration + */ + @get:Internal + internal val reporter: Reporter by lazy { + resolveReporter(baseline) + } + + /** + * Function to execute diKTat + */ + @TaskAction + fun run() { + if (extension.debug) { + project.logger.lifecycle("Running diktat $DIKTAT_VERSION with ktlint $KTLINT_VERSION") + } + if (!shouldRun) { + /* + If ktlint receives empty patterns, it implicitly uses **/*.kt, **/*.kts instead. + This can lead to diktat analyzing gradle buildscripts and so on. We want to prevent it. + */ + project.logger.warn("Inputs for $name do not exist, will not run diktat") + project.logger.info("Skipping diktat execution") + } else { + val diktatProcessor = DiktatProcessor.builder() + .diktatRuleSetProvider(extension.diktatConfigFile.toPath()) + .logLevel( + if (extension.debug) { + DiktatLogLevel.DEBUG + } else { + DiktatLogLevel.INFO + } + ) + .build() + + reporter.beforeAll() + val lintErrors: MutableList = mutableListOf() + actualInputs.files + .also { files -> + project.logger.info("Analyzing ${files.size} files with diktat in project ${project.name}") + project.logger.debug("Analyzing $files") + } + .forEach { file -> + processFile( + file = file, + diktatProcessor = diktatProcessor, + lintErrors = lintErrors + ) + } + reporter.afterAll() + if (lintErrors.isNotEmpty() && !ignoreFailures) { + throw GradleException("There are ${lintErrors.size} lint errors") + } + } + } + + private fun processFile( + file: File, + diktatProcessor: DiktatProcessor, + lintErrors: MutableList + ) { + project.logger.lifecycle("Checking file $file") + reporter.before(file.absolutePath) + val baselineErrors = baseline.baselineRules?.get( + file.relativeTo(project.projectDir).invariantSeparatorsPath + ) ?: emptyList() + val diktatCallback = DiktatCallback { error, isCorrected -> + val ktLintError = error.unwrap() + if (!baselineErrors.containsLintError(ktLintError)) { + reporter.onLintError(file.absolutePath, ktLintError, isCorrected) + lintErrors.add(ktLintError) + } + } + val command = DiktatProcessCommand.builder() + .processor(diktatProcessor) + .file(file.toPath()) + .callback(diktatCallback) + .build() + doRun(command) { formattedText -> + val fileName = file.absolutePath + val fileContent = file.readText(Charsets.UTF_8) + if (fileContent != formattedText) { + project.logger.info("Original and formatted content differ, writing to $fileName...") + file.writeText(formattedText, Charsets.UTF_8) + } + } + reporter.after(file.absolutePath) + } + + /** + * An abstract method which should be overridden by fix and check tasks + * + * @param diktatCommand + * @param formattedContentConsumer + */ + protected abstract fun doRun(diktatCommand: DiktatProcessCommand, formattedContentConsumer: (String) -> Unit) + + private fun resolveReporter(baselineResults: CurrentBaseline): Reporter { + val reporterType = project.getReporterType(extension) + if (isSarifReporterActive(reporterType)) { + // need to set user.home specially for ktlint, so it will be able to put a relative path URI in SARIF + System.setProperty("user.home", project.rootDir.toString()) + } + val output = project.getOutputFile(extension)?.outputStream()?.let { PrintStream(it) } ?: System.`out` + val actualReporter = if (extension.githubActions) { + SarifReporter(output) + } else { + when (reporterType) { + "sarif" -> SarifReporter(output) + "plain" -> PlainReporter(output) + "json" -> JsonReporter(output) + "html" -> HtmlReporter(output) + else -> { + project.logger.warn("Reporter name $reporterType was not specified or is invalid. Falling to 'plain' reporter") + PlainReporter(output) + } + } + } + + return if (baselineResults.baselineGenerationNeeded) { + val baseline = requireNotNull(extension.baseline) { + "baseline is not provided, but baselineGenerationNeeded is true" + } + val baselineReporter = BaselineReporter(PrintStream(FileOutputStream(baseline, true))) + return Reporter.from(actualReporter, baselineReporter) + } else { + actualReporter + } + } +} diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt index 36718bd318..83dcf425d8 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt @@ -2,8 +2,7 @@ package org.cqfn.diktat.plugin.gradle.tasks import org.cqfn.diktat.plugin.gradle.DiktatExtension import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.MERGE_SARIF_REPORTS_TASK_NAME -import org.cqfn.diktat.plugin.gradle.DiktatJavaExecTaskBase -import org.cqfn.diktat.plugin.gradle.createReporterFlag +import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.getOutputFile import org.cqfn.diktat.plugin.gradle.isSarifReporterActive import io.github.detekt.sarif4k.SarifSchema210 @@ -91,12 +90,12 @@ internal fun Project.configureMergeReportsTask(diktatExtension: DiktatExtension) } } rootProject.tasks.withType(SarifReportMergeTask::class.java).configureEach { reportMergeTask -> - if (isSarifReporterActive(createReporterFlag(diktatExtension))) { + if (isSarifReporterActive(getReporterType(diktatExtension))) { getOutputFile(diktatExtension)?.let { reportMergeTask.input.from(it) } - reportMergeTask.shouldRunAfter(tasks.withType(DiktatJavaExecTaskBase::class.java)) + reportMergeTask.shouldRunAfter(tasks.withType(DiktatTaskBase::class.java)) } } - tasks.withType(DiktatJavaExecTaskBase::class.java).configureEach { diktatJavaExecTaskBase -> + tasks.withType(DiktatTaskBase::class.java).configureEach { diktatJavaExecTaskBase -> diktatJavaExecTaskBase.finalizedBy(rootProject.tasks.withType(SarifReportMergeTask::class.java)) } } diff --git a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt index 376111138d..80cb06bf37 100644 --- a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt +++ b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt @@ -1,5 +1,6 @@ package org.cqfn.diktat.plugin.gradle +import org.cqfn.diktat.plugin.gradle.tasks.DiktatCheckTask import org.gradle.api.Project import org.gradle.testfixtures.ProjectBuilder import org.junit.jupiter.api.Assertions @@ -29,7 +30,7 @@ class DiktatGradlePluginTest { fun `check default extension properties`() { val diktatExtension = project.extensions.getByName("diktat") as DiktatExtension val actualInputs = project.tasks - .named("diktatCheck", DiktatJavaExecTaskBase::class.java) + .named("diktatCheck", DiktatCheckTask::class.java) .get() .actualInputs Assertions.assertFalse(diktatExtension.debug) @@ -42,7 +43,7 @@ class DiktatGradlePluginTest { val diktatExtension = project.extensions.getByName("diktat") as DiktatExtension Assertions.assertEquals("", diktatExtension.reporter) - val reporterFlag = project.createReporterFlag(diktatExtension) + val reporterFlag = project.getReporterType(diktatExtension) Assertions.assertEquals("--reporter=plain", reporterFlag) } } diff --git a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt index 00a4f08bbf..a363adff6e 100644 --- a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt +++ b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskTest.kt @@ -1,7 +1,9 @@ package org.cqfn.diktat.plugin.gradle -import org.cqfn.diktat.common.config.rules.DIKTAT_CONF_PROPERTY -import org.cqfn.diktat.common.ktlint.ktlintDisabledRulesArgument +import org.cqfn.diktat.plugin.gradle.tasks.DiktatCheckTask +import com.pinterest.ktlint.reporter.json.JsonReporter +import com.pinterest.ktlint.reporter.plain.PlainReporter +import com.pinterest.ktlint.reporter.sarif.SarifReporter import org.gradle.api.Project import org.gradle.testfixtures.ProjectBuilder @@ -33,28 +35,22 @@ class DiktatJavaExecTaskTest { @Test fun `check command line for various inputs`() { - assertCommandLineEquals( + assertFiles( listOf( - null, - ktlintDisabledRulesArgument, - combinePathParts("src", "main", "kotlin", "Test.kt"), - "--reporter=plain" + combinePathParts("src", "main", "kotlin", "Test.kt") ) ) { inputs { include("src/**/*.kt") } } + + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is PlainReporter) } @Test fun `check command line in debug mode`() { - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - "--debug", - combinePathParts("src", "main", "kotlin", "Test.kt"), - "--reporter=plain" - ) + assertFiles( + listOf(combinePathParts("src", "main", "kotlin", "Test.kt")) ) { inputs { include("src/**/*.kt") } debug = true @@ -65,19 +61,17 @@ class DiktatJavaExecTaskTest { fun `check command line with excludes`() { project.file("src/main/kotlin/generated").mkdirs() project.file("src/main/kotlin/generated/Generated.kt").createNewFile() - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - combinePathParts("src", "main", "kotlin", "Test.kt"), - "--reporter=plain" - ) + assertFiles( + listOf(combinePathParts("src", "main", "kotlin", "Test.kt")) ) { inputs { include("src/**/*.kt") exclude("src/main/kotlin/generated") } } + + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is PlainReporter) } @Test @@ -93,7 +87,7 @@ class DiktatJavaExecTaskTest { val task = project.registerDiktatTask { inputs { exclude("*") } } - Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml").absolutePath, task.systemProperties[DIKTAT_CONF_PROPERTY]) + Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml"), task.extension.diktatConfigFile) } @Test @@ -102,96 +96,74 @@ class DiktatJavaExecTaskTest { inputs { exclude("*") } diktatConfigFile = project.file("../diktat-analysis.yml") } - Assertions.assertEquals(File(project.projectDir.parentFile, "diktat-analysis.yml").absolutePath, task.systemProperties[DIKTAT_CONF_PROPERTY]) + Assertions.assertEquals(File(project.projectDir.parentFile, "diktat-analysis.yml"), task.extension.diktatConfigFile) } @Test fun `check command line has reporter type and output`() { - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - "--reporter=json,output=${project.projectDir.resolve("some.txt")}" - ) - ) { + assertFiles(emptyList()) { inputs { exclude("*") } diktatConfigFile = project.file("../diktat-analysis.yml") reporter = "json" output = "some.txt" } + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is JsonReporter) } @Test fun `check command line has reporter type without output`() { - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - "--reporter=json" - ) - ) { + assertFiles(emptyList()) { inputs { exclude("*") } diktatConfigFile = project.file("../diktat-analysis.yml") reporter = "json" } + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is JsonReporter) } @Test fun `check command line in githubActions mode`() { val path = project.file("${project.buildDir}/reports/diktat/diktat.sarif") - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - "--reporter=sarif,output=$path" - ) - ) { + assertFiles(emptyList()) { inputs { exclude("*") } diktatConfigFile = project.file("../diktat-analysis.yml") githubActions = true } - val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is SarifReporter) Assertions.assertEquals( project.rootDir.toString(), - task.systemProperties["user.home"] + System.getProperty("user.home") ) } @Test fun `githubActions mode should have higher precedence over explicit reporter`() { val path = project.file("${project.buildDir}/reports/diktat/diktat.sarif") - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - "--reporter=sarif,output=$path" - ) - ) { + assertFiles(emptyList()) { inputs { exclude("*") } diktatConfigFile = project.file("../diktat-analysis.yml") githubActions = true reporter = "json" output = "report.json" } + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is SarifReporter) } @Test fun `should set system property with SARIF reporter`() { - assertCommandLineEquals( - listOf( - null, - ktlintDisabledRulesArgument, - "--reporter=sarif" - ) - ) { + assertFiles(emptyList()) { inputs { exclude("*") } diktatConfigFile = project.file("../diktat-analysis.yml") reporter = "sarif" } - val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + assert(task.reporter is SarifReporter) Assertions.assertEquals( project.rootDir.toString(), - task.systemProperties["user.home"] + System.getProperty("user.home") ) } @@ -204,10 +176,10 @@ class DiktatJavaExecTaskTest { inputs { exclude("*") } } } - val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase - val subprojectTask = subproject.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase - Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml").absolutePath, task.systemProperties[DIKTAT_CONF_PROPERTY]) - Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml").absolutePath, subprojectTask.systemProperties[DIKTAT_CONF_PROPERTY]) + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + val subprojectTask = subproject.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml"), task.extension.diktatConfigFile) + Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml"), subprojectTask.extension.diktatConfigFile) } @Test @@ -220,10 +192,10 @@ class DiktatJavaExecTaskTest { diktatConfigFile = it.rootProject.file("diktat-analysis.yml") } } - val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase - val subprojectTask = subproject.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase - Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml").absolutePath, task.systemProperties[DIKTAT_CONF_PROPERTY]) - Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml").absolutePath, subprojectTask.systemProperties[DIKTAT_CONF_PROPERTY]) + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + val subprojectTask = subproject.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml"), task.extension.diktatConfigFile) + Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml"), subprojectTask.extension.diktatConfigFile) } @Test @@ -237,21 +209,29 @@ class DiktatJavaExecTaskTest { diktatConfigFile = it.file("diktat-analysis.yml") } } - val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase - val subprojectTask = subproject.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase - Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml").absolutePath, task.systemProperties[DIKTAT_CONF_PROPERTY]) - Assertions.assertEquals(File(subproject.projectDir, "diktat-analysis.yml").absolutePath, subprojectTask.systemProperties[DIKTAT_CONF_PROPERTY]) + val task = project.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + val subprojectTask = subproject.tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask + Assertions.assertEquals(File(project.projectDir, "diktat-analysis.yml"), task.extension.diktatConfigFile) + Assertions.assertEquals(File(subproject.projectDir, "diktat-analysis.yml"), subprojectTask.extension.diktatConfigFile) } - private fun Project.registerDiktatTask(extensionConfiguration: DiktatExtension.() -> Unit): DiktatJavaExecTaskBase { + private fun Project.registerDiktatTask(extensionConfiguration: DiktatExtension.() -> Unit): DiktatCheckTask { pluginManager.apply(DiktatGradlePlugin::class.java) extensions.configure("diktat", extensionConfiguration) - return tasks.getByName(DIKTAT_CHECK_TASK) as DiktatJavaExecTaskBase + return tasks.getByName(DIKTAT_CHECK_TASK) as DiktatCheckTask } - private fun assertCommandLineEquals(expected: List, extensionConfiguration: DiktatExtension.() -> Unit) { + private fun assertFiles(expected: List, extensionConfiguration: DiktatExtension.() -> Unit) { val task = project.registerDiktatTask(extensionConfiguration) - Assertions.assertIterableEquals(expected, task.commandLine) + val files = task.actualInputs.files + Assertions.assertEquals(expected.size, files.size) + Assertions.assertTrue { + expected.zip(files) + .map { (expectedStr, file) -> + file.path.endsWith(expectedStr) + } + .all { it } + } } private fun setupMultiProject() { diff --git a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt index 472480f89f..08b6eff6e3 100644 --- a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt +++ b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt @@ -28,7 +28,7 @@ class ReporterSelectionTest { Assertions.assertEquals( "--reporter=plain", - project.createReporterFlag(diktatExtension) + project.getReporterType(diktatExtension) ) } } diff --git a/diktat-maven-plugin/build.gradle.kts b/diktat-maven-plugin/build.gradle.kts index ba822027cb..cf8e5702c4 100644 --- a/diktat-maven-plugin/build.gradle.kts +++ b/diktat-maven-plugin/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { compileOnly(libs.maven.core) implementation(libs.kotlin.stdlib.jdk8) - implementation(projects.diktatRules) + implementation(projects.diktatRuleset) implementation(libs.ktlint.core) implementation(libs.ktlint.reporter.plain) implementation(libs.ktlint.reporter.sarif) diff --git a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt index 274a1d00fc..39e4336657 100644 --- a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt +++ b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt @@ -4,14 +4,15 @@ package org.cqfn.diktat.plugin.maven -import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider +import org.cqfn.diktat.DiktatProcessCommand +import org.cqfn.diktat.DiktatProcessor +import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.unwrap import org.cqfn.diktat.ruleset.utils.isKotlinCodeOrScript -import com.pinterest.ktlint.core.KtLint import com.pinterest.ktlint.core.LintError import com.pinterest.ktlint.core.Reporter import com.pinterest.ktlint.core.RuleExecutionException -import com.pinterest.ktlint.core.RuleSet import com.pinterest.ktlint.core.internal.CurrentBaseline import com.pinterest.ktlint.core.internal.containsLintError import com.pinterest.ktlint.core.internal.loadBaseline @@ -31,6 +32,10 @@ import org.apache.maven.project.MavenProject import java.io.File import java.io.FileOutputStream import java.io.PrintStream +import java.nio.file.Path +import kotlin.io.path.absolutePathString +import kotlin.io.path.readText +import kotlin.io.path.writeText /** * Base [Mojo] for checking and fixing code using diktat @@ -98,9 +103,10 @@ abstract class DiktatBaseMojo : AbstractMojo() { private lateinit var mavenSession: MavenSession /** - * @param params instance of [KtLint.ExperimentalParams] used in analysis + * @param command instance of [DiktatProcessCommand] used in analysis + * @param formattedContentConsumer consumer for formatted content of the file */ - abstract fun runAction(params: KtLint.ExperimentalParams) + abstract fun runAction(command: DiktatProcessCommand, formattedContentConsumer: (String) -> Unit) /** * Perform code check using diktat ruleset @@ -117,19 +123,24 @@ abstract class DiktatBaseMojo : AbstractMojo() { if (excludes.isNotEmpty()) " and excluding $excludes" else "" ) - val ruleSets by lazy { - listOf(DiktatRuleSetProvider(configFile).get()) + val diktatProcessor by lazy { + DiktatProcessor.builder() + .diktatRuleSetProvider(configFile) + .logLevel( + if (debug) DiktatLogLevel.DEBUG else DiktatLogLevel.INFO + ) + .build() } val baselineResults = baseline?.let { loadBaseline(it.absolutePath) } ?: CurrentBaseline(emptyMap(), false) reporterImpl = resolveReporter(baselineResults) reporterImpl.beforeAll() - val lintErrors: MutableList = mutableListOf() + val lintErrors: MutableList = mutableListOf() inputs .map(::File) .forEach { - checkDirectory(it, lintErrors, baselineResults.baselineRules ?: emptyMap(), ruleSets) + diktatProcessor.checkDirectory(it, lintErrors, baselineResults.baselineRules ?: emptyMap()) } reporterImpl.afterAll() @@ -198,11 +209,10 @@ abstract class DiktatBaseMojo : AbstractMojo() { * @throws MojoExecutionException if [RuleExecutionException] has been thrown by ktlint */ @Suppress("TYPE_ALIAS") - private fun checkDirectory( + private fun DiktatProcessor.checkDirectory( directory: File, lintErrors: MutableList, baselineRules: Map>, - ruleSets: Iterable ) { val (excludedDirs, excludedFiles) = excludes.map(::File).partition { it.isDirectory } directory @@ -217,13 +227,12 @@ abstract class DiktatBaseMojo : AbstractMojo() { try { reporterImpl.before(file.absolutePath) checkFile( - file, + file.toPath(), lintErrors, baselineRules.getOrDefault( file.relativeTo(mavenProject.basedir.parentFile).invariantSeparatorsPath, emptyList() ), - ruleSets ) reporterImpl.after(file.absolutePath) } catch (e: RuleExecutionException) { @@ -233,26 +242,29 @@ abstract class DiktatBaseMojo : AbstractMojo() { } } - private fun checkFile(file: File, - lintErrors: MutableList, - baselineErrors: List, - ruleSets: Iterable + private fun DiktatProcessor.checkFile( + file: Path, + lintErrors: MutableList, + baselineErrors: List, ) { - val text = file.readText() - val params = - KtLint.ExperimentalParams( - fileName = file.absolutePath, - text = text, - ruleSets = ruleSets, - script = file.extension.equals("kts", ignoreCase = true), - cb = { lintError, isCorrected -> - if (!baselineErrors.containsLintError(lintError)) { - reporterImpl.onLintError(file.absolutePath, lintError, isCorrected) - lintErrors.add(lintError) - } - }, - debug = debug - ) - runAction(params) + val command = DiktatProcessCommand.builder() + .processor(this) + .file(file) + .callback { error, isCorrected -> + val ktLintError = error.unwrap() + if (!baselineErrors.containsLintError(ktLintError)) { + reporterImpl.onLintError(file.absolutePathString(), ktLintError, isCorrected) + lintErrors.add(ktLintError) + } + } + .build() + runAction(command) { formattedText -> + val fileName = file.absolutePathString() + val fileContent = file.readText(Charsets.UTF_8) + if (fileContent != formattedText) { + log.info("Original and formatted content differ, writing to $fileName...") + file.writeText(formattedText, Charsets.UTF_8) + } + } } } diff --git a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatMojo.kt b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatMojo.kt index 1ff3f810c0..9934bf3350 100644 --- a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatMojo.kt +++ b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatMojo.kt @@ -4,25 +4,19 @@ package org.cqfn.diktat.plugin.maven +import org.cqfn.diktat.DiktatProcessCommand import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider -import org.cqfn.diktat.ruleset.utils.ignoreCorrectedErrors -import com.pinterest.ktlint.core.KtLint import org.apache.maven.plugins.annotations.Mojo -import java.io.File - /** * Main [Mojo] that call [DiktatRuleSetProvider]'s rules on [inputs] files */ @Mojo(name = "check") @Suppress("unused") class DiktatCheckMojo : DiktatBaseMojo() { - /** - * @param params instance of [KtLint.ExperimentalParams] used in analysis - */ - override fun runAction(params: KtLint.ExperimentalParams) { - KtLint.lint(params) + override fun runAction(command: DiktatProcessCommand, formattedContentConsumer: (String) -> Unit) { + command.check() } } @@ -33,16 +27,8 @@ class DiktatCheckMojo : DiktatBaseMojo() { @Mojo(name = "fix") @Suppress("unused") class DiktatFixMojo : DiktatBaseMojo() { - /** - * @param params instance of [KtLint.Params] used in analysis - */ - override fun runAction(params: KtLint.ExperimentalParams) { - val fileName = params.fileName - val fileContent = File(fileName).readText(charset("UTF-8")) - val formattedText = KtLint.format(params.ignoreCorrectedErrors()) - if (fileContent != formattedText) { - log.info("Original and formatted content differ, writing to $fileName...") - File(fileName).writeText(formattedText, charset("UTF-8")) - } + override fun runAction(command: DiktatProcessCommand, formattedContentConsumer: (String) -> Unit) { + val formattedText = command.fix() + formattedContentConsumer(formattedText) } } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt index 661056c931..942e754229 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt @@ -102,7 +102,7 @@ import java.io.File * * @param diktatConfigFile - configuration file where all configurations for inspections and rules are stored */ -class DiktatRuleSetProvider(private var diktatConfigFile: String = DIKTAT_ANALYSIS_CONF) : RuleSetProvider { +class DiktatRuleSetProvider(private val diktatConfigFile: String = DIKTAT_ANALYSIS_CONF) : RuleSetProvider { private val possibleConfigs: Sequence = sequence { yield(resolveDefaultConfig()) yield(resolveConfigFileFromJarLocation()) @@ -113,7 +113,7 @@ class DiktatRuleSetProvider(private var diktatConfigFile: String = DIKTAT_ANALYS " (it can be placed to the run directory or the default file from resources will be used)") val configPath = possibleConfigs .firstOrNull { it != null && File(it).exists() } - diktatConfigFile = configPath + val resultedDiktatConfigFile = configPath ?: run { val possibleConfigsList = possibleConfigs.toList() log.warn( @@ -129,7 +129,7 @@ class DiktatRuleSetProvider(private var diktatConfigFile: String = DIKTAT_ANALYS } RulesConfigReader(javaClass.classLoader) - .readResource(diktatConfigFile) + .readResource(resultedDiktatConfigFile) ?.onEach(::validate) ?: emptyList() } diff --git a/diktat-ruleset/build.gradle.kts b/diktat-ruleset/build.gradle.kts index e5f043e33a..68232cffa9 100644 --- a/diktat-ruleset/build.gradle.kts +++ b/diktat-ruleset/build.gradle.kts @@ -36,11 +36,6 @@ tasks.named("shadowJar") { archiveClassifier.set("") } -// disable default jar -tasks.named("jar") { - enabled = false -} - // it triggers shadowJar with default build tasks { build { diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt new file mode 100644 index 0000000000..18a204b194 --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt @@ -0,0 +1,128 @@ +package org.cqfn.diktat + +import org.cqfn.diktat.api.DiktatCallback +import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.unwrap +import org.cqfn.diktat.ruleset.utils.isKotlinScript +import com.pinterest.ktlint.core.KtLint +import com.pinterest.ktlint.core.api.EditorConfigOverride +import java.nio.file.Path +import kotlin.io.path.absolutePathString +import kotlin.io.path.readText + +/** + * Command to run `diktat` + * + * @property processor + * @property file + * @property fileContent + * @property isScript + * @property callback + */ +class DiktatProcessCommand private constructor( + private val processor: DiktatProcessor, + private val file: Path, + private val fileContent: String, + private val isScript: Boolean, + private val callback: DiktatCallback, +) { + /** + * Run `diktat fix` using parameters from current command + * + * @return result of `diktat fix` + */ + fun fix(): String = KtLint.format(ktLintParams()) + + /** + * Run `diktat check` using parameters from current command + */ + fun check(): Unit = KtLint.lint(ktLintParams()) + + @Suppress("DEPRECATION") + private fun ktLintParams(): KtLint.ExperimentalParams = KtLint.ExperimentalParams( + fileName = file.absolutePathString(), + text = fileContent, + ruleSets = setOf(processor.diktatRuleSetProvider.get()), + userData = emptyMap(), + cb = callback.unwrap(), + script = isScript, + editorConfigPath = null, + debug = processor.logLevel == DiktatLogLevel.DEBUG, + editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, + isInvokedFromCli = false + ) + + companion object { + /** + * @return a builder for [DiktatProcessCommand] + */ + fun builder(): Builder = Builder() + } + + /** + * Builder for [DiktatProcessCommand] + * + * @property processor + * @property file + * @property fileContent + * @property isScript + * @property callback + */ + class Builder internal constructor( + private var processor: DiktatProcessor? = null, + private var file: Path? = null, + private var fileContent: String? = null, + private var isScript: Boolean? = null, + private var callback: DiktatCallback? = null, + ) { + /** + * @param processor + * @return updated builder + */ + fun processor(processor: DiktatProcessor) = apply { this.processor = processor } + + /** + * @param file + * @return updated builder + */ + fun file(file: Path) = apply { this.file = file } + + /** + * @param fileContent + * @return updated builder + */ + fun fileContent(fileContent: String) = apply { this.fileContent = fileContent } + + /** + * @param isScript + * @return updated builder + */ + fun isScript(isScript: Boolean) = apply { this.isScript = isScript } + + /** + * @param callback + * @return updated builder + */ + fun callback(callback: DiktatCallback) = apply { this.callback = callback } + + /** + * @return built [DiktatProcessCommand] + */ + fun build(): DiktatProcessCommand { + val resolvedFile = requireNotNull(file) { + "file is required" + } + return DiktatProcessCommand( + processor = requireNotNull(processor) { + "processor is required" + }, + file = resolvedFile, + fileContent = fileContent ?: resolvedFile.readText(Charsets.UTF_8), + isScript = isScript ?: resolvedFile.isKotlinScript(), + callback = requireNotNull(callback) { + "callback is required" + }, + ) + } + } +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt new file mode 100644 index 0000000000..ddef195a5d --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt @@ -0,0 +1,68 @@ +package org.cqfn.diktat + +import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider +import java.nio.file.Path +import kotlin.io.path.absolutePathString + +/** + * Processor to run `diktat` + * + * @property diktatRuleSetProvider + * @property logLevel + */ +class DiktatProcessor private constructor( + val diktatRuleSetProvider: DiktatRuleSetProvider, + val logLevel: DiktatLogLevel, +) { + companion object { + /** + * @return a builder for [DiktatProcessor] + */ + fun builder(): Builder = Builder() + } + + /** + * Builder for [DiktatProcessCommand] + * + * @property diktatRuleSetProvider + * @property logLevel + */ + class Builder internal constructor( + private var diktatRuleSetProvider: DiktatRuleSetProvider? = null, + private var logLevel: DiktatLogLevel = DiktatLogLevel.INFO, + ) { + /** + * @param diktatRuleSetProvider + * @return updated builder + */ + fun diktatRuleSetProvider(diktatRuleSetProvider: DiktatRuleSetProvider) = apply { this.diktatRuleSetProvider = diktatRuleSetProvider } + + + /** + * @param configFile a config file to load [DiktatRuleSetProvider] + * @return updated builder + */ + fun diktatRuleSetProvider(configFile: String) = diktatRuleSetProvider(DiktatRuleSetProvider(configFile)) + + /** + * @param configFile a config file to load [DiktatRuleSetProvider] + * @return updated builder + */ + fun diktatRuleSetProvider(configFile: Path) = diktatRuleSetProvider(configFile.absolutePathString()) + + /** + * @param logLevel + * @return updated builder + */ + fun logLevel(logLevel: DiktatLogLevel) = apply { this.logLevel = logLevel } + + /** + * @return built [DiktatProcessCommand] + */ + fun build(): DiktatProcessor = DiktatProcessor( + diktatRuleSetProvider = diktatRuleSetProvider ?: DiktatRuleSetProvider(), + logLevel = logLevel, + ) + } +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt new file mode 100644 index 0000000000..de6ea06de7 --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt @@ -0,0 +1,15 @@ +package org.cqfn.diktat.api + +/** + * Callback for diktat process + */ +@FunctionalInterface +fun interface DiktatCallback : Function2 { + /** + * Performs this callback on the given [error] taking into account [isCorrected] flag. + * + * @param error the error found by diktat + * @param isCorrected true if the error fixed by diktat + */ + override fun invoke(error: DiktatError, isCorrected: Boolean) +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt new file mode 100644 index 0000000000..3d4aac4758 --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt @@ -0,0 +1,31 @@ +package org.cqfn.diktat.api + +/** + * Error found by `diktat` + */ +interface DiktatError { + /** + * @return line number (one-based) + */ + fun getLine(): Int + + /** + * @return column number (one-based) + */ + fun getCol(): Int + + /** + * @return rule id + */ + fun getRuleId(): String + + /** + * @return error message + */ + fun getDetail(): String + + /** + * @return true if the found error can be fixed + */ + fun canBeAutoCorrected(): Boolean +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt new file mode 100644 index 0000000000..6e6e18641d --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt @@ -0,0 +1,10 @@ +package org.cqfn.diktat.api + +/** + * Log level of `diktat processing` + */ +enum class DiktatLogLevel { + DEBUG, + INFO, + ; +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt new file mode 100644 index 0000000000..b9352d2a57 --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt @@ -0,0 +1,22 @@ +/** + * This file contains utility methods for LintErrorCallback + */ + +package org.cqfn.diktat.ktlint + +import org.cqfn.diktat.api.DiktatCallback +import org.cqfn.diktat.ruleset.utils.LintErrorCallback + +/** + * @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) +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt new file mode 100644 index 0000000000..b293a1cee5 --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt @@ -0,0 +1,34 @@ +package org.cqfn.diktat.ktlint + +import org.cqfn.diktat.api.DiktatError +import com.pinterest.ktlint.core.LintError + +/** + * Wrapper for KtLint error + * + * @property lintError + */ +data class LintErrorWrapper( + val lintError: LintError +) : DiktatError { + override fun getLine(): Int = lintError.line + + override fun getCol(): Int = lintError.col + + override fun getRuleId(): String = lintError.ruleId + + override fun getDetail(): String = lintError.detail + + override fun canBeAutoCorrected(): Boolean = lintError.canBeAutoCorrected +} + +/** + * @return [DiktatError] from KtLint [LintError] + */ +fun LintError.wrap(): DiktatError = LintErrorWrapper(this) + +/** + * @return KtLint [LintError] from [DiktatError] or exception + */ +fun DiktatError.unwrap(): LintError = (this as? LintErrorWrapper)?.lintError + ?: error("Unsupported wrapper of ${DiktatError::class.java.simpleName}: ${this::class.java.canonicalName}") From 7e8d558f7eb8a7d82ec08d0ae7fbfab8f1431421 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Tue, 28 Mar 2023 18:38:41 +0300 Subject: [PATCH 02/18] fixed test --- .../org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt index 08b6eff6e3..b0f65c0ec0 100644 --- a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt +++ b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/ReporterSelectionTest.kt @@ -27,7 +27,7 @@ class ReporterSelectionTest { } Assertions.assertEquals( - "--reporter=plain", + "plain", project.getReporterType(diktatExtension) ) } From 3ecd65e4cd7e7cabea3c1b02b37aeb21862c0293 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Tue, 28 Mar 2023 18:49:34 +0300 Subject: [PATCH 03/18] added LintErrorReporter --- .../plugin/gradle/tasks/DiktatTaskBase.kt | 13 +++++----- .../diktat/plugin/maven/DiktatBaseMojo.kt | 25 +++++++++--------- .../cqfn/diktat/ktlint/LintErrorReporter.kt | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt index 7082dc864e..d283ce1171 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -4,12 +4,12 @@ import org.cqfn.diktat.DiktatProcessCommand import org.cqfn.diktat.DiktatProcessor import org.cqfn.diktat.api.DiktatCallback import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.LintErrorReporter import org.cqfn.diktat.ktlint.unwrap import org.cqfn.diktat.plugin.gradle.DiktatExtension import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.getOutputFile import org.cqfn.diktat.plugin.gradle.isSarifReporterActive -import com.pinterest.ktlint.core.LintError import com.pinterest.ktlint.core.Reporter import com.pinterest.ktlint.core.internal.CurrentBaseline import com.pinterest.ktlint.core.internal.containsLintError @@ -116,7 +116,7 @@ abstract class DiktatTaskBase( .build() reporter.beforeAll() - val lintErrors: MutableList = mutableListOf() + val lintErrorReporter = LintErrorReporter() actualInputs.files .also { files -> project.logger.info("Analyzing ${files.size} files with diktat in project ${project.name}") @@ -126,12 +126,12 @@ abstract class DiktatTaskBase( processFile( file = file, diktatProcessor = diktatProcessor, - lintErrors = lintErrors + reporter = Reporter.from(reporter, lintErrorReporter) ) } reporter.afterAll() - if (lintErrors.isNotEmpty() && !ignoreFailures) { - throw GradleException("There are ${lintErrors.size} lint errors") + if (!lintErrorReporter.isEmpty() && !ignoreFailures) { + throw GradleException("There are ${lintErrorReporter.errorCount()} lint errors") } } } @@ -139,7 +139,7 @@ abstract class DiktatTaskBase( private fun processFile( file: File, diktatProcessor: DiktatProcessor, - lintErrors: MutableList + reporter: Reporter ) { project.logger.lifecycle("Checking file $file") reporter.before(file.absolutePath) @@ -150,7 +150,6 @@ abstract class DiktatTaskBase( val ktLintError = error.unwrap() if (!baselineErrors.containsLintError(ktLintError)) { reporter.onLintError(file.absolutePath, ktLintError, isCorrected) - lintErrors.add(ktLintError) } } val command = DiktatProcessCommand.builder() diff --git a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt index 39e4336657..4cf0a6fd7a 100644 --- a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt +++ b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt @@ -7,6 +7,7 @@ package org.cqfn.diktat.plugin.maven import org.cqfn.diktat.DiktatProcessCommand import org.cqfn.diktat.DiktatProcessor import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.LintErrorReporter import org.cqfn.diktat.ktlint.unwrap import org.cqfn.diktat.ruleset.utils.isKotlinCodeOrScript @@ -73,7 +74,6 @@ abstract class DiktatBaseMojo : AbstractMojo() { */ @Parameter(property = "diktat.baseline") var baseline: File? = null - private lateinit var reporterImpl: Reporter /** * Path to diktat yml config file. Can be either absolute or relative to project's root directory. @@ -133,19 +133,19 @@ abstract class DiktatBaseMojo : AbstractMojo() { } val baselineResults = baseline?.let { loadBaseline(it.absolutePath) } ?: CurrentBaseline(emptyMap(), false) - reporterImpl = resolveReporter(baselineResults) + val reporterImpl = resolveReporter(baselineResults) reporterImpl.beforeAll() - val lintErrors: MutableList = mutableListOf() + val lintErrorReporter = LintErrorReporter() inputs .map(::File) .forEach { - diktatProcessor.checkDirectory(it, lintErrors, baselineResults.baselineRules ?: emptyMap()) + diktatProcessor.checkDirectory(it, Reporter.from(reporterImpl, lintErrorReporter), baselineResults.baselineRules ?: emptyMap()) } reporterImpl.afterAll() - if (lintErrors.isNotEmpty()) { - throw MojoFailureException("There are ${lintErrors.size} lint errors") + if (!lintErrorReporter.isEmpty()) { + throw MojoFailureException("There are ${lintErrorReporter.errorCount()} lint errors") } } @@ -211,7 +211,7 @@ abstract class DiktatBaseMojo : AbstractMojo() { @Suppress("TYPE_ALIAS") private fun DiktatProcessor.checkDirectory( directory: File, - lintErrors: MutableList, + reporter: Reporter, baselineRules: Map>, ) { val (excludedDirs, excludedFiles) = excludes.map(::File).partition { it.isDirectory } @@ -225,16 +225,16 @@ abstract class DiktatBaseMojo : AbstractMojo() { .forEach { file -> log.debug("Checking file $file") try { - reporterImpl.before(file.absolutePath) + reporter.before(file.absolutePath) checkFile( file.toPath(), - lintErrors, + reporter, baselineRules.getOrDefault( file.relativeTo(mavenProject.basedir.parentFile).invariantSeparatorsPath, emptyList() ), ) - reporterImpl.after(file.absolutePath) + reporter.after(file.absolutePath) } catch (e: RuleExecutionException) { log.error("Unhandled exception during rule execution: ", e) throw MojoExecutionException("Unhandled exception during rule execution", e) @@ -244,7 +244,7 @@ abstract class DiktatBaseMojo : AbstractMojo() { private fun DiktatProcessor.checkFile( file: Path, - lintErrors: MutableList, + reporter: Reporter, baselineErrors: List, ) { val command = DiktatProcessCommand.builder() @@ -253,8 +253,7 @@ abstract class DiktatBaseMojo : AbstractMojo() { .callback { error, isCorrected -> val ktLintError = error.unwrap() if (!baselineErrors.containsLintError(ktLintError)) { - reporterImpl.onLintError(file.absolutePathString(), ktLintError, isCorrected) - lintErrors.add(ktLintError) + reporter.onLintError(file.absolutePathString(), ktLintError, isCorrected) } } .build() diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt new file mode 100644 index 0000000000..de26a6f456 --- /dev/null +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt @@ -0,0 +1,26 @@ +package org.cqfn.diktat.ktlint + +import com.pinterest.ktlint.core.LintError +import com.pinterest.ktlint.core.Reporter +import java.util.concurrent.atomic.AtomicInteger + +/** + * An implementation of [Reporter] which counts [LintError]s + */ +class LintErrorReporter : Reporter { + private val errorCounter: AtomicInteger = AtomicInteger() + + override fun onLintError(file: String, err: LintError, corrected: Boolean) { + errorCounter.incrementAndGet() + } + + /** + * @return true if there are no reported [LintError], otherwise -- false. + */ + fun isEmpty(): Boolean = errorCounter.get() == 0 + + /** + * @return count of reported [LintError] + */ + fun errorCount(): Int = errorCounter.get() +} From d521c50c6c3157b9156768338445bae6aae7bb37 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 11:10:59 +0300 Subject: [PATCH 04/18] diktatFix & detektAll --- .../plugin/gradle/tasks/DiktatCheckTask.kt | 8 ++-- .../plugin/gradle/tasks/DiktatTaskBase.kt | 43 +++++++++++++------ .../gradle/tasks/SarifReportMergeTask.kt | 4 +- .../diktat/plugin/maven/DiktatBaseMojo.kt | 2 +- .../org/cqfn/diktat/DiktatProcessCommand.kt | 16 +++---- .../kotlin/org/cqfn/diktat/DiktatProcessor.kt | 15 +++---- .../cqfn/diktat/ktlint/LintErrorReporter.kt | 10 +++-- 7 files changed, 59 insertions(+), 39 deletions(-) diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt index ba817089af..9e33195639 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatCheckTask.kt @@ -30,9 +30,9 @@ abstract class DiktatCheckTask @Inject constructor( diktatExtension: DiktatExtension, patternSet: PatternSet ): TaskProvider = - tasks.register( - DiktatGradlePlugin.DIKTAT_CHECK_TASK, DiktatCheckTask::class.java, - diktatExtension, patternSet - ) + tasks.register( + DiktatGradlePlugin.DIKTAT_CHECK_TASK, DiktatCheckTask::class.java, + diktatExtension, patternSet + ) } } diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt index d283ce1171..d45a343179 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -1,3 +1,7 @@ +@file:Suppress( + "Deprecation" +) + package org.cqfn.diktat.plugin.gradle.tasks import org.cqfn.diktat.DiktatProcessCommand @@ -7,18 +11,19 @@ import org.cqfn.diktat.api.DiktatLogLevel import org.cqfn.diktat.ktlint.LintErrorReporter import org.cqfn.diktat.ktlint.unwrap import org.cqfn.diktat.plugin.gradle.DiktatExtension -import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.getOutputFile +import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.isSarifReporterActive + import com.pinterest.ktlint.core.Reporter import com.pinterest.ktlint.core.internal.CurrentBaseline import com.pinterest.ktlint.core.internal.containsLintError import com.pinterest.ktlint.core.internal.loadBaseline import com.pinterest.ktlint.reporter.baseline.BaselineReporter -import com.pinterest.ktlint.reporter.sarif.SarifReporter import com.pinterest.ktlint.reporter.html.HtmlReporter import com.pinterest.ktlint.reporter.json.JsonReporter import com.pinterest.ktlint.reporter.plain.PlainReporter +import com.pinterest.ktlint.reporter.sarif.SarifReporter import generated.DIKTAT_VERSION import generated.KTLINT_VERSION import org.gradle.api.DefaultTask @@ -33,12 +38,14 @@ import org.gradle.api.tasks.SkipWhenEmpty import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.VerificationTask import org.gradle.api.tasks.util.PatternFilterable + import java.io.File import java.io.FileOutputStream import java.io.PrintStream /** * A base task to run `diktat` + * @property extension */ abstract class DiktatTaskBase( @get:Internal internal val extension: DiktatExtension, @@ -71,6 +78,23 @@ abstract class DiktatTaskBase( !actualInputs.isEmpty } + /** + * [DiktatProcessor] created from [extension] + */ + @get:Internal + internal val diktatProcessor: DiktatProcessor by lazy { + DiktatProcessor.builder() + .diktatRuleSetProvider(extension.diktatConfigFile.toPath()) + .logLevel( + if (extension.debug) { + DiktatLogLevel.DEBUG + } else { + DiktatLogLevel.INFO + } + ) + .build() + } + /** * A baseline loaded from provided file or empty */ @@ -90,6 +114,8 @@ abstract class DiktatTaskBase( /** * Function to execute diKTat + * + * @throws GradleException */ @TaskAction fun run() { @@ -104,17 +130,6 @@ abstract class DiktatTaskBase( project.logger.warn("Inputs for $name do not exist, will not run diktat") project.logger.info("Skipping diktat execution") } else { - val diktatProcessor = DiktatProcessor.builder() - .diktatRuleSetProvider(extension.diktatConfigFile.toPath()) - .logLevel( - if (extension.debug) { - DiktatLogLevel.DEBUG - } else { - DiktatLogLevel.INFO - } - ) - .build() - reporter.beforeAll() val lintErrorReporter = LintErrorReporter() actualInputs.files @@ -130,7 +145,7 @@ abstract class DiktatTaskBase( ) } reporter.afterAll() - if (!lintErrorReporter.isEmpty() && !ignoreFailures) { + if (lintErrorReporter.isNotEmpty() && !ignoreFailures) { throw GradleException("There are ${lintErrorReporter.errorCount()} lint errors") } } diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt index 83dcf425d8..eafaf09f84 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt @@ -2,9 +2,10 @@ package org.cqfn.diktat.plugin.gradle.tasks import org.cqfn.diktat.plugin.gradle.DiktatExtension import org.cqfn.diktat.plugin.gradle.DiktatGradlePlugin.Companion.MERGE_SARIF_REPORTS_TASK_NAME -import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.getOutputFile +import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.isSarifReporterActive + import io.github.detekt.sarif4k.SarifSchema210 import org.gradle.api.DefaultTask import org.gradle.api.Project @@ -17,6 +18,7 @@ import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskExecutionException import org.gradle.api.tasks.VerificationTask + import kotlinx.serialization.SerializationException import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString diff --git a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt index 4cf0a6fd7a..7eedfa4cce 100644 --- a/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt +++ b/diktat-maven-plugin/src/main/kotlin/org/cqfn/diktat/plugin/maven/DiktatBaseMojo.kt @@ -144,7 +144,7 @@ abstract class DiktatBaseMojo : AbstractMojo() { } reporterImpl.afterAll() - if (!lintErrorReporter.isEmpty()) { + if (lintErrorReporter.isNotEmpty()) { throw MojoFailureException("There are ${lintErrorReporter.errorCount()} lint errors") } } diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt index 18a204b194..9c2f7ba7b8 100644 --- a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt @@ -42,7 +42,7 @@ class DiktatProcessCommand private constructor( private fun ktLintParams(): KtLint.ExperimentalParams = KtLint.ExperimentalParams( fileName = file.absolutePathString(), text = fileContent, - ruleSets = setOf(processor.diktatRuleSetProvider.get()), + ruleSets = setOf(processor.diktatRuleSetProvider.get()), userData = emptyMap(), cb = callback.unwrap(), script = isScript, @@ -52,13 +52,6 @@ class DiktatProcessCommand private constructor( isInvokedFromCli = false ) - companion object { - /** - * @return a builder for [DiktatProcessCommand] - */ - fun builder(): Builder = Builder() - } - /** * Builder for [DiktatProcessCommand] * @@ -125,4 +118,11 @@ class DiktatProcessCommand private constructor( ) } } + + companion object { + /** + * @return a builder for [DiktatProcessCommand] + */ + fun builder(): Builder = Builder() + } } diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt index ddef195a5d..5ab801b359 100644 --- a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt @@ -11,17 +11,11 @@ import kotlin.io.path.absolutePathString * @property diktatRuleSetProvider * @property logLevel */ +@Suppress("USE_DATA_CLASS") // to hide `copy` method class DiktatProcessor private constructor( val diktatRuleSetProvider: DiktatRuleSetProvider, val logLevel: DiktatLogLevel, ) { - companion object { - /** - * @return a builder for [DiktatProcessor] - */ - fun builder(): Builder = Builder() - } - /** * Builder for [DiktatProcessCommand] * @@ -38,7 +32,6 @@ class DiktatProcessor private constructor( */ fun diktatRuleSetProvider(diktatRuleSetProvider: DiktatRuleSetProvider) = apply { this.diktatRuleSetProvider = diktatRuleSetProvider } - /** * @param configFile a config file to load [DiktatRuleSetProvider] * @return updated builder @@ -65,4 +58,10 @@ class DiktatProcessor private constructor( logLevel = logLevel, ) } + companion object { + /** + * @return a builder for [DiktatProcessor] + */ + fun builder(): Builder = Builder() + } } diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt index de26a6f456..2bd5e13828 100644 --- a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt +++ b/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt @@ -10,14 +10,18 @@ import java.util.concurrent.atomic.AtomicInteger class LintErrorReporter : Reporter { private val errorCounter: AtomicInteger = AtomicInteger() - override fun onLintError(file: String, err: LintError, corrected: Boolean) { + override fun onLintError( + file: String, + err: LintError, + corrected: Boolean + ) { errorCounter.incrementAndGet() } /** - * @return true if there are no reported [LintError], otherwise -- false. + * @return true if there is a reported [LintError], otherwise -- false. */ - fun isEmpty(): Boolean = errorCounter.get() == 0 + fun isNotEmpty(): Boolean = errorCounter.get() != 0 /** * @return count of reported [LintError] From 66310b12624300d4ac096645552c465542e37e87 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 11:26:34 +0300 Subject: [PATCH 05/18] fixed test in gradle plugin and diktat-ruleset --- .../org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt | 2 +- .../org/cqfn/diktat/ruleset/smoke/DiktatSaveSmokeTest.kt | 5 ++++- .../org/cqfn/diktat/ruleset/smoke/DiktatSmokeTestUtils.kt | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt index 80cb06bf37..08b92ebf7b 100644 --- a/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt +++ b/diktat-gradle-plugin/src/test/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginTest.kt @@ -44,6 +44,6 @@ class DiktatGradlePluginTest { Assertions.assertEquals("", diktatExtension.reporter) val reporterFlag = project.getReporterType(diktatExtension) - Assertions.assertEquals("--reporter=plain", reporterFlag) + Assertions.assertEquals("plain", reporterFlag) } } 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 3b82f5dcc9..ba20b120d3 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 @@ -27,6 +27,7 @@ import kotlin.io.path.createDirectories import kotlin.io.path.div import kotlin.io.path.exists import kotlin.io.path.listDirectoryEntries +import kotlin.io.path.name import kotlin.io.path.readText @DisabledOnOs(OS.MAC) @@ -170,7 +171,9 @@ class DiktatSaveSmokeTest : DiktatSmokeTestBase() { val diktatFrom = buildDirectory .takeIf(Path::exists) ?.listDirectoryEntries(DIKTAT_FAT_JAR_GLOB) - ?.singleOrNull() + ?.singleOrNull { jarFile -> + !jarFile.name.startsWith(DIKTAT_RULESET_JAR_PREFIX) + } softly.assertThat(diktatFrom) .describedAs(diktatFrom?.toString() ?: "$BUILD_DIRECTORY/$DIKTAT_FAT_JAR_GLOB") .isNotNull 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 a4c1397768..689bd9ad5c 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,6 +15,7 @@ import kotlin.system.measureNanoTime 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 DIKTAT_RULESET_JAR_PREFIX = "diktat-ruleset-" internal const val KTLINT_FAT_JAR = "ktlint" internal const val KTLINT_VERSION = "0.46.1" From 6b0061b1569620b854892e11cf566c2ff3053728 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 11:35:32 +0300 Subject: [PATCH 06/18] fixed snapshot test --- .github/workflows/diktat_snapshot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/diktat_snapshot.yml b/.github/workflows/diktat_snapshot.yml index 6ab4b7e62f..eac88b0323 100644 --- a/.github/workflows/diktat_snapshot.yml +++ b/.github/workflows/diktat_snapshot.yml @@ -48,6 +48,7 @@ jobs: arguments: | :diktat-common:publishToMavenLocal :diktat-rules:publishToMavenLocal + :diktat-ruleset:publishToMavenLocal :diktat-gradle-plugin:publishToMavenLocal :generateLibsForDiktatSnapshot -x detekt From 06ef2c0015a154877a528732a4e019a5c7cebded Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 11:42:56 +0300 Subject: [PATCH 07/18] proper fix for snapshot plugin --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index f4c6c56c5c..4a4215b9fe 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,7 @@ tasks.create("generateLibsForDiktatSnapshot") { val dependencies = setOf( projects.diktatCommon, projects.diktatRules, + projects.diktatRuleset, projects.diktatGradlePlugin, ) mustRunAfter(dependencies.map { ":${it.name}:publishToMavenLocal" }) From 54e1dce6d4b0b61ee9c21a6408092ee29f8da696 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 12:15:47 +0300 Subject: [PATCH 08/18] proper fix for snapshot plugin number 2 --- build.gradle.kts | 4 +++- diktat-maven-plugin/build.gradle.kts | 7 ++++++- diktat-ruleset/build.gradle.kts | 18 ++++++++++++++++-- .../buildutils/PublishingConfiguration.kt | 5 ++++- ... nexus-publishing-configuration.gradle.kts} | 4 ---- ...ng-signing-default-configuration.gradle.kts | 2 +- 6 files changed, 30 insertions(+), 10 deletions(-) rename gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/{publishing-configuration.gradle.kts => nexus-publishing-configuration.gradle.kts} (95%) diff --git a/build.gradle.kts b/build.gradle.kts index 4a4215b9fe..d510778560 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,4 @@ +import org.cqfn.diktat.buildutils.configurePublications import org.cqfn.diktat.buildutils.configureSigning import org.jetbrains.kotlin.incremental.createDirectory import java.nio.file.Files @@ -7,7 +8,7 @@ plugins { id("org.cqfn.diktat.buildutils.versioning-configuration") id("org.cqfn.diktat.buildutils.git-hook-configuration") id("org.cqfn.diktat.buildutils.code-quality-convention") - id("org.cqfn.diktat.buildutils.publishing-configuration") + id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") alias(libs.plugins.talaiot.base) java `maven-publish` @@ -26,6 +27,7 @@ talaiot { project.description = "diKTat kotlin formatter and fixer" +configurePublications() configureSigning() tasks.create("generateLibsForDiktatSnapshot") { diff --git a/diktat-maven-plugin/build.gradle.kts b/diktat-maven-plugin/build.gradle.kts index cf8e5702c4..95ebac7efe 100644 --- a/diktat-maven-plugin/build.gradle.kts +++ b/diktat-maven-plugin/build.gradle.kts @@ -1,10 +1,12 @@ +import org.cqfn.diktat.buildutils.configurePublications +import org.cqfn.diktat.buildutils.configureSigning import de.benediktritter.maven.plugin.development.task.GenerateHelpMojoSourcesTask import de.benediktritter.maven.plugin.development.task.GenerateMavenPluginDescriptorTask plugins { id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration") id("org.cqfn.diktat.buildutils.code-quality-convention") - id("org.cqfn.diktat.buildutils.publishing-configuration") + id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") id("de.benediktritter.maven-plugin-development") version "0.4.1" `maven-publish` } @@ -51,3 +53,6 @@ publishing { } } } + +configurePublications() +configureSigning() diff --git a/diktat-ruleset/build.gradle.kts b/diktat-ruleset/build.gradle.kts index 68232cffa9..f704cd78cf 100644 --- a/diktat-ruleset/build.gradle.kts +++ b/diktat-ruleset/build.gradle.kts @@ -1,10 +1,12 @@ +import org.cqfn.diktat.buildutils.configurePublications +import org.cqfn.diktat.buildutils.configureSigning import com.github.jengelman.gradle.plugins.shadow.ShadowExtension import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration") id("org.cqfn.diktat.buildutils.code-quality-convention") - id("org.cqfn.diktat.buildutils.publishing-configuration") + id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") id("com.github.johnrengelman.shadow") version "7.1.2" `maven-publish` } @@ -36,6 +38,11 @@ tasks.named("shadowJar") { archiveClassifier.set("") } +tasks.named("jar") { + // FIXME: need to extract shadowJar to a dedicated module + archiveClassifier.set("library") +} + // it triggers shadowJar with default build tasks { build { @@ -43,9 +50,13 @@ tasks { } } -// it creates a publication for shadowJar publishing { publications { + // it creates a publication for diktat-ruleset + create("maven") { + from(components["java"]) + } + // it creates a publication for shadowJar create("shadow") { // https://github.com/johnrengelman/shadow/issues/417#issuecomment-830668442 project.extensions.configure { @@ -54,3 +65,6 @@ publishing { } } } + +configurePublications() +configureSigning() diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt index 9577cc28c2..f5762bbcee 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt @@ -68,8 +68,11 @@ fun Project.configureSigning() { } } +/** + * Updates pom.xml for publication + */ @Suppress("TOO_LONG_FUNCTION") -internal fun Project.configurePublications() { +fun Project.configurePublications() { val dokkaJar: Jar = tasks.create("dokkaJar") { group = "documentation" archiveClassifier.set("javadoc") diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-configuration.gradle.kts b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/nexus-publishing-configuration.gradle.kts similarity index 95% rename from gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-configuration.gradle.kts rename to gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/nexus-publishing-configuration.gradle.kts index 50ca4ce47c..7bbdabbc40 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-configuration.gradle.kts +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/nexus-publishing-configuration.gradle.kts @@ -31,7 +31,3 @@ run { } } } - -run { - configurePublications() -} diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts index d53e3a5ad6..af28fd3e96 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts @@ -5,7 +5,7 @@ import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.get plugins { - id("org.cqfn.diktat.buildutils.publishing-configuration") + id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") } run { From 1fcef235d9488c6df04345f90388d0cea413b1eb Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 13:43:46 +0300 Subject: [PATCH 09/18] extracted processor and command to diktat-runner --- diktat-gradle-plugin/build.gradle.kts | 6 +- diktat-maven-plugin/build.gradle.kts | 3 +- diktat-ruleset/build.gradle.kts | 22 +++-- .../ruleset/smoke/DiktatSaveSmokeTest.kt | 5 +- .../ruleset/smoke/DiktatSmokeTestUtils.kt | 1 - .../diktat-runner-api/build.gradle.kts | 11 +++ .../diktat/AbstractDiktatProcessCommand.kt | 77 ++++++++--------- .../kotlin/org/cqfn/diktat/DiktatProcessor.kt | 1 + .../org/cqfn/diktat/api/DiktatCallback.kt | 0 .../kotlin/org/cqfn/diktat/api/DiktatError.kt | 0 .../org/cqfn/diktat/api/DiktatLogLevel.kt | 0 .../build.gradle.kts | 13 +++ .../org/cqfn/diktat/DiktatProcessCommand.kt | 84 +++++++++++++++++++ .../diktat/ktlint/LintErrorCallbackWrapper.kt | 0 .../cqfn/diktat/ktlint/LintErrorReporter.kt | 0 .../cqfn/diktat/ktlint/LintErrorWrapper.kt | 0 .../buildutils/PublishingConfiguration.kt | 66 ++++++++------- settings.gradle.kts | 2 + 18 files changed, 200 insertions(+), 91 deletions(-) create mode 100644 diktat-runner/diktat-runner-api/build.gradle.kts rename diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt => diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt (54%) rename {diktat-ruleset => diktat-runner/diktat-runner-api}/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt (99%) rename {diktat-ruleset => diktat-runner/diktat-runner-api}/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt (100%) rename {diktat-ruleset => diktat-runner/diktat-runner-api}/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt (100%) rename {diktat-ruleset => diktat-runner/diktat-runner-api}/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt (100%) create mode 100644 diktat-runner/diktat-runner-ktlint-engine/build.gradle.kts create mode 100644 diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt rename {diktat-ruleset => diktat-runner/diktat-runner-ktlint-engine}/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt (100%) rename {diktat-ruleset => diktat-runner/diktat-runner-ktlint-engine}/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt (100%) rename {diktat-ruleset => diktat-runner/diktat-runner-ktlint-engine}/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt (100%) diff --git a/diktat-gradle-plugin/build.gradle.kts b/diktat-gradle-plugin/build.gradle.kts index 13aa895d28..0d70ded181 100644 --- a/diktat-gradle-plugin/build.gradle.kts +++ b/diktat-gradle-plugin/build.gradle.kts @@ -13,14 +13,16 @@ plugins { dependencies { implementation(kotlin("gradle-plugin-api")) - implementation(projects.diktatRuleset) - implementation(libs.sarif4k.jvm) + implementation(projects.diktatRunner.diktatRunnerKtlintEngine) implementation(libs.ktlint.core) implementation(libs.ktlint.reporter.plain) implementation(libs.ktlint.reporter.sarif) implementation(libs.ktlint.reporter.json) implementation(libs.ktlint.reporter.html) implementation(libs.ktlint.reporter.baseline) + // merge sarif reports + implementation(libs.sarif4k.jvm) + implementation(libs.kotlinx.serialization.json) testImplementation(libs.junit.jupiter.api) testRuntimeOnly(libs.junit.jupiter.engine) } diff --git a/diktat-maven-plugin/build.gradle.kts b/diktat-maven-plugin/build.gradle.kts index 95ebac7efe..c4b1d93ff0 100644 --- a/diktat-maven-plugin/build.gradle.kts +++ b/diktat-maven-plugin/build.gradle.kts @@ -17,7 +17,8 @@ dependencies { compileOnly(libs.maven.core) implementation(libs.kotlin.stdlib.jdk8) - implementation(projects.diktatRuleset) + implementation(projects.diktatRules) + implementation(projects.diktatRunner.diktatRunnerKtlintEngine) implementation(libs.ktlint.core) implementation(libs.ktlint.reporter.plain) implementation(libs.ktlint.reporter.sarif) diff --git a/diktat-ruleset/build.gradle.kts b/diktat-ruleset/build.gradle.kts index f704cd78cf..552fe94fb7 100644 --- a/diktat-ruleset/build.gradle.kts +++ b/diktat-ruleset/build.gradle.kts @@ -1,5 +1,4 @@ -import org.cqfn.diktat.buildutils.configurePublications -import org.cqfn.diktat.buildutils.configureSigning +import org.cqfn.diktat.buildutils.configurePom import com.github.jengelman.gradle.plugins.shadow.ShadowExtension import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar @@ -38,9 +37,9 @@ tasks.named("shadowJar") { archiveClassifier.set("") } -tasks.named("jar") { - // FIXME: need to extract shadowJar to a dedicated module - archiveClassifier.set("library") +// disable default jar +tasks.named("jar") { + enabled = false } // it triggers shadowJar with default build @@ -52,19 +51,18 @@ tasks { publishing { publications { - // it creates a publication for diktat-ruleset - create("maven") { - from(components["java"]) - } // it creates a publication for shadowJar create("shadow") { // https://github.com/johnrengelman/shadow/issues/417#issuecomment-830668442 project.extensions.configure { component(this@create) } + this.artifactId = "diktat" + this.pom { + configurePom(project) + // need to override name + name.set("diktat") + } } } } - -configurePublications() -configureSigning() 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 ba20b120d3..3b82f5dcc9 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 @@ -27,7 +27,6 @@ import kotlin.io.path.createDirectories import kotlin.io.path.div import kotlin.io.path.exists import kotlin.io.path.listDirectoryEntries -import kotlin.io.path.name import kotlin.io.path.readText @DisabledOnOs(OS.MAC) @@ -171,9 +170,7 @@ class DiktatSaveSmokeTest : DiktatSmokeTestBase() { val diktatFrom = buildDirectory .takeIf(Path::exists) ?.listDirectoryEntries(DIKTAT_FAT_JAR_GLOB) - ?.singleOrNull { jarFile -> - !jarFile.name.startsWith(DIKTAT_RULESET_JAR_PREFIX) - } + ?.singleOrNull() softly.assertThat(diktatFrom) .describedAs(diktatFrom?.toString() ?: "$BUILD_DIRECTORY/$DIKTAT_FAT_JAR_GLOB") .isNotNull 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 689bd9ad5c..a4c1397768 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 @@ import kotlin.system.measureNanoTime 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 DIKTAT_RULESET_JAR_PREFIX = "diktat-ruleset-" internal const val KTLINT_FAT_JAR = "ktlint" internal const val KTLINT_VERSION = "0.46.1" diff --git a/diktat-runner/diktat-runner-api/build.gradle.kts b/diktat-runner/diktat-runner-api/build.gradle.kts new file mode 100644 index 0000000000..eaad652c9a --- /dev/null +++ b/diktat-runner/diktat-runner-api/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration") + id("org.cqfn.diktat.buildutils.code-quality-convention") + id("org.cqfn.diktat.buildutils.publishing-signing-default-configuration") +} + +project.description = "This module builds diktat-runner-api" + +dependencies { + implementation(projects.diktatRules) +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt similarity index 54% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt rename to diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt index 9c2f7ba7b8..9b37db70b2 100644 --- a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt +++ b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt @@ -1,17 +1,12 @@ package org.cqfn.diktat import org.cqfn.diktat.api.DiktatCallback -import org.cqfn.diktat.api.DiktatLogLevel -import org.cqfn.diktat.ktlint.unwrap import org.cqfn.diktat.ruleset.utils.isKotlinScript -import com.pinterest.ktlint.core.KtLint -import com.pinterest.ktlint.core.api.EditorConfigOverride import java.nio.file.Path -import kotlin.io.path.absolutePathString import kotlin.io.path.readText /** - * Command to run `diktat` + * An abstract implementation for command to run `diktat` * * @property processor * @property file @@ -19,41 +14,27 @@ import kotlin.io.path.readText * @property isScript * @property callback */ -class DiktatProcessCommand private constructor( - private val processor: DiktatProcessor, - private val file: Path, - private val fileContent: String, - private val isScript: Boolean, - private val callback: DiktatCallback, +abstract class AbstractDiktatProcessCommand( + protected val processor: DiktatProcessor, + protected val file: Path, + protected val fileContent: String, + protected val isScript: Boolean, + protected val callback: DiktatCallback, ) { /** * Run `diktat fix` using parameters from current command * * @return result of `diktat fix` */ - fun fix(): String = KtLint.format(ktLintParams()) + abstract fun fix(): String /** * Run `diktat check` using parameters from current command */ - fun check(): Unit = KtLint.lint(ktLintParams()) - - @Suppress("DEPRECATION") - private fun ktLintParams(): KtLint.ExperimentalParams = KtLint.ExperimentalParams( - fileName = file.absolutePathString(), - text = fileContent, - ruleSets = setOf(processor.diktatRuleSetProvider.get()), - userData = emptyMap(), - cb = callback.unwrap(), - script = isScript, - editorConfigPath = null, - debug = processor.logLevel == DiktatLogLevel.DEBUG, - editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, - isInvokedFromCli = false - ) + abstract fun check() /** - * Builder for [DiktatProcessCommand] + * Builder for [AbstractDiktatProcessCommand] * * @property processor * @property file @@ -61,13 +42,13 @@ class DiktatProcessCommand private constructor( * @property isScript * @property callback */ - class Builder internal constructor( - private var processor: DiktatProcessor? = null, - private var file: Path? = null, - private var fileContent: String? = null, - private var isScript: Boolean? = null, - private var callback: DiktatCallback? = null, - ) { + abstract class Builder { + private var processor: DiktatProcessor? = null + private var file: Path? = null + private var fileContent: String? = null + private var isScript: Boolean? = null + private var callback: DiktatCallback? = null + /** * @param processor * @return updated builder @@ -99,13 +80,13 @@ class DiktatProcessCommand private constructor( fun callback(callback: DiktatCallback) = apply { this.callback = callback } /** - * @return built [DiktatProcessCommand] + * @return built [C] */ - fun build(): DiktatProcessCommand { + fun build(): C { val resolvedFile = requireNotNull(file) { "file is required" } - return DiktatProcessCommand( + return doBuild( processor = requireNotNull(processor) { "processor is required" }, @@ -117,12 +98,22 @@ class DiktatProcessCommand private constructor( }, ) } - } - companion object { /** - * @return a builder for [DiktatProcessCommand] + * @return [C] is built using values from builder + * + * @param processor + * @param file + * @param fileContent + * @param isScript + * @param callback */ - fun builder(): Builder = Builder() + abstract fun doBuild( + processor: DiktatProcessor, + file: Path, + fileContent: String, + isScript: Boolean, + callback: DiktatCallback, + ): C } } diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt similarity index 99% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt rename to diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt index 5ab801b359..69475f996f 100644 --- a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt +++ b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/DiktatProcessor.kt @@ -58,6 +58,7 @@ class DiktatProcessor private constructor( logLevel = logLevel, ) } + companion object { /** * @return a builder for [DiktatProcessor] diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt similarity index 100% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt rename to diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/api/DiktatCallback.kt diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt similarity index 100% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt rename to diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/api/DiktatError.kt diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt similarity index 100% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt rename to diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/api/DiktatLogLevel.kt diff --git a/diktat-runner/diktat-runner-ktlint-engine/build.gradle.kts b/diktat-runner/diktat-runner-ktlint-engine/build.gradle.kts new file mode 100644 index 0000000000..9e3534faa5 --- /dev/null +++ b/diktat-runner/diktat-runner-ktlint-engine/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration") + id("org.cqfn.diktat.buildutils.code-quality-convention") + id("org.cqfn.diktat.buildutils.publishing-signing-default-configuration") +} + +project.description = "This module builds diktat-runner implementation using ktlint" + +dependencies { + api(projects.diktatRunner.diktatRunnerApi) + implementation(projects.diktatRules) + implementation(libs.ktlint.core) +} diff --git a/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt new file mode 100644 index 0000000000..09b8c2302e --- /dev/null +++ b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt @@ -0,0 +1,84 @@ +package org.cqfn.diktat + +import org.cqfn.diktat.api.DiktatCallback +import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.unwrap +import com.pinterest.ktlint.core.KtLint +import com.pinterest.ktlint.core.api.EditorConfigOverride +import java.nio.file.Path +import kotlin.io.path.absolutePathString + +/** + * Command to run `diktat` + * + * @property processor + * @property file + * @property fileContent + * @property isScript + * @property callback + */ +class DiktatProcessCommand private constructor( + processor: DiktatProcessor, + file: Path, + fileContent: String, + isScript: Boolean, + callback: DiktatCallback, +) : AbstractDiktatProcessCommand( + processor, + file, + fileContent, + isScript, + callback, +) { + /** + * Run `diktat fix` using parameters from current command + * + * @return result of `diktat fix` + */ + override fun fix(): String = KtLint.format(ktLintParams()) + + /** + * Run `diktat check` using parameters from current command + */ + override fun check(): Unit = KtLint.lint(ktLintParams()) + + @Suppress("DEPRECATION") + private fun ktLintParams(): KtLint.ExperimentalParams = KtLint.ExperimentalParams( + fileName = file.absolutePathString(), + text = fileContent, + ruleSets = setOf(processor.diktatRuleSetProvider.get()), + userData = emptyMap(), + cb = callback.unwrap(), + script = isScript, + editorConfigPath = null, + debug = processor.logLevel == DiktatLogLevel.DEBUG, + editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride, + isInvokedFromCli = false + ) + + /** + * Builder for [DiktatProcessCommand] + */ + class Builder internal constructor() : AbstractDiktatProcessCommand.Builder() { + override fun doBuild( + processor: DiktatProcessor, + file: Path, + fileContent: String, + isScript: Boolean, + callback: DiktatCallback, + ): DiktatProcessCommand = DiktatProcessCommand( + processor = processor, + file = file, + fileContent = fileContent, + isScript = isScript, + callback = callback, + ) + } + + companion object { + /** + * @return a builder for [DiktatProcessCommand] + */ + fun builder(): Builder = Builder() + } +} diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt similarity index 100% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt rename to diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorCallbackWrapper.kt diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt similarity index 100% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt rename to diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorReporter.kt diff --git a/diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt similarity index 100% rename from diktat-ruleset/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt rename to diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/ktlint/LintErrorWrapper.kt diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt index f5762bbcee..8f92f6024f 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/PublishingConfiguration.kt @@ -13,6 +13,7 @@ import io.github.gradlenexus.publishplugin.NexusPublishExtension import org.gradle.api.Named import org.gradle.api.Project import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPom import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.tasks.bundling.Jar import org.gradle.internal.logging.text.StyledTextOutput @@ -89,39 +90,48 @@ fun Project.configurePublications() { */ this.artifact(dokkaJar) this.pom { - name.set(project.name) - description.set(project.description ?: project.name) - url.set("https://www.cqfn.org/diKTat/") - licenses { - license { - name.set("MIT License") - url.set("http://www.opensource.org/licenses/mit-license.php") - } - } - developers { - developer { - id.set("akuleshov7") - name.set("Andrey Kuleshov") - email.set("andrewkuleshov7@gmail.com") - url.set("https://github.com/akuleshov7") - } - developer { - id.set("petertrr") - name.set("Peter Trifanov") - email.set("peter.trifanov@gmail.com") - url.set("https://github.com/petertrr") - } - } - scm { - connection.set("scm:git:git://github.com/saveourtool/diktat.git") - developerConnection.set("scm:git:ssh://github.com:saveourtool/diktat.git") - url.set("http://github.com/saveourtool/diktat/tree/master") - } + configurePom(project) } } } } +/** + * Configures _pom.xml_ + * + * @param project + */ +fun MavenPom.configurePom(project: Project) { + name.set(project.name) + description.set(project.description ?: project.name) + url.set("https://www.cqfn.org/diKTat/") + licenses { + license { + name.set("MIT License") + url.set("http://www.opensource.org/licenses/mit-license.php") + } + } + developers { + developer { + id.set("akuleshov7") + name.set("Andrey Kuleshov") + email.set("andrewkuleshov7@gmail.com") + url.set("https://github.com/akuleshov7") + } + developer { + id.set("petertrr") + name.set("Peter Trifanov") + email.set("peter.trifanov@gmail.com") + url.set("https://github.com/petertrr") + } + } + scm { + connection.set("scm:git:git://github.com/saveourtool/diktat.git") + developerConnection.set("scm:git:ssh://github.com:saveourtool/diktat.git") + url.set("http://github.com/saveourtool/diktat/tree/master") + } +} + internal fun Project.configureNexusPublishing() { configure { repositories { diff --git a/settings.gradle.kts b/settings.gradle.kts index d5dc0258b0..b9c909cb82 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,6 +39,8 @@ include("diktat-rules") include("diktat-ruleset") include("diktat-test-framework") include("diktat-dev-ksp") +include("diktat-runner:diktat-runner-api") +include("diktat-runner:diktat-runner-ktlint-engine") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") From 93a00b7076b85c81035e1200b665f0033c4e1638 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 13:45:29 +0300 Subject: [PATCH 10/18] fixed diktat-snapshot --- .github/workflows/diktat_snapshot.yml | 3 ++- build.gradle.kts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/diktat_snapshot.yml b/.github/workflows/diktat_snapshot.yml index eac88b0323..f1c541fa03 100644 --- a/.github/workflows/diktat_snapshot.yml +++ b/.github/workflows/diktat_snapshot.yml @@ -48,7 +48,8 @@ jobs: arguments: | :diktat-common:publishToMavenLocal :diktat-rules:publishToMavenLocal - :diktat-ruleset:publishToMavenLocal + :diktat-runner:diktat-runner-api:publishToMavenLocal + :diktat-runner:diktat-runner-ktlint-engine:publishToMavenLocal :diktat-gradle-plugin:publishToMavenLocal :generateLibsForDiktatSnapshot -x detekt diff --git a/build.gradle.kts b/build.gradle.kts index d510778560..cff56d774d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,7 +36,8 @@ tasks.create("generateLibsForDiktatSnapshot") { val dependencies = setOf( projects.diktatCommon, projects.diktatRules, - projects.diktatRuleset, + projects.diktatRunner.diktatRunnerApi, + projects.diktatRunner.diktatRunnerKtlintEngine, projects.diktatGradlePlugin, ) mustRunAfter(dependencies.map { ":${it.name}:publishToMavenLocal" }) From e14c2219a5eb641c62dbeef5fbece9af517a22bd Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 13:53:37 +0300 Subject: [PATCH 11/18] reverted changes related to publishing-configuration --- build.gradle.kts | 4 +--- diktat-maven-plugin/build.gradle.kts | 7 +------ diktat-ruleset/build.gradle.kts | 2 +- ...tion.gradle.kts => publishing-configuration.gradle.kts} | 4 ++++ .../publishing-signing-default-configuration.gradle.kts | 2 +- 5 files changed, 8 insertions(+), 11 deletions(-) rename gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/{nexus-publishing-configuration.gradle.kts => publishing-configuration.gradle.kts} (95%) diff --git a/build.gradle.kts b/build.gradle.kts index cff56d774d..1ca245c2a6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import org.cqfn.diktat.buildutils.configurePublications import org.cqfn.diktat.buildutils.configureSigning import org.jetbrains.kotlin.incremental.createDirectory import java.nio.file.Files @@ -8,7 +7,7 @@ plugins { id("org.cqfn.diktat.buildutils.versioning-configuration") id("org.cqfn.diktat.buildutils.git-hook-configuration") id("org.cqfn.diktat.buildutils.code-quality-convention") - id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") + id("org.cqfn.diktat.buildutils.publishing-configuration") alias(libs.plugins.talaiot.base) java `maven-publish` @@ -27,7 +26,6 @@ talaiot { project.description = "diKTat kotlin formatter and fixer" -configurePublications() configureSigning() tasks.create("generateLibsForDiktatSnapshot") { diff --git a/diktat-maven-plugin/build.gradle.kts b/diktat-maven-plugin/build.gradle.kts index c4b1d93ff0..1e0034d8ef 100644 --- a/diktat-maven-plugin/build.gradle.kts +++ b/diktat-maven-plugin/build.gradle.kts @@ -1,12 +1,10 @@ -import org.cqfn.diktat.buildutils.configurePublications -import org.cqfn.diktat.buildutils.configureSigning import de.benediktritter.maven.plugin.development.task.GenerateHelpMojoSourcesTask import de.benediktritter.maven.plugin.development.task.GenerateMavenPluginDescriptorTask plugins { id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration") id("org.cqfn.diktat.buildutils.code-quality-convention") - id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") + id("org.cqfn.diktat.buildutils.publishing-configuration") id("de.benediktritter.maven-plugin-development") version "0.4.1" `maven-publish` } @@ -54,6 +52,3 @@ publishing { } } } - -configurePublications() -configureSigning() diff --git a/diktat-ruleset/build.gradle.kts b/diktat-ruleset/build.gradle.kts index 552fe94fb7..43fb22d3aa 100644 --- a/diktat-ruleset/build.gradle.kts +++ b/diktat-ruleset/build.gradle.kts @@ -5,7 +5,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration") id("org.cqfn.diktat.buildutils.code-quality-convention") - id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") + id("org.cqfn.diktat.buildutils.publishing-configuration") id("com.github.johnrengelman.shadow") version "7.1.2" `maven-publish` } diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/nexus-publishing-configuration.gradle.kts b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-configuration.gradle.kts similarity index 95% rename from gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/nexus-publishing-configuration.gradle.kts rename to gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-configuration.gradle.kts index 7bbdabbc40..50ca4ce47c 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/nexus-publishing-configuration.gradle.kts +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-configuration.gradle.kts @@ -31,3 +31,7 @@ run { } } } + +run { + configurePublications() +} diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts index af28fd3e96..d53e3a5ad6 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/publishing-signing-default-configuration.gradle.kts @@ -5,7 +5,7 @@ import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.get plugins { - id("org.cqfn.diktat.buildutils.nexus-publishing-configuration") + id("org.cqfn.diktat.buildutils.publishing-configuration") } run { From 91d86977574ea8831836fcabc19d9cee7d3a8b81 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 14:32:38 +0300 Subject: [PATCH 12/18] migrated from ProjectDependency to Project in `generateLibsForDiktatSnapshot` --- build.gradle.kts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1ca245c2a6..106d4180a5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,13 +32,13 @@ tasks.create("generateLibsForDiktatSnapshot") { val dir = rootProject.buildDir.resolve("diktat-snapshot") val dependencies = setOf( - projects.diktatCommon, - projects.diktatRules, - projects.diktatRunner.diktatRunnerApi, - projects.diktatRunner.diktatRunnerKtlintEngine, - projects.diktatGradlePlugin, + rootProject.project(":diktat-common"), + rootProject.project(":diktat-rules"), + rootProject.project(":diktat-runner:diktat-runner-api"), + rootProject.project(":diktat-runner:diktat-runner-ktlint-engine"), + rootProject.project(":diktat-gradle-plugin"), ) - mustRunAfter(dependencies.map { ":${it.name}:publishToMavenLocal" }) + mustRunAfter(dependencies.map { "${it.path}:publishToMavenLocal" }) val libsFile = rootProject.file("gradle/libs.versions.toml") inputs.file(libsFile) @@ -74,19 +74,19 @@ tasks.create("generateLibsForDiktatSnapshot") { } /** - * @param projectDependency + * @param project * @return resolved path to directory according to maven coordinate */ -fun File.pathToMavenArtifact(projectDependency: ProjectDependency): File = projectDependency.group.toString() +fun File.pathToMavenArtifact(project: Project): File = project.group.toString() .split(".") .fold(this) { dirToArtifact, newPart -> dirToArtifact.resolve(newPart) } - .resolve(projectDependency.name) - .resolve(projectDependency.version.toString()) + .resolve(project.name) + .resolve(project.version.toString()) /** * @return generated pom.xml for project dependency */ -fun ProjectDependency.pomFile(): File = rootProject.file("$name/build/publications/") +fun Project.pomFile(): File = buildDir.resolve("publications") .let { publicationsDir -> publicationsDir.resolve("pluginMaven") .takeIf { it.exists() } @@ -95,16 +95,16 @@ fun ProjectDependency.pomFile(): File = rootProject.file("$name/build/publicatio .resolve("pom-default.xml") /** - * @return file name of pom.xml for project dependency + * @return file name of pom.xml for project */ -fun ProjectDependency.pomFileName(): String = "$name-$version.pom" +fun Project.pomFileName(): String = "$name-$version.pom" /** * @return generated artifact for project dependency */ -fun ProjectDependency.artifactFile(): File = rootProject.file("$name/build/libs/$name-$version.jar") +fun Project.artifactFile(): File = buildDir.resolve("libs/${artifactFileName()}") /** * @return file name of artifact for project dependency */ -fun ProjectDependency.artifactFileName(): String = "$name-$version.jar" +fun Project.artifactFileName(): String = "$name-$version.jar" From 4b7b8109e7e0ba4c04476c0185c6dd725b936960 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 14:34:25 +0300 Subject: [PATCH 13/18] diktatFix --- .../org/cqfn/diktat/AbstractDiktatProcessCommand.kt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt index 9b37db70b2..98b6c05338 100644 --- a/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt +++ b/diktat-runner/diktat-runner-api/src/main/kotlin/org/cqfn/diktat/AbstractDiktatProcessCommand.kt @@ -35,12 +35,6 @@ abstract class AbstractDiktatProcessCommand( /** * Builder for [AbstractDiktatProcessCommand] - * - * @property processor - * @property file - * @property fileContent - * @property isScript - * @property callback */ abstract class Builder { private var processor: DiktatProcessor? = null @@ -100,13 +94,12 @@ abstract class AbstractDiktatProcessCommand( } /** - * @return [C] is built using values from builder - * * @param processor * @param file * @param fileContent * @param isScript * @param callback + * @return [C] is built using values from builder */ abstract fun doBuild( processor: DiktatProcessor, From fb66e6da99cc7a3e6f4cd3b12a4e55c1975ed5e2 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 14:45:12 +0300 Subject: [PATCH 14/18] a base interface in gradle plugin for old configuration --- .../diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt | 6 ++++++ .../org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt new file mode 100644 index 0000000000..f01de26c59 --- /dev/null +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt @@ -0,0 +1,6 @@ +package org.cqfn.diktat.plugin.gradle.tasks + +/** + * An interface with old name for base class for backward compatibility in plugin configuration + */ +interface DiktatJavaExecTaskBase diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt index d45a343179..5543dcb84b 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -50,7 +50,7 @@ import java.io.PrintStream abstract class DiktatTaskBase( @get:Internal internal val extension: DiktatExtension, private val inputs: PatternFilterable -) : DefaultTask(), VerificationTask { +) : DefaultTask(), VerificationTask, DiktatJavaExecTaskBase { /** * Files that will be analyzed by diktat */ From 56b6eeb97ebcc5dab93c3033caa44afa39e298c0 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 14:46:03 +0300 Subject: [PATCH 15/18] fixed package name --- .../diktat/plugin/gradle/{tasks => }/DiktatJavaExecTaskBase.kt | 2 +- .../org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/{tasks => }/DiktatJavaExecTaskBase.kt (75%) diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt similarity index 75% rename from diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt rename to diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt index f01de26c59..b4782d5564 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatJavaExecTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt @@ -1,4 +1,4 @@ -package org.cqfn.diktat.plugin.gradle.tasks +package org.cqfn.diktat.plugin.gradle /** * An interface with old name for base class for backward compatibility in plugin configuration diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt index 5543dcb84b..75d2fc1b32 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -11,6 +11,7 @@ import org.cqfn.diktat.api.DiktatLogLevel import org.cqfn.diktat.ktlint.LintErrorReporter import org.cqfn.diktat.ktlint.unwrap import org.cqfn.diktat.plugin.gradle.DiktatExtension +import org.cqfn.diktat.plugin.gradle.DiktatJavaExecTaskBase import org.cqfn.diktat.plugin.gradle.getOutputFile import org.cqfn.diktat.plugin.gradle.getReporterType import org.cqfn.diktat.plugin.gradle.isSarifReporterActive From 0600a2a4833d2c0f512144c5929377ff8560bfa6 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Wed, 29 Mar 2023 15:21:05 +0300 Subject: [PATCH 16/18] fixed snapshot running --- .../diktat/plugin/gradle/DiktatJavaExecTaskBase.kt | 4 +++- .../cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt | 7 ++++++- .../diktat-convention-configuration.gradle.kts | 11 +++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt index b4782d5564..f201a70c58 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt @@ -1,6 +1,8 @@ package org.cqfn.diktat.plugin.gradle +import org.gradle.api.Task + /** * An interface with old name for base class for backward compatibility in plugin configuration */ -interface DiktatJavaExecTaskBase +interface DiktatJavaExecTaskBase : Task diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt index 75d2fc1b32..2a1328bcd7 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -48,6 +48,7 @@ import java.io.PrintStream * A base task to run `diktat` * @property extension */ +@Suppress("WRONG_NEWLINES") abstract class DiktatTaskBase( @get:Internal internal val extension: DiktatExtension, private val inputs: PatternFilterable @@ -113,6 +114,10 @@ abstract class DiktatTaskBase( resolveReporter(baseline) } + init { + ignoreFailures = extension.ignoreFailures + } + /** * Function to execute diKTat * @@ -157,7 +162,7 @@ abstract class DiktatTaskBase( diktatProcessor: DiktatProcessor, reporter: Reporter ) { - project.logger.lifecycle("Checking file $file") + project.logger.debug("Checking file $file") reporter.before(file.absolutePath) val baselineErrors = baseline.baselineRules?.get( file.relativeTo(project.projectDir).invariantSeparatorsPath diff --git a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/diktat-convention-configuration.gradle.kts b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/diktat-convention-configuration.gradle.kts index 49bf317b0e..351442a41b 100644 --- a/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/diktat-convention-configuration.gradle.kts +++ b/gradle/plugins/src/main/kotlin/org/cqfn/diktat/buildutils/diktat-convention-configuration.gradle.kts @@ -27,8 +27,11 @@ diktat { } tasks.withType().configureEach { - javaLauncher.set(project.extensions.getByType().launcherFor { - // a temporary workaround -- diktat-gradle-plugin doesn't detect java version of `javaLauncher` - languageVersion.set(JavaLanguageVersion.of(11)) - }) + val project = this@configureEach.project + if (this is JavaExec) { + javaLauncher.set(project.extensions.getByType().launcherFor { + // a temporary workaround -- diktat-gradle-plugin doesn't detect java version of `javaLauncher` + languageVersion.set(JavaLanguageVersion.of(11)) + }) + } } From bb1a81efe36111f840837f71cfad7c9fa26aaec5 Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Thu, 30 Mar 2023 11:34:41 +0300 Subject: [PATCH 17/18] fixed merge issue + marked as deprecated DiktatJavaExecTaskBase --- .../org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt | 1 + .../src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt index f201a70c58..aca13fb5b8 100644 --- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt @@ -5,4 +5,5 @@ import org.gradle.api.Task /** * An interface with old name for base class for backward compatibility in plugin configuration */ +@Deprecated("will be removed in 2.x") interface DiktatJavaExecTaskBase : Task diff --git a/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt index 09b8c2302e..04a605af5d 100644 --- a/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt +++ b/diktat-runner/diktat-runner-ktlint-engine/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt @@ -2,6 +2,7 @@ package org.cqfn.diktat import org.cqfn.diktat.api.DiktatCallback import org.cqfn.diktat.api.DiktatLogLevel +import org.cqfn.diktat.ktlint.KtLintRuleSetProviderWrapper.Companion.toKtLint import org.cqfn.diktat.ktlint.unwrap import com.pinterest.ktlint.core.KtLint import com.pinterest.ktlint.core.api.EditorConfigOverride @@ -46,7 +47,7 @@ class DiktatProcessCommand private constructor( private fun ktLintParams(): KtLint.ExperimentalParams = KtLint.ExperimentalParams( fileName = file.absolutePathString(), text = fileContent, - ruleSets = setOf(processor.diktatRuleSetProvider.get()), + ruleSets = setOf(processor.diktatRuleSetProvider.toKtLint().get()), userData = emptyMap(), cb = callback.unwrap(), script = isScript, From b544b3dc05237673b1cb7a9d2f434529145cd67e Mon Sep 17 00:00:00 2001 From: Nariman Abdullin Date: Thu, 30 Mar 2023 11:49:46 +0300 Subject: [PATCH 18/18] deleted unused file --- .../cqfn/diktat/common/ktlint/KtLintUtils.kt | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 diktat-common/src/main/kotlin/org/cqfn/diktat/common/ktlint/KtLintUtils.kt diff --git a/diktat-common/src/main/kotlin/org/cqfn/diktat/common/ktlint/KtLintUtils.kt b/diktat-common/src/main/kotlin/org/cqfn/diktat/common/ktlint/KtLintUtils.kt deleted file mode 100644 index 4e45c72d02..0000000000 --- a/diktat-common/src/main/kotlin/org/cqfn/diktat/common/ktlint/KtLintUtils.kt +++ /dev/null @@ -1,22 +0,0 @@ -@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") - -package org.cqfn.diktat.common.ktlint - -private val ktlintRuleSetIds: List by lazy { - listOf( - "standard", - "experimental", - "test", - "custom" - ) -} - -/** - * Contains the necessary value of the `--disabled_rules` _KtLint_ argument. - */ -val ktlintDisabledRulesArgument: String by lazy { - ktlintRuleSetIds.joinToString( - prefix = "--disabled_rules=", - separator = "," - ) -}