Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

Add rules to lint baseline merging output + pretty print #58

Merged
merged 5 commits into from
Oct 31, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 52 additions & 18 deletions src/main/kotlin/slack/cli/lint/LintBaselineMergerCli.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ import io.github.detekt.sarif4k.ArtifactLocation
import io.github.detekt.sarif4k.Level
import io.github.detekt.sarif4k.Location
import io.github.detekt.sarif4k.Message
import io.github.detekt.sarif4k.MultiformatMessageString
import io.github.detekt.sarif4k.PhysicalLocation
import io.github.detekt.sarif4k.Region
import io.github.detekt.sarif4k.ReportingConfiguration
import io.github.detekt.sarif4k.ReportingDescriptor
import io.github.detekt.sarif4k.Result
import io.github.detekt.sarif4k.Run
import io.github.detekt.sarif4k.SarifSchema210
Expand All @@ -43,6 +46,7 @@ import kotlin.io.path.name
import kotlin.io.path.readText
import kotlin.io.path.relativeTo
import kotlin.io.path.writeText
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
Expand All @@ -68,23 +72,16 @@ public class LintBaselineMergerCli : CliktCommand("Merges multiple lint baseline

private val verbose by option("--verbose", "-v").flag()

@OptIn(ExperimentalSerializationApi::class)
private val json = Json {
prettyPrint = true
prettyPrintIndent = " "
}

private val xml = XML { defaultPolicy { ignoreUnknownChildren() } }

override fun run() {
val xml = XML { defaultPolicy { ignoreUnknownChildren() } }
val issues = mutableMapOf<LintIssues.LintIssue, Path>()
projectDir
.toFile()
.walkTopDown()
.skipBuildAndCacheDirs()
.map { it.toPath() }
.filter { it.name == baselineFileName }
.forEach { file ->
if (verbose) println("Parsing $file")
val lintIssues = xml.decodeFromString(serializer<LintIssues>(), file.readText())
for (issue in lintIssues.issues) {
if (verbose) println("Parsed $issue")
issues[issue] = file.parent
}
}
val issues = parseIssues()

if (verbose) println("Merging ${issues.size} issues")
val idsToLocations =
Expand All @@ -95,6 +92,21 @@ public class LintBaselineMergerCli : CliktCommand("Merges multiple lint baseline
}
.toSortedMap()

if (verbose) println("Gathering rules")
val rules =
issues.keys
.map { issue ->
ReportingDescriptor(
id = issue.id,
name = issue.id,
shortDescription = MultiformatMessageString(text = issue.message),
fullDescription = MultiformatMessageString(text = issue.message),
defaultConfiguration = ReportingConfiguration(level = Level.Error)
)
}
.sortedBy { it.id }
val ruleIndices = rules.withIndex().associate { (index, rule) -> rule.id to index.toLong() }

if (verbose) println("Writing to $outputFile")
outputFile.deleteIfExists()
outputFile.createParentDirectories()
Expand All @@ -105,14 +117,15 @@ public class LintBaselineMergerCli : CliktCommand("Merges multiple lint baseline
runs =
listOf(
Run(
tool = Tool(ToolComponent(name = "lint")),
tool = Tool(ToolComponent(name = "lint", rules = rules)),
results =
buildList {
for ((id, locations) in idsToLocations) {
add(
Result(
ruleID = id,
level = Level.Error,
ruleIndex = ruleIndices.getValue(id),
locations =
locations.sortedBy { it.physicalLocation?.artifactLocation?.uri },
message = Message(text = "Lint issue $id")
Expand All @@ -123,7 +136,28 @@ public class LintBaselineMergerCli : CliktCommand("Merges multiple lint baseline
)
)
)
Json.encodeToString(SarifSchema210.serializer(), outputSarif).let { outputFile.writeText(it) }

json.encodeToString(SarifSchema210.serializer(), outputSarif).let { outputFile.writeText(it) }
}

private fun parseIssues(): Map<LintIssues.LintIssue, Path> {
val issues = mutableMapOf<LintIssues.LintIssue, Path>()
projectDir
.toFile()
.walkTopDown()
.skipBuildAndCacheDirs()
.map { it.toPath() }
.filter { it.name == baselineFileName }
.forEach { file ->
if (verbose) println("Parsing $file")
val lintIssues = xml.decodeFromString(serializer<LintIssues>(), file.readText())
for (issue in lintIssues.issues) {
if (verbose) println("Parsed $issue")
issues[issue] = file.parent
}
}

return issues
}

/**
Expand Down