Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to KtLint 0.48.2 #1571

Merged
merged 42 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
cf19276
Add `experimental`, `test`, and `custom` to the list of ignored rule …
0x6675636b796f75676974687562 Nov 16, 2022
b8f4350
Builder to run Diktat (#1562)
nulls Nov 16, 2022
a2ba01a
Migrate to the new rule set API (#1570)
0x6675636b796f75676974687562 Nov 18, 2022
9a9e768
Add main for diktat.jar (#1566)
nulls Dec 6, 2022
134a6e4
Migration is in progress
nulls Mar 13, 2023
0597736
WIP
nulls Mar 13, 2023
76ee541
WIP #2
nulls Mar 14, 2023
78adb2a
WIP
nulls Mar 14, 2023
2f635b8
reverted changes related to codegen
nulls Mar 15, 2023
ea78576
Extract common integration test code (#1629)
0x6675636b796f75676974687562 Mar 16, 2023
10359a0
Merge remote-tracking branch 'origin/master' into feature/ktlint-wrapper
nulls Mar 24, 2023
f8eb5c7
Merge branch 'feature/ktlint-0.48.2' into feature/ktlint-wrapper
nulls Mar 27, 2023
2ff1a1f
diktatFix
nulls Mar 27, 2023
c421595
Merge branch 'master' into feature/ktlint-wrapper
nulls Mar 27, 2023
efeaad0
Merge branch 'master' into feature/ktlint-wrapper
nulls Mar 27, 2023
4696d73
fix merge issues
nulls Mar 27, 2023
75592fc
Merge remote-tracking branch 'origin/master' into feature/ktlint-wrapper
nulls Mar 30, 2023
a2e17aa
supported changes from master
nulls Mar 30, 2023
f52f1ee
suppress unused
nulls Mar 30, 2023
66144de
Merge remote-tracking branch 'origin/master' into feature/ktlint-wrapper
nulls Mar 30, 2023
0ab27fb
supported changed after merge
nulls Mar 30, 2023
c9e4bbc
diktatFix
nulls Mar 30, 2023
2ca20bd
diktatFix & detektAll
nulls Mar 30, 2023
3197715
refactored tests
nulls Mar 30, 2023
e3a78e9
Merge remote-tracking branch 'origin/master' into feature/ktlint-wrapper
nulls Apr 5, 2023
9570c44
fixed merge issues
nulls Apr 5, 2023
bad26d0
fixed merge issues
nulls Apr 5, 2023
a32b06b
reused DiktatProcessor for ad-hook format and lint
nulls Apr 5, 2023
f369663
Merge remote-tracking branch 'origin/master' into feature/ktlint-wrapper
nulls Apr 6, 2023
9e02d9e
cleanup old code
nulls Apr 6, 2023
18f9be5
self review
nulls Apr 6, 2023
faf458f
Merge branch 'master' into feature/ktlint-wrapper
nulls Apr 6, 2023
7bd9a7a
fixed Baseline loading and Color importing in plain reporter + reusin…
nulls Apr 7, 2023
cb848c8
fixed condition in loading baseline
nulls Apr 7, 2023
bc9b330
formatting
nulls Apr 7, 2023
4630fc6
fixed file path
nulls Apr 7, 2023
57a1c34
fixed file path for snippets
nulls Apr 7, 2023
6d59816
fixed getting KtFile
nulls Apr 7, 2023
eb6406b
fixed Smoke tests
nulls Apr 7, 2023
7ec85c4
disabled ktlint's rule properly
nulls Apr 7, 2023
6a4bfcf
temp directory for Unix in the same way as for Windows
nulls Apr 7, 2023
128cf9f
fixed build_and_test.yml
nulls Apr 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# https://editorconfig.org
root = true

[*]
charset = utf-8
indent_size = 4
Expand Down Expand Up @@ -99,3 +102,9 @@ ij_kotlin_while_on_new_line = false
ij_kotlin_wrap_elvis_expressions = 1
ij_kotlin_wrap_expression_body_functions = 1
ij_kotlin_wrap_first_method_in_call_chain = false

# disable ktlint rules
ktlint_standard = disabled
ktlint_experimental = disabled
ktlint_test = disabled
ktlint_custom = disabled
2 changes: 1 addition & 1 deletion .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ jobs:
if: matrix.type == 'ktlint'
run: |
filename=$(ls -1 diktat-*.jar | head -n1)
echo DIKTAT_RUN="java -jar ktlint -R \"$filename\" --disabled_rules=standard,experimental,test,custom" >> $GITHUB_ENV
echo DIKTAT_RUN="java -jar ktlint -R \"$filename\"" >> $GITHUB_ENV
shell: bash

- name: Download diktat cli jar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import org.cqfn.diktat.api.DiktatProcessorListener
import org.cqfn.diktat.api.DiktatProcessorListener.Companion.closeAfterAllAsProcessorListener
import org.cqfn.diktat.ktlint.DiktatErrorImpl.Companion.wrap
import org.cqfn.diktat.ktlint.DiktatReporterImpl.Companion.wrap
import com.pinterest.ktlint.core.internal.loadBaseline
import com.pinterest.ktlint.core.api.Baseline
import com.pinterest.ktlint.core.api.loadBaseline
import com.pinterest.ktlint.reporter.baseline.BaselineReporter
import java.io.PrintStream
import java.nio.file.Path
Expand All @@ -16,17 +17,15 @@ import kotlin.io.path.outputStream
/**
* A factory to create or generate [DiktatBaseline] using `KtLint`
*/
@Suppress("DEPRECATION")
class DiktatBaselineFactoryImpl : DiktatBaselineFactory {
override fun tryToLoad(
baselineFile: Path,
sourceRootDir: Path,
): DiktatBaseline? = loadBaseline(baselineFile.absolutePathString())
.takeUnless { it.baselineGenerationNeeded }
.takeIf { it.status == Baseline.Status.VALID }
?.let { ktLintBaseline ->
DiktatBaseline { file ->
ktLintBaseline.baselineRules
?.get(file.relativePathStringTo(sourceRootDir))
ktLintBaseline.lintErrorsPerFile[file.relativePathStringTo(sourceRootDir)]
.orEmpty()
.map { it.wrap() }
.toSet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,56 @@ import org.cqfn.diktat.DiktatProcessorFactory
import org.cqfn.diktat.api.DiktatCallback
import org.cqfn.diktat.api.DiktatRuleSet
import org.cqfn.diktat.ktlint.DiktatErrorImpl.Companion.wrap
import org.cqfn.diktat.ktlint.KtLintRuleSetWrapper.Companion.toKtLint
import org.cqfn.diktat.util.isKotlinScript

import com.pinterest.ktlint.core.KtLint
import org.cqfn.diktat.ktlint.KtLintRuleWrapper.Companion.toKtLint
import com.pinterest.ktlint.core.Code
import com.pinterest.ktlint.core.KtLintRuleEngine
import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.api.EditorConfigOverride

import java.nio.charset.StandardCharsets
import java.nio.file.Path

import kotlin.io.path.absolutePathString
import kotlin.io.path.readText

private typealias KtLintCallback = (LintError, Boolean) -> Unit
private typealias FormatCallback = (LintError, Boolean) -> Unit
private typealias LintCallback = (LintError) -> Unit

/**
* A factory to create [DiktatProcessor] using [DiktatProcessorFactory] and `KtLint` as engine
*/
class DiktatProcessorFactoryImpl : DiktatProcessorFactory {
override fun invoke(diktatRuleSet: DiktatRuleSet): DiktatProcessor = object : DiktatProcessor {
override fun fix(file: Path, callback: DiktatCallback): String = KtLint.format(file.toKtLintParams(diktatRuleSet, callback))
override fun fix(
code: String,
isScript: Boolean,
callback: DiktatCallback
): String = KtLint.format(code.toKtLintParams(isScript, diktatRuleSet, callback))
override fun check(file: Path, callback: DiktatCallback) = KtLint.lint(file.toKtLintParams(diktatRuleSet, callback))
override fun check(
code: String,
isScript: Boolean,
callback: DiktatCallback
) = KtLint.lint(code.toKtLintParams(isScript, diktatRuleSet, callback))
override fun invoke(diktatRuleSet: DiktatRuleSet): DiktatProcessor {
val ktLintRuleEngine = diktatRuleSet.toKtLintEngine()
return object : DiktatProcessor {
override fun fix(
file: Path,
callback: DiktatCallback,
): String = ktLintRuleEngine.format(file.toKtLint(), callback.toKtLintForFormat())
override fun fix(
code: String,
isScript: Boolean,
callback: DiktatCallback
): String = ktLintRuleEngine.format(code.toKtLint(isScript), callback.toKtLintForFormat())
override fun check(
file: Path,
callback: DiktatCallback,
) = ktLintRuleEngine.lint(file.toKtLint(), callback.toKtLintForLint())
override fun check(
code: String,
isScript: Boolean,
callback: DiktatCallback
) = ktLintRuleEngine.lint(code.toKtLint(isScript), callback.toKtLintForLint())
}
}

companion object {
private fun Path.toKtLintParams(
diktatRuleSet: DiktatRuleSet,
callback: DiktatCallback,
): KtLint.ExperimentalParams = ktLintParams(
fileName = absolutePathString(),
text = readText(StandardCharsets.UTF_8).replace("\r\n", "\n").replace("\r", "\n"),
isScript = isKotlinScript(),
diktatRuleSet = diktatRuleSet,
callback = callback,
)
private fun DiktatRuleSet.toKtLintEngine(): KtLintRuleEngine = KtLintRuleEngine(ruleProviders = toKtLint())

private fun String.toKtLintParams(
isScript: Boolean,
diktatRuleSet: DiktatRuleSet,
callback: DiktatCallback,
): KtLint.ExperimentalParams = ktLintParams(
fileName = if (isScript) "test.kts" else "test.kt",
text = this,
isScript = isScript,
diktatRuleSet = diktatRuleSet,
callback = callback,
)
private fun Path.toKtLint(): Code = Code.CodeFile(this.toFile())

private fun ktLintParams(
fileName: String,
text: String,
isScript: Boolean,
diktatRuleSet: DiktatRuleSet,
callback: DiktatCallback,
): KtLint.ExperimentalParams = KtLint.ExperimentalParams(
fileName = fileName,
text = text,
ruleSets = setOf(diktatRuleSet.toKtLint()),
userData = emptyMap(),
cb = callback.toKtLint(),
script = isScript,
editorConfigPath = null,
debug = false, // we do not use it
editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride,
isInvokedFromCli = false
)
private fun String.toKtLint(isScript: Boolean): Code = Code.CodeSnippet(this, isScript)

private fun DiktatCallback.toKtLint(): KtLintCallback = { error, isCorrected ->
private fun DiktatCallback.toKtLintForFormat(): FormatCallback = { error, isCorrected ->
this(error.wrap(), isCorrected)
}

private fun DiktatCallback.toKtLintForLint(): LintCallback = { error ->
this(error.wrap(), false)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import com.pinterest.ktlint.core.ReporterProvider
import com.pinterest.ktlint.reporter.checkstyle.CheckStyleReporterProvider
import com.pinterest.ktlint.reporter.html.HtmlReporterProvider
import com.pinterest.ktlint.reporter.json.JsonReporterProvider
import com.pinterest.ktlint.reporter.plain.Color
import com.pinterest.ktlint.reporter.plain.PlainReporterProvider
import com.pinterest.ktlint.reporter.plain.internal.Color
import com.pinterest.ktlint.reporter.sarif.SarifReporterProvider
import java.io.OutputStream
import java.io.PrintStream
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.cqfn.diktat.ktlint

import org.cqfn.diktat.api.DiktatRule
import org.cqfn.diktat.api.DiktatRuleSet
import org.cqfn.diktat.common.config.rules.DIKTAT_RULE_SET_ID
import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.RuleProvider
import org.jetbrains.kotlin.com.intellij.lang.ASTNode

private typealias EmitType = (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit
Expand All @@ -18,17 +20,26 @@ class KtLintRuleWrapper(
id = rule.id.qualifiedWithRuleSetId(DIKTAT_RULE_SET_ID),
visitorModifiers = createVisitorModifiers(rule, prevRule),
) {
@Deprecated(
"Marked for deletion in ktlint 0.48.0",
replaceWith = ReplaceWith("beforeVisitChildNodes(node, autoCorrect, emit)"),
)
override fun visit(
override fun beforeVisitChildNodes(
node: ASTNode,
autoCorrect: Boolean,
emit: EmitType,
) = rule.invoke(node, autoCorrect, emit)

companion object {
private fun Sequence<DiktatRule>.wrapRules(): Sequence<Rule> = runningFold(null as KtLintRuleWrapper?) { prevRule, diktatRule ->
KtLintRuleWrapper(diktatRule, prevRule)
}.filterNotNull()

/**
* @return [Set] of __KtLint__'s [RuleProvider]s created from [DiktatRuleSet]
*/
fun DiktatRuleSet.toKtLint(): Set<RuleProvider> = rules
.asSequence()
.wrapRules()
.map { it.asProvider() }
.toSet()

private fun createVisitorModifiers(
rule: DiktatRule,
prevRule: KtLintRuleWrapper?,
Expand All @@ -51,5 +62,10 @@ class KtLintRuleWrapper(
* @return a rule to which a logic is delegated
*/
internal fun Rule.unwrap(): DiktatRule = (this as? KtLintRuleWrapper)?.rule ?: error("Provided rule ${javaClass.simpleName} is not wrapped by diktat")

/**
* @return wraps [Rule] to [RuleProvider]
*/
internal fun Rule.asProvider(): RuleProvider = RuleProvider { this }
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package org.cqfn.diktat.ktlint

import com.pinterest.ktlint.core.Code
import com.pinterest.ktlint.core.KtLintRuleEngine
import org.cqfn.diktat.api.DiktatErrorEmitter
import org.cqfn.diktat.api.DiktatRule
import org.cqfn.diktat.api.DiktatRuleSet
import org.cqfn.diktat.ktlint.KtLintRuleSetWrapper.Companion.toKtLint
import org.cqfn.diktat.ktlint.KtLintRuleWrapper.Companion.toKtLint
import org.cqfn.diktat.ktlint.KtLintRuleWrapper.Companion.unwrap
import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.RuleProvider
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

class KtLintRuleSetWrapperTest {
class KtLintRuleWrapperTest {
@Test
fun `check KtLintRuleSetWrapper with duplicate`() {
val rule = mockRule("rule")
Expand All @@ -27,12 +29,12 @@ class KtLintRuleSetWrapperTest {
val rule1 = mockRule(id = "rule-first")
val rule2 = mockRule(id = "rule-second")

val orderedRuleSet = DiktatRuleSet(listOf(rule1, rule2)).toKtLint()
val orderedRuleProviders = DiktatRuleSet(listOf(rule1, rule2)).toKtLint()

val orderedRuleSetIterator = orderedRuleSet.rules.iterator()
val orderedRule1 = orderedRuleSetIterator.next()
val orderedRule2 = orderedRuleSetIterator.next()
Assertions.assertFalse(orderedRuleSetIterator.hasNext(), "Extra elements after ordering")
val orderedRuleProviderIterator = orderedRuleProviders.iterator()
val orderedRule1 = orderedRuleProviderIterator.next().createNewRuleInstance()
val orderedRule2 = orderedRuleProviderIterator.next().createNewRuleInstance()
Assertions.assertFalse(orderedRuleProviderIterator.hasNext(), "Extra elements after ordering")

Assertions.assertEquals(rule1, orderedRule1.unwrap(), "First rule is modified")

Expand Down Expand Up @@ -74,18 +76,18 @@ class KtLintRuleSetWrapperTest {
/*
* Make sure OrderedRuleSet preserves the order.
*/
val ruleSet = DiktatRuleSet(rules).toKtLint()
assertThat(ruleSet.rules.map(Rule::id)).containsExactlyElementsOf(rules.map(DiktatRule::id).map { it.qualifiedWithRuleSetId() })
val ruleProviders = DiktatRuleSet(rules).toKtLint()
assertThat(ruleProviders.map(RuleProvider::createNewRuleInstance).map(Rule::id))
.containsExactlyElementsOf(rules.map(DiktatRule::id).map { it.qualifiedWithRuleSetId() })

@Language("kotlin")
val code = "fun foo() { }"

KtLint.lint(
KtLint.ExperimentalParams(
fileName = "TestFileName.kt",
text = code,
ruleSets = listOf(ruleSet),
cb = { _, _ -> },
KtLintRuleEngine(
ruleProviders = ruleProviders
).lint(
code = Code.CodeSnippet(
content = code
)
)

Expand Down Expand Up @@ -123,20 +125,13 @@ class KtLintRuleSetWrapperTest {
* |
* V
* C(File) -> C(Node) -> C(Leaf)
*
* val expectedRuleInvocationOrder = rules.asSequence()
* .map(Rule::id)
* .flatMap { ruleId ->
* generateSequence { ruleId }.take(astNodeCount)
* }
* .toList()
*/
val expectedRuleInvocationOrder = generateSequence {
rules.map(DiktatRule::id)
}
.take(astNodeCount)
.flatten()
.toList()
val expectedRuleInvocationOrder = rules.asSequence()
.map(DiktatRule::id)
.flatMap { ruleId ->
generateSequence { ruleId }.take(astNodeCount)
}
.toList()

assertThat(actualRuleInvocationOrder)
.containsExactlyElementsOf(expectedRuleInvocationOrder)
Expand Down
Loading