Skip to content

Commit

Permalink
Add config generator for custom rules (#5080)
Browse files Browse the repository at this point in the history
* [WIP] Add config generator for custom rules

* [WIP] Add config generator for custom rules

* [WIP] Add config generator for custom rules

* Fix tests for Windows

* WIP

* Fix handling filenames

Co-authored-by: Brais Gabín <braisgabin@gmail.com>

* Update tests

Co-authored-by: Brais Gabín <braisgabin@gmail.com>
  • Loading branch information
VitalyVPinchuk and BraisGabin committed Sep 12, 2022
1 parent 0b9ff32 commit 1c3e62b
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 3 deletions.
Expand Up @@ -43,6 +43,12 @@ class DetektPrinter(private val arguments: GeneratorArgs) {
}
}

fun printCustomRuleConfig(pages: List<RuleSetPage>, folder: String) {
yamlWriter.write(Paths.get(folder), "config") {
ConfigPrinter.printCustomRuleConfig(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,24 @@ class Generator(

outPrinter.println("\nGenerated all detekt documentation in $time ms.")
}

fun executeCustomRuleConfig() {
val parser = KtCompiler()
val time = measureTimeMillis {
arguments.inputPath
.map { parseAll(parser, it.resolve("src/main/kotlin/")) to it }
.forEach { (list: Collection<KtFile>, folder: Path) ->
val collector = DetektCollector()
list.forEach { file ->
collector.visit(file)
}
printer.printCustomRuleConfig(
collector.items,
folder.resolve("src/main/resources/config/").toString()
)
}
}

outPrinter.println("\nGenerated custom rules config in $time ms.")
}
}
Expand Up @@ -16,21 +16,21 @@ class GeneratorArgs {

@Parameter(
names = ["--documentation", "-d"],
required = true,
required = false,
description = "Output path for generated documentation."
)
private var documentation: String? = null

@Parameter(
names = ["--config", "-c"],
required = true,
required = false,
description = "Output path for generated detekt config."
)
private var config: String? = null

@Parameter(
names = ["--cli-options"],
required = true,
required = false,
description = "Output path for generated cli options page."
)
private var cliOptions: String? = null
Expand All @@ -42,6 +42,14 @@ class GeneratorArgs {
)
var help: Boolean = false

@Parameter(
names = ["--generate-custom-rule-config", "-gcrc"],
required = false,
description = "Generate config for user-defined rules. " +
"Path to user rules can be specified with --input option"
)
var generateCustomRuleConfig: Boolean = false

val inputPath: List<Path> by lazy {
checkNotNull(input) { "Input parameter was not initialized by jcommander!" }
.splitToSequence(",", ";")
Expand Down
Expand Up @@ -17,6 +17,11 @@ fun main(args: Array<String>) {
exitProcess(0)
}

if (options.generateCustomRuleConfig) {
Generator(options).executeCustomRuleConfig()
return
}

require(Files.isDirectory(options.documentationPath)) { "Documentation path must be a directory." }
require(Files.isDirectory(options.configPath)) { "Config path must be a directory." }

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

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

private fun defaultBuildConfiguration(): String = """
build:
maxIssues: 0
Expand Down
@@ -0,0 +1,59 @@
package io.gitlab.arturbosch.detekt.generator.printer

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.io.path.readText

class GeneratorSpec {
@Test
fun `config files generated successfully`() {
assertThat(Paths.get(tempDir1.toString(), configPath)).exists()
assertThat(Paths.get(tempDir2.toString(), configPath)).exists()
}

@Test
fun `config files have their own content`() {
assertThat(Paths.get(tempDir1.toString(), configPath).readText())
.contains("complexity:")
.doesNotContain("coroutines:")

assertThat(Paths.get(tempDir2.toString(), configPath).readText())
.contains("coroutines:")
.doesNotContain("complexity:")
}

companion object {
private const val sourceDir1 = "../detekt-rules-complexity"
private const val sourceDir2 = "../detekt-rules-coroutines"
private const val configPath = "/src/main/resources/config/config.yml"

private val tempDir1: File = Files.createTempDirectory(null).toFile()
private val tempDir2: File = Files.createTempDirectory(null).toFile()

@JvmStatic
@BeforeAll
fun init() {
File(Paths.get(sourceDir1).toString()).copyRecursively(tempDir1)
File(Paths.get(sourceDir2).toString()).copyRecursively(tempDir2)

val args = arrayOf(
"--generate-custom-rule-config",
"--input",
"$tempDir1, $tempDir2",
)
io.gitlab.arturbosch.detekt.generator.main(args)
}

@JvmStatic
@AfterAll
fun tearDown() {
tempDir1.deleteRecursively()
tempDir2.deleteRecursively()
}
}
}

0 comments on commit 1c3e62b

Please sign in to comment.