From f12bb7f7621e7600973c3d4f37ab2aaee6dffb72 Mon Sep 17 00:00:00 2001 From: "Vitaly V. Pinchuk" Date: Tue, 12 Jul 2022 17:19:41 +0300 Subject: [PATCH] [WIP] Add config generator for custom rules --- detekt-generator/build.gradle.kts | 36 ++++++++++++ .../detekt/generator/CustomConfig.kt | 23 ++++++++ .../detekt/generator/DetektPrinter.kt | 6 ++ .../arturbosch/detekt/generator/Generator.kt | 14 +++++ .../detekt/generator/GeneratorArgs.kt | 55 +++++++++++++++++-- .../arturbosch/detekt/generator/Main.kt | 2 +- .../printer/defaultconfig/ConfigPrinter.kt | 7 +++ 7 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/CustomConfig.kt diff --git a/detekt-generator/build.gradle.kts b/detekt-generator/build.gradle.kts index e1a96393dcba..1fc4ad2aaaf0 100644 --- a/detekt-generator/build.gradle.kts +++ b/detekt-generator/build.gradle.kts @@ -67,6 +67,42 @@ val generateDocumentation by tasks.registering(JavaExec::class) { ) } +val generateCustomConfig by tasks.registering(JavaExec::class) { + dependsOn(tasks.assemble, ":detekt-api:dokkaHtml") + description = "Generates custom rules config based on Rule annotations" + group = "documentation" + +// inputs.files( +// ruleModules.map { fileTree(it) }, +// fileTree("${rootProject.rootDir}/detekt-formatting/src/main/kotlin"), +// file("${rootProject.rootDir}/detekt-generator/build/libs/detekt-generator-${Versions.DETEKT}-all.jar"), +// ) + +// outputs.files( +// fileTree(documentationDir), +// file(defaultConfigFile), +// file(deprecationFile), +// file(cliOptionsFile), +// ) + + classpath( + configurations.runtimeClasspath.get(), + configurations.compileClasspath.get(), + sourceSets.main.get().output, + ) + mainClass.set("io.gitlab.arturbosch.detekt.generator.CustomConfig") + args = listOf( + "--input", + """ + ${rootProject.rootDir}/detekt-rules-complexity/, + ${rootProject.rootDir}/detekt-rules-coroutines/, + ${rootProject.rootDir}/detekt-rules-documentation/, + """.trimIndent(), + "--config", + configDir, + ) +} + val verifyGeneratorOutput by tasks.registering(Exec::class) { notCompatibleWithConfigurationCache("cannot serialize object of type java.io.ByteArrayOutputStream") dependsOn(generateDocumentation) diff --git a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/CustomConfig.kt b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/CustomConfig.kt new file mode 100644 index 000000000000..5fc9a48edfa8 --- /dev/null +++ b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/CustomConfig.kt @@ -0,0 +1,23 @@ +@file:JvmName("CustomConfig") + +package io.gitlab.arturbosch.detekt.generator + +import com.beust.jcommander.JCommander +import java.nio.file.Files +import kotlin.system.exitProcess + +@Suppress("detekt.SpreadOperator") +fun main(args: Array) { + val options = GeneratorArgsReduced() + val parser = JCommander(options) + parser.parse(*args) + + if (options.help) { + parser.usage() + exitProcess(0) + } + + require(Files.isDirectory(options.configPath)) { "Config path must be a directory." } + + Generator(options).executeCustomConfig() +} diff --git a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/DetektPrinter.kt b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/DetektPrinter.kt index a9dbb1e11f89..e3fca881122e 100644 --- a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/DetektPrinter.kt +++ b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/DetektPrinter.kt @@ -38,6 +38,12 @@ class DetektPrinter(private val arguments: GeneratorArgs) { } } + fun printCustomConfig(pages: List) { + yamlWriter.write(arguments.configPath, "custom-rules-config") { + ConfigPrinter.printCustomConfig(pages) + } + } + private fun markdownHeader(ruleSet: String): String { check(ruleSet.length > 1) { "Rule set name must be not empty or less than two symbols." } return """ diff --git a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Generator.kt b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Generator.kt index af96985c7635..63270eb53909 100644 --- a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Generator.kt +++ b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Generator.kt @@ -39,4 +39,18 @@ class Generator( outPrinter.println("\nGenerated all detekt documentation in $time ms.") } + + fun executeCustomConfig() { + val parser = KtCompiler() + val time = measureTimeMillis { + val ktFiles = arguments.inputPath + .flatMap { parseAll(parser, it) } + + ktFiles.forEach(collector::visit) + + printer.printCustomConfig(collector.items) + } + + outPrinter.println("\nGenerated custom rules config in $time ms.") + } } diff --git a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/GeneratorArgs.kt b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/GeneratorArgs.kt index 6a6b4fa6f0fb..85bf279acc15 100644 --- a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/GeneratorArgs.kt +++ b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/GeneratorArgs.kt @@ -5,7 +5,14 @@ import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -class GeneratorArgs { +abstract class GeneratorArgs { + abstract val inputPath: List + abstract val configPath: Path + open val documentationPath: Path = Paths.get("") + open val cliOptionsPath: Path = Paths.get("") +} + +class GeneratorArgsFull : GeneratorArgs() { @Parameter( names = ["--input", "-i"], @@ -42,7 +49,7 @@ class GeneratorArgs { ) var help: Boolean = false - val inputPath: List by lazy { + override val inputPath: List by lazy { checkNotNull(input) { "Input parameter was not initialized by jcommander!" } .splitToSequence(",", ";") .map(String::trim) @@ -51,20 +58,58 @@ class GeneratorArgs { .onEach { require(Files.exists(it)) { "Input path must exist!" } } .toList() } - val documentationPath: Path + + override val documentationPath: Path get() = Paths.get( checkNotNull(documentation) { "Documentation output path was not initialized by jcommander!" } ) - val configPath: Path + override val configPath: Path get() = Paths.get(checkNotNull(config) { "Configuration output path was not initialized by jcommander!" }) - val cliOptionsPath: Path + override val cliOptionsPath: Path get() = Paths.get( checkNotNull(cliOptions) { "Cli options output path was not initialized by jcommander!" } ) } + +class GeneratorArgsReduced : GeneratorArgs() { + + @Parameter( + names = ["--input", "-i"], + required = true, + description = "Input paths to analyze." + ) + private var input: String? = null + + @Parameter( + names = ["--config", "-c"], + required = true, + description = "Output path for generated detekt config." + ) + private var config: String? = null + + @Parameter( + names = ["--help", "-h"], + help = true, + description = "Shows the usage." + ) + var help: Boolean = false + + override val inputPath: List by lazy { + checkNotNull(input) { "Input parameter was not initialized by jcommander!" } + .splitToSequence(",", ";") + .map(String::trim) + .filter { it.isNotEmpty() } + .map { first -> Paths.get(first) } + .onEach { require(Files.exists(it)) { "Input path must exist!" } } + .toList() + } + + override val configPath: Path + get() = Paths.get(checkNotNull(config) { "Configuration output path was not initialized by jcommander!" }) +} diff --git a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Main.kt b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Main.kt index d4b72ee1189d..7b7594968a15 100644 --- a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Main.kt +++ b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/Main.kt @@ -8,7 +8,7 @@ import kotlin.system.exitProcess @Suppress("detekt.SpreadOperator") fun main(args: Array) { - val options = GeneratorArgs() + val options = GeneratorArgsFull() val parser = JCommander(options) parser.parse(*args) diff --git a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinter.kt b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinter.kt index 9131be470888..bf19004e2e19 100644 --- a/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinter.kt +++ b/detekt-generator/src/main/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinter.kt @@ -24,6 +24,13 @@ object ConfigPrinter : DocumentationPrinter> { } } + fun printCustomConfig(item: List): String { + return yaml { + item.sortedBy { it.ruleSet.name } + .forEach { printRuleSetPage(it) } + } + } + private fun defaultBuildConfiguration(): String = """ build: maxIssues: 0