Skip to content

Commit

Permalink
Update KtLint to 0.48.1
Browse files Browse the repository at this point in the history
  • Loading branch information
lwasyl committed Jan 4, 2023
1 parent 10049e9 commit 2e3144e
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 101 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,8 +1,11 @@
package org.jmailen.gradle.kotlinter.support

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties
import com.pinterest.ktlint.core.KtLintRuleEngine
import com.pinterest.ktlint.core.api.EditorConfigOverride
import com.pinterest.ktlint.core.api.EditorConfigOverride.Companion.EMPTY_EDITOR_CONFIG_OVERRIDE
import com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty
import org.ec4j.core.model.PropertyType
import org.ec4j.core.model.PropertyType.PropertyValueParser.IDENTITY_VALUE_PARSER
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.ProjectLayout
import org.gradle.api.logging.Logger
Expand All @@ -12,20 +15,39 @@ internal fun editorConfigOverride(ktLintParams: KtLintParams): EditorConfigOverr
val rules = ktLintParams.disabledRules

return if (rules.isEmpty()) {
EditorConfigOverride.emptyEditorConfigOverride
EMPTY_EDITOR_CONFIG_OVERRIDE
} 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()
.toTypedArray()
.let { EditorConfigOverride.from(*it) }
}
}

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

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(KtLint::reloadEditorConfigFile)
changedFiles.map(File::toPath).forEach(::reloadEditorConfigFile)
}
}

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,8 +1,6 @@
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.KtLintRuleEngine
import org.gradle.api.logging.LogLevel
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
Expand All @@ -26,40 +24,40 @@ abstract class FormatWorkerAction : WorkAction<FormatWorkerParameters> {
private val output: File? = parameters.output.asFile.orNull

override fun execute() {
resetEditorconfigCacheIfNeeded(
val ktLintEngine = KtLintRuleEngine(
ruleProviders = resolveRuleProviders(defaultRuleSetProviders, ktLintParams.experimentalRules),
editorConfigOverride = editorConfigOverride(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(file.toPath()) { 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 +71,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,9 +1,7 @@
package org.jmailen.gradle.kotlinter.tasks.lint

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.KtLintRuleEngine
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
Expand Down Expand Up @@ -31,28 +29,30 @@ abstract class LintWorkerAction : WorkAction<LintWorkerParameters> {
private val ktLintParams: KtLintParams = parameters.ktLintParams.get()

override fun execute() {
resetEditorconfigCacheIfNeeded(
changedEditorconfigFiles = parameters.changedEditorconfigFiles,
val ktLintEngine = KtLintRuleEngine(
ruleProviders = resolveRuleProviders(defaultRuleSetProviders, ktLintParams.experimentalRules),
editorConfigOverride = editorConfigOverride(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(file.toPath()) { error ->
hasError = true
reporters.onEach { reporter ->
// some reporters want relative paths, some want absolute
Expand All @@ -72,24 +72,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
Expand Up @@ -84,14 +84,21 @@ internal class ExtensionTest : WithGradleTest.Kotlin() {
val script =
"""
kotlinter {
disabledRules = ["filename"]
experimentalRules = true
disabledRules = ["filename", "experimental:unnecessary-parentheses-before-trailing-lambda"]
}
""".trimIndent()
appendText(script)
}
projectRoot.resolve("src/main/kotlin/FileName.kt") {
writeText(kotlinClass("DifferentClassName"))
}
projectRoot.resolve("src/main/kotlin/UnnecessaryParentheses.kt") {
writeText("""
val failing = "should not have '()'".count() { it == 'x' }
""".trimIndent())
}

build("lintKotlin").apply {
assertEquals(TaskOutcome.SUCCESS, task(":lintKotlinMain")?.outcome)
Expand Down
Expand Up @@ -55,6 +55,38 @@ internal class KotlinProjectTest : WithGradleTest.Kotlin() {
}
}

@Test
fun `lintKotlinMain fails when lint errors for experimental rules are detected`() {
settingsFile()
buildFile()

buildFile.appendText(
"""
kotlinter {
experimentalRules = true
}
""".trimIndent(),
)

kotlinSourceFile(
"ExperimentalRuleViolations.kt",
"""
val variable = "should not contain '()'".count() { it == 'x' }
""".trimIndent(),
)

buildAndFail("lintKotlinMain").apply {
assertTrue(output.contains(".*ExperimentalRuleViolation.kt.* Lint error > \\[.*] Empty parentheses \"\\{\"".toRegex()))
output.lines().filter { it.contains("Lint error") }.forEach { line ->
val filePath = pathPattern.find(line)?.groups?.get(1)?.value.orEmpty()
assertTrue(File(filePath).exists())
}
assertEquals(FAILED, task(":lintKotlinMain")?.outcome)
}
}

@Test
fun `lintKotlinMain succeeds when no lint errors detected`() {
settingsFile()
Expand Down
@@ -1,12 +1,13 @@
package org.jmailen.gradle.kotlinter.support

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.KtLintRuleEngine
import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.RuleProvider
import com.pinterest.ktlint.core.RuleSetProviderV2
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.io.File

class RuleSetsTest {

Expand Down Expand Up @@ -34,10 +35,11 @@ class RuleSetsTest {

@Test
fun `test compatibility`() {
KtLint.lint(
KtLint.ExperimentalParams(
fileName = "/tmp/src/test/KotlinClass.kt",
text = """
KtLintRuleEngine(
ruleProviders = resolveRuleProviders(defaultRuleSetProviders),
).lint(
filePath = File("/tmp/src/test/KotlinClass.kt").toPath(),
code = """
package test
class KotlinClass {
Expand All @@ -46,10 +48,8 @@ class RuleSetsTest {
}
}
""".trimIndent(),
ruleProviders = resolveRuleProviders(defaultRuleSetProviders),
cb = { _, _ -> },
),
""".trimIndent(),
callback = { _ -> },
)
}
}
Expand Down

0 comments on commit 2e3144e

Please sign in to comment.