Skip to content

Commit

Permalink
Clear ktlint caches when .editorconfig changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszkwiecinski committed Jun 27, 2022
1 parent 08fdfac commit a88d650
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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.EditorConfigOverride
import org.gradle.api.file.ProjectLayout
import org.gradle.api.logging.Logger
import org.gradle.api.provider.Property
import java.io.File

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

return if (rules.isEmpty()) {
EditorConfigOverride.emptyEditorConfigOverride
} else {
EditorConfigOverride.from(DefaultEditorConfigProperties.disabledRulesProperty to rules.joinToString(separator = ","))
}
}

internal fun resetEditorconfigCacheIfNeeded(
wasEditorConfigChanged: Property<Boolean>,
logger: Logger,
) {
if (wasEditorConfigChanged.get()) {
logger.info("Editorconfig changed, resetting KtLint caches")
KtLint.trimMemory() // Calling trimMemory() will also reset internal loaded `.editorconfig` cache
}
}

internal fun ProjectLayout.findApplicableEditorConfigFiles(): Sequence<File> {
val projectEditorConfig = projectDirectory.file(".editorconfig").asFile

return generateSequence(seed = projectEditorConfig) { editorconfig ->
if (editorconfig.isRootEditorConfig) {
null
} else {
editorconfig.parentFile?.parentFile?.resolve(".editorconfig")
}
}
}

private val File.isRootEditorConfig: Boolean
get() {
if (!isFile || !canRead()) return false

return useLines { lines ->
lines.any { line -> line.matches(editorConfigRootRegex) }
}
}

/**
* According to https://editorconfig.org/ root-most EditorConfig file contains line with `root=true`
*/
private val editorConfigRootRegex = "^root\\s?=\\s?true".toRegex()

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.SourceTask
import org.gradle.internal.exceptions.MultiCauseException
import org.gradle.work.Incremental
import org.gradle.work.InputChanges
import org.jmailen.gradle.kotlinter.KotlinterExtension.Companion.DEFAULT_DISABLED_RULES
import org.jmailen.gradle.kotlinter.KotlinterExtension.Companion.DEFAULT_EXPERIMENTAL_RULES
import org.jmailen.gradle.kotlinter.support.KtLintParams
import org.jmailen.gradle.kotlinter.support.findApplicableEditorConfigFiles

abstract class ConfigurableKtLintTask(
projectLayout: ProjectLayout,
Expand All @@ -30,6 +33,7 @@ abstract class ConfigurableKtLintTask(

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:Incremental
internal val editorconfigFiles: FileCollection = objectFactory.fileCollection().apply {
from(projectLayout.findApplicableEditorConfigFiles().toList())
}
Expand All @@ -39,6 +43,9 @@ abstract class ConfigurableKtLintTask(
experimentalRules = experimentalRules.get(),
disabledRules = disabledRules.get()
)

protected fun wasEditorconfigChanged(inputChanges: InputChanges) =
inputChanges.isIncremental && inputChanges.getFileChanges(editorconfigFiles).any()
}

internal inline fun <reified T> ObjectFactory.property(default: T? = null): Property<T> =
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.gradle.api.model.ObjectFactory
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.work.InputChanges
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import org.jmailen.gradle.kotlinter.support.KotlinterError
Expand All @@ -31,14 +32,15 @@ open class FormatTask @Inject constructor(
}

@TaskAction
fun run() {
fun run(inputChanges: InputChanges) {
val result = with(workerExecutor.noIsolation()) {
submit(FormatWorkerAction::class.java) { p ->
p.name.set(name)
p.files.from(source)
p.projectDirectory.set(projectLayout.projectDirectory.asFile)
p.ktLintParams.set(getKtLintParams())
p.output.set(report)
p.wasEditorConfigChanged.set(wasEditorconfigChanged(inputChanges))
}
runCatching { await() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.work.InputChanges
import org.gradle.workers.WorkerExecutor
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import org.jmailen.gradle.kotlinter.KotlinterExtension.Companion.DEFAULT_IGNORE_FAILURES
Expand Down Expand Up @@ -43,14 +44,15 @@ open class LintTask @Inject constructor(
val ignoreFailures: Property<Boolean> = objectFactory.property(default = DEFAULT_IGNORE_FAILURES)

@TaskAction
fun run() {
fun run(inputChanges: InputChanges) {
val result = with(workerExecutor.noIsolation()) {
submit(LintWorkerAction::class.java) { p ->
p.name.set(name)
p.files.from(source)
p.projectDirectory.set(projectLayout.projectDirectory.asFile)
p.reporters.putAll(reports)
p.ktLintParams.set(getKtLintParams())
p.wasEditorConfigChanged.set(wasEditorconfigChanged(inputChanges))
}
runCatching { await() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ 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.resetEditorconfigCacheIfNeeded
import org.jmailen.gradle.kotlinter.support.resolveRuleSets
import org.jmailen.gradle.kotlinter.tasks.FormatTask
import java.io.File
Expand All @@ -25,6 +26,11 @@ abstract class FormatWorkerAction : WorkAction<FormatWorkerParameters> {
private val output: File? = parameters.output.asFile.orNull

override fun execute() {
resetEditorconfigCacheIfNeeded(
wasEditorConfigChanged = parameters.wasEditorConfigChanged,
logger = logger,
)

val fixes = mutableListOf<String>()
try {
files.forEach { file ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.jmailen.gradle.kotlinter.support.KtLintParams

interface FormatWorkerParameters : WorkParameters {
val name: Property<String>
val wasEditorConfigChanged: Property<Boolean>
val files: ConfigurableFileCollection
val projectDirectory: RegularFileProperty
val ktLintParams: Property<KtLintParams>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.jmailen.gradle.kotlinter.support.defaultRuleSetProviders
import org.jmailen.gradle.kotlinter.support.editorConfigOverride
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.resolveRuleSets
import org.jmailen.gradle.kotlinter.tasks.LintTask
import java.io.File
Expand All @@ -30,6 +31,10 @@ abstract class LintWorkerAction : WorkAction<LintWorkerParameters> {
private val ktLintParams: KtLintParams = parameters.ktLintParams.get()

override fun execute() {
resetEditorconfigCacheIfNeeded(
wasEditorConfigChanged = parameters.wasEditorConfigChanged,
logger = logger,
)
var hasError = false

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import java.io.File

interface LintWorkerParameters : WorkParameters {
val name: Property<String>
val wasEditorConfigChanged: Property<Boolean>
val files: ConfigurableFileCollection
val projectDirectory: RegularFileProperty
val reporters: MapProperty<String, File>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.jmailen.gradle.kotlinter.functional.utils.kotlinClass
import org.jmailen.gradle.kotlinter.functional.utils.resolve
import org.jmailen.gradle.kotlinter.functional.utils.settingsFile
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
Expand Down Expand Up @@ -100,18 +101,59 @@ internal class EditorConfigTest : WithGradleTest.Kotlin() {
assertTrue(output.contains("[indent] Unexpected indentation (2) (should be 6)"))
}
}

@Test
fun `editorconfig changes are taken into account on task re-runs`() {
fun `editorconfig changes are taken into account on lint task re-runs`() {
projectRoot.resolve(".editorconfig") {
writeText(editorConfig)
writeText(
"""
[*.{kt,kts}]
disabled_rules=filename
""".trimIndent(),
)
}

projectRoot.resolve("src/main/kotlin/FileName.kt") {
writeText(kotlinClass("DifferentClassName"))
}
buildAndFail("lintKotlin").apply {
build("lintKotlin").apply {
assertEquals(TaskOutcome.SUCCESS, task(":lintKotlinMain")?.outcome)
assertFalse(output.contains("resetting KtLint caches"))
}

projectRoot.resolve(".editorconfig") {
writeText(editorConfig)
}
buildAndFail("lintKotlin", "--info").apply {
assertEquals(TaskOutcome.FAILED, task(":lintKotlinMain")?.outcome)
assertTrue(output.contains("[filename] File 'FileName.kt' contains a single top level declaration"))
assertTrue(output.contains("resetting KtLint caches"))
}

projectRoot.resolve("src/main/kotlin/FileName.kt") {
writeText(kotlinClass("FileName"))
}
build("lintKotlin").apply {
assertEquals(TaskOutcome.SUCCESS, task(":lintKotlinMain")?.outcome)
assertFalse(output.contains("resetting KtLint caches"))
}
build("lintKotlin").apply {
assertEquals(TaskOutcome.UP_TO_DATE, task(":lintKotlinMain")?.outcome)
assertFalse(output.contains("resetting KtLint caches"))
}
}

@Test
fun `editorconfig changes are ignored for format task re-runs`() {
projectRoot.resolve(".editorconfig") {
writeText(editorConfig)
}

projectRoot.resolve("src/main/kotlin/FileName.kt") {
writeText(kotlinClass("DifferentClassName"))
}
build("formatKotlin").apply {
assertEquals(TaskOutcome.SUCCESS, task(":formatKotlinMain")?.outcome)
assertTrue(output.contains("Format could not fix > [filename] File 'FileName.kt' contains a single top level declaration"))
}

projectRoot.resolve(".editorconfig") {
Expand All @@ -122,8 +164,10 @@ internal class EditorConfigTest : WithGradleTest.Kotlin() {
""".trimIndent(),
)
}
build("lintKotlin").apply {
assertEquals(TaskOutcome.SUCCESS, task(":lintKotlinMain")?.outcome)
build("formatKotlin", "--info").apply {
assertEquals(TaskOutcome.SUCCESS, task(":formatKotlinMain")?.outcome)
assertTrue(output.contains("Format could not fix"))
assertFalse(output.contains("resetting KtLint caches"))
}
}
}

0 comments on commit a88d650

Please sign in to comment.