mirror of
https://github.com/jlengrand/detekt.git
synced 2026-03-10 08:11:23 +00:00
Add dependencies for gradle plugin (for custom rules)
Following the feature request https://github.com/arturbosch/detekt/issues/795, this commit implements a way to configure Detekt plugins using Gradle plugin.
This commit is contained in:
committed by
Artur Bosch
parent
53bf050cae
commit
cc369068ff
23
README.md
23
README.md
@@ -37,6 +37,7 @@ It operates on the abstract syntax tree provided by the Kotlin compiler.
|
||||
3. [in android projects](#gradleandroid)
|
||||
4. [plugin tasks](#tasks)
|
||||
5. [detekt-closure](#closure)
|
||||
6. [custom rules](#gradleCustomRules)
|
||||
3. [Standalone gradle task](#gradle)
|
||||
4. [Standalone maven task](#maventask)
|
||||
5. [Rule sets](#rulesets)
|
||||
@@ -298,6 +299,26 @@ detekt {
|
||||
|
||||
For more information on using idea as a headless formatting/inspection tool see [here](https://www.jetbrains.com/help/idea/working-with-intellij-idea-features-from-command-line.html).
|
||||
|
||||
##### <a name="gradleCustomRules">Using custom rules with Gradle plugin</a>
|
||||
|
||||
When your _detekt_ custom rules are located in a module of your Gradle project (e.g. `:detekt-extensions`), you can
|
||||
enable them with the following syntax:
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
detekt project(':detekt-extensions')
|
||||
}
|
||||
|
||||
detekt {
|
||||
profile("main") {
|
||||
input = "$projectDir/src/main/kotlin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
More generally, you can use dependencies on `detekt` configuration; these dependencies will be resolved, built if
|
||||
needed, and added to _detekt_ classpath.
|
||||
|
||||
#### <a name="gradle">Using _detekt_ in custom gradle projects</a>
|
||||
|
||||
1. Add following lines to your build.gradle file.
|
||||
@@ -597,7 +618,7 @@ If you contributed to detekt but your name is not in the list, please feel free
|
||||
- [Svyatoslav Chatchenko](https://github.com/MyDogTom) - Active on Issues, NamingConventions and UnusedImport fixes
|
||||
- [Sean Flanigan](https://github.com/seanf) - Config from classpath resource
|
||||
- [Sebastian Schuberth](https://github.com/sschuberth) - Active on Issues, Windows support
|
||||
- [Olivier Lemasle](https://github.com/olivierlemasle) - NP-Bugfix
|
||||
- [Olivier Lemasle](https://github.com/olivierlemasle) - NP-Bugfix, fix TooGenericExceptionCaught, Gradle plugin improvement
|
||||
- [Marc Prengemann](https://github.com/winterDroid) - Support for custom output formats, prototyped Rule-Context-Issue separation
|
||||
- [Sebastiano Poggi](https://github.com/rock3r) - Enhanced milestone report script, Magic number fixes
|
||||
- [Ilya Tretyakov](https://github.com/jvilya) - Sonar runs should not auto correct formatting.
|
||||
|
||||
@@ -4,7 +4,7 @@ import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
||||
import io.gitlab.arturbosch.detekt.extensions.INPUT_PARAMETER
|
||||
import io.gitlab.arturbosch.detekt.extensions.OUTPUT_PARAMETER
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
@@ -13,6 +13,7 @@ import java.io.File
|
||||
/**
|
||||
* @author Artur Bosch
|
||||
* @author Marvin Ramin
|
||||
* @author Olivier Lemasle
|
||||
*/
|
||||
open class DetektCheckTask : DefaultTask() {
|
||||
|
||||
@@ -22,6 +23,8 @@ open class DetektCheckTask : DefaultTask() {
|
||||
@OutputDirectory
|
||||
val output: File?
|
||||
|
||||
private val classpath: FileCollection
|
||||
|
||||
init {
|
||||
description = "Analyze your kotlin code with detekt."
|
||||
group = "verification"
|
||||
@@ -33,19 +36,18 @@ open class DetektCheckTask : DefaultTask() {
|
||||
|
||||
val outputIndex = arguments.indexOf(OUTPUT_PARAMETER)
|
||||
output = File(arguments[outputIndex + 1])
|
||||
|
||||
classpath = detektExtension.resolveClasspath(project)
|
||||
dependsOn(classpath)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun check() {
|
||||
val detektExtension = project.extensions.getByName("detekt") as DetektExtension
|
||||
|
||||
val configuration = project.buildscript.configurations.maybeCreate("detektCheck")
|
||||
project.buildscript.dependencies.add(configuration.name, DefaultExternalModuleDependency(
|
||||
"io.gitlab.arturbosch.detekt", "detekt-cli", detektExtension.version))
|
||||
|
||||
project.javaexec {
|
||||
it.main = "io.gitlab.arturbosch.detekt.cli.Main"
|
||||
it.classpath = configuration
|
||||
it.classpath = classpath
|
||||
it.args(detektExtension.resolveArguments(project))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,24 @@ package io.gitlab.arturbosch.detekt
|
||||
|
||||
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
/**
|
||||
* @author Artur Bosch
|
||||
* @author Olivier Lemasle
|
||||
*/
|
||||
open class DetektCreateBaselineTask : DefaultTask() {
|
||||
|
||||
private val classpath: FileCollection
|
||||
|
||||
init {
|
||||
description = "Creates a detekt baseline on the given --baseline path."
|
||||
group = "verification"
|
||||
|
||||
val detektExtension = project.extensions.getByName("detekt") as DetektExtension
|
||||
classpath = detektExtension.resolveClasspath(project)
|
||||
dependsOn(classpath)
|
||||
}
|
||||
|
||||
private val createBaseline = "--create-baseline"
|
||||
@@ -21,13 +28,9 @@ open class DetektCreateBaselineTask : DefaultTask() {
|
||||
fun baseline() {
|
||||
val detektExtension = project.extensions.getByName("detekt") as DetektExtension
|
||||
|
||||
val configuration = project.buildscript.configurations.maybeCreate("detektBaseline")
|
||||
project.buildscript.dependencies.add(configuration.name, DefaultExternalModuleDependency(
|
||||
"io.gitlab.arturbosch.detekt", "detekt-cli", detektExtension.version))
|
||||
|
||||
project.javaexec {
|
||||
it.main = "io.gitlab.arturbosch.detekt.cli.Main"
|
||||
it.classpath = configuration
|
||||
it.classpath = classpath
|
||||
it.args(detektExtension.resolveArguments(project).plus(createBaseline))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,30 +2,31 @@ package io.gitlab.arturbosch.detekt
|
||||
|
||||
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
/**
|
||||
* @author Artur Bosch
|
||||
* @author Olivier Lemasle
|
||||
*/
|
||||
open class DetektGenerateConfigTask : DefaultTask() {
|
||||
|
||||
private val classpath: FileCollection
|
||||
|
||||
init {
|
||||
description = "Generate a detekt configuration file inside your project."
|
||||
group = "verification"
|
||||
|
||||
val detektExtension = project.extensions.getByName("detekt") as DetektExtension
|
||||
classpath = detektExtension.resolveClasspath(project)
|
||||
dependsOn(classpath)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun generateConfig() {
|
||||
val detektExtension = project.extensions.getByName("detekt") as DetektExtension
|
||||
|
||||
val configuration = project.buildscript.configurations.maybeCreate("detektConfig")
|
||||
project.buildscript.dependencies.add(configuration.name, DefaultExternalModuleDependency(
|
||||
"io.gitlab.arturbosch.detekt", "detekt-cli", detektExtension.version))
|
||||
|
||||
project.javaexec {
|
||||
it.main = "io.gitlab.arturbosch.detekt.cli.Main"
|
||||
it.classpath = configuration
|
||||
it.classpath = classpath
|
||||
it.args("--input", project.projectDir.absolutePath, "--generate-config")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.gradle.api.Project
|
||||
class DetektPlugin : Plugin<Project> {
|
||||
|
||||
override fun apply(project: Project) {
|
||||
project.configurations.create("detekt")
|
||||
|
||||
val profilesContainer = project.container(ProfileExtension::class.java)
|
||||
project.extensions.add(PROFILES_EXTENSION_NAME, profilesContainer)
|
||||
profilesContainer.all { ProfileStorage.add(it) }
|
||||
|
||||
@@ -2,10 +2,13 @@ package io.gitlab.arturbosch.detekt.extensions
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
|
||||
|
||||
/**
|
||||
* @author Artur Bosch
|
||||
* @author Said Tahsin Dane
|
||||
* @author Olivier Lemasle
|
||||
*/
|
||||
open class DetektExtension(open var version: String = SUPPORTED_DETEKT_VERSION,
|
||||
open var debug: Boolean = DEFAULT_DEBUG_VALUE,
|
||||
@@ -34,6 +37,17 @@ open class DetektExtension(open var version: String = SUPPORTED_DETEKT_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveClasspath(project: Project): FileCollection = project
|
||||
.configurations
|
||||
.getByName("detekt")
|
||||
.withDependencies {
|
||||
it.add(
|
||||
DefaultExternalModuleDependency(
|
||||
"io.gitlab.arturbosch.detekt", "detekt-cli", version
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun resolveArguments(project: Project): List<String> {
|
||||
return with(extractArguments()) {
|
||||
if (!contains(INPUT_PARAMETER)) {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package io.gitlab.arturbosch.detekt
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.jetbrains.spek.api.Spek
|
||||
import org.jetbrains.spek.api.dsl.describe
|
||||
import org.jetbrains.spek.api.dsl.it
|
||||
import org.gradle.testkit.runner.GradleRunner
|
||||
import org.gradle.testkit.runner.TaskOutcome
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* @author Olivier Lemasle
|
||||
*/
|
||||
internal class FunctionalTest : Spek({
|
||||
|
||||
describe("The Detekt Gradle plugin") {
|
||||
|
||||
it("uses built-in rules") {
|
||||
val rootDir = createTempDir(prefix = "withoutCustomRules")
|
||||
writeFiles(rootDir)
|
||||
|
||||
// Using a custom "project-cache-dir" to avoid a Gradle error on Windows
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(rootDir)
|
||||
.withArguments("--project-cache-dir", createTempDir(prefix = "cache").absolutePath, "detektCheck")
|
||||
.withPluginClasspath()
|
||||
.build()
|
||||
|
||||
assertThat(result.output).contains("number of classes: 1")
|
||||
assertThat(result.output).contains("Ruleset: comments")
|
||||
assertThat(result.task(":detektCheck")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
|
||||
|
||||
// Asserts that the "custom" module is not built, and that custom ruleset is not enabled
|
||||
assertThat(result.output).doesNotContain("Ruleset: test-custom")
|
||||
assertThat(File(rootDir, "custom/build")).doesNotExist()
|
||||
}
|
||||
|
||||
it("can use custom rules from a project's module") {
|
||||
val rootDir = createTempDir(prefix = "withCustomRules")
|
||||
writeFiles(rootDir)
|
||||
|
||||
File(rootDir, "build.gradle").appendText(
|
||||
"""
|
||||
|dependencies {
|
||||
| detekt project(':custom')
|
||||
|}
|
||||
""".trimMargin()
|
||||
)
|
||||
|
||||
val result = GradleRunner.create()
|
||||
.withProjectDir(rootDir)
|
||||
.withArguments("--project-cache-dir", createTempDir(prefix = "cache").absolutePath, "detektCheck")
|
||||
.withPluginClasspath()
|
||||
.build()
|
||||
|
||||
assertThat(result.output).contains("number of classes: 1")
|
||||
assertThat(result.output).contains("Ruleset: comments")
|
||||
assertThat(result.task(":detektCheck")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
|
||||
|
||||
// Asserts that the "custom" module is built, and that custom ruleset is enabled
|
||||
assertThat(result.output).contains("Ruleset: test-custom")
|
||||
assertThat(File(rootDir, "custom/build")).exists()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// build.gradle
|
||||
private val buildFileContent = """
|
||||
|plugins {
|
||||
| id 'io.gitlab.arturbosch.detekt'
|
||||
|}
|
||||
|repositories {
|
||||
| jcenter()
|
||||
|}
|
||||
|detekt {
|
||||
| profile('main') {
|
||||
| input = "${"$"}projectDir/src/main/kotlin"
|
||||
| }
|
||||
|}
|
||||
|
|
||||
""".trimMargin()
|
||||
|
||||
// settings.gradle
|
||||
private const val settingsFileContent = """include ":custom""""
|
||||
|
||||
// src/main/kotlin/MyClass.kt
|
||||
private val ktFileContent = """
|
||||
|class MyClass
|
||||
|
|
||||
""".trimMargin()
|
||||
|
||||
// custom/build.gradle
|
||||
private val customBuildFileContent = """
|
||||
|plugins {
|
||||
| id "org.jetbrains.kotlin.jvm" version "1.2.31"
|
||||
|}
|
||||
|repositories {
|
||||
| jcenter()
|
||||
|}
|
||||
|dependencies {
|
||||
| implementation "io.gitlab.arturbosch.detekt:detekt-api:1.0.0.RC6-4"
|
||||
|}
|
||||
""".trimMargin()
|
||||
|
||||
// custom/src/main/kotlin/RulesProvider.kt
|
||||
private val customRulesProviderContent = """
|
||||
|import io.gitlab.arturbosch.detekt.api.Config
|
||||
|import io.gitlab.arturbosch.detekt.api.RuleSet
|
||||
|import io.gitlab.arturbosch.detekt.api.RuleSetProvider
|
||||
|
|
||||
|class RulesProvider : RuleSetProvider {
|
||||
| override val ruleSetId: String = "test-custom"
|
||||
| override fun instance(config: Config) = RuleSet(ruleSetId, listOf())
|
||||
|}
|
||||
|
|
||||
""".trimMargin()
|
||||
|
||||
// custom/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
|
||||
private const val ruleSetProviderSpiContent = "RulesProvider"
|
||||
|
||||
private fun writeFiles(root: File) {
|
||||
File(root, "build.gradle").writeText(buildFileContent)
|
||||
File(root, "settings.gradle").writeText(settingsFileContent)
|
||||
File(root, "src/main/kotlin").mkdirs()
|
||||
File(root, "src/main/kotlin/MyClass.kt").writeText(ktFileContent)
|
||||
File(root, "custom").mkdirs()
|
||||
File(root, "custom/build.gradle").writeText(customBuildFileContent)
|
||||
File(root, "custom/src/main/kotlin").mkdirs()
|
||||
File(root, "custom/src/main/kotlin/RulesProvider.kt").writeText(customRulesProviderContent)
|
||||
File(root, "custom/src/main/resources/META-INF/services").mkdirs()
|
||||
File(root, "custom/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider")
|
||||
.writeText(ruleSetProviderSpiContent)
|
||||
}
|
||||
Reference in New Issue
Block a user