From cfc1f871c78e1ea6e84cf805566fde8eadb1051c Mon Sep 17 00:00:00 2001 From: Nacho Lopez Date: Sun, 10 Sep 2023 12:29:51 +0200 Subject: [PATCH] Update ktlint to 1.0.0 (#94) * Update ktlint to 1.0.0 Due to the reasons exposed in https://github.com/pinterest/ktlint/pull/2044/, this is not trivial - we need to rewrite the fixes manually or remove them altogether. Not being able to rely on the embedded kotlin compiler plugin for this is less than ideal, I wanted to stay away from ASTNode as much as possible :( TODO: - [x] Fix spotless version - [x] Fix ViewModelInjection autofix - [x] Fix PreviewPublic autofix * Fix ComposePreviewPublic autofix * Use ASTNode for ComposeViewModelInjection autofix --- build.gradle | 4 +++- gradle/libs.versions.toml | 2 +- .../compose/rules/ComposePreviewPublic.kt | 11 +++++++++- .../rules/ComposeViewModelInjection.kt | 22 ++++++++++++++++--- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index c4924f6b..c24d1fd5 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,9 @@ subprojects { spotless { kotlin { target "**/*.kt" - ktlint(libs.versions.ktlint.get()) + // ktlint(libs.versions.ktlint.get()) + ktlint("0.50.0") + licenseHeaderFile rootProject.file('spotless/copyright.txt') } groovyGradle { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 22c58873..d79ae4fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "1.9.10" -ktlint = "0.50.0" +ktlint = "1.0.0" detekt = "1.23.1" junit = "5.10.0" diff --git a/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposePreviewPublic.kt b/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposePreviewPublic.kt index 24dd519d..4a568b5d 100644 --- a/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposePreviewPublic.kt +++ b/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposePreviewPublic.kt @@ -4,7 +4,9 @@ package io.nlopez.compose.rules import io.nlopez.rules.core.ComposeKtVisitor import io.nlopez.rules.core.Emitter +import io.nlopez.rules.core.util.firstChildLeafOrSelf import io.nlopez.rules.core.util.isPreview +import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.psiUtil.isPublic @@ -19,7 +21,14 @@ class ComposePreviewPublic : ComposeKtVisitor { emitter.report(function, ComposablesPreviewShouldNotBePublic, true) if (autoCorrect) { - function.addModifier(KtTokens.PRIVATE_KEYWORD) + // Ideally if the kotlin embeddable compiler exposes what we need, this would be it: + // function.addModifier(KtTokens.PRIVATE_KEYWORD) + + // For now we need to do it by hand with ASTNode: find the "fun" modifier, and prepend "private". + val node = function.node.findChildByType(KtTokens.FUN_KEYWORD) + ?.firstChildLeafOrSelf() as? LeafPsiElement + ?: return + node.rawReplaceWithText(KtTokens.PRIVATE_KEYWORD.value + " " + KtTokens.FUN_KEYWORD.value) } } diff --git a/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposeViewModelInjection.kt b/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposeViewModelInjection.kt index aa21002a..57221ed5 100644 --- a/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposeViewModelInjection.kt +++ b/rules/common/src/main/kotlin/io/nlopez/compose/rules/ComposeViewModelInjection.kt @@ -73,7 +73,13 @@ class ComposeViewModelInjection : ComposeKtVisitor { when { // If there are no parameters, we will insert the code directly - lastParameters.isEmpty() -> parameterList.addParameter(newParam) + lastParameters.isEmpty() -> { + // Ideally this should be: + // parameterList.addParameter(newParam) + // but since Kotlin 1.9 we can't use these methods without crashing. + (parameterList.node.lastChildLeafOrSelf() as LeafPsiElement) + .rawReplaceWithText("${newParam.text})") + } // If the last element is a function, we need to preserve the trailing lambda, so we will insert // the code before that last param lastParameters.last().typeReference?.typeElement is KtFunctionType -> { @@ -92,9 +98,19 @@ class ComposeViewModelInjection : ComposeKtVisitor { lastToken.rawReplaceWithText("${lastToken.text} $newCode,") } } - + // Add as the last parameter else -> { - parameterList.addParameter(newParam) + // Ideally this should just be: + // parameterList.addParameter(newParam) + // but since Kotlin 1.9 we can't use these methods without crashing. + + val hasTrailingComma = composable.valueParameters.last().node.nextCodeSibling()?.text == "," + // If it has a trailing comma, no need to add a new one + val preCommaIfNeeded = if (hasTrailingComma) "" else "," + // And if it has a trailing comma, we'll need to preserve that in the style + val trailingCommaIfNeeded = if (hasTrailingComma) "," else "" + (parameterList.node.lastChildLeafOrSelf() as LeafPsiElement) + .rawReplaceWithText("$preCommaIfNeeded${newParam.text}$trailingCommaIfNeeded)") } }