diff --git a/build.gradle.kts b/build.gradle.kts index 7374eb9af..3dc34fd76 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -184,7 +184,8 @@ subprojects { kotlinOptions.freeCompilerArgs = listOf( "-progressive", "-Xskip-runtime-version-check", - "-Xdisable-default-scripting-plugin" + "-Xdisable-default-scripting-plugin", + "-Xopt-in=kotlin.RequiresOptIn" ) kotlinOptions.allWarningsAsErrors = shouldTreatCompilerWarningsAsErrors() } diff --git a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Extension.kt b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Extension.kt index 647e2177a..1eb18a99c 100644 --- a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Extension.kt +++ b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Extension.kt @@ -6,12 +6,14 @@ package io.gitlab.arturbosch.detekt.api * - [FileProcessListener] * - [ConsoleReport] * - [OutputReport] + * - [ConfigValidator] */ interface Extension { /** * Name of the extension. */ val id: String get() = javaClass.simpleName + /** * Is used to run extensions in a specific order. * The higher the priority the sooner the extension will run in detekt's lifecycle. @@ -23,6 +25,14 @@ interface Extension { * to setup this extension. */ fun init(config: Config) { - // for setup code + // implement for setup code + } + + /** + * Setup extension by querying common paths and config options. + */ + @OptIn(UnstableApi::class) + fun init(context: SetupContext) { + // implement for setup code } } diff --git a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/SetupContext.kt b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/SetupContext.kt new file mode 100644 index 000000000..0562aa8ef --- /dev/null +++ b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/SetupContext.kt @@ -0,0 +1,19 @@ +package io.gitlab.arturbosch.detekt.api + +import java.net.URI + +/** + * Context providing useful processing settings to initialize extensions. + */ +@UnstableApi +interface SetupContext { + /** + * All config locations which where used to create [config]. + */ + val configUris: Collection + + /** + * Configuration which is used to setup detekt. + */ + val config: Config +} diff --git a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/UnstableApi.kt b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/UnstableApi.kt new file mode 100644 index 000000000..3110c3f2d --- /dev/null +++ b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/UnstableApi.kt @@ -0,0 +1,7 @@ +package io.gitlab.arturbosch.detekt.api + +/** + * Experimental detekt api which may change on minor or patch versions. + */ +@RequiresOptIn +annotation class UnstableApi diff --git a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Configurations.kt b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Configurations.kt index cdaf81ba6..d273cc1ef 100644 --- a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Configurations.kt +++ b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Configurations.kt @@ -6,6 +6,8 @@ import io.gitlab.arturbosch.detekt.api.internal.DisabledAutoCorrectConfig import io.gitlab.arturbosch.detekt.api.internal.FailFastConfig import io.gitlab.arturbosch.detekt.api.internal.PathFilters import io.gitlab.arturbosch.detekt.api.internal.YamlConfig +import java.net.URI +import java.net.URL import java.nio.file.Path fun CliArgs.createFilters(): PathFilters? = PathFilters.of(includes, excludes) @@ -71,3 +73,10 @@ private fun parsePathConfig(configPath: String): Config { const val DEFAULT_CONFIG = "default-detekt-config.yml" fun loadDefaultConfig() = YamlConfig.loadResource(ClasspathResourceConverter().convert(DEFAULT_CONFIG)) + +fun CliArgs.extractUris(): Collection { + val pathUris = config?.let { MultipleExistingPathConverter().convert(it).map(Path::toUri) } ?: emptyList() + val resourceUris = configResource?.let { MultipleClasspathResourceConverter().convert(it).map(URL::toURI) } + ?: emptyList() + return resourceUris + pathUris +} diff --git a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/OutputFacade.kt b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/OutputFacade.kt index d9bba0f3c..c5dbb7f0c 100644 --- a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/OutputFacade.kt +++ b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/OutputFacade.kt @@ -23,6 +23,7 @@ class OutputFacade( reports.forEach { report -> report.init(config) + report.init(settings) when (report) { is ConsoleReport -> handleConsoleReport(report, result) is OutputReport -> handleOutputReport(report, result) diff --git a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/config/ConfigValidators.kt b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/config/ConfigValidators.kt index a62a17cc3..9a5f7dbb9 100644 --- a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/config/ConfigValidators.kt +++ b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/config/ConfigValidators.kt @@ -7,7 +7,9 @@ import io.gitlab.arturbosch.detekt.core.ProcessingSettings import java.util.ServiceLoader fun loadValidators(settings: ProcessingSettings): List = - ServiceLoader.load(ConfigValidator::class.java, settings.pluginLoader).toList() + ServiceLoader.load(ConfigValidator::class.java, settings.pluginLoader) + .onEach { it.init(settings.config); it.init(settings) } + .toList() fun checkConfiguration(settings: ProcessingSettings) { val props = settings.config.subConfig("config") diff --git a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/runners/Runner.kt b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/runners/Runner.kt index 3597a9853..963ef91fe 100644 --- a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/runners/Runner.kt +++ b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/runners/Runner.kt @@ -11,6 +11,7 @@ import io.gitlab.arturbosch.detekt.cli.console.red import io.gitlab.arturbosch.detekt.cli.createClasspath import io.gitlab.arturbosch.detekt.cli.createFilters import io.gitlab.arturbosch.detekt.cli.createPlugins +import io.gitlab.arturbosch.detekt.cli.extractUris import io.gitlab.arturbosch.detekt.cli.getOrComputeWeightedAmountOfIssues import io.gitlab.arturbosch.detekt.cli.isValidAndSmallerOrEqual import io.gitlab.arturbosch.detekt.cli.loadConfiguration @@ -89,8 +90,8 @@ class Runner( languageVersion = languageVersion, jvmTarget = jvmTarget, debug = arguments.debug, - outPrinter = outputPrinter, - errorPrinter = errorPrinter + outPrinter = outputPrinter, errorPrinter = errorPrinter, + configUris = extractUris() ) } settings.debug { "Loading config took $configLoadTime ms" } diff --git a/detekt-cli/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.FileProcessListener b/detekt-cli/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.FileProcessListener index 626c2cf97..d0ede32a1 100644 --- a/detekt-cli/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.FileProcessListener +++ b/detekt-cli/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.FileProcessListener @@ -9,3 +9,4 @@ io.gitlab.arturbosch.detekt.core.processors.ProjectLLOCProcessor io.gitlab.arturbosch.detekt.core.processors.ProjectCLOCProcessor io.gitlab.arturbosch.detekt.core.processors.ProjectLOCProcessor io.gitlab.arturbosch.detekt.core.processors.ProjectSLOCProcessor +io.gitlab.arturbosch.detekt.rules.documentation.LicenceHeaderLoaderExtension diff --git a/detekt-cli/src/main/resources/default-detekt-config.yml b/detekt-cli/src/main/resources/default-detekt-config.yml index 6e315b1f5..13da81504 100644 --- a/detekt-cli/src/main/resources/default-detekt-config.yml +++ b/detekt-cli/src/main/resources/default-detekt-config.yml @@ -34,13 +34,16 @@ console-reports: comments: active: true excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt" + AbsentOrWrongFileLicense: + active: false + licenseTemplateFile: 'license.template' CommentOverPrivateFunction: active: false CommentOverPrivateProperty: active: false EndOfSentenceFormat: active: false - endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!:]$) + endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' UndocumentedPublicClass: active: false searchInNestedClass: true diff --git a/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocator.kt b/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocator.kt index f52b498c6..9cad2e61c 100644 --- a/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocator.kt +++ b/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocator.kt @@ -15,8 +15,9 @@ class FileProcessorLocator(private val settings: ProcessingSettings) { if (processorsActive) { ServiceLoader.load(FileProcessListener::class.java, settings.pluginLoader) .filter { it.id !in excludes } - .onEach { it.init(config) } + .onEach { it.init(config); it.init(settings) } .toList() + .also { settings.debug { "Registered file processors: $it" } } } else { emptyList() } diff --git a/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/ProcessingSettings.kt b/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/ProcessingSettings.kt index a98c7a9d7..3db1dbfbd 100644 --- a/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/ProcessingSettings.kt +++ b/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/ProcessingSettings.kt @@ -1,6 +1,8 @@ package io.gitlab.arturbosch.detekt.core import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.SetupContext +import io.gitlab.arturbosch.detekt.api.UnstableApi import io.gitlab.arturbosch.detekt.api.internal.PathFilters import io.gitlab.arturbosch.detekt.api.internal.createCompilerConfiguration import io.gitlab.arturbosch.detekt.api.internal.createKotlinCoreEnvironment @@ -12,6 +14,7 @@ import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.utils.closeQuietly import java.io.Closeable import java.io.PrintStream +import java.net.URI import java.net.URLClassLoader import java.nio.file.Files import java.nio.file.Path @@ -24,10 +27,11 @@ import java.util.concurrent.ForkJoinPool * Always close the settings as dispose the Kotlin compiler and detekt class loader. * If using a custom executor service be aware that detekt won't shut it down after use! */ +@OptIn(UnstableApi::class) @Suppress("LongParameterList") class ProcessingSettings @JvmOverloads constructor( val inputPaths: List, - val config: Config = Config.empty, + override val config: Config = Config.empty, val pathFilters: PathFilters? = null, val parallelCompilation: Boolean = false, val excludeDefaultRuleSets: Boolean = false, @@ -39,8 +43,9 @@ class ProcessingSettings @JvmOverloads constructor( val outPrinter: PrintStream = System.out, val errorPrinter: PrintStream = System.err, val autoCorrect: Boolean = false, - val debug: Boolean = false -) : AutoCloseable, Closeable { + val debug: Boolean = false, + override val configUris: Collection = emptyList() +) : AutoCloseable, Closeable, SetupContext { /** * Single project input path constructor. */ @@ -58,7 +63,8 @@ class ProcessingSettings @JvmOverloads constructor( outPrinter: PrintStream = System.out, errorPrinter: PrintStream = System.err, autoCorrect: Boolean = false, - debug: Boolean = false + debug: Boolean = false, + configUris: Collection = emptyList() ) : this( listOf(inputPath), config, @@ -73,7 +79,8 @@ class ProcessingSettings @JvmOverloads constructor( outPrinter, errorPrinter, autoCorrect, - debug + debug, + configUris ) init { diff --git a/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicense.kt b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicense.kt new file mode 100644 index 000000000..ae9669280 --- /dev/null +++ b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicense.kt @@ -0,0 +1,47 @@ +package io.gitlab.arturbosch.detekt.rules.documentation + +import io.gitlab.arturbosch.detekt.api.CodeSmell +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.Debt +import io.gitlab.arturbosch.detekt.api.Entity +import io.gitlab.arturbosch.detekt.api.Issue +import io.gitlab.arturbosch.detekt.api.Rule +import io.gitlab.arturbosch.detekt.api.Severity +import org.jetbrains.kotlin.psi.KtFile + +/** + * This rule will report every Kotlin source file which doesn't have required license header. + * + * @configuration licenseTemplateFile - path to file with license header template resolved relatively to config file + * (default: `'license.template'`) + */ +class AbsentOrWrongFileLicense(config: Config = Config.empty) : Rule(config) { + + override val issue = Issue( + id = RULE_NAME, + severity = Severity.Maintainability, + description = "License text is absent or incorrect in the file.", + debt = Debt.FIVE_MINS + ) + + override fun visitCondition(root: KtFile): Boolean = + super.visitCondition(root) && root.hasLicenseHeader() + + override fun visitKtFile(file: KtFile) { + if (!file.hasValidLicense()) { + report(CodeSmell( + issue, + Entity.from(file), + "Expected license not found or incorrect in the file: ${file.name}." + )) + } + } + + private fun KtFile.hasValidLicense(): Boolean = text.startsWith(getLicenseHeader()) + + companion object { + const val PARAM_LICENSE_TEMPLATE_FILE = "licenseTemplateFile" + const val DEFAULT_LICENSE_TEMPLATE_FILE = "license.template" + val RULE_NAME: String = AbsentOrWrongFileLicense::class.java.simpleName + } +} diff --git a/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormat.kt b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormat.kt index 8a3d01e7a..5b2e25535 100644 --- a/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormat.kt +++ b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormat.kt @@ -30,7 +30,7 @@ class KDocStyle(config: Config = Config.empty) : MultiRule() { * It should end with proper punctuation or with a correct URL. * * @configuration endOfSentenceFormat - regular expression which should match the end of the first sentence in the KDoc - * (default: `([.?!][ \t\n\r\f<])|([.?!:]$)`) + * (default: `'([.?!][ \t\n\r\f<])|([.?!:]$)'`) */ @Suppress("MemberNameEqualsClassName") class EndOfSentenceFormat(config: Config = Config.empty) : Rule(config) { diff --git a/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtension.kt b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtension.kt new file mode 100644 index 000000000..cc2ecc015 --- /dev/null +++ b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtension.kt @@ -0,0 +1,78 @@ +package io.gitlab.arturbosch.detekt.rules.documentation + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.FileProcessListener +import io.gitlab.arturbosch.detekt.api.SetupContext +import io.gitlab.arturbosch.detekt.api.SingleAssign +import io.gitlab.arturbosch.detekt.api.UnstableApi +import io.gitlab.arturbosch.detekt.rules.documentation.AbsentOrWrongFileLicense.Companion.DEFAULT_LICENSE_TEMPLATE_FILE +import io.gitlab.arturbosch.detekt.rules.documentation.AbsentOrWrongFileLicense.Companion.PARAM_LICENSE_TEMPLATE_FILE +import io.gitlab.arturbosch.detekt.rules.documentation.AbsentOrWrongFileLicense.Companion.RULE_NAME +import org.jetbrains.kotlin.com.intellij.openapi.util.Key +import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtilRt +import org.jetbrains.kotlin.psi.KtFile +import java.io.BufferedReader +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +@OptIn(UnstableApi::class) +class LicenceHeaderLoaderExtension : FileProcessListener { + + private var config: Config by SingleAssign() + private var configPath: Path? = null + + override fun init(context: SetupContext) { + this.config = context.config + this.configPath = context.configUris.lastOrNull()?.let(Paths::get) + } + + override fun onStart(files: List) { + fun Config.isActive() = this.valueOrDefault(Config.ACTIVE_KEY, false) + + fun shouldRuleRun(): Boolean { + val comments = config.subConfig("comments") + val ruleConfig = comments.subConfig(RULE_NAME) + return comments.isActive() && ruleConfig.isActive() + } + + fun getPathToTemplate(): String = config.subConfig("comments") + .subConfig(RULE_NAME) + .valueOrDefault(PARAM_LICENSE_TEMPLATE_FILE, DEFAULT_LICENSE_TEMPLATE_FILE) + + fun loadLicence(dir: Path): String { + val templateFile = dir.resolve(getPathToTemplate()) + + require(Files.exists(templateFile)) { + """ + Rule '$RULE_NAME': License template file not found at `${templateFile.toAbsolutePath()}`. + Create file license header file or check your running path. + """.trimIndent() + } + + return Files.newBufferedReader(templateFile) + .use(BufferedReader::readText) + .let(StringUtilRt::convertLineSeparators) + } + + fun cacheLicence(dir: Path) { + val licenceHeader = loadLicence(dir) + for (file in files) { + file.putUserData(LICENCE_KEY, licenceHeader) + } + } + + if (configPath != null && shouldRuleRun()) { + val configDir = configPath?.parent + if (configDir != null) { + cacheLicence(configDir) + } + } + } +} + +internal val LICENCE_KEY = Key.create("LICENCE_HEADER") + +internal fun KtFile.hasLicenseHeader(): Boolean = this.getUserData(LICENCE_KEY) != null + +internal fun KtFile.getLicenseHeader(): String = this.getUserData(LICENCE_KEY) ?: error("License header expected") diff --git a/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/providers/CommentSmellProvider.kt b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/providers/CommentSmellProvider.kt index 2f7941fde..0a84dc5a8 100644 --- a/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/providers/CommentSmellProvider.kt +++ b/detekt-rules/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/providers/CommentSmellProvider.kt @@ -3,6 +3,7 @@ package io.gitlab.arturbosch.detekt.rules.providers import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.api.RuleSet import io.gitlab.arturbosch.detekt.api.internal.DefaultRuleSetProvider +import io.gitlab.arturbosch.detekt.rules.documentation.AbsentOrWrongFileLicense import io.gitlab.arturbosch.detekt.rules.documentation.CommentOverPrivateFunction import io.gitlab.arturbosch.detekt.rules.documentation.CommentOverPrivateProperty import io.gitlab.arturbosch.detekt.rules.documentation.KDocStyle @@ -27,7 +28,8 @@ class CommentSmellProvider : DefaultRuleSetProvider { KDocStyle(config), UndocumentedPublicClass(config), UndocumentedPublicFunction(config), - UndocumentedPublicProperty(config) + UndocumentedPublicProperty(config), + AbsentOrWrongFileLicense(config) )) } } diff --git a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt new file mode 100644 index 000000000..a15b99e58 --- /dev/null +++ b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt @@ -0,0 +1,69 @@ +package io.gitlab.arturbosch.detekt.rules.documentation + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.Finding +import io.gitlab.arturbosch.detekt.api.SetupContext +import io.gitlab.arturbosch.detekt.api.UnstableApi +import io.gitlab.arturbosch.detekt.api.internal.YamlConfig +import io.gitlab.arturbosch.detekt.test.assertThat +import io.gitlab.arturbosch.detekt.test.compileContentForTest +import io.gitlab.arturbosch.detekt.test.lint +import io.gitlab.arturbosch.detekt.test.resource +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe +import java.net.URI +import java.nio.file.Paths + +internal class AbsentOrWrongFileLicenseSpec : Spek({ + + describe("AbsentOrWrongFileLicense rule") { + context("file with correct license header") { + it("reports nothing") { + val findings = checkLicence(""" + /* LICENSE */ + package cases + """.trimIndent()) + + assertThat(findings).isEmpty() + } + } + + context("file with incorrect license header") { + it("reports missed license header") { + val findings = checkLicence(""" + /* WRONG LICENSE */ + package cases + """.trimIndent()) + + assertThat(findings).hasSize(1) + } + } + + context("file with absent license header") { + it("reports missed license header") { + val findings = checkLicence(""" + package cases + """.trimIndent()) + + assertThat(findings).hasSize(1) + } + } + } +}) + +@OptIn(UnstableApi::class) +private fun checkLicence(content: String): List { + val file = compileContentForTest(content) + + val resource = resource("license-config.yml") + val config = YamlConfig.load(Paths.get(resource)) + LicenceHeaderLoaderExtension().apply { + init(object : SetupContext { + override val configUris: Collection = listOf(resource) + override val config: Config = config + }) + onStart(listOf(file)) + } + + return AbsentOrWrongFileLicense().lint(file) +} diff --git a/detekt-rules/src/test/resources/license-config.yml b/detekt-rules/src/test/resources/license-config.yml new file mode 100644 index 000000000..c5cb6b9cb --- /dev/null +++ b/detekt-rules/src/test/resources/license-config.yml @@ -0,0 +1,5 @@ +comments: + active: true + AbsentOrWrongFileLicense: + active: true + licenseTemplateFile: "license.template" diff --git a/detekt-rules/src/test/resources/license.template b/detekt-rules/src/test/resources/license.template new file mode 100644 index 000000000..9e6ea0315 --- /dev/null +++ b/detekt-rules/src/test/resources/license.template @@ -0,0 +1 @@ +/* LICENSE */ diff --git a/docs/pages/documentation/comments.md b/docs/pages/documentation/comments.md index c26ed5ef7..d66bbc8e1 100644 --- a/docs/pages/documentation/comments.md +++ b/docs/pages/documentation/comments.md @@ -9,6 +9,20 @@ folder: documentation This rule set provides rules that address issues in comments and documentation of the code. +### AbsentOrWrongFileLicense + +This rule will report every Kotlin source file which doesn't have required license header. + +**Severity**: Maintainability + +**Debt**: 5min + +#### Configuration options: + +* ``licenseTemplateFile`` (default: ``'license.template'``) + + path to file with license header template resolved relatively to config file + ### CommentOverPrivateFunction This rule reports comments and documentation that has been added to private functions. These comments get reported @@ -50,7 +64,7 @@ It should end with proper punctuation or with a correct URL. #### Configuration options: -* ``endOfSentenceFormat`` (default: ``([.?!][ \t\n\r\f<])|([.?!:]$)``) +* ``endOfSentenceFormat`` (default: ``'([.?!][ \t\n\r\f<])|([.?!:]$)'``) regular expression which should match the end of the first sentence in the KDoc diff --git a/docs/pages/kdoc/detekt-api/alltypes/index.md b/docs/pages/kdoc/detekt-api/alltypes/index.md index 8914b6bcc..999b4e20a 100644 --- a/docs/pages/kdoc/detekt-api/alltypes/index.md +++ b/docs/pages/kdoc/detekt-api/alltypes/index.md @@ -357,6 +357,13 @@ A rule set is a collection of rules and must be defined within a rule set provid A rule set provider, as the name states, is responsible for creating rule sets. +| + +##### [io.gitlab.arturbosch.detekt.api.SetupContext](../io.gitlab.arturbosch.detekt.api/-setup-context/index.html) + +Context providing useful processing settings to initialize extensions. + + | ##### [io.gitlab.arturbosch.detekt.api.Severity](../io.gitlab.arturbosch.detekt.api/-severity/index.html) @@ -422,6 +429,13 @@ Provides a threshold attribute for this rule, which is specified manually for de but can be also obtained from within a configuration object. +| + +##### [io.gitlab.arturbosch.detekt.api.UnstableApi](../io.gitlab.arturbosch.detekt.api/-unstable-api/index.html) + +Experimental detekt api which may change on minor or patch versions. + + | ##### [io.gitlab.arturbosch.detekt.api.internal.ValidatableConfiguration](../io.gitlab.arturbosch.detekt.api.internal/-validatable-configuration/index.html) diff --git a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/index.md b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/index.md index de47a1767..51268cb8c 100644 --- a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/index.md +++ b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/index.md @@ -14,6 +14,7 @@ Currently supported extensions are: * [FileProcessListener](../-file-process-listener/index.html) * [ConsoleReport](../-console-report/index.html) * [OutputReport](../-output-report/index.html) +* [ConfigValidator](../-config-validator/index.html) ### Properties @@ -22,7 +23,7 @@ Currently supported extensions are: ### Functions -| [init](init.html) | Allows to read any or even user defined properties from the detekt yaml config to setup this extension.`open fun init(config: `[`Config`](../-config/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) | +| [init](init.html) | Allows to read any or even user defined properties from the detekt yaml config to setup this extension.`open fun init(config: `[`Config`](../-config/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html)
Setup extension by querying common paths and config options.`open fun init(context: `[`SetupContext`](../-setup-context/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) | ### Inheritors diff --git a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/init.md b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/init.md index 8ab47f284..6b741d907 100644 --- a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/init.md +++ b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-extension/init.md @@ -11,3 +11,7 @@ title: Extension.init - detekt-api Allows to read any or even user defined properties from the detekt yaml config to setup this extension. +`open fun init(context: `[`SetupContext`](../-setup-context/index.html)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) + +Setup extension by querying common paths and config options. + diff --git a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-yaml-config/index.md b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-yaml-config/index.md index 3029b2df8..254a42440 100644 --- a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-yaml-config/index.md +++ b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/-yaml-config/index.md @@ -13,6 +13,7 @@ yaml specification. ### Properties +| [location](location.html) | `val location: Location` | | [parent](parent.html) | Returns the parent config which encloses this config part.`val parent: Parent?` | | [properties](properties.html) | `val properties: `[`Map`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/index.html)`<`[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)`, `[`Any`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html)`>` | diff --git a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/index.md b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/index.md index 4a72ec5b1..324c557de 100644 --- a/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/index.md +++ b/docs/pages/kdoc/detekt-api/io.gitlab.arturbosch.detekt.api/index.md @@ -44,6 +44,7 @@ title: io.gitlab.arturbosch.detekt.api - detekt-api | [RuleSet](-rule-set/index.html) | A rule set is a collection of rules and must be defined within a rule set provider implementation.`class RuleSet` | | [RuleSetId](-rule-set-id.html) | `typealias RuleSetId = `[`String`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) | | [RuleSetProvider](-rule-set-provider/index.html) | A rule set provider, as the name states, is responsible for creating rule sets.`interface RuleSetProvider` | +| [SetupContext](-setup-context/index.html) | Context providing useful processing settings to initialize extensions.`interface SetupContext` | | [Severity](-severity/index.html) | Rules can classified into different severity grades. Maintainer can choose a grade which is most harmful to their projects.`enum class Severity` | | [SingleAssign](-single-assign/index.html) | Allows to assign a property just once. Further assignments result in [IllegalStateException](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-illegal-state-exception/index.html)'s.`class SingleAssign` | | [SourceLocation](-source-location/index.html) | Stores line and column information of a location.`data class SourceLocation` | @@ -53,6 +54,10 @@ title: io.gitlab.arturbosch.detekt.api - detekt-api | [ThresholdRule](-threshold-rule/index.html) | Provides a threshold attribute for this rule, which is specified manually for default values but can be also obtained from within a configuration object.`abstract class ThresholdRule : `[`Rule`](-rule/index.html) | | [YamlConfig](-yaml-config.html) | Config implementation using the yaml format. SubConfigurations can return sub maps according to the yaml specification.`typealias ~~YamlConfig~~ = `[`YamlConfig`](../io.gitlab.arturbosch.detekt.api.internal/-yaml-config/index.html) | +### Annotations + +| [UnstableApi](-unstable-api/index.html) | Experimental detekt api which may change on minor or patch versions.`annotation class UnstableApi` | + ### Extensions for External Classes | [kotlin.String](kotlin.-string/index.html) | |