Skip to content

Commit

Permalink
Bump ktlint to 0.48.1 (#304)
Browse files Browse the repository at this point in the history
Co-authored-by: Mateusz Kwieciński <mateusz.kwiatek@gmail.com>
  • Loading branch information
lwasyl and mateuszkwiecinski committed Jan 24, 2023
1 parent 5abda8a commit 27ab24e
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 128 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Expand Up @@ -27,7 +27,7 @@ description = projectDescription
object Versions {
const val androidTools = "7.3.1"
const val junit = "5.9.1"
const val ktlint = "0.47.1"
const val ktlint = "0.48.1"
const val mockitoKotlin = "4.1.0"
}

Expand Down
@@ -1,33 +1,83 @@
package org.jmailen.gradle.kotlinter.support

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties
import com.pinterest.ktlint.core.api.EditorConfigDefaults
import com.pinterest.ktlint.core.api.EditorConfigOverride
import org.gradle.api.file.ConfigurableFileCollection
import com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty
import org.ec4j.core.model.EditorConfig
import org.ec4j.core.model.Glob
import org.ec4j.core.model.Property
import org.ec4j.core.model.PropertyType
import org.ec4j.core.model.PropertyType.PropertyValueParser.IDENTITY_VALUE_PARSER
import org.ec4j.core.model.Section
import org.gradle.api.file.ProjectLayout
import org.gradle.api.logging.Logger
import java.io.File

internal fun editorConfigOverride(ktLintParams: KtLintParams): EditorConfigOverride {
val rules = ktLintParams.disabledRules
internal fun editorConfigOverride(ktLintParams: KtLintParams) =
getPropertiesForDisabledRules(ktLintParams)
.let(::buildEditorConfigOverride)

internal fun editorConfigDefaults(ktLintParams: KtLintParams): EditorConfigDefaults =
getPropertiesForExperimentalRules(ktLintParams)
.let(::buildEditorConfigDefaults)

private fun getPropertiesForDisabledRules(
ktLintParams: KtLintParams,
): List<Pair<EditorConfigProperty<String>, String>> {
val rules = ktLintParams.disabledRules
return if (rules.isEmpty()) {
EditorConfigOverride.emptyEditorConfigOverride
emptyList()
} else {
EditorConfigOverride.from(DefaultEditorConfigProperties.ktlintDisabledRulesProperty to rules.joinToString(separator = ","))
rules
.asSequence()
.map(::getKtlintRulePropertyName)
.map { propertyName ->
EditorConfigProperty(
type = PropertyType(propertyName, "Rule to be disabled", IDENTITY_VALUE_PARSER),
defaultValue = "disabled",
)
}
.map { it to "disabled" }
.toList()
}
}

internal fun resetEditorconfigCacheIfNeeded(
changedEditorconfigFiles: ConfigurableFileCollection,
logger: Logger,
) {
val changedFiles = changedEditorconfigFiles.files
if (changedFiles.any()) {
logger.info("Editorconfig changed, resetting KtLint caches")
changedFiles.map(File::toPath).forEach(KtLint::reloadEditorConfigFile)
private fun getPropertiesForExperimentalRules(ktLintParams: KtLintParams) =
Property
.builder()
.name("ktlint_experimental")
.value(if (ktLintParams.experimentalRules) "enabled" else "disabled")
.let(::listOf)

private fun buildEditorConfigOverride(editorConfigProperties: List<Pair<EditorConfigProperty<String>, String>>) =
if (editorConfigProperties.isEmpty()) {
EditorConfigOverride.EMPTY_EDITOR_CONFIG_OVERRIDE
} else {
EditorConfigOverride.from(*editorConfigProperties.toTypedArray())
}

private fun buildEditorConfigDefaults(kotlinSectionProperties: List<Property.Builder>) =
if (kotlinSectionProperties.isEmpty()) {
EditorConfigDefaults.EMPTY_EDITOR_CONFIG_DEFAULTS
} else {
EditorConfigDefaults(
EditorConfig
.builder()
.section(
Section
.builder()
.glob(Glob("*.{kt,kts}"))
.properties(kotlinSectionProperties),
)
.build(),
)
}

private fun getKtlintRulePropertyName(ruleName: String) =
if (ruleName.contains(':')) { // Rule from a non-standard rule set
"ktlint_${ruleName.replace(':', '_')}"
} else {
"ktlint_standard_$ruleName"
}
}

internal fun ProjectLayout.findApplicableEditorConfigFiles(): Sequence<File> {
val projectEditorConfig = projectDirectory.file(".editorconfig").asFile
Expand Down
@@ -0,0 +1,23 @@
package org.jmailen.gradle.kotlinter.support

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

internal fun createKtlintEngine(ktLintParams: KtLintParams) = KtLintRuleEngine(
ruleProviders = resolveRuleProviders(defaultRuleSetProviders),
editorConfigOverride = editorConfigOverride(ktLintParams),
editorConfigDefaults = editorConfigDefaults(ktLintParams),
)

internal fun KtLintRuleEngine.resetEditorconfigCacheIfNeeded(
changedEditorconfigFiles: ConfigurableFileCollection,
logger: Logger,
) {
val changedFiles = changedEditorconfigFiles.files
if (changedFiles.any()) {
logger.info("Editorconfig changed, resetting KtLint caches")
changedFiles.map(File::toPath).forEach(::reloadEditorConfigFile)
}
}
Expand Up @@ -2,15 +2,12 @@ package org.jmailen.gradle.kotlinter.support

import com.pinterest.ktlint.core.RuleProvider
import com.pinterest.ktlint.core.RuleSetProviderV2
import com.pinterest.ktlint.ruleset.experimental.ExperimentalRuleSetProvider
import java.util.ServiceLoader

internal fun resolveRuleProviders(
providers: Iterable<RuleSetProviderV2>,
includeExperimentalRules: Boolean = false,
): Set<RuleProvider> = providers
.asSequence()
.filter { includeExperimentalRules || it !is ExperimentalRuleSetProvider }
.sortedWith(
compareBy {
when (it.id) {
Expand Down
Expand Up @@ -52,7 +52,7 @@ open class LintTask @Inject constructor(
p.projectDirectory.set(projectLayout.projectDirectory.asFile)
p.reporters.putAll(reports)
p.ktLintParams.set(getKtLintParams())
p.changedEditorconfigFiles.from(getChangedEditorconfigFiles(inputChanges))
p.changedEditorConfigFiles.from(getChangedEditorconfigFiles(inputChanges))
}
runCatching { await() }
}
Expand Down
@@ -1,19 +1,15 @@
package org.jmailen.gradle.kotlinter.tasks.format

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.RuleProvider
import com.pinterest.ktlint.core.Code
import org.gradle.api.logging.LogLevel
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.gradle.internal.logging.slf4j.DefaultContextAwareTaskLogger
import org.gradle.workers.WorkAction
import org.jmailen.gradle.kotlinter.support.KotlinterError
import org.jmailen.gradle.kotlinter.support.KtLintParams
import org.jmailen.gradle.kotlinter.support.defaultRuleSetProviders
import org.jmailen.gradle.kotlinter.support.editorConfigOverride
import org.jmailen.gradle.kotlinter.support.createKtlintEngine
import org.jmailen.gradle.kotlinter.support.resetEditorconfigCacheIfNeeded
import org.jmailen.gradle.kotlinter.support.resolveRuleProviders
import org.jmailen.gradle.kotlinter.tasks.FormatTask
import java.io.File

Expand All @@ -26,40 +22,36 @@ abstract class FormatWorkerAction : WorkAction<FormatWorkerParameters> {
private val output: File? = parameters.output.asFile.orNull

override fun execute() {
resetEditorconfigCacheIfNeeded(
val ktLintEngine = createKtlintEngine(ktLintParams = ktLintParams)
ktLintEngine.resetEditorconfigCacheIfNeeded(
changedEditorconfigFiles = parameters.changedEditorConfigFiles,
logger = logger,
)

val fixes = mutableListOf<String>()
try {
files.forEach { file ->
val ruleSets = resolveRuleProviders(defaultRuleSetProviders, ktLintParams.experimentalRules)
val sourceText = file.readText()
val relativePath = file.toRelativeString(projectDirectory)

logger.log(LogLevel.DEBUG, "$name checking format: $relativePath")

when (file.extension) {
"kt" -> this::formatKt
"kts" -> this::formatKts
else -> {
logger.log(LogLevel.DEBUG, "$name ignoring non Kotlin file: $relativePath")
null
}
}?.let { formatFunc ->
val formattedText = formatFunc.invoke(file, ruleSets) { error, corrected ->
val msg = when (corrected) {
true -> "${file.path}:${error.line}:${error.col}: Format fixed > [${error.ruleId}] ${error.detail}"
false -> "${file.path}:${error.line}:${error.col}: Format could not fix > [${error.ruleId}] ${error.detail}"
}
logger.log(LogLevel.QUIET, msg)
fixes.add(msg)
}
if (!formattedText.contentEquals(sourceText)) {
logger.log(LogLevel.QUIET, "${file.path}: Format fixed")
file.writeText(formattedText)
if (file.extension !in supportedExtensions) {
logger.log(LogLevel.DEBUG, "$name ignoring non Kotlin file: $relativePath")
return@forEach
}

val formattedText = ktLintEngine.format(Code.CodeFile(file)) { error, corrected ->
val msg = when (corrected) {
true -> "${file.path}:${error.line}:${error.col}: Format fixed > [${error.ruleId}] ${error.detail}"
false -> "${file.path}:${error.line}:${error.col}: Format could not fix > [${error.ruleId}] ${error.detail}"
}
logger.log(LogLevel.QUIET, msg)
fixes.add(msg)
}
if (!formattedText.contentEquals(sourceText)) {
logger.log(LogLevel.QUIET, "${file.path}: Format fixed")
file.writeText(formattedText)
}
}
} catch (t: Throwable) {
Expand All @@ -73,27 +65,6 @@ abstract class FormatWorkerAction : WorkAction<FormatWorkerParameters> {
},
)
}

private fun formatKt(file: File, ruleSets: Set<RuleProvider>, onError: ErrorHandler) =
format(file, ruleSets, onError, false)

private fun formatKts(file: File, ruleSets: Set<RuleProvider>, onError: ErrorHandler) =
format(file, ruleSets, onError, true)

private fun format(file: File, ruleProviders: Set<RuleProvider>, onError: ErrorHandler, script: Boolean): String {
return KtLint.format(
KtLint.ExperimentalParams(
fileName = file.path,
text = file.readText(),
ruleProviders = ruleProviders,
script = script,
editorConfigOverride = editorConfigOverride(ktLintParams),
cb = { error, corrected ->
onError(error, corrected)
},
),
)
}
}

typealias ErrorHandler = (error: LintError, corrected: Boolean) -> Unit
private val supportedExtensions = setOf("kt", "kts")
@@ -1,22 +1,18 @@
package org.jmailen.gradle.kotlinter.tasks.lint

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.Code
import com.pinterest.ktlint.core.Reporter
import com.pinterest.ktlint.core.RuleProvider
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.gradle.internal.logging.slf4j.DefaultContextAwareTaskLogger
import org.gradle.workers.WorkAction
import org.jmailen.gradle.kotlinter.support.KotlinterError
import org.jmailen.gradle.kotlinter.support.KtLintParams
import org.jmailen.gradle.kotlinter.support.LintFailure
import org.jmailen.gradle.kotlinter.support.defaultRuleSetProviders
import org.jmailen.gradle.kotlinter.support.editorConfigOverride
import org.jmailen.gradle.kotlinter.support.createKtlintEngine
import org.jmailen.gradle.kotlinter.support.reporterFor
import org.jmailen.gradle.kotlinter.support.reporterPathFor
import org.jmailen.gradle.kotlinter.support.resetEditorconfigCacheIfNeeded
import org.jmailen.gradle.kotlinter.support.resolveRuleProviders
import org.jmailen.gradle.kotlinter.tasks.LintTask
import java.io.File

Expand All @@ -31,28 +27,27 @@ abstract class LintWorkerAction : WorkAction<LintWorkerParameters> {
private val ktLintParams: KtLintParams = parameters.ktLintParams.get()

override fun execute() {
resetEditorconfigCacheIfNeeded(
changedEditorconfigFiles = parameters.changedEditorconfigFiles,
val ktLintEngine = createKtlintEngine(ktLintParams = ktLintParams)
ktLintEngine.resetEditorconfigCacheIfNeeded(
changedEditorconfigFiles = parameters.changedEditorConfigFiles,
logger = logger,
)

var hasError = false

try {
reporters.onEach { it.beforeAll() }
files.forEach { file ->
val ruleSets = resolveRuleProviders(defaultRuleSetProviders, ktLintParams.experimentalRules)
val relativePath = file.toRelativeString(projectDirectory)
reporters.onEach { it.before(relativePath) }
logger.debug("$name linting: $relativePath")
val lintFunc = when (file.extension) {
"kt" -> ::lintKt
"kts" -> ::lintKts
else -> {
logger.debug("$name ignoring non Kotlin file: $relativePath")
null
}

if (file.extension !in supportedExtensions) {
logger.debug("$name ignoring non Kotlin file: $relativePath")
return@forEach
}
lintFunc?.invoke(file, ruleSets) { error ->

ktLintEngine.lint(Code.CodeFile(file)) { error ->
hasError = true
reporters.onEach { reporter ->
// some reporters want relative paths, some want absolute
Expand All @@ -72,24 +67,6 @@ abstract class LintWorkerAction : WorkAction<LintWorkerParameters> {
throw LintFailure("kotlin source failed lint check")
}
}

private fun lintKt(file: File, ruleSets: Set<RuleProvider>, onError: (error: LintError) -> Unit) =
lint(file, ruleSets, onError, false)

private fun lintKts(file: File, ruleSets: Set<RuleProvider>, onError: (error: LintError) -> Unit) =
lint(file, ruleSets, onError, true)

private fun lint(file: File, ruleProviders: Set<RuleProvider>, onError: ErrorHandler, script: Boolean) =
KtLint.lint(
KtLint.ExperimentalParams(
fileName = file.path,
text = file.readText(),
ruleProviders = ruleProviders,
script = script,
editorConfigOverride = editorConfigOverride(ktLintParams),
cb = { error, _ -> onError(error) },
),
)
}

typealias ErrorHandler = (error: LintError) -> Unit
private val supportedExtensions = setOf("kt", "kts")
Expand Up @@ -10,7 +10,7 @@ import java.io.File

interface LintWorkerParameters : WorkParameters {
val name: Property<String>
val changedEditorconfigFiles: ConfigurableFileCollection
val changedEditorConfigFiles: ConfigurableFileCollection
val files: ConfigurableFileCollection
val projectDirectory: RegularFileProperty
val reporters: MapProperty<String, File>
Expand Down
Expand Up @@ -60,7 +60,7 @@ internal class EditorConfigTest : WithGradleTest.Kotlin() {
// language=editorconfig
"""
[*.{kt,kts}]
ktlint_disabled_rules = filename
ktlint_standard_filename = disabled
""".trimIndent(),
)
}
Expand Down Expand Up @@ -111,7 +111,7 @@ internal class EditorConfigTest : WithGradleTest.Kotlin() {
// language=editorconfig
"""
[*.{kt,kts}]
ktlint_disabled_rules = filename
ktlint_standard_filename = disabled
""".trimIndent(),
)
}
Expand Down Expand Up @@ -164,7 +164,7 @@ internal class EditorConfigTest : WithGradleTest.Kotlin() {
// language=editorconfig
"""
[*.{kt,kts}]
ktlint_disabled_rules = filename
ktlint_standard_filename = disabled
""".trimIndent(),
)
}
Expand Down

0 comments on commit 27ab24e

Please sign in to comment.