diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatExtension.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatExtension.kt index a51ed2152f..5bb0cbd070 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatExtension.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatExtension.kt @@ -1,50 +1,44 @@ package com.saveourtool.diktat.plugin.gradle +import org.gradle.api.Action +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.VerificationTask import org.gradle.api.tasks.util.PatternFilterable -import org.gradle.api.tasks.util.PatternSet -import java.io.File /** * An extension to configure diktat in build.gradle(.kts) file - * - * @param patternSet */ -open class DiktatExtension( - private val patternSet: PatternSet -) { +abstract class DiktatExtension { /** * Boolean flag to support `ignoreFailures` property of [VerificationTask]. */ - var ignoreFailures: Boolean = false - - /** - * Flag that indicates whether to turn debug logging on - */ - var debug = false + abstract val ignoreFailures: Property /** * Property that will be used if you need to publish the report to GitHub */ - var githubActions = false + abstract val githubActions: Property // = false /** * Type of the reporter to use */ - var reporter: String = "" + abstract val reporter: Property /** * Destination for reporter. If empty, will write to stdout. */ - var output: String = "" + abstract val output: RegularFileProperty /** * Baseline file, containing a list of errors that will be ignored. * If this file doesn't exist, it will be created on the first invocation. */ - var baseline: String? = null + abstract val baseline: RegularFileProperty /** * Path to diktat yml config file. Can be either absolute or relative to project's root directory. @@ -52,14 +46,18 @@ open class DiktatExtension( */ @get:InputFile @get:PathSensitive(PathSensitivity.RELATIVE) - lateinit var diktatConfigFile: File + abstract val diktatConfigFile: RegularFileProperty + + /** + * @return [PatternFilterable] to configure input files for diktat task + */ + @Nested + abstract fun getInputs(): PatternFilterable /** * Configure input files for diktat task * - * @param action configuration lambda for `PatternFilterable` + * @param action configuration lambda for [PatternFilterable] */ - fun inputs(action: PatternFilterable.() -> Unit) { - action(patternSet) - } + fun inputs(action: Action) = action.execute(getInputs()) } diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatGradlePlugin.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatGradlePlugin.kt index 8ed30418fe..bebe2a6c70 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatGradlePlugin.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatGradlePlugin.kt @@ -5,7 +5,6 @@ import com.saveourtool.diktat.plugin.gradle.tasks.DiktatFixTask.Companion.regist import com.saveourtool.diktat.plugin.gradle.tasks.configureMergeReportsTask import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.tasks.util.PatternSet /** * Plugin that configures diktat and registers tasks to run diktat @@ -17,17 +16,15 @@ class DiktatGradlePlugin : Plugin { */ @Suppress("TOO_LONG_FUNCTION") override fun apply(project: Project) { - val patternSet = PatternSet() val diktatExtension = project.extensions.create( DIKTAT_EXTENSION, DiktatExtension::class.java, - patternSet ).apply { - diktatConfigFile = project.rootProject.file("diktat-analysis.yml") + diktatConfigFile.set(project.rootProject.file("diktat-analysis.yml")) } - project.registerDiktatCheckTask(diktatExtension, patternSet) - project.registerDiktatFixTask(diktatExtension, patternSet) + project.registerDiktatCheckTask(diktatExtension) + project.registerDiktatFixTask(diktatExtension) project.configureMergeReportsTask(diktatExtension) } diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt deleted file mode 100644 index 25d1093126..0000000000 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/DiktatJavaExecTaskBase.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.saveourtool.diktat.plugin.gradle - -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-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/Utils.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/Utils.kt index 57ef395c6c..c20a776b31 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/Utils.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/Utils.kt @@ -47,24 +47,24 @@ fun Any.closureOf(action: T.() -> Unit): Closure = * @return CLI flag as string */ fun Project.getReporterType(diktatExtension: DiktatExtension): String { - val name = diktatExtension.reporter.trim() + val reporter = diktatExtension.reporter.getOrElse("") val validReporters = listOf("sarif", "plain", "json", "html") 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") + diktatExtension.githubActions.getOrElse(false) -> { + if (reporter.isNotEmpty()) { + logger.warn("`diktat.githubActions` is set to true, so custom reporter [$reporter] will be ignored and SARIF reporter will be used") } "sarif" } - name.isEmpty() -> { + reporter.isEmpty() -> { logger.info("Reporter name was not set. Using 'plain' reporter") "plain" } - name !in validReporters -> { - logger.warn("Reporter name is invalid (provided value: [$name]). Falling back to 'plain' reporter") + reporter !in validReporters -> { + logger.warn("Reporter name is invalid (provided value: [$reporter]). Falling back to 'plain' reporter") "plain" } - else -> name + else -> reporter } return reporterType @@ -78,15 +78,14 @@ fun Project.getReporterType(diktatExtension: DiktatExtension): String { * @return destination [File] or null if stdout is used */ internal fun Project.getOutputFile(diktatExtension: DiktatExtension): File? = when { - diktatExtension.githubActions -> project.layout.buildDirectory + diktatExtension.githubActions.getOrElse(false) -> project.layout.buildDirectory .file("reports/diktat/diktat.sarif") .get() .asFile .also { Files.createDirectories(it.parentFile.toPath()) } - diktatExtension.output.isNotEmpty() -> file(diktatExtension.output) - else -> null + else -> diktatExtension.output.map { it.asFile }.orNull } /** diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatCheckTask.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatCheckTask.kt index 6f656825a8..2e83f345bc 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatCheckTask.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatCheckTask.kt @@ -6,7 +6,6 @@ import com.saveourtool.diktat.plugin.gradle.DiktatExtension import com.saveourtool.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 @@ -15,8 +14,7 @@ import javax.inject.Inject */ abstract class DiktatCheckTask @Inject constructor( extension: DiktatExtension, - inputs: PatternFilterable -) : DiktatTaskBase(extension, inputs) { +) : DiktatTaskBase(extension) { override fun doRun( runner: DiktatRunner, args: DiktatRunnerArguments @@ -30,11 +28,10 @@ abstract class DiktatCheckTask @Inject constructor( */ fun Project.registerDiktatCheckTask( diktatExtension: DiktatExtension, - patternSet: PatternSet ): TaskProvider = tasks.register( DiktatGradlePlugin.DIKTAT_CHECK_TASK, DiktatCheckTask::class.java, - diktatExtension, patternSet + diktatExtension, ) } } diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatFixTask.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatFixTask.kt index 0e7fdc4e4e..3671f2b5a6 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatFixTask.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatFixTask.kt @@ -6,8 +6,6 @@ import com.saveourtool.diktat.plugin.gradle.DiktatExtension import com.saveourtool.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 /** @@ -15,8 +13,7 @@ import javax.inject.Inject */ abstract class DiktatFixTask @Inject constructor( extension: DiktatExtension, - inputs: PatternFilterable -) : DiktatTaskBase(extension, inputs) { +) : DiktatTaskBase(extension) { override fun doRun( runner: DiktatRunner, args: DiktatRunnerArguments @@ -27,16 +24,14 @@ abstract class DiktatFixTask @Inject constructor( 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 + diktatExtension, ) } } diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatTaskBase.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatTaskBase.kt index dd2e7d9e74..b96d5576c5 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatTaskBase.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/DiktatTaskBase.kt @@ -14,59 +14,22 @@ import com.saveourtool.diktat.ruleset.rules.DiktatRuleConfigReaderImpl import com.saveourtool.diktat.ruleset.rules.DiktatRuleSetFactoryImpl 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.SourceTask import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.VerificationTask -import org.gradle.api.tasks.util.PatternFilterable import java.nio.file.Path /** * A base task to run `diktat` * - * @param inputs * @property extension */ -@Suppress("WRONG_NEWLINES", "Deprecation") abstract class DiktatTaskBase( @get:Internal internal val extension: DiktatExtension, - private val inputs: PatternFilterable -) : DefaultTask(), VerificationTask, com.saveourtool.diktat.plugin.gradle.DiktatJavaExecTaskBase { - /** - * 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 - } +) : SourceTask(), VerificationTask { private val diktatRunnerFactory by lazy { DiktatRunnerFactory( diktatRuleConfigReader = DiktatRuleConfigReaderImpl(), @@ -78,10 +41,10 @@ abstract class DiktatTaskBase( } private val diktatRunnerArguments by lazy { DiktatRunnerArguments( - configFile = extension.diktatConfigFile.toPath(), + configFile = extension.diktatConfigFile.get().asFile.toPath(), sourceRootDir = project.projectDir.toPath(), - files = actualInputs.files.map { it.toPath() }, - baselineFile = extension.baseline?.let { project.file(it).toPath() }, + files = source.files.map { it.toPath() }, + baselineFile = extension.baseline.map { it.asFile.toPath() }.orNull, reporterType = project.getReporterType(extension), reporterOutput = project.getOutputFile(extension)?.outputStream(), loggingListener = object : DiktatProcessorListener { @@ -105,7 +68,15 @@ abstract class DiktatTaskBase( } init { - ignoreFailures = extension.ignoreFailures + ignoreFailures = extension.ignoreFailures.getOrElse(false) + extension.getInputs().run { + if (includes.isEmpty() && excludes.isEmpty()) { + patternSet.include("src/**/*.kt") + } else { + patternSet.setIncludes(includes) + patternSet.setExcludes(excludes) + } + } } /** @@ -115,14 +86,8 @@ abstract class DiktatTaskBase( */ @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.lifecycle("Running diktat $DIKTAT_VERSION") + if (source.isEmpty) { project.logger.warn("Inputs for $name do not exist, will not run diktat") project.logger.info("Skipping diktat execution") } else { diff --git a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt index 7991df9f01..c108fb395d 100644 --- a/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt +++ b/diktat-gradle-plugin/src/main/kotlin/com/saveourtool/diktat/plugin/gradle/tasks/SarifReportMergeTask.kt @@ -96,7 +96,7 @@ internal fun Project.configureMergeReportsTask(diktatExtension: DiktatExtension) reportMergeTask.shouldRunAfter(tasks.withType(DiktatTaskBase::class.java)) } } - tasks.withType(DiktatTaskBase::class.java).configureEach { diktatJavaExecTaskBase -> - diktatJavaExecTaskBase.finalizedBy(rootProject.tasks.withType(SarifReportMergeTask::class.java)) + tasks.withType(DiktatTaskBase::class.java).configureEach { diktatTaskBase -> + diktatTaskBase.finalizedBy(rootProject.tasks.withType(SarifReportMergeTask::class.java)) } }