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

Diktat CLI runner #1653

Merged
merged 37 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e884d00
### What's done:
nulls Mar 30, 2023
bbc78fb
### What's done:
nulls Mar 31, 2023
a96d996
fixed import in diktat-runner-cli
nulls Mar 31, 2023
b188481
fixed reporter creation
nulls Mar 31, 2023
3ff383a
WIP
nulls Mar 31, 2023
57be974
extracted plain reporter to a dedicated function in factory
nulls Apr 3, 2023
fee0e51
moved all ktlint to diktat-runner-ktlint-engine
nulls Apr 3, 2023
019395b
fixed DiktatMain
nulls Apr 3, 2023
2a697d1
fixed `loggerWithKtlintConfig`
nulls Apr 3, 2023
61f1103
renaming
nulls Apr 3, 2023
001781d
Merge remote-tracking branch 'origin/master' into feature/diktat-cli
nulls Apr 3, 2023
f0a1c3e
fixed renaming
nulls Apr 3, 2023
3bd0aff
Merge remote-tracking branch 'origin/master' into feature/diktat-cli
nulls Apr 5, 2023
0ca2da5
reverted unwanted changes
nulls Apr 5, 2023
d87a462
fixed DiktatMain to use a new DiktatRunner
nulls Apr 5, 2023
93d16b6
diktatFix
nulls Apr 5, 2023
bbe9ac9
fixed --version and --license
nulls Apr 5, 2023
fcd27bf
fixed --license
nulls Apr 5, 2023
57129b1
supported test using diktat-cli
nulls Apr 5, 2023
fc1203f
fixed checking condition in github's matrix
nulls Apr 5, 2023
f4abea8
fixed build of diktat-cli
nulls Apr 5, 2023
10f8efa
added dependency to diktat-api explicitly
nulls Apr 5, 2023
2f3369b
fixed clash in file name
nulls Apr 5, 2023
8751906
fixed absolute path resolving
nulls Apr 5, 2023
f47e211
fixed absolute path resolving
nulls Apr 5, 2023
863c956
matching by two globs
nulls Apr 5, 2023
484edc1
diktatFix
nulls Apr 5, 2023
32af2fd
added test for glob walker
nulls Apr 5, 2023
09d905e
review notes
nulls Apr 6, 2023
16ae41b
added a debug code
nulls Apr 6, 2023
64a1f22
Merge remote-tracking branch 'origin/master' into feature/diktat-cli
nulls Apr 6, 2023
be77b21
fixed running on Windows
nulls Apr 6, 2023
ba07c84
added more debug info
nulls Apr 6, 2023
b779464
added debug print for all cases
nulls Apr 6, 2023
ec7162b
moved debug print to tests
nulls Apr 6, 2023
031d03b
fixed test on MacOs + updated debug info
nulls Apr 6, 2023
0183ae1
cleanup debug
nulls Apr 6, 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
48 changes: 37 additions & 11 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,20 @@ jobs:
name: gradle-reports
path: '**/build/reports/'
retention-days: 1
- name: Upload diktat jar
- name: Upload diktat-ruleset jar
uses: actions/upload-artifact@v3
with:
name: diktat-ruleset
path: diktat-ruleset/build/libs/diktat-*.jar
# no need to store artifact longer, it is used only by dependant jobs
retention-days: 1
- name: Upload diktat-cli jar
uses: actions/upload-artifact@v3
with:
name: diktat-cli
path: diktat-cli/build/libs/diktat-cli-*.jar
# no need to store artifact longer, it is used only by dependant jobs
retention-days: 1
- name: Code coverage report
uses: codecov/codecov-action@v3
with:
Expand All @@ -77,37 +84,55 @@ jobs:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
java-version: [8, 11]
type: [ ktlint, cli ]

steps:
- uses: actions/checkout@v3

- name: Retrieve Ktlint version
if: matrix.type == 'ktlint'
run: |
ktlint_version=$(cat gradle/libs.versions.toml | grep '^ktlint =' | awk -F'[=]' '{print $2}' | tr -d '" ')
echo KTLINT_VERSION=$ktlint_version >> $GITHUB_ENV
shell: bash

- name: Setup environment
if: matrix.type == 'ktlint'
run: |
curl -o ktlint -sSL https://github.com/pinterest/ktlint/releases/download/${{ env.KTLINT_VERSION }}/ktlint && chmod a+x ktlint
java -version
shell: bash

- name: Download diktat jar
if: matrix.type == 'ktlint'
uses: actions/download-artifact@v3
with:
name: diktat-ruleset

- name: Retrieve diktat jar file name
- name: Generate run command using ktlint
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
shell: bash

- name: Download diktat cli jar
if: matrix.type == 'cli'
uses: actions/download-artifact@v3
with:
name: diktat-cli

- name: Generate run command using cli
if: matrix.type == 'cli'
run: |
filename=$(ls diktat-*.jar)
echo DIKTAT_JAR=$filename >> $GITHUB_ENV
filename=$(ls -1 diktat-cli-*.jar | head -n1)
echo DIKTAT_RUN="java -jar \"$filename\"" >> $GITHUB_ENV
shell: bash

- name: Run diKTat from cli
continue-on-error: true
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom 'examples/maven/src/main/kotlin/Test.kt' &>out.txt
${{ env.DIKTAT_RUN }} 'examples/maven/src/main/kotlin/Test.kt' &>out.txt
shell: bash

- name: Check output
Expand All @@ -121,14 +146,15 @@ jobs:
continue-on-error: true
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom "$PWD/examples/maven/src/main/kotlin/Test.kt" &>out.txt
${{ env.DIKTAT_RUN }} "$PWD/examples/maven/src/main/kotlin/Test.kt" &>out.txt
shell: bash

- name: Run diKTat from cli on windows (absolute paths)
continue-on-error: true
if: runner.os == 'Windows'
# cannot use '&>out.txt' since it's Windows
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom "%cd%/examples/maven/src/main/kotlin/Test.kt" > out.txt 2>&1
${{ env.DIKTAT_RUN }} "%cd%/examples/maven/src/main/kotlin/Test.kt" > out.txt 2>&1
nulls marked this conversation as resolved.
Show resolved Hide resolved
shell: cmd

- name: Check output (absolute paths)
Expand All @@ -141,7 +167,7 @@ jobs:
- name: Run diKTat from cli (glob paths, 1 of 4)
continue-on-error: true
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom 'examples/maven/src/main/kotlin/*.kt' &>out.txt
${{ env.DIKTAT_RUN }} 'examples/maven/src/main/kotlin/*.kt' &>out.txt
shell: bash

- name: Check output (glob paths, 1 of 4)
Expand All @@ -154,7 +180,7 @@ jobs:
- name: Run diKTat from cli (glob paths, 2 of 4)
continue-on-error: true
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom 'examples/**/main/kotlin/*.kt' &>out.txt
${{ env.DIKTAT_RUN }} 'examples/**/main/kotlin/*.kt' &>out.txt
shell: bash

- name: Check output (glob paths, 2 of 4)
Expand All @@ -167,7 +193,7 @@ jobs:
- name: Run diKTat from cli (glob paths, 3 of 4)
continue-on-error: true
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom 'examples/**/*.kt' &>out.txt
${{ env.DIKTAT_RUN }} 'examples/**/*.kt' &>out.txt
shell: bash

- name: Check output (glob paths, 3 of 4)
Expand All @@ -180,7 +206,7 @@ jobs:
- name: Run diKTat from cli (glob paths, 4 of 4)
continue-on-error: true
run: |
java -jar ktlint -R ${{ env.DIKTAT_JAR }} --disabled_rules=standard,experimental,test,custom '**/*.kt' &>out.txt
${{ env.DIKTAT_RUN }} '**/*.kt' &>out.txt
shell: bash

- name: Check output (glob paths, 4 of 4)
Expand Down
30 changes: 30 additions & 0 deletions diktat-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,33 @@ project.description = "This module builds diktat-api"
dependencies {
implementation(libs.kotlin.compiler.embeddable)
}

val generateDiktatVersionFile by tasks.registering {
val outputDir = File("$buildDir/generated/src")
val versionsFile = outputDir.resolve("generated/DiktatVersion.kt")

val diktatVersion = version.toString()

inputs.property("diktat version", diktatVersion)
outputs.dir(outputDir)

doFirst {
versionsFile.parentFile.mkdirs()
versionsFile.writeText(
"""
package generated

const val DIKTAT_VERSION = "$diktatVersion"

""".trimIndent()
)
}
}

kotlin.sourceSets.getByName("main") {
kotlin.srcDir(
generateDiktatVersionFile.map {
it.outputs.files.singleFile
}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import kotlin.io.path.absolutePathString
* @property baselineFile an optional path to file with baseline
* @property reporterType type of reporter to report the detected errors
* @property reporterOutput output for reporter
* @property loggingListener listener to log diktat runner phases
* @property groupByFileInPlain a flag `groupByFile` which is applicable for plain reporter only, **null** by default
* @property colorNameInPlain a color name which is applicable for plain reporter only, **null** by default
* @property loggingListener listener to log diktat runner phases, [DiktatProcessorListener.empty] by default
*/
data class DiktatRunnerArguments(
val configFileName: String,
Expand All @@ -23,6 +25,8 @@ data class DiktatRunnerArguments(
val baselineFile: Path?,
val reporterType: String,
val reporterOutput: OutputStream?,
val groupByFileInPlain: Boolean? = null,
val colorNameInPlain: String? = null,
val loggingListener: DiktatProcessorListener = DiktatProcessorListener.empty,
) {
constructor(
Expand All @@ -32,14 +36,18 @@ data class DiktatRunnerArguments(
baselineFile: Path?,
reporterType: String,
reporterOutput: OutputStream?,
loggingListener: DiktatProcessorListener,
groupByFileInPlain: Boolean? = null,
colorNameInPlain: String? = null,
loggingListener: DiktatProcessorListener = DiktatProcessorListener.empty,
) : this(
configFile.absolutePathString(),
sourceRootDir,
files,
baselineFile,
reporterType,
reporterOutput,
groupByFileInPlain,
colorNameInPlain,
loggingListener,
)
}
24 changes: 21 additions & 3 deletions diktat-api/src/main/kotlin/org/cqfn/diktat/DiktatRunnerFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import java.nio.file.Path

/**
* A factory to create [DiktatRunner]
*
* @property diktatReporterFactory a factory for [DiktatReporter]
*/
class DiktatRunnerFactory(
private val diktatRuleSetFactory: DiktatRuleSetFactory,
private val diktatProcessorFactory: DiktatProcessorFactory,
private val diktatBaselineFactory: DiktatBaselineFactory,
private val diktatReporterFactory: DiktatReporterFactory,
val diktatReporterFactory: DiktatReporterFactory,
) : Function1<DiktatRunnerArguments, DiktatRunner> {
/**
* @param args
Expand All @@ -27,7 +29,11 @@ class DiktatRunnerFactory(
val diktatRuleSet = diktatRuleSetFactory.create(args.configFileName)
val processor = diktatProcessorFactory(diktatRuleSet)
val (baseline, baselineGenerator) = resolveBaseline(args.baselineFile, args.sourceRootDir)
val (reporter, closer) = resolveReporter(args.reporterType, args.reporterOutput, args.sourceRootDir)
val (reporter, closer) = resolveReporter(
args.reporterType, args.reporterOutput,
args.colorNameInPlain, args.groupByFileInPlain,
args.sourceRootDir
)
return DiktatRunner(
diktatProcessor = processor,
diktatBaseline = baseline,
Expand All @@ -53,14 +59,26 @@ class DiktatRunnerFactory(
private fun resolveReporter(
reporterType: String,
reporterOutput: OutputStream?,
colorNameInPlain: String?,
groupByFileInPlain: Boolean?,
sourceRootDir: Path,
): Pair<DiktatReporter, DiktatProcessorListener> {
val (outputStream, closeListener) = reporterOutput
?.let { it to it.closeAfterAllAsProcessorListener() }
?: run {
System.`out` to DiktatProcessorListener.empty
}
val actualReporter = diktatReporterFactory(reporterType, outputStream, sourceRootDir)
val actualReporter = if (reporterType == diktatReporterFactory.plainId) {
diktatReporterFactory.createPlain(outputStream, sourceRootDir, colorNameInPlain, groupByFileInPlain)
} else {
require(colorNameInPlain == null) {
"colorization is applicable only for plain reporter"
}
require(groupByFileInPlain == null) {
"groupByFile is applicable only for plain reporter"
}
diktatReporterFactory(reporterType, outputStream, sourceRootDir)
}
return actualReporter to closeListener
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ interface DiktatReporterFactory : Function3<String, OutputStream, Path, DiktatRe
outputStream: OutputStream,
sourceRootDir: Path,
colorName: String? = null,
groupByFile: Boolean = false,
groupByFile: Boolean? = null,
): DiktatReporter
}
72 changes: 72 additions & 0 deletions diktat-cli/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.kotlin.incremental.createDirectory

@Suppress("DSL_SCOPE_VIOLATION", "RUN_IN_SCRIPT") // https://github.com/gradle/gradle/issues/22797
plugins {
id("org.cqfn.diktat.buildutils.kotlin-jvm-configuration")
id("org.cqfn.diktat.buildutils.code-quality-convention")
id("org.cqfn.diktat.buildutils.publishing-signing-default-configuration")
alias(libs.plugins.kotlin.plugin.serialization)
alias(libs.plugins.shadow)
}

project.description = "This module builds diktat-cli to run diktat as CLI using ktlint"

dependencies {
implementation(projects.diktatApi)
implementation(projects.diktatKtlintEngine)
implementation(projects.diktatRules)
implementation(libs.kotlinx.cli)
implementation(libs.log4j2.core)
implementation(libs.log4j2.slf4j)

testImplementation(libs.junit.jupiter)
testImplementation(libs.junit.platform.suite)
testImplementation(libs.assertj.core)
testImplementation(libs.mockito)
}

val addLicenseTask = tasks.register("addLicense") {
val licenseFile = rootProject.file("LICENSE")
val outputDir = File("$buildDir/generated/src")

inputs.file(licenseFile)
outputs.dir(outputDir)

doLast {
licenseFile.copyTo(
outputDir.resolve("META-INF").resolve("diktat")
.also { it.createDirectory() }
.resolve(licenseFile.name),
overwrite = true
)
}
}

sourceSets.getByName("main") {
resources.srcDir(
addLicenseTask.map {
it.outputs.files.singleFile
}
)
}

tasks.named<ShadowJar>("shadowJar") {
archiveClassifier.set("")
manifest {
attributes["Main-Class"] = "org.cqfn.diktat.DiktatMainKt"
}
duplicatesStrategy = DuplicatesStrategy.FAIL
}

// disable default jar
tasks.named("jar") {
enabled = false
}

// it triggers shadowJar with default build
tasks {
build {
dependsOn(shadowJar)
}
}
Loading