Skip to content

Commit

Permalink
[WIP] Add config generator for custom rules
Browse files Browse the repository at this point in the history
  • Loading branch information
VitalyVPinchuk committed Jul 14, 2022
1 parent d017c47 commit f12bb7f
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 6 deletions.
36 changes: 36 additions & 0 deletions detekt-generator/build.gradle.kts
Expand Up @@ -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)
Expand Down
@@ -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<String>) {
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()
}
Expand Up @@ -38,6 +38,12 @@ class DetektPrinter(private val arguments: GeneratorArgs) {
}
}

fun printCustomConfig(pages: List<RuleSetPage>) {
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 """
Expand Down
Expand Up @@ -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.")
}
}
Expand Up @@ -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<Path>
abstract val configPath: Path
open val documentationPath: Path = Paths.get("")
open val cliOptionsPath: Path = Paths.get("")
}

class GeneratorArgsFull : GeneratorArgs() {

@Parameter(
names = ["--input", "-i"],
Expand Down Expand Up @@ -42,7 +49,7 @@ class GeneratorArgs {
)
var help: Boolean = false

val inputPath: List<Path> by lazy {
override val inputPath: List<Path> by lazy {
checkNotNull(input) { "Input parameter was not initialized by jcommander!" }
.splitToSequence(",", ";")
.map(String::trim)
Expand All @@ -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<Path> 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!" })
}
Expand Up @@ -8,7 +8,7 @@ import kotlin.system.exitProcess

@Suppress("detekt.SpreadOperator")
fun main(args: Array<String>) {
val options = GeneratorArgs()
val options = GeneratorArgsFull()
val parser = JCommander(options)
parser.parse(*args)

Expand Down
Expand Up @@ -24,6 +24,13 @@ object ConfigPrinter : DocumentationPrinter<List<RuleSetPage>> {
}
}

fun printCustomConfig(item: List<RuleSetPage>): String {
return yaml {
item.sortedBy { it.ruleSet.name }
.forEach { printRuleSetPage(it) }
}
}

private fun defaultBuildConfiguration(): String = """
build:
maxIssues: 0
Expand Down

0 comments on commit f12bb7f

Please sign in to comment.