Skip to content

Commit

Permalink
Support configuration of reporters in DSL (#1808)
Browse files Browse the repository at this point in the history
- extended DiktatExtension to support configuration of reporters in DSL
- supported `json`, `checkstyle`, `html`, `sarif` and `plain` as function to configure in extensions
- now `mergeDiktatReports` depends only to `diktatCheck` (previously it depended to `diktatFix` too)
- now diktat gradle plugin supports multiple reporters
  • Loading branch information
nulls authored Nov 21, 2023
1 parent 81a7429 commit ad37745
Show file tree
Hide file tree
Showing 20 changed files with 513 additions and 258 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import java.nio.file.Path
*/
sealed interface DiktatReporterCreationArguments {
/**
* Identifier of [DiktatReporter] which needs to be created
* Type of [DiktatReporter] which needs to be created
*/
val id: String
val reporterType: DiktatReporterType

/**
* Output for [DiktatReporter]
Expand All @@ -33,23 +33,23 @@ sealed interface DiktatReporterCreationArguments {

companion object {
/**
* @param id ID of [DiktatReporter]
* @param reporterType type of [DiktatReporter]
* @param outputStream stdout will be used when it's empty
* @param sourceRootDir a dir to detect relative path for processing files
* @param colorNameInPlain a color name for colorful output which is applicable for plain ([DiktatReporterFactory.PLAIN_ID]) reporter only,
* @param colorNameInPlain a color name for colorful output which is applicable for plain ([DiktatReporterType.PLAIN]) reporter only,
* `null` means to disable colorization.
* @param groupByFileInPlain a flag `groupByFile` which is applicable for plain ([DiktatReporterFactory.PLAIN_ID]) reporter only.
* @param groupByFileInPlain a flag `groupByFile` which is applicable for plain ([DiktatReporterType.PLAIN]) reporter only.
* @return created [DiktatReporter]
*/
operator fun invoke(
id: String,
reporterType: DiktatReporterType,
outputStream: OutputStream?,
sourceRootDir: Path?,
colorNameInPlain: String? = null,
groupByFileInPlain: Boolean? = null,
): DiktatReporterCreationArguments {
val (outputStreamOrStdout, closeOutputStreamAfterAll) = outputStream?.let { it to true } ?: (System.`out` to false)
return if (id == DiktatReporterFactory.PLAIN_ID) {
return if (reporterType == DiktatReporterType.PLAIN) {
PlainDiktatReporterCreationArguments(
outputStreamOrStdout, closeOutputStreamAfterAll, sourceRootDir, colorNameInPlain, groupByFileInPlain
)
Expand All @@ -61,15 +61,15 @@ sealed interface DiktatReporterCreationArguments {
"groupByFile is applicable only for plain reporter"
}
DiktatReporterCreationArgumentsImpl(
id, outputStreamOrStdout, closeOutputStreamAfterAll, sourceRootDir
reporterType, outputStreamOrStdout, closeOutputStreamAfterAll, sourceRootDir
)
}
}
}
}

/**
* Implementation of [DiktatReporterCreationArguments] for [DiktatReporterFactory.PLAIN_ID]
* Implementation of [DiktatReporterCreationArguments] for [DiktatReporterType.PLAIN]
*
* @property outputStream
* @property closeOutputStreamAfterAll
Expand All @@ -84,17 +84,17 @@ data class PlainDiktatReporterCreationArguments(
val colorName: String? = null,
val groupByFile: Boolean? = null,
) : DiktatReporterCreationArguments {
override val id: String = DiktatReporterFactory.PLAIN_ID
override val reporterType: DiktatReporterType = DiktatReporterType.PLAIN
}

/**
* @property id
* @property reporterType
* @property outputStream
* @property closeOutputStreamAfterAll
* @property sourceRootDir
*/
private data class DiktatReporterCreationArgumentsImpl(
override val id: String,
override val reporterType: DiktatReporterType,
override val outputStream: OutputStream,
override val closeOutputStreamAfterAll: Boolean,
override val sourceRootDir: Path?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ typealias DiktatReporter = DiktatProcessorListener
* A factory to create [DiktatReporter]
*/
interface DiktatReporterFactory : Function1<DiktatReporterCreationArguments, DiktatReporter> {
/**
* Set of supported IDs, must contain [DiktatReporterFactory.NONE_ID]
*/
val ids: Set<String>

/**
* Names of color for plain output
*/
Expand All @@ -23,16 +18,4 @@ interface DiktatReporterFactory : Function1<DiktatReporterCreationArguments, Dik
override operator fun invoke(
args: DiktatReporterCreationArguments,
): DiktatReporter

companion object {
/**
* ID of [DiktatReporter] for disabled reporter
*/
const val NONE_ID: String = "none"

/**
* ID of [DiktatReporter] for plain output
*/
const val PLAIN_ID: String = "plain"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.saveourtool.diktat.api

/**
* @property id
* @property extension
*/
enum class DiktatReporterType(
val id: String,
val extension: String,
) {
CHECKSTYLE("checkstyle", "xml"),
HTML("html", "html"),
JSON("json", "json"),
NONE("none", ""),
PLAIN("plain", "txt"),
SARIF("sarif", "sarif"),
;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.saveourtool.diktat.DiktatRunnerArguments
import com.saveourtool.diktat.api.DiktatProcessorListener
import com.saveourtool.diktat.api.DiktatReporterCreationArguments
import com.saveourtool.diktat.api.DiktatReporterFactory
import com.saveourtool.diktat.api.DiktatReporterFactory.Companion.PLAIN_ID
import com.saveourtool.diktat.api.DiktatReporterType
import com.saveourtool.diktat.common.config.rules.DIKTAT
import com.saveourtool.diktat.common.config.rules.DIKTAT_ANALYSIS_CONF
import com.saveourtool.diktat.util.isKotlinCodeOrScript
Expand Down Expand Up @@ -33,14 +33,14 @@ import kotlinx.cli.vararg
* @param logLevel
* @property config path to `diktat-analysis.yml`
* @property mode mode of `diktat`
* @property reporterProviderId
* @property reporterType
* @property output
* @property patterns
*/
data class DiktatProperties(
val config: String,
val mode: DiktatMode,
val reporterProviderId: String,
val reporterType: DiktatReporterType,
val output: String?,
private val groupByFileInPlain: Boolean,
private val colorNameInPlain: String?,
Expand Down Expand Up @@ -76,7 +76,7 @@ data class DiktatProperties(
loggingListener: DiktatProcessorListener,
): DiktatRunnerArguments {
val reporterCreationArguments = DiktatReporterCreationArguments(
id = reporterProviderId,
reporterType = reporterType,
outputStream = getReporterOutput(),
groupByFileInPlain = groupByFileInPlain,
colorNameInPlain = colorNameInPlain,
Expand Down Expand Up @@ -136,7 +136,7 @@ data class DiktatProperties(
shortName = "m",
description = "Mode of `diktat` controls that `diktat` fixes or only finds any deviations from the code style."
).default(DiktatMode.CHECK)
val reporterType: String by parser.reporterType(diktatReporterFactory)
val reporterType: DiktatReporterType by parser.reporterType()
val output: String? by parser.option(
type = ArgType.String,
fullName = "output",
Expand Down Expand Up @@ -190,7 +190,7 @@ data class DiktatProperties(
return DiktatProperties(
config = config,
mode = mode,
reporterProviderId = reporterType,
reporterType = reporterType,
output = output,
groupByFileInPlain = groupByFileInPlain,
colorNameInPlain = colorName,
Expand All @@ -200,20 +200,15 @@ data class DiktatProperties(
}

/**
* @param diktatReporterFactory
* @return a single type of [com.saveourtool.diktat.api.DiktatReporter] as parsed cli arg
*/
private fun ArgParser.reporterType(diktatReporterFactory: DiktatReporterFactory) = option(
type = ArgType.Choice(
choices = diktatReporterFactory.ids.toList(),
toVariant = { it },
variantToString = { it },
),
private fun ArgParser.reporterType() = option(
type = ArgType.Choice<DiktatReporterType>(),
fullName = "reporter",
shortName = "r",
description = "The reporter to use"
)
.default(PLAIN_ID)
.default(DiktatReporterType.PLAIN)

/**
* @param diktatReporterFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
package com.saveourtool.diktat.plugin.gradle

import com.saveourtool.diktat.plugin.gradle.extension.Reporters
import org.gradle.api.Action
import org.gradle.api.model.ObjectFactory
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.api.tasks.util.PatternSet
import java.io.File
import javax.inject.Inject

/**
* An extension to configure diktat in build.gradle(.kts) file
*
* @param objectFactory
* @param patternSet
*/
open class DiktatExtension(
private val patternSet: PatternSet
open class DiktatExtension @Inject constructor(
objectFactory: ObjectFactory,
private val patternSet: PatternSet,
) {
/**
* All reporters
*/
@get:Internal
val reporters: Reporters = objectFactory.newInstance(Reporters::class.java)

/**
* Boolean flag to support `ignoreFailures` property of [VerificationTask].
*/
Expand All @@ -30,16 +43,6 @@ open class DiktatExtension(
*/
var githubActions = false

/**
* Type of the reporter to use
*/
var reporter: String = ""

/**
* Destination for reporter. If empty, will write to stdout.
*/
var output: String = ""

/**
* Baseline file, containing a list of errors that will be ignored.
* If this file doesn't exist, it will be created on the first invocation.
Expand All @@ -62,4 +65,11 @@ open class DiktatExtension(
fun inputs(action: PatternFilterable.() -> Unit) {
action(patternSet)
}

/**
* Configure reporters
*
* @param action configuration lambda for [Reporters]
*/
fun reporters(action: Action<Reporters>): Unit = action.execute(reporters)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,23 @@ import org.gradle.api.tasks.util.PatternSet
/**
* Plugin that configures diktat and registers tasks to run diktat
*/
@Suppress("unused", "MagicNumber")
class DiktatGradlePlugin : Plugin<Project> {
/**
* @param project a gradle [Project] that the plugin is applied to
*/
@Suppress("TOO_LONG_FUNCTION")
override fun apply(project: Project) {
val patternSet = PatternSet()
val diktatExtension = project.extensions.create(
DIKTAT_EXTENSION,
DiktatExtension::class.java,
patternSet
patternSet,
).apply {
diktatConfigFile = project.rootProject.file("diktat-analysis.yml")
}

project.registerDiktatCheckTask(diktatExtension, patternSet)
project.registerDiktatFixTask(diktatExtension, patternSet)
project.configureMergeReportsTask(diktatExtension)
project.configureMergeReportsTask()
}

companion object {
Expand All @@ -37,11 +35,6 @@ class DiktatGradlePlugin : Plugin<Project> {
*/
const val DIKTAT_CHECK_TASK = "diktatCheck"

/**
* DiKTat configuration
*/
const val DIKTAT_CONFIGURATION = "diktat"

/**
* DiKTat extension
*/
Expand All @@ -56,10 +49,5 @@ class DiktatGradlePlugin : Plugin<Project> {
* Name of the task that merges SARIF reports of diktat tasks
*/
internal const val MERGE_SARIF_REPORTS_TASK_NAME = "mergeDiktatReports"

/**
* Version of JVM with more strict module system, which requires `add-opens` for kotlin compiler
*/
const val MIN_JVM_REQUIRES_ADD_OPENS = 16
}
}

This file was deleted.

Loading

0 comments on commit ad37745

Please sign in to comment.