diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt index 2a9db72b0..0ea707254 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt @@ -159,7 +159,7 @@ open class Detekt @Inject constructor( set(value) = basePathProp.set(value) @get:Internal - var reports = DetektReports() + var reports: DetektReports = objects.newInstance(DetektReports::class.java) @get:Internal val reportsDir: Property = project.objects.property(File::class.java) @@ -187,7 +187,7 @@ open class Detekt @Inject constructor( internal val customReportFiles: ConfigurableFileCollection @OutputFiles @Optional - get() = objects.fileCollection().from(reports.custom.mapNotNull { it.destination }) + get() = objects.fileCollection().from(reports.custom.mapNotNull { it.outputLocation.asFile.orNull }) private val defaultReportsDir: Directory = project.layout.buildDirectory.get() .dir(ReportingExtension.DEFAULT_REPORTS_DIR_NAME) @@ -253,7 +253,7 @@ open class Detekt @Inject constructor( private fun convertCustomReportsToArguments(): List = reports.custom.map { val reportId = it.reportId - val destination = it.destination + val destination = it.outputLocation.asFile.orNull checkNotNull(reportId) { "If a custom report is specified, the reportId must be present" } check(!DetektReportType.isWellKnownReportId(reportId)) { @@ -268,10 +268,10 @@ open class Detekt @Inject constructor( private fun getTargetFileProvider( report: DetektReport ): RegularFileProperty { - val isEnabled = report.enabled ?: DetektExtension.DEFAULT_REPORT_ENABLED_VALUE + val isEnabled = report.required.getOrElse(DetektExtension.DEFAULT_REPORT_ENABLED_VALUE) val provider = objects.fileProperty() if (isEnabled) { - val destination = report.destination ?: reportsDir.getOrElse(defaultReportsDir.asFile) + val destination = report.outputLocation.asFile.orNull ?: reportsDir.getOrElse(defaultReportsDir.asFile) .resolve("${DetektReport.DEFAULT_FILENAME}.${report.type.extension}") provider.set(destination) } diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/CustomDetektReport.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/CustomDetektReport.kt index 60b8a09db..f68e252a6 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/CustomDetektReport.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/CustomDetektReport.kt @@ -1,18 +1,29 @@ package io.gitlab.arturbosch.detekt.extensions +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputFile import java.io.File +import javax.inject.Inject -class CustomDetektReport { +open class CustomDetektReport @Inject constructor(objects: ObjectFactory) { @Internal var reportId: String? = null + @Deprecated("Use outputLocation.set(value)") + @get:Internal + var destination: File? + get() = outputLocation.asFile.getOrNull() + set(value) { + outputLocation.set(value) + } + @OutputFile - var destination: File? = null + val outputLocation: RegularFileProperty = objects.fileProperty() override fun toString(): String { - return "CustomDetektReport(reportId=$reportId, destination=$destination)" + return "CustomDetektReport(reportId=$reportId, outputLocation=$outputLocation)" } } diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektExtension.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektExtension.kt index 849e8b4e4..f7f46bf48 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektExtension.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektExtension.kt @@ -18,10 +18,12 @@ open class DetektExtension @Inject constructor(objects: ObjectFactory) : CodeQua isIgnoreFailures = value } + @Deprecated("Use reportsDir which is equivalent", ReplaceWith("reportsDir")) val customReportsDir: File? get() = reportsDir - val reports = DetektReports() + @Deprecated("Customise the reports on the Detekt task(s) instead.", level = DeprecationLevel.WARNING) + val reports: DetektReports = objects.newInstance(DetektReports::class.java) @Deprecated(message = "Please use the source property instead.", replaceWith = ReplaceWith("source")) var input: ConfigurableFileCollection @@ -78,6 +80,8 @@ open class DetektExtension @Inject constructor(objects: ObjectFactory) : CodeQua */ var ignoredFlavors: List = emptyList() + @Suppress("DeprecatedCallableAddReplaceWith", "DEPRECATION") + @Deprecated("Customise the reports on the Detekt task(s) instead.", level = DeprecationLevel.WARNING) fun reports(configure: Action) { configure.execute(reports) } diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReport.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReport.kt index 7702a9dc3..e4dee58d7 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReport.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReport.kt @@ -1,15 +1,35 @@ package io.gitlab.arturbosch.detekt.extensions +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputFile import java.io.File +import javax.inject.Inject -class DetektReport(val type: DetektReportType) { +open class DetektReport @Inject constructor(val type: DetektReportType, objects: ObjectFactory) { - var enabled: Boolean? = null + @Deprecated("Use required.set(value)") + var enabled: Boolean? + get() = required.get() + set(value) = required.set(value) - var destination: File? = null + @Deprecated("Use outputLocation.set(value)") + var destination: File? + get() = outputLocation.asFile.getOrNull() + set(value) { + outputLocation.set(value) + } + + @Input + val required: Property = objects.property(Boolean::class.java) + + @OutputFile + val outputLocation: RegularFileProperty = objects.fileProperty() override fun toString(): String { - return "DetektReport(type='$type', enabled=$enabled, destination=$destination)" + return "DetektReport(type='$type', required=$required, outputLocation=$outputLocation)" } companion object { diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReports.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReports.kt index 5e8877c2b..d437e6f11 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReports.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/extensions/DetektReports.kt @@ -5,18 +5,20 @@ import io.gitlab.arturbosch.detekt.extensions.DetektReportType.HTML import io.gitlab.arturbosch.detekt.extensions.DetektReportType.SARIF import io.gitlab.arturbosch.detekt.extensions.DetektReportType.TXT import io.gitlab.arturbosch.detekt.extensions.DetektReportType.XML +import org.gradle.api.model.ObjectFactory import org.gradle.util.ConfigureUtil +import javax.inject.Inject @Suppress("TooManyFunctions") -class DetektReports { +open class DetektReports @Inject constructor(val objects: ObjectFactory) { - val xml = DetektReport(XML) + val xml: DetektReport = objects.newInstance(DetektReport::class.java, XML) - val html = DetektReport(HTML) + val html: DetektReport = objects.newInstance(DetektReport::class.java, HTML) - val txt = DetektReport(TXT) + val txt: DetektReport = objects.newInstance(DetektReport::class.java, TXT) - val sarif = DetektReport(SARIF) + val sarif: DetektReport = objects.newInstance(DetektReport::class.java, SARIF) val custom = mutableListOf() @@ -35,5 +37,6 @@ class DetektReports { fun custom(configure: CustomDetektReport.() -> Unit): Unit = createAndAddCustomReport().configure() fun custom(closure: Closure<*>): CustomDetektReport = ConfigureUtil.configure(closure, createAndAddCustomReport()) - private fun createAndAddCustomReport() = CustomDetektReport().apply { custom.add(this) } + private fun createAndAddCustomReport() = + objects.newInstance(CustomDetektReport::class.java).apply { custom.add(this) } } diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektAndroid.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektAndroid.kt index 7c96042eb..13ad988e4 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektAndroid.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektAndroid.kt @@ -124,11 +124,34 @@ internal fun Project.registerAndroidDetektTask( extension.baseline?.existingVariantOrBaseFile(variant.name)?.let { baselineFile -> baseline.set(layout.file(project.provider { baselineFile })) } - reports = extension.reports - reports.xml.setDefaultIfUnset(File(extension.reportsDir, variant.name + ".xml")) - reports.html.setDefaultIfUnset(File(extension.reportsDir, variant.name + ".html")) - reports.txt.setDefaultIfUnset(File(extension.reportsDir, variant.name + ".txt")) - reports.sarif.setDefaultIfUnset(File(extension.reportsDir, variant.name + ".sarif")) + reports.xml.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, variant.name + ".xml").absolutePath + } + ) + ) + reports.html.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, variant.name + ".html").absolutePath + } + ) + ) + reports.txt.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, variant.name + ".txt").absolutePath + } + ) + ) + reports.sarif.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, variant.name + ".sarif").absolutePath + } + ) + ) description = "EXPERIMENTAL: Run detekt analysis for ${variant.name} classes with type resolution" } diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektJvm.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektJvm.kt index 74972d0c2..473128fdc 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektJvm.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektJvm.kt @@ -32,11 +32,36 @@ internal class DetektJvm(private val project: Project) { extension.baseline?.existingVariantOrBaseFile(sourceSet.name)?.let { baselineFile -> baseline.set(layout.file(project.provider { baselineFile })) } - reports = extension.reports - reports.xml.setDefaultIfUnset(File(extension.reportsDir, sourceSet.name + ".xml")) - reports.html.setDefaultIfUnset(File(extension.reportsDir, sourceSet.name + ".html")) - reports.txt.setDefaultIfUnset(File(extension.reportsDir, sourceSet.name + ".txt")) - reports.sarif.setDefaultIfUnset(File(extension.reportsDir, sourceSet.name + ".sarif")) + + reports.xml.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, sourceSet.name + ".xml").absolutePath + } + ) + ) + reports.html.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, sourceSet.name + ".html").absolutePath + } + ) + ) + reports.txt.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, sourceSet.name + ".txt").absolutePath + } + ) + ) + reports.sarif.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, sourceSet.name + ".sarif").absolutePath + } + ) + ) + description = "EXPERIMENTAL: Run detekt analysis for ${sourceSet.name} classes with type resolution" } } diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektMultiplatform.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektMultiplatform.kt index af8043f5b..8c0972a44 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektMultiplatform.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektMultiplatform.kt @@ -25,6 +25,7 @@ internal class DetektMultiplatform(private val project: Project) { } } + @Suppress("LongMethod") private fun Project.registerMultiplatformTasks(extension: DetektExtension) { // We need another project.afterEvaluate as the Android target is attached on // a project.afterEvaluate inside AGP. We should further investigate and potentially remove this. @@ -90,6 +91,7 @@ internal class DetektMultiplatform(private val project: Project) { } } + @Suppress("LongMethod") private fun Project.registerMultiplatformTasksForNonAndroidTarget( compilation: KotlinCompilation, target: KotlinTarget, @@ -116,11 +118,34 @@ internal class DetektMultiplatform(private val project: Project) { }?.let { baselineFile -> baseline.set(layout.file(provider { baselineFile })) } - reports = extension.reports - reports.xml.setDefaultIfUnset(File(extension.reportsDir, compilation.name + ".xml")) - reports.html.setDefaultIfUnset(File(extension.reportsDir, compilation.name + ".html")) - reports.txt.setDefaultIfUnset(File(extension.reportsDir, compilation.name + ".txt")) - reports.sarif.setDefaultIfUnset(File(extension.reportsDir, compilation.name + ".sarif")) + reports.xml.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, compilation.name + ".xml").absolutePath + } + ) + ) + reports.html.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, compilation.name + ".html").absolutePath + } + ) + ) + reports.txt.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, compilation.name + ".txt").absolutePath + } + ) + ) + reports.sarif.outputLocation.convention( + layout.projectDirectory.file( + providers.provider { + File(extension.reportsDir, compilation.name + ".sarif").absolutePath + } + ) + ) description = "Run detekt analysis for target ${target.name} and source set ${compilation.name}" if (runWithTypeResolution) { diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektPlain.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektPlain.kt index b0ce3be50..396145d32 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektPlain.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/DetektPlain.kt @@ -22,8 +22,7 @@ internal class DetektPlain(private val project: Project) { setSource(existingInputDirectoriesProvider(project, extension)) setIncludes(DetektPlugin.defaultIncludes) setExcludes(DetektPlugin.defaultExcludes) - reportsDir.set(project.provider { extension.customReportsDir }) - reports = extension.reports + reportsDir.set(project.provider { extension.reportsDir }) } tasks.matching { it.name == LifecycleBasePlugin.CHECK_TASK_NAME }.configureEach { diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt index 9d8528355..9391fd398 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt @@ -3,10 +3,8 @@ package io.gitlab.arturbosch.detekt.internal import io.gitlab.arturbosch.detekt.Detekt import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask import io.gitlab.arturbosch.detekt.extensions.DetektExtension -import io.gitlab.arturbosch.detekt.extensions.DetektReport import org.gradle.api.Project import org.gradle.api.tasks.TaskProvider -import java.io.File internal fun Project.registerDetektTask( name: String, @@ -14,6 +12,33 @@ internal fun Project.registerDetektTask( configuration: Detekt.() -> Unit ): TaskProvider = tasks.register(name, Detekt::class.java) { + with(extension.reports) { + if (xml.outputLocation.isPresent) { + logger.warn( + "XML report location set on detekt {} extension will be ignored for $name task. See " + + "https://detekt.github.io/detekt/gradle.html#reports" + ) + } + if (sarif.outputLocation.isPresent) { + logger.warn( + "SARIF report location set on detekt {} extension will be ignored for $name task. See " + + "https://detekt.github.io/detekt/gradle.html#reports" + ) + } + if (txt.outputLocation.isPresent) { + logger.warn( + "TXT report location set on detekt {} extension will be ignored for $name task. See " + + "https://detekt.github.io/detekt/gradle.html#reports" + ) + } + if (html.outputLocation.isPresent) { + logger.warn( + "HTML report location set on detekt {} extension will be ignored for $name task. See " + + "https://detekt.github.io/detekt/gradle.html#reports" + ) + } + } + it.debugProp.set(provider { extension.debug }) it.parallelProp.set(provider { extension.parallel }) it.disableDefaultRuleSetsProp.set(provider { extension.disableDefaultRuleSets }) @@ -44,9 +69,3 @@ internal fun Project.registerCreateBaselineTask( it.allRules.set(provider { extension.allRules }) configuration(it) } - -internal fun DetektReport.setDefaultIfUnset(default: File) { - if (destination == null) { - destination = default - } -} diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt index 90dde1c22..dd66b8656 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt @@ -23,7 +23,7 @@ object DetektAndroidSpec : Spek({ buildFileContent = """ $APP_PLUGIN_BLOCK $ANDROID_BLOCK - $DETEKT_BLOCK + $DETEKT_REPORTS_BLOCK """.trimIndent(), srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java"), baselineFiles = listOf( @@ -82,7 +82,7 @@ object DetektAndroidSpec : Spek({ buildFileContent = """ $APP_PLUGIN_BLOCK $ANDROID_BLOCK - $DETEKT_BLOCK + $DETEKT_REPORTS_BLOCK """.trimIndent(), srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") ) @@ -117,7 +117,7 @@ object DetektAndroidSpec : Spek({ buildFileContent = """ $LIB_PLUGIN_BLOCK $ANDROID_BLOCK - $DETEKT_BLOCK + $DETEKT_REPORTS_BLOCK """.trimIndent(), srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java"), baselineFiles = listOf( @@ -177,7 +177,7 @@ object DetektAndroidSpec : Spek({ buildFileContent = """ $LIB_PLUGIN_BLOCK $ANDROID_BLOCK_WITH_FLAVOR - $DETEKT_BLOCK + $DETEKT_REPORTS_BLOCK """.trimIndent(), srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") ) @@ -419,8 +419,8 @@ private val ANDROID_BLOCK_WITH_FLAVOR = """ } """.trimIndent() -private val DETEKT_BLOCK = """ - detekt { +private val DETEKT_REPORTS_BLOCK = """ + tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { reports { txt.enabled = false } diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt index e215dfe46..4de151945 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt @@ -8,49 +8,121 @@ import org.spekframework.spek2.style.specification.describe object DetektJvmSpec : Spek({ describe("When applying detekt in a JVM project") { + context("disabled TXT report") { - val gradleRunner = DslGradleRunner( - projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), - buildFileName = "build.gradle", - baselineFiles = listOf("detekt-baseline.xml", "detekt-baseline-main.xml", "detekt-baseline-test.xml"), - mainBuildFileContent = """ - plugins { - id "org.jetbrains.kotlin.jvm" - id "io.gitlab.arturbosch.detekt" - } - - repositories { - mavenCentral() - mavenLocal() - } - - detekt { - reports { - txt.enabled = false + val gradleRunner = DslGradleRunner( + projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), + buildFileName = "build.gradle", + baselineFiles = listOf("detekt-baseline.xml", "detekt-baseline-main.xml", "detekt-baseline-test.xml"), + mainBuildFileContent = """ + plugins { + id "org.jetbrains.kotlin.jvm" + id "io.gitlab.arturbosch.detekt" } - } - """.trimIndent(), - dryRun = true - ) - gradleRunner.setupProject() - it("configures detekt type resolution task main") { - gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-main.xml """) - assertThat(buildResult.output).contains("--report xml:") - assertThat(buildResult.output).contains("--report sarif:") - assertThat(buildResult.output).doesNotContain("--report txt:") - assertThat(buildResult.output).contains("--classpath") + repositories { + mavenCentral() + mavenLocal() + } + + tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { + reports { + txt.enabled = false + } + } + """.trimIndent(), + dryRun = true + ) + gradleRunner.setupProject() + + it("configures detekt type resolution task main") { + gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-main.xml """) + assertThat(buildResult.output).contains("--report xml:") + assertThat(buildResult.output).contains("--report sarif:") + assertThat(buildResult.output).doesNotContain("--report txt:") + assertThat(buildResult.output).contains("--classpath") + } + } + + it("configures detekt type resolution task test") { + gradleRunner.runTasksAndCheckResult(":detektTest") { buildResult -> + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-test.xml """) + assertThat(buildResult.output).contains("--report xml:") + assertThat(buildResult.output).contains("--report sarif:") + assertThat(buildResult.output).doesNotContain("--report txt:") + assertThat(buildResult.output).contains("--classpath") + } } } - it("configures detekt type resolution task test") { - gradleRunner.runTasksAndCheckResult(":detektTest") { buildResult -> - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-test.xml """) - assertThat(buildResult.output).contains("--report xml:") - assertThat(buildResult.output).contains("--report sarif:") - assertThat(buildResult.output).doesNotContain("--report txt:") - assertThat(buildResult.output).contains("--classpath") + context("report location set on extension & task") { + val gradleRunner = DslGradleRunner( + projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), + buildFileName = "build.gradle", + mainBuildFileContent = """ + plugins { + id "org.jetbrains.kotlin.jvm" + id "io.gitlab.arturbosch.detekt" + } + + repositories { + mavenCentral() + mavenLocal() + } + + detekt { + reports { + txt.destination = file("output-path.txt") + } + } + + tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { + reports { + txt.destination = file("output-path2.txt") + } + } + """.trimIndent(), + dryRun = false + ) + gradleRunner.setupProject() + + it("logs a warning") { + gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> + assertThat(buildResult.output).contains("TXT report location set on detekt {} extension will be ignored for detektMain task.") + } + } + } + + context("report location set on task only") { + val gradleRunner = DslGradleRunner( + projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), + buildFileName = "build.gradle", + mainBuildFileContent = """ + plugins { + id "org.jetbrains.kotlin.jvm" + id "io.gitlab.arturbosch.detekt" + } + + repositories { + mavenCentral() + mavenLocal() + } + + tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { + reports { + txt.destination = file("output-path2.txt") + } + } + """.trimIndent(), + dryRun = false + ) + gradleRunner.setupProject() + + it("logs a warning") { + gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> + assertThat(buildResult.output).doesNotContain("report location set on detekt {} extension will be ignored") + } } } } diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektMultiplatformSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektMultiplatformSpec.kt index 2027be938..004d03b5e 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektMultiplatformSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektMultiplatformSpec.kt @@ -352,7 +352,7 @@ private val KMM_PLUGIN_BLOCK = """ """.trimIndent() private val DETEKT_BLOCK = """ - detekt { + tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { reports.txt.enabled = false } """.trimIndent() diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektPlainSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektPlainSpec.kt index 3dc65d259..111d255e1 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektPlainSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektPlainSpec.kt @@ -52,7 +52,7 @@ object DetektPlainSpec : Spek({ mavenLocal() } - detekt { + tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { reports { sarif.enabled = true txt.enabled = false diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt index 1e268f8e9..f2d1be169 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt @@ -202,11 +202,6 @@ internal object DetektTaskDslSpec : Spek({ val config = """ |detekt { | reportsDir = file("build/detekt-reports") - | reports { - | sarif { - | enabled = true - | } - | } |} """ @@ -244,6 +239,9 @@ internal object DetektTaskDslSpec : Spek({ val config = """ |detekt { | reportsDir = file("build/detekt-reports") + |} + | + |tasks.detekt { | reports { | xml.destination = file("build/xml-reports/custom-detekt.xml") | } @@ -277,7 +275,7 @@ internal object DetektTaskDslSpec : Spek({ beforeGroup { val config = """ - |detekt { + |tasks.detekt { | reports { | xml.enabled = false | html { @@ -309,7 +307,7 @@ internal object DetektTaskDslSpec : Spek({ beforeGroup { val config = """ - |detekt { + |tasks.detekt { | reports { | custom { | reportId = "customXml" @@ -342,7 +340,7 @@ internal object DetektTaskDslSpec : Spek({ beforeGroup { val config = """ - |detekt { + |tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { | reports { | custom { | destination = file("build/reports/custom.xml") @@ -363,7 +361,7 @@ internal object DetektTaskDslSpec : Spek({ beforeGroup { val config = """ - |detekt { + |tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { | reports { | custom { | reportId = "customJson" @@ -386,7 +384,7 @@ internal object DetektTaskDslSpec : Spek({ val aDirectory = "\${rootDir}/src" val config = """ - |detekt { + |tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { | reports { | custom { | reportId = "foo" @@ -410,7 +408,7 @@ internal object DetektTaskDslSpec : Spek({ beforeGroup { val config = """ - |detekt { + |tasks.withType(io.gitlab.arturbosch.detekt.Detekt).configureEach { | reports { | custom { | reportId = "${wellKnownType.reportId}" diff --git a/docs/pages/changelog 1.x.x.md b/docs/pages/changelog 1.x.x.md index 6cc020115..81fa2e178 100644 --- a/docs/pages/changelog 1.x.x.md +++ b/docs/pages/changelog 1.x.x.md @@ -6,6 +6,64 @@ permalink: changelog.html toc: true --- +#### SNAPSHOT (unreleased) + +##### Notable Changes + +- Report configuration is changing in the Gradle plugin. The `reports` extension on the `detekt` extension has been + deprecated. See the Migration section below for steps to migrate to the new recommended configuration - [#3687](https://github.com/detekt/detekt/pull/3687) + +##### Migration + +Configuring reports in the Gradle plugin should be done at the task level instead of at the extension (or global) level. +The previous recommendation resulted in the report output for multiple tasks overwriting each other when multiple detekt +tasks were executed in the same Gradle run. + +Before this release the recommended way to configure reports was using the `detekt` extension: +```kotlin +detekt { + reports { + xml { + enabled = true + destination = file("build/reports/detekt/detekt.xml") + } + } +} +``` + +This meant all detekt tasks would output the report to the same destination. From this detekt release you should enable +and disable reports for all tasks using the `withType` Gradle method: + +```kotlin +// Kotlin DSL +tasks.withType().configureEach { + reports { + xml.required.set(true) + } +} +``` + +```groovy +// Groovy DSL +tasks.withType(Detekt).configureEach { + reports { + xml.required.set(true) + } +} +``` + +To customize the report output location configure the task individually: +```kotlin +tasks.detektMain { + reports { + xml { + outputLocation.set(file("build/reports/detekt/customPath.xml")) + required.set(true) // reports can also be enabled and disabled at the task level as needed + } + } +} +``` + #### 1.18.1 - 2021-08-30 This is a point release for Detekt `1.18.0` containing bugfixes for problems that got discovered just after the release.