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

Support configuration of reporters in DSL #1808

Merged
merged 26 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
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 patternSet
*/
open class DiktatExtension(
private val patternSet: PatternSet
open class DiktatExtension @Inject constructor(
objectFactory: ObjectFactory,
private val patternSet: PatternSet,
) {
@get:Internal
val reporters: Reporters = objectFactory.newInstance(Reporters::class.java)

/**
* Boolean flag to support `ignoreFailures` property of [VerificationTask].
*/
Expand All @@ -25,21 +34,6 @@ open class DiktatExtension(
*/
var debug = false

/**
* Property that will be used if you need to publish the report to GitHub
*/
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 +56,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
@@ -1,5 +1,6 @@
package com.saveourtool.diktat.plugin.gradle

import com.saveourtool.diktat.plugin.gradle.extension.DefaultReporter
import com.saveourtool.diktat.plugin.gradle.tasks.DiktatCheckTask.Companion.registerDiktatCheckTask
import com.saveourtool.diktat.plugin.gradle.tasks.DiktatFixTask.Companion.registerDiktatFixTask
import com.saveourtool.diktat.plugin.gradle.tasks.configureMergeReportsTask
Expand All @@ -10,18 +11,18 @@ 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 reporters = mutableListOf<DefaultReporter>()
val diktatExtension = project.extensions.create(
DIKTAT_EXTENSION,
DiktatExtension::class.java,
patternSet
patternSet,
reporters,
).apply {
diktatConfigFile = project.rootProject.file("diktat-analysis.yml")
}
Expand All @@ -37,11 +38,6 @@ class DiktatGradlePlugin : Plugin<Project> {
*/
const val DIKTAT_CHECK_TASK = "diktatCheck"

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

/**
* DiKTat extension
*/
Expand All @@ -56,10 +52,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
kgevorkyan marked this conversation as resolved.
Show resolved Hide resolved
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,74 +7,18 @@
package com.saveourtool.diktat.plugin.gradle

import org.gradle.api.Project
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import org.gradle.api.file.RegularFile
import org.gradle.api.provider.Provider
import org.gradle.api.reporting.ReportingExtension

/**
* @param diktatExtension
* @return returns sourceRootDir as projectDir for sarif report
* @param fileName
* @param extension
* @return default location of report with provided [extension]
*/
fun Project.getSourceRootDir(diktatExtension: DiktatExtension): Path? = when {
diktatExtension.githubActions -> projectDir.toPath()
diktatExtension.reporter == "sarif" -> projectDir.toPath()
else -> null
}

/**
* Create CLI flag to set reporter for ktlint based on [diktatExtension].
* [DiktatExtension.githubActions] should have higher priority than a custom input.
*
* @param diktatExtension extension of type [DiktatExtension]
* @return CLI flag as string
*/
fun Project.getReporterType(diktatExtension: DiktatExtension): String {
val name = diktatExtension.reporter.trim()
val validReporters = listOf("sarif", "plain", "json", "html")
val reporterType = when {
diktatExtension.githubActions -> {
if (diktatExtension.reporter.isNotEmpty()) {
logger.warn("`diktat.githubActions` is set to true, so custom reporter [$name] will be ignored and SARIF reporter will be used")
}
"sarif"
}
name.isEmpty() -> {
logger.info("Reporter name was not set. Using 'plain' reporter")
"plain"
}
name !in validReporters -> {
logger.warn("Reporter name is invalid (provided value: [$name]). Falling back to 'plain' reporter")
"plain"
}
else -> name
}

return reporterType
}

/**
* Get destination file for Diktat report or null if stdout is used.
* [DiktatExtension.githubActions] should have higher priority than a custom input.
*
* @param diktatExtension extension of type [DiktatExtension]
* @return destination [File] or null if stdout is used
*/
internal fun Project.getOutputFile(diktatExtension: DiktatExtension): File? = when {
diktatExtension.githubActions -> project.layout.buildDirectory
.file("reports/diktat/diktat.sarif")
.get()
.asFile
.also {
Files.createDirectories(it.parentFile.toPath())
}
diktatExtension.output.isNotEmpty() -> file(diktatExtension.output)
else -> null
}

/**
* Whether SARIF reporter is enabled or not
*
* @param reporterFlag
* @return whether SARIF reporter is enabled
*/
internal fun isSarifReporterActive(reporterFlag: String) = reporterFlag.contains("sarif")
internal fun Project.defaultReportLocation(
extension: String,
kgevorkyan marked this conversation as resolved.
Show resolved Hide resolved
fileName: String = "diktat",
): Provider<RegularFile> = project.layout
.buildDirectory
.file("${ReportingExtension.DEFAULT_REPORTS_DIR_NAME}/diktat/$fileName.$extension")
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.saveourtool.diktat.plugin.gradle.extension

import com.saveourtool.diktat.plugin.gradle.defaultReportLocation
import org.gradle.api.Project
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.model.ObjectFactory
import javax.inject.Inject

/**
* A base interface for reporter
*
* @property id identifier of reporter
* @param extension extension of generated report
* @param objectFactory
* @param project
*/
abstract class DefaultReporter @Inject constructor(
Fixed Show fixed Hide fixed
val id: String,
extension: String,
objectFactory: ObjectFactory,
project: Project,
): Reporter() {
override val output: RegularFileProperty = objectFactory.fileProperty()
.also { fileProperty ->
fileProperty.set(project.defaultReportLocation(extension = extension))
}
}


abstract class PlainReporter @Inject constructor(
Fixed Show fixed Hide fixed
kgevorkyan marked this conversation as resolved.
Show resolved Hide resolved
objectFactory: ObjectFactory,
project: Project,
): DefaultReporter("plain", "txt", objectFactory, project)

abstract class JsonReporter @Inject constructor(
Fixed Show fixed Hide fixed
objectFactory: ObjectFactory,
project: Project,
): DefaultReporter("json", "json", objectFactory, project)

abstract class SarifReporter @Inject constructor(
objectFactory: ObjectFactory,
project: Project,
): DefaultReporter("sarif", "sarif", objectFactory, project) {
/**
* Location for merged output
*/
abstract val mergeOutput: RegularFileProperty
}

abstract class GithubActionsReporter @Inject constructor(
Fixed Show fixed Hide fixed
project: Project,
objectFactory: ObjectFactory,
) : SarifReporter(objectFactory, project) {
override val mergeOutput: RegularFileProperty = objectFactory.fileProperty()
.also { fileProperty ->
fileProperty.set(project.rootProject.defaultReportLocation(fileName = "diktat-merged", extension = "sarif"))
}
}

abstract class CheckstyleReporter @Inject constructor(
Fixed Show fixed Hide fixed
objectFactory: ObjectFactory,
project: Project,
): DefaultReporter("checkstyle", "xml", objectFactory, project)

abstract class HtmlReporter @Inject constructor(
Fixed Show fixed Hide fixed
objectFactory: ObjectFactory,
project: Project,
): DefaultReporter("html", "html", objectFactory, project)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.saveourtool.diktat.plugin.gradle.extension

import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.OutputFile
import javax.inject.Inject

/**
* A base interface for reporter
*/
abstract class Reporter {
Fixed Show fixed Hide fixed
/**
* Location for output
*/
@get:OutputFile
abstract val output: RegularFileProperty
}
Loading
Loading