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

Builder to run Diktat #1562

Merged
merged 11 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
2 changes: 1 addition & 1 deletion diktat-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
</dependency>
<dependency>
<groupId>org.cqfn.diktat</groupId>
<artifactId>diktat-rules</artifactId>
<artifactId>diktat</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

package org.cqfn.diktat.plugin.maven

import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
import org.cqfn.diktat.DiktatProcessCommand
import org.cqfn.diktat.api.DiktatLogLevel
import org.cqfn.diktat.ktlint.unwrap

import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.LintError
import com.pinterest.ktlint.core.Reporter
import com.pinterest.ktlint.core.RuleExecutionException
import com.pinterest.ktlint.core.RuleSet
import com.pinterest.ktlint.core.api.Baseline
import com.pinterest.ktlint.core.api.Baseline.Status.VALID
import com.pinterest.ktlint.core.api.containsLintError
Expand Down Expand Up @@ -98,9 +98,9 @@ abstract class DiktatBaseMojo : AbstractMojo() {
private lateinit var mavenSession: MavenSession

/**
* @param params instance of [KtLint.ExperimentalParams] used in analysis
* @param command instance of [DiktatProcessCommand] used in analysis
*/
abstract fun runAction(params: KtLint.ExperimentalParams)
abstract fun runAction(command: DiktatProcessCommand)

/**
* Perform code check using diktat ruleset
Expand All @@ -117,9 +117,6 @@ abstract class DiktatBaseMojo : AbstractMojo() {
if (excludes.isNotEmpty()) " and excluding $excludes" else ""
)

val ruleSets by lazy {
listOf(DiktatRuleSetProvider(configFile).get())
}
val baselineResults = baseline?.let { loadBaseline(it.absolutePath) }
?: Baseline(status = VALID)
reporterImpl = resolveReporter(baselineResults)
Expand All @@ -129,7 +126,7 @@ abstract class DiktatBaseMojo : AbstractMojo() {
inputs
.map(::File)
.forEach {
checkDirectory(it, lintErrors, baselineResults.lintErrorsPerFile, ruleSets)
checkDirectory(it, lintErrors, baselineResults.lintErrorsPerFile)
}

reporterImpl.afterAll()
Expand Down Expand Up @@ -201,8 +198,7 @@ abstract class DiktatBaseMojo : AbstractMojo() {
private fun checkDirectory(
directory: File,
lintErrors: MutableList<LintError>,
baselineRules: Map<String, List<LintError>>,
ruleSets: Iterable<RuleSet>
baselineRules: Map<String, List<LintError>>
) {
val (excludedDirs, excludedFiles) = excludes.map(::File).partition { it.isDirectory }
directory
Expand All @@ -222,8 +218,7 @@ abstract class DiktatBaseMojo : AbstractMojo() {
baselineRules.getOrDefault(
file.relativeTo(mavenProject.basedir.parentFile).invariantSeparatorsPath,
emptyList()
),
ruleSets
)
)
reporterImpl.after(file.absolutePath)
} catch (e: RuleExecutionException) {
Expand All @@ -233,26 +228,26 @@ abstract class DiktatBaseMojo : AbstractMojo() {
}
}

private fun checkFile(file: File,
lintErrors: MutableList<LintError>,
baselineErrors: List<LintError>,
ruleSets: Iterable<RuleSet>
private fun checkFile(
file: File,
lintErrors: MutableList<LintError>,
baselineErrors: List<LintError>
) {
val text = file.readText()
val params =
KtLint.ExperimentalParams(
fileName = file.absolutePath,
text = text,
ruleSets = ruleSets,
script = file.extension.equals("kts", ignoreCase = true),
cb = { lintError, isCorrected ->
if (!baselineErrors.containsLintError(lintError)) {
reporterImpl.onLintError(file.absolutePath, lintError, isCorrected)
lintErrors.add(lintError)
}
},
debug = debug
val command = DiktatProcessCommand.Builder()
.file(file.toPath())
.fileContent(file.readText(Charsets.UTF_8))
.isScript(file.extension.equals("kts", ignoreCase = true))
.callback { error, isCorrected ->
val ktLintError = error.unwrap()
if (!baselineErrors.containsLintError(ktLintError)) {
reporterImpl.onLintError(file.absolutePath, ktLintError, isCorrected)
lintErrors.add(ktLintError)
}
}
.logLevel(
if (debug) DiktatLogLevel.DEBUG else DiktatLogLevel.INFO
)
runAction(params)
.build()
runAction(command)
0x6675636b796f75676974687562 marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

package org.cqfn.diktat.plugin.maven

import org.cqfn.diktat.DiktatProcessCommand
import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
import org.cqfn.diktat.ruleset.utils.ignoreCorrectedErrors

import com.pinterest.ktlint.core.KtLint
import org.apache.maven.plugins.annotations.Mojo

import java.io.File
import kotlin.io.path.absolutePathString
import kotlin.io.path.writeText

/**
* Main [Mojo] that call [DiktatRuleSetProvider]'s rules on [inputs] files
Expand All @@ -19,10 +18,10 @@ import java.io.File
@Suppress("unused")
class DiktatCheckMojo : DiktatBaseMojo() {
/**
* @param params instance of [KtLint.ExperimentalParams] used in analysis
* @param command instance of [DiktatProcessCommand] used in analysis
*/
override fun runAction(params: KtLint.ExperimentalParams) {
KtLint.lint(params)
override fun runAction(command: DiktatProcessCommand) {
command.check()
}
}

Expand All @@ -34,15 +33,15 @@ class DiktatCheckMojo : DiktatBaseMojo() {
@Suppress("unused")
class DiktatFixMojo : DiktatBaseMojo() {
/**
* @param params instance of [KtLint.Params] used in analysis
* @param command instance of [DiktatProcessCommand] used in analysis
*/
override fun runAction(params: KtLint.ExperimentalParams) {
val fileName = params.fileName
val fileContent = File(fileName).readText(charset("UTF-8"))
val formattedText = KtLint.format(params.ignoreCorrectedErrors())
override fun runAction(command: DiktatProcessCommand) {
val fileName = command.file.absolutePathString()
val fileContent = command.fileContent
val formattedText = command.fix()
if (fileContent != formattedText) {
log.info("Original and formatted content differ, writing to $fileName...")
File(fileName).writeText(formattedText, charset("UTF-8"))
command.file.writeText(formattedText, Charsets.UTF_8)
}
}
}
35 changes: 20 additions & 15 deletions diktat-ruleset/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<version>${project.version}</version>
<exclusions>
<!-- Kotlin runtime & libraries will be provided by ktlint executable -->
<!-- FIXME: should be removed after making diktat.jar as executable -->
<exclusion>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-common</artifactId>
Expand Down Expand Up @@ -47,27 +48,27 @@
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-common</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk7</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-compiler-embeddable</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down Expand Up @@ -98,6 +99,20 @@
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<source>src/main/java</source>
<source>src/main/kotlin</source>
<source>src/main/resources</source>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>process-test-sources</phase>
Expand All @@ -116,16 +131,6 @@
</execution>
</executions>
</plugin>
<plugin>
<!-- Disable build of default jar -->
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<!-- Build fat jar, overriding the primary jar -->
<groupId>org.apache.maven.plugins</groupId>
Expand Down
119 changes: 119 additions & 0 deletions diktat-ruleset/src/main/kotlin/org/cqfn/diktat/DiktatProcessCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.cqfn.diktat

import org.cqfn.diktat.api.DiktatCallback
import org.cqfn.diktat.api.DiktatLogLevel
import org.cqfn.diktat.ktlint.unwrap
import org.cqfn.diktat.ruleset.rules.DiktatRuleSetProvider
import com.pinterest.ktlint.core.KtLint
import com.pinterest.ktlint.core.api.EditorConfigDefaults
import com.pinterest.ktlint.core.api.EditorConfigOverride
import java.nio.file.Path
import kotlin.io.path.absolutePathString

/**
* Command to run `diktat`
*/
class DiktatProcessCommand private constructor(
val file: Path,
Fixed Show fixed Hide fixed
val fileContent: String,
Fixed Show fixed Hide fixed
private val callback: DiktatCallback,
private val isScript: Boolean,
private val logLevel: DiktatLogLevel,
) {
/**
* Run `diktat fix` using parameters from current command
*
* @return result of `diktat fix`
*/
fun fix(): String {
return KtLint.format(ktLintParams())
Fixed Show fixed Hide fixed
}

/**
* Run `diktat check` using parameters from current command
*/
fun check() {
KtLint.lint(ktLintParams())
}

@Suppress("DEPRECATION")
private fun ktLintParams(): KtLint.ExperimentalParams = KtLint.ExperimentalParams(
fileName = file.absolutePathString(),
text = fileContent,
ruleSets = setOf(DiktatRuleSetProvider().get()),
ruleProviders = emptySet(),
userData = emptyMap(),
cb = callback.unwrap(),
script = isScript,
editorConfigPath = null,
debug = logLevel == DiktatLogLevel.DEBUG,
editorConfigDefaults = EditorConfigDefaults.emptyEditorConfigDefaults,
editorConfigOverride = EditorConfigOverride.emptyEditorConfigOverride,
isInvokedFromCli = false
)

/**
* Builder for [DiktatProcessCommand]
*
* @property file
* @property fileContent
* @property callback
* @property isScript
*/
data class Builder(
var file: Path? = null,
var fileContent: String? = null,
var callback: DiktatCallback? = null,
var isScript: Boolean? = null,
var logLevel: DiktatLogLevel = DiktatLogLevel.INFO,
Fixed Show fixed Hide fixed
) {
/**
* @param file
* @return updated builder
*/
fun file(file: Path) = apply { this.file = file }

/**
* @param fileContent
* @return updated builder
*/
fun fileContent(fileContent: String) = apply { this.fileContent = fileContent }

/**
* @param callback
* @return updated builder
*/
fun callback(callback: DiktatCallback) = apply { this.callback = callback }

/**
* @param isScript
* @return updated builder
*/
fun isScript(isScript: Boolean) = apply { this.isScript = isScript }

/**
* @param logLevel
* @return updated builder
*/
fun logLevel(logLevel: DiktatLogLevel) = apply { this.logLevel = logLevel }

/**
* @return built [DiktatProcessCommand]
*/
fun build() = DiktatProcessCommand(
requireNotNull(file) {
"file is required"
},
requireNotNull(fileContent) {
"fileContent is required"
},
requireNotNull(callback) {
"callback is required"
},
requireNotNull(isScript) {
"isScript is required"
},
logLevel,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.cqfn.diktat.api

import java.util.function.BiConsumer
0x6675636b796f75676974687562 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Callback for diktat process
0x6675636b796f75676974687562 marked this conversation as resolved.
Show resolved Hide resolved
*/
@FunctionalInterface
fun interface DiktatCallback : BiConsumer<DiktatError, Boolean> {
/**
* Performs this callback on the given [error] taking into account [isCorrected] flag.
*
* @param error the error found by diktat
* @param isCorrected true if the error fixed by diktat
*/
override fun accept(error: DiktatError, isCorrected: Boolean)
}
Loading