From 4667f9c2f377287f941d32d8b1184b3adf51d404 Mon Sep 17 00:00:00 2001 From: Niklas Baudy Date: Sat, 24 Aug 2024 11:23:55 +0200 Subject: [PATCH] Breaking: Remove Detekt. Please use their own Gradle Plugin. --- gradle.properties | 2 +- .../quality/tools/CodeQualityToolsPlugin.kt | 50 ---- .../tools/CodeQualityToolsPluginExtension.kt | 3 - .../code/quality/tools/CpdExtension.kt | 1 - .../code/quality/tools/DetektCheckTask.kt | 143 ------------ .../code/quality/tools/DetektExtension.kt | 52 ----- .../tools/CodeQualityToolsPluginDetektTest.kt | 214 ------------------ .../CodeQualityToolsPluginExtensionTest.kt | 3 +- .../tools/CommonCodeQualityToolsTest.kt | 3 +- 9 files changed, 3 insertions(+), 468 deletions(-) delete mode 100644 src/main/kotlin/com/vanniktech/code/quality/tools/DetektCheckTask.kt delete mode 100644 src/main/kotlin/com/vanniktech/code/quality/tools/DetektExtension.kt diff --git a/gradle.properties b/gradle.properties index ae1cda5..6a43424 100755 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ POM_ARTIFACT_ID=gradle-code-quality-tools-plugin POM_NAME=Gradle Code Quality Tools Plugin POM_PACKAGING=jar -POM_DESCRIPTION=Gradle plugin that generates Checkstyle, PMD, CPD, Lint, Detekt & Ktlint Tasks for every subproject. +POM_DESCRIPTION=Gradle plugin that generates Checkstyle, PMD, CPD, Lint & Ktlint Tasks for every subproject. POM_INCEPTION_YEAR=2016 POM_URL=http://github.com/vanniktech/gradle-code-quality-tools-plugin/ diff --git a/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPlugin.kt b/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPlugin.kt index 56e7024..3b48cef 100755 --- a/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPlugin.kt +++ b/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPlugin.kt @@ -1,5 +1,3 @@ -@file:Suppress("Detekt.TooManyFunctions", "UnstableApiUsage") - package com.vanniktech.code.quality.tools import com.android.build.gradle.BaseExtension @@ -47,7 +45,6 @@ class CodeQualityToolsPlugin : Plugin { project.addKtlint(rootProject, extension) project.addKotlin(extension) project.addCpd(extension) - project.addDetekt(rootProject, extension) project.addLint(extension) } } @@ -143,7 +140,6 @@ fun Project.addCheckstyle(rootProject: Project, extension: CodeQualityToolsPlugi return false } -@Suppress("Detekt.ComplexMethod") fun Project.addLint(extension: CodeQualityToolsPluginExtension): Boolean { val isNotIgnored = !shouldIgnore(extension) val isEnabled = extension.lint.enabled @@ -297,52 +293,6 @@ fun Project.addCpd(extension: CodeQualityToolsPluginExtension): Boolean { return false } -fun Project.addDetekt(rootProject: Project, extension: CodeQualityToolsPluginExtension): Boolean { - val isNotIgnored = !shouldIgnore(extension) - val isEnabled = extension.detekt.enabled - val isDetektSupported = isKotlinProject() - - if (isNotIgnored && isEnabled && isDetektSupported) { - val detektConfiguration = configurations.create("detekt") { configuration -> - configuration.attributes { - it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.javaObjectType, Usage.JAVA_RUNTIME)) - } - - configuration.isCanBeConsumed = false - configuration.isVisible = false - - configuration.defaultDependencies { - it.add(dependencies.create("io.gitlab.arturbosch.detekt:detekt-cli:${extension.detekt.toolVersion}")) - } - } - - tasks.register("detektCheck", DetektCheckTask::class.java) { task -> - task.failFast = extension.detekt.failFast - task.buildUponDefaultConfig = extension.detekt.buildUponDefaultConfig - task.parallel = extension.detekt.parallel - task.version = extension.detekt.toolVersion - task.outputDirectory = layout.buildDirectory.dir("reports/detekt/") - task.configFile = rootProject.file(extension.detekt.config) - task.inputFile = file(extension.detekt.input) - task.classpath.from(detektConfiguration) - task.inputs.files(kotlinFiles(baseDir = extension.detekt.input)) - - task.inputs.property("baseline-file-exists", false) - - extension.detekt.baselineFileName?.let { - val file = file(it) - task.baselineFilePath = file.toString() - task.inputs.property("baseline-file-exists", file.exists()) - } - } - - tasks.named(CHECK_TASK_NAME).configure { it.dependsOn("detektCheck") } - return true - } - - return false -} - private fun Project.shouldIgnore(extension: CodeQualityToolsPluginExtension) = extension.ignoreProjects.contains(name) private fun Project.isJavaProject(): Boolean { diff --git a/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtension.kt b/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtension.kt index 69f218a..45b3783 100644 --- a/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtension.kt +++ b/src/main/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtension.kt @@ -49,9 +49,6 @@ open class CodeQualityToolsPluginExtension @Inject constructor( val ktlint = objectFactory.newInstance(KtlintExtension::class.java) fun ktlint(action: Action) = action.execute(ktlint) - val detekt = objectFactory.newInstance(DetektExtension::class.java) - fun detekt(action: Action) = action.execute(detekt) - val cpd = objectFactory.newInstance(CpdExtension::class.java) fun cpd(action: Action) = action.execute(cpd) diff --git a/src/main/kotlin/com/vanniktech/code/quality/tools/CpdExtension.kt b/src/main/kotlin/com/vanniktech/code/quality/tools/CpdExtension.kt index 8bca665..b3e25f0 100644 --- a/src/main/kotlin/com/vanniktech/code/quality/tools/CpdExtension.kt +++ b/src/main/kotlin/com/vanniktech/code/quality/tools/CpdExtension.kt @@ -23,6 +23,5 @@ open class CpdExtension { * A positive integer indicating the minimum token count to trigger a CPD match. * @since 0.6.0 */ - @Suppress("Detekt.MagicNumber") // Will be fixed with RC12. var minimumTokenCount: Int = 50 } diff --git a/src/main/kotlin/com/vanniktech/code/quality/tools/DetektCheckTask.kt b/src/main/kotlin/com/vanniktech/code/quality/tools/DetektCheckTask.kt deleted file mode 100644 index f36b5db..0000000 --- a/src/main/kotlin/com/vanniktech/code/quality/tools/DetektCheckTask.kt +++ /dev/null @@ -1,143 +0,0 @@ -package com.vanniktech.code.quality.tools - -import org.gradle.api.DefaultTask -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.Directory -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.Classpath -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity.RELATIVE -import org.gradle.api.tasks.TaskAction -import org.gradle.process.ExecOperations -import org.gradle.workers.WorkAction -import org.gradle.workers.WorkParameters -import org.gradle.workers.WorkerExecutionException -import org.gradle.workers.WorkerExecutor -import java.io.File -import javax.inject.Inject - -@CacheableTask abstract class DetektCheckTask : DefaultTask() { - @InputDirectory @PathSensitive(RELATIVE) lateinit var inputFile: File - @Input var failFast: Boolean = true - @Input var buildUponDefaultConfig: Boolean = false - @Input var parallel: Boolean = false - @Input lateinit var version: String - @get:Classpath abstract val classpath: ConfigurableFileCollection - - // Ideally this would be an optional input file - https://github.com/gradle/gradle/issues/2016 - @Input @Optional var baselineFilePath: String? = null - @InputFile @PathSensitive(RELATIVE) lateinit var configFile: File - @OutputDirectory lateinit var outputDirectory: Provider - - init { - group = "verification" - description = "Runs detekt." - } - - @get:Inject internal abstract val workerExecutor: WorkerExecutor - - @TaskAction fun run() { - val queue = workerExecutor.noIsolation() - - queue.submit(DetektWorker::class.java) { - it.baselineFilePath.set(baselineFilePath) - it.buildUponDefaultConfig.set(buildUponDefaultConfig) - it.classpath.from(classpath) - it.configFile.set(configFile) - it.failFast.set(failFast) - it.inputFile.set(inputFile) - it.outputDirectory.set(outputDirectory.get()) - it.parallel.set(parallel) - } - } -} - -internal data class ReportingMetaInformation( - val reportId: String, - val fileEnding: String, - val fileNameSuffix: String, -) - -internal interface DetektParameters : WorkParameters { - val baselineFilePath: Property - val buildUponDefaultConfig: Property - val classpath: ConfigurableFileCollection - val configFile: RegularFileProperty - val failFast: Property - val inputFile: RegularFileProperty - val outputDirectory: DirectoryProperty - val parallel: Property -} - -internal abstract class DetektWorker @Inject internal constructor( - private val execOperations: ExecOperations, -) : WorkAction { - override fun execute() { - parameters.baselineFilePath.orNull?.let { file -> - if (!File(file).exists()) { - executeDetekt(shouldCreateBaseLine = true) - throw WorkerExecutionException("Aborting build since new baseline file was created") - } - } - - executeDetekt() - } - - private fun executeDetekt(shouldCreateBaseLine: Boolean = false) { - val reportKey = "--report" - val reportValue = listOf( - ReportingMetaInformation("plain", "txt", "plain"), - ReportingMetaInformation("xml", "xml", "checkstyle"), - ReportingMetaInformation("html", "html", "report"), - ).joinToString(separator = ",") { - it.fileEnding + ":" + File(parameters.outputDirectory.asFile.get(), "detekt-${it.fileNameSuffix}.${it.fileEnding}").absolutePath - } - - execOperations.javaexec { task -> - task.mainClass.set("io.gitlab.arturbosch.detekt.cli.Main") - task.classpath = parameters.classpath - task.args( - "--input", - parameters.inputFile.get().asFile, - reportKey, - reportValue, - ) - - val configFile = parameters.configFile.asFile.get() - if (configFile.exists()) { - task.args("--config", configFile) - } - - task.args("--excludes", "**/build/**") - - if (parameters.failFast.get()) { - task.args("--fail-fast") - } - - if (parameters.buildUponDefaultConfig.get()) { - task.args("--build-upon-default-config") - } - - if (parameters.parallel.get()) { - task.args("--parallel") - } - - if (shouldCreateBaseLine) { - task.args("--create-baseline") - } - - parameters.baselineFilePath.orNull?.let { - task.args("--baseline", it) - } - } - } -} diff --git a/src/main/kotlin/com/vanniktech/code/quality/tools/DetektExtension.kt b/src/main/kotlin/com/vanniktech/code/quality/tools/DetektExtension.kt deleted file mode 100644 index 77f78bd..0000000 --- a/src/main/kotlin/com/vanniktech/code/quality/tools/DetektExtension.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.vanniktech.code.quality.tools - -open class DetektExtension { - /** - * Ability to enable or disable only detekt for every subproject that is not ignored. - * @since 0.6.0 - */ - var enabled: Boolean = true - - /** @since 0.6.0 */ - var toolVersion: String = "1.0.0" - - /** @since 0.6.0 */ - var config: String = "code_quality_tools/detekt.yml" - - /** - * Optional baseline file. - * If one is present, it will be used in the detektCheck task. - * If this name is specified, however, the file is not present it will be generated. - * This mirrors the baseline mechanism from Android Lint. - * - * @since 0.11.0 - */ - var baselineFileName: String? = null - - /** - * Whether to failFast or not. This will be forwarded to the CLI starting with Detekt 1.0.0 RC13 - * @since 0.18.0 - */ - var failFast: Boolean = true - - /** - * Whether to use preconfigured defaults. Allows provided configurations to override them. - * @since 0.19.0 - */ - var buildUponDefaultConfig: Boolean = false - - /** - * Enables parallel compilation of source files. - * Should only be used if the analyzing project has more than ~200 Kotlin files. - * @since 0.19.0 - */ - var parallel: Boolean = false - - /** - * Directories to look for source files. - * Defaults to current directory. - * - * @since 0.21.0 - */ - var input: String = "." -} diff --git a/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginDetektTest.kt b/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginDetektTest.kt index 8b2ef51..ea39606 100755 --- a/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginDetektTest.kt +++ b/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginDetektTest.kt @@ -1,217 +1,3 @@ package com.vanniktech.code.quality.tools -import org.gradle.testkit.runner.GradleRunner -import org.gradle.testkit.runner.TaskOutcome -import org.junit.Assert.assertEquals -import org.junit.Rule -import org.junit.Test -import org.junit.rules.TemporaryFolder -import java.io.File - -class CodeQualityToolsPluginDetektTest { - @get:Rule val testProjectDir = TemporaryFolder() - - private val testCode = "package com.vanniktech.test;\nfun foo(param: Int) = param * param\n" - private val testPath = "src/main/kotlin/com/vanniktech/test/Foo.kt" - - @Test fun success() { - Roboter(testProjectDir) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, testCode) - .succeeds() - } - - @Test fun works() { - Roboter(testProjectDir, version = "1.0.0") - .withConfiguration("") // Fail Fast is configured via the CLI parameter. - .withKotlinFile(testPath, testCode) - .succeeds() - } - - @Test fun parallel() { - Roboter(testProjectDir, parallel = true) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, testCode) - .succeeds() - } - - @Test fun noSrcFolder() { - Roboter(testProjectDir) - .withConfiguration("failFast: true") - .succeeds() - } - - @Test fun defaultConfigFile() { - Roboter(testProjectDir, buildUponDefaultConfig = true) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, testCode) - .succeeds() - } - - @Test fun differentConfigFile() { - Roboter(testProjectDir, config = "code_quality_tools/config-detekt.yml") - .withConfiguration("failFast: true") - .withKotlinFile(testPath, testCode) - .succeeds() - } - - @Test fun fails() { - Roboter(testProjectDir) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, "fun foo() = Unit") - .fails(containsMessage = "NewLineAtEndOfFile - [Foo.kt]") - } - - @Test fun ignoresFileInBuildDirectory() { - Roboter(testProjectDir) - .withConfiguration("failFast: true") - .withKotlinFile("build/Foo.kt", "fun foo() = Unit") - .succeeds() - } - - @Test fun failsOnKotlinScript() { - Roboter(testProjectDir) - .withConfiguration("failFast: true") - .withKotlinFile("build.gradle.kts", "fun foo() = Unit") - .fails(containsMessage = "NewLineAtEndOfFile - [build.gradle.kts]") - } - - @Test fun disabled() { - Roboter(testProjectDir, enabled = false) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, "fun foo() = Unit") - .doesNothing() - } - - @Test fun creatingInitialBaselineFails() { - Roboter(testProjectDir, baselineFileName = "detekt-baseline.xml") - .withConfiguration("failFast: true") - .withKotlinFile(testPath, "fun foo() = Unit") - .fails(containsMessage = "NewLineAtEndOfFile - [Foo.kt]") - .baseLineContains("NewLineAtEndOfFile:Foo.kt\$.Foo.kt") - } - - @Test fun runningWithBaseLineSucceeds() { - Roboter(testProjectDir, baselineFileName = "detekt-baseline.xml") - .withConfiguration("failFast: true") - .withBaseLineFile( - """ - - - - - InvalidPackageDeclaration:Foo.kt$.Foo.kt - - - """.trimIndent(), - ) - .withKotlinFile(testPath, "fun foo(i: Int) = i * 3\n") - .succeeds() - } - - @Test fun checkTaskRunsDetekt() { - Roboter(testProjectDir) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, "fun foo() = Unit") - .fails(taskToRun = "check", taskToCheck = "detektCheck", containsMessage = "NewLineAtEndOfFile - [Foo.kt] at") - } - - @Test fun runningWithExplicitInputSucceeds() { - Roboter(testProjectDir, inputDirectoryName = testProjectDir.root.toString()) - .withConfiguration("failFast: true") - .withKotlinFile(testPath, testCode) - .succeeds() - } - - class Roboter( - private val directory: TemporaryFolder, - private val config: String = "code_quality_tools/detekt.yml", - enabled: Boolean = true, - version: String = "1.0.0", - private val baselineFileName: String? = null, - buildUponDefaultConfig: Boolean = false, - parallel: Boolean = false, - inputDirectoryName: String = ".", - ) { - init { - directory.newFile("build.gradle").writeText( - """ - |plugins { - | id "kotlin" - | id "com.vanniktech.code.quality.tools" - |} - | - |codeQualityTools { - | detekt { - | enabled = $enabled - | parallel = $parallel - | buildUponDefaultConfig = $buildUponDefaultConfig - | config = "$config" - | toolVersion = "$version" - | baselineFileName = ${baselineFileName.wrap("\"")} - | input = ${inputDirectoryName.wrap("\"")} - | } - | ktlint.enabled = false - | checkstyle.enabled = false - | pmd.enabled = false - | cpd.enabled = false - |} - | - |repositories { - | jcenter() - |} - | - """.trimMargin(), - ) - } - - fun withBaseLineFile(content: String) = write(requireNotNull(baselineFileName), content) - - fun withConfiguration(configuration: String) = write(config, configuration) - - fun withKotlinFile(path: String, content: String) = write(path, content) - - private fun write(path: String, content: String) = apply { - val paths = path.split("/").dropLast(1).toTypedArray() - if (paths.isNotEmpty()) directory.newFolder(*paths) - directory.newFile(path).writeText(content) - } - - fun succeeds(taskToRun: String = "detektCheck") = apply { - assertEquals(TaskOutcome.SUCCESS, run(taskToRun).build().task(":$taskToRun")?.outcome) - assertReportsExist() - } - - fun fails( - taskToRun: String = "detektCheck", - taskToCheck: String = taskToRun, - assertReportsExist: Boolean = true, - containsMessage: String, - ) = apply { - val buildResult = run(taskToRun).buildAndFail() - assertEquals(TaskOutcome.FAILED, buildResult.task(":$taskToCheck")?.outcome) - assertEquals(true, buildResult.output.contains(containsMessage)) - if (assertReportsExist) { - assertReportsExist() - } - } - - private fun assertReportsExist() { - assertEquals(true, File(directory.root, "build/reports/detekt/detekt-report.html").exists()) - assertEquals(true, File(directory.root, "build/reports/detekt/detekt-checkstyle.xml").exists()) - assertEquals(true, File(directory.root, "build/reports/detekt/detekt-plain.txt").exists()) - } - - fun doesNothing(taskToRun: String = "detektCheck") = apply { - assertEquals(null, run(taskToRun).buildAndFail().task(":$taskToRun")) - } - - fun baseLineContains(content: String) { - assertEquals(true, File(directory.root, baselineFileName).readText().contains(content)) - } - - private fun run(taskToRun: String) = GradleRunner.create().withPluginClasspath().withProjectDir(directory.root).withArguments(taskToRun) - } -} - private fun String?.wrap(wrap: String) = if (this == null) null else "$wrap$this$wrap" diff --git a/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtensionTest.kt b/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtensionTest.kt index 54a3795..c23c118 100644 --- a/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtensionTest.kt +++ b/src/test/kotlin/com/vanniktech/code/quality/tools/CodeQualityToolsPluginExtensionTest.kt @@ -4,7 +4,7 @@ import org.junit.Assert.assertEquals import org.junit.Test class CodeQualityToolsPluginExtensionTest { - @Test @Suppress("Detekt.LongMethod") fun defaults() { + @Test fun defaults() { val extension = defaultExtensions() assertEquals(true, extension.failEarly) @@ -12,7 +12,6 @@ class CodeQualityToolsPluginExtensionTest { assertEquals(false, extension.htmlReports) assertEquals(false, extension.textReports) - assertEquals("1.0.0", extension.detekt.toolVersion) assertEquals("1.0.1", extension.ktlint.toolVersion) assertEquals("8.6", extension.checkstyle.toolVersion) assertEquals("6.0.0", extension.pmd.toolVersion) diff --git a/src/test/kotlin/com/vanniktech/code/quality/tools/CommonCodeQualityToolsTest.kt b/src/test/kotlin/com/vanniktech/code/quality/tools/CommonCodeQualityToolsTest.kt index 3aa7dc8..8a1154f 100755 --- a/src/test/kotlin/com/vanniktech/code/quality/tools/CommonCodeQualityToolsTest.kt +++ b/src/test/kotlin/com/vanniktech/code/quality/tools/CommonCodeQualityToolsTest.kt @@ -11,7 +11,6 @@ import org.gradle.testfixtures.ProjectBuilder import org.jetbrains.kotlin.gradle.plugin.KotlinApiPlugin import org.junit.Before -@Suppress("Detekt.UnnecessaryAbstractClass") abstract class CommonCodeQualityToolsTest { lateinit var rootProject: Project @@ -37,7 +36,7 @@ abstract class CommonCodeQualityToolsTest { lateinit var projects: Array - @Before @Suppress("Detekt.LongMethod") fun setUp() { + @Before fun setUp() { rootProject = ProjectBuilder.builder().withName("root").build() emptyProject = ProjectBuilder.builder().withName("empty").withParent(rootProject).build()