Skip to content

Commit

Permalink
Merge pull request #64 from usefulness/mateuszkwiecinski/bump_ktlint_…
Browse files Browse the repository at this point in the history
…to_0_49_0
  • Loading branch information
mateuszkwiecinski authored May 13, 2023
2 parents 3e79607 + 8c28597 commit f407bea
Show file tree
Hide file tree
Showing 33 changed files with 199 additions and 131 deletions.
7 changes: 5 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ gradle-doctor = "0.8.1"
google-agp = "8.0.1"
maven-junit = "5.9.3"
maven-assertj = "3.24.2"
maven-ktlint = "0.48.2"
maven-ktlint = "0.49.1"
maven-commons = "2.11.0"

[libraries]
agp-gradle = { module = "com.android.tools.build:gradle", version.ref = "google-agp" }
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin" }
ktlint-core = { module = "com.pinterest.ktlint:ktlint-core", version.ref = "maven-ktlint" }
ktlint-rule-engine = { module = "com.pinterest.ktlint:ktlint-rule-engine", version.ref = "maven-ktlint" }
ktlint-cli-ruleset-core = { module = "com.pinterest.ktlint:ktlint-cli-ruleset-core", version.ref = "maven-ktlint" }
ktlint-cli-reporter = { module = "com.pinterest.ktlint:ktlint-cli-reporter", version.ref = "maven-ktlint" }
ktlint-reporter-baseline = { module = "com.pinterest.ktlint:ktlint-reporter-baseline", version.ref = "maven-ktlint" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "maven-junit" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "maven-junit" }
assertj-core = { module = "org.assertj:assertj-core", version.ref = "maven-assertj" }
Expand Down
10 changes: 8 additions & 2 deletions ktlint-gradle-plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ description = "Lint and formatting for Kotlin using ktlint with configuration-fr

configurations {
register("testRuntimeDependencies") {
extendsFrom(compileOnly)
attributes {
// KGP publishes multiple variants https://kotlinlang.org/docs/whatsnew17.html#support-for-gradle-plugin-variants
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.class, Usage.JAVA_RUNTIME))
Expand All @@ -32,12 +31,19 @@ configurations {
dependencies {
compileOnly(libs.kotlin.gradle)
compileOnly(libs.agp.gradle)
compileOnly(libs.ktlint.core)
compileOnly(libs.ktlint.rule.engine)
compileOnly(libs.ktlint.cli.ruleset.core)
compileOnly(libs.ktlint.cli.reporter)
compileOnly(libs.ktlint.reporter.baseline)

testRuntimeOnly(libs.junit.jupiter.engine)

testImplementation(libs.junit.jupiter.api)
testImplementation(libs.commons.io)
testImplementation(libs.assertj.core)

testRuntimeDependencies(libs.kotlin.gradle)
testRuntimeDependencies(libs.agp.gradle)
}

kotlin {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
package io.github.usefulness.support

import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.api.Baseline
import com.pinterest.ktlint.core.api.loadBaseline
import com.pinterest.ktlint.cli.reporter.baseline.Baseline
import com.pinterest.ktlint.cli.reporter.baseline.loadBaseline
import com.pinterest.ktlint.cli.reporter.core.api.KtlintCliError
import java.io.File

internal fun File.readKtlintBaseline(): Map<String, List<LintError>>? {
internal fun File.readKtlintBaseline(): Map<String, List<KtlintCliError>>? {
val baseline = loadBaseline(absolutePath)
when (baseline.status) {
Baseline.Status.VALID -> Unit
Baseline.Status.NOT_FOUND,
Baseline.Status.INVALID,
Baseline.Status.DISABLED,
-> return null
}
}.let { }

return baseline.lintErrorsPerFile
}

internal fun File.getBaselineKey(projectDir: File) =
toRelativeString(projectDir).replace(File.separatorChar, '/')

/**
* Same as ktlint, avoids unnecessary incompatibility issues
*/
internal fun List<LintError>.doesNotContain(lintError: LintError) =
none {
it.col == lintError.col &&
it.line == lintError.line &&
it.ruleId == lintError.ruleId
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.github.usefulness.support

import com.pinterest.ktlint.core.api.EditorConfigDefaults
import com.pinterest.ktlint.core.api.EditorConfigOverride
import com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty
import com.pinterest.ktlint.rule.engine.api.EditorConfigDefaults
import com.pinterest.ktlint.rule.engine.api.EditorConfigOverride
import com.pinterest.ktlint.rule.engine.core.api.editorconfig.EditorConfigProperty
import org.ec4j.core.model.EditorConfig
import org.ec4j.core.model.Glob
import org.ec4j.core.model.Property
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.github.usefulness.support

import com.pinterest.ktlint.core.KtLintRuleEngine
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.logging.Logger
import java.io.File
import com.pinterest.ktlint.rule.engine.api.KtLintRuleEngine

internal fun createKtlintEngine(
disabledRules: List<String>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package io.github.usefulness.support

import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.cli.reporter.core.api.KtlintCliError
import java.io.File
import java.io.Serializable

internal data class KtlintErrorResult(
val file: File,
val errors: List<Pair<LintError, Boolean>>,
val errors: List<KtlintCliError>,
) : Serializable {

companion object {

const val serialVersionUID = 1L
const val serialVersionUID = 2L
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.usefulness.support

import com.pinterest.ktlint.core.Reporter
import com.pinterest.ktlint.core.ReporterProvider
import com.pinterest.ktlint.cli.reporter.core.api.ReporterV2
import com.pinterest.ktlint.cli.reporter.core.api.ReporterProviderV2
import java.io.File
import java.io.PrintStream
import java.util.ServiceLoader
Expand Down Expand Up @@ -33,7 +33,7 @@ internal fun reporterPathFor(reporterType: ReporterType, output: File, relativeR

internal fun resolveReporters(
enabled: Map<ReporterType, File>,
): Map<ReporterType, Reporter> {
): Map<ReporterType, ReporterV2> {
val allReporterProviders = defaultReporters().associateBy { it.id }

return enabled
Expand All @@ -56,5 +56,5 @@ private fun ReporterType.generateOpt() = when (this) {
ReporterType.Plain -> mapOf("color_name" to "DARK_GRAY")
}

private fun defaultReporters(): List<ReporterProvider<*>> =
ServiceLoader.load(ReporterProvider::class.java).toList()
private fun defaultReporters(): List<ReporterProviderV2<*>> =
ServiceLoader.load(ReporterProviderV2::class.java).toList()
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package io.github.usefulness.support

import com.pinterest.ktlint.core.RuleProvider
import com.pinterest.ktlint.core.RuleSetProviderV2
import com.pinterest.ktlint.cli.ruleset.core.api.RuleSetProviderV3
import com.pinterest.ktlint.rule.engine.core.api.RuleProvider
import com.pinterest.ktlint.rule.engine.core.api.RuleSetId
import java.util.ServiceLoader

internal fun resolveRuleProviders(
providers: Iterable<RuleSetProviderV2>,
providers: Iterable<RuleSetProviderV3>,
): Set<RuleProvider> = providers
.asSequence()
.sortedWith(
compareBy {
when (it.id) {
"standard" -> 0
when (it.id.value) {
RuleSetId.STANDARD.value -> 0
else -> 1
}
},
)
.map(RuleSetProviderV2::getRuleProviders)
.map(RuleSetProviderV3::getRuleProviders)
.flatten()
.toSet()

// statically resolve providers from plugin classpath. ServiceLoader#load alone resolves classes lazily which fails when run in parallel
internal val defaultRuleSetProviders: List<RuleSetProviderV2> =
ServiceLoader.load(RuleSetProviderV2::class.java).toList()
internal val defaultRuleSetProviders: List<RuleSetProviderV3> =
ServiceLoader.load(RuleSetProviderV3::class.java).toList()
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.github.usefulness.tasks.workers

import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.cli.reporter.baseline.doesNotContain
import com.pinterest.ktlint.cli.reporter.core.api.KtlintCliError
import com.pinterest.ktlint.cli.reporter.core.api.KtlintCliError.Status
import io.github.usefulness.support.KtlintRunMode
import io.github.usefulness.support.doesNotContain
import io.github.usefulness.support.getBaselineKey
import io.github.usefulness.support.readKtlintBaseline
import io.github.usefulness.support.readKtlintErrors
Expand All @@ -29,7 +30,7 @@ internal abstract class ConsoleReportWorker : WorkAction<ConsoleReportWorker.Par
var hasUncoveredErrors = false
discoveredErrors.forEach { (file, errors) ->
val baselineErrors = baselineContent[file.getBaselineKey(projectDir)].orEmpty()
errors.forEach { (lintError, corrected) ->
errors.forEach { lintError ->
when (mode) {
KtlintRunMode.Check ->
if (baselineErrors.doesNotContain(lintError)) {
Expand All @@ -38,13 +39,21 @@ internal abstract class ConsoleReportWorker : WorkAction<ConsoleReportWorker.Par
}

KtlintRunMode.Format -> {
when (corrected) {
true -> logger.quiet(lintError.generateMessage(file = file, message = "Format fixed"))
false -> {
when (lintError.status) {
Status.BASELINE_IGNORED -> Unit
Status.LINT_CAN_NOT_BE_AUTOCORRECTED -> {
hasUncoveredErrors = true
logger.warn(lintError.generateMessage(file = file, message = "Format could not fix"))
}
}

Status.FORMAT_IS_AUTOCORRECTED -> logger.quiet(lintError.generateMessage(file = file, message = "Format fixed"))
Status.LINT_CAN_BE_AUTOCORRECTED,
Status.KOTLIN_PARSE_EXCEPTION,
Status.KTLINT_RULE_ENGINE_EXCEPTION,
-> logger.warn(
lintError.generateMessage(file = file, message = "Internal exception status=${lintError.status}"),
)
}.let { }
}
}
}
Expand All @@ -59,7 +68,7 @@ internal abstract class ConsoleReportWorker : WorkAction<ConsoleReportWorker.Par
}
}

private fun LintError.generateMessage(file: File, message: String) = "${file.path}:$line:$col: $message > [$ruleId] $detail"
private fun KtlintCliError.generateMessage(file: File, message: String) = "${file.path}:$line:$col: $message > [$ruleId] $detail"

interface Parameters : WorkParameters {
val errorsContainer: DirectoryProperty
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.usefulness.tasks.workers

import com.pinterest.ktlint.cli.reporter.baseline.doesNotContain
import io.github.usefulness.support.ReporterType
import io.github.usefulness.support.doesNotContain
import io.github.usefulness.support.getBaselineKey
import io.github.usefulness.support.readKtlintBaseline
import io.github.usefulness.support.readKtlintErrors
Expand Down Expand Up @@ -37,15 +37,15 @@ internal abstract class GenerateReportsWorker : WorkAction<GenerateReportsWorker
reporters.onEach { (_, reporter) -> reporter.before(relativePath) }

reporters.onEach { (type, reporter) ->
result.errors.forEach { (lintError, corrected) ->
result.errors.forEach { lintError ->
if (baselineErrors.doesNotContain(lintError)) {
// some reporters want relative paths, some want absolute
val filePath = reporterPathFor(
reporterType = type,
output = result.file,
relativeRoot = projectDir,
)
reporter.onLintError(filePath, lintError, corrected)
reporter.onLintError(filePath, lintError)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.github.usefulness.tasks.workers

import com.pinterest.ktlint.core.Code
import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.cli.reporter.core.api.KtlintCliError
import com.pinterest.ktlint.cli.reporter.core.api.KtlintCliError.Status
import com.pinterest.ktlint.rule.engine.api.Code
import com.pinterest.ktlint.rule.engine.api.LintError
import io.github.usefulness.support.KtlintErrorResult
import io.github.usefulness.support.KtlintRunMode
import io.github.usefulness.support.createKtlintEngine
Expand All @@ -15,6 +17,7 @@ import org.gradle.api.provider.Property
import org.gradle.internal.logging.slf4j.DefaultContextAwareTaskLogger
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.jetbrains.kotlin.utils.addToStdlib.applyIf

internal abstract class KtlintWorker : WorkAction<KtlintWorker.Parameters> {
private val logger = DefaultContextAwareTaskLogger(Logging.getLogger(KtlintWorker::class.java))
Expand All @@ -36,7 +39,9 @@ internal abstract class KtlintWorker : WorkAction<KtlintWorker.Parameters> {
logger.info("$name - resolved ${ktLintEngine.ruleProviders.size} RuleProviders")
logger.info("$name - executing against ${files.count()} file(s)")
if (logger.isDebugEnabled) {
logger.debug("Resolved RuleSetProviders = ${ktLintEngine.ruleProviders.joinToString { it.createNewRuleInstance().id }}")
logger.debug(
"Resolved RuleSetProviders = ${ktLintEngine.ruleProviders.joinToString { it.createNewRuleInstance().ruleId.value }}",
)
}

val errors = mutableListOf<KtlintErrorResult>()
Expand All @@ -50,24 +55,24 @@ internal abstract class KtlintWorker : WorkAction<KtlintWorker.Parameters> {
return@forEach
}

val fileErrors = mutableListOf<Pair<LintError, Boolean>>()
val fileErrors = mutableListOf<KtlintCliError>()
when (parameters.mode.get()) {
KtlintRunMode.Check,
null,
-> ktLintEngine.lint(
code = Code.CodeFile(file),
callback = { fileErrors.add(it to false) },
code = Code.fromFile(file),
callback = { fileErrors.add(it.toKtlintCliErrorForLint()) },
)

KtlintRunMode.Format -> {
var fileFixed = false
val fixedContent = ktLintEngine.format(
code = Code.CodeFile(file),
code = Code.fromFile(file),
callback = { error, corrected ->
if (corrected) {
fileFixed = true
}
fileErrors.add(error to corrected)
fileErrors.add(error.toKtlintCliErrorForFormat(corrected))
},
)

Expand Down Expand Up @@ -99,4 +104,28 @@ internal abstract class KtlintWorker : WorkAction<KtlintWorker.Parameters> {
}
}

private fun LintError.toKtlintCliErrorForLint() = KtlintCliError(
line = line,
col = col,
ruleId = ruleId.value,
detail = detail,
status = if (canBeAutoCorrected) {
Status.LINT_CAN_BE_AUTOCORRECTED
} else {
Status.LINT_CAN_NOT_BE_AUTOCORRECTED
},
)

private fun LintError.toKtlintCliErrorForFormat(corrected: Boolean): KtlintCliError = KtlintCliError(
line = line,
col = col,
ruleId = ruleId.value,
detail = detail.applyIf(corrected) { "$this (cannot be auto-corrected)" },
status = if (corrected) {
Status.FORMAT_IS_AUTOCORRECTED
} else {
Status.LINT_CAN_NOT_BE_AUTOCORRECTED
},
)

private val supportedExtensions = setOf("kt", "kts")
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ internal class AndroidProjectTest : WithGradleTest.Android() {
android {
namespace 'io.github.usefulness'
compileSdkVersion 31
compileSdk 33
defaultConfig {
minSdkVersion 23
}
Expand Down
Loading

0 comments on commit f407bea

Please sign in to comment.