mirror of
https://github.com/jlengrand/detekt.git
synced 2026-03-10 08:11:23 +00:00
Split InvalidPackageDeclaration to create MissingPackageDeclaration (#4149)
This commit is contained in:
@@ -447,7 +447,6 @@ naming:
|
||||
ignoreOverridden: true
|
||||
InvalidPackageDeclaration:
|
||||
active: false
|
||||
excludes: ['**/*.kts']
|
||||
rootPackage: ''
|
||||
MatchingDeclarationName:
|
||||
active: true
|
||||
@@ -556,6 +555,9 @@ potential-bugs:
|
||||
ignoreOnClassesPattern: ''
|
||||
MapGetWithNotNullAssertionOperator:
|
||||
active: false
|
||||
MissingPackageDeclaration:
|
||||
active: false
|
||||
excludes: ['**/*.kts']
|
||||
MissingWhenCase:
|
||||
active: true
|
||||
allowElseExpression: true
|
||||
|
||||
@@ -48,7 +48,7 @@ private object TestExclusions : Exclusions() {
|
||||
private object KotlinScriptExclusions : Exclusions() {
|
||||
|
||||
override val pattern = "['**/*.kts']"
|
||||
override val rules = setOf("InvalidPackageDeclaration")
|
||||
override val rules = setOf("MissingPackageDeclaration")
|
||||
}
|
||||
|
||||
private object LibraryExclusions : Exclusions() {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.gitlab.arturbosch.detekt.rules.bugs
|
||||
|
||||
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
|
||||
import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
|
||||
/**
|
||||
* Reports when the package declaration is missing.
|
||||
*/
|
||||
class MissingPackageDeclaration(config: Config = Config.empty) : Rule(config) {
|
||||
|
||||
override val issue = Issue(
|
||||
javaClass.simpleName,
|
||||
Severity.Maintainability,
|
||||
"Kotlin source files should define a package",
|
||||
debt = Debt.FIVE_MINS
|
||||
)
|
||||
|
||||
private var packageDeclaration: KtPackageDirective? = null
|
||||
|
||||
override fun visitPackageDirective(directive: KtPackageDirective) {
|
||||
super.visitPackageDirective(directive)
|
||||
packageDeclaration = directive
|
||||
}
|
||||
|
||||
override fun postVisit(root: KtFile) {
|
||||
super.postVisit(root)
|
||||
if (packageDeclaration?.text.isNullOrBlank()) {
|
||||
report(CodeSmell(issue, Entity.from(root), "The file does not contain a package declaration."))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ class PotentialBugProvider : DefaultRuleSetProvider {
|
||||
IteratorNotThrowingNoSuchElementException(config),
|
||||
LateinitUsage(config),
|
||||
MapGetWithNotNullAssertionOperator(config),
|
||||
MissingPackageDeclaration(config),
|
||||
MissingWhenCase(config),
|
||||
RedundantElseInWhen(config),
|
||||
UnconditionalJumpStatementInLoop(config),
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.gitlab.arturbosch.detekt.rules.bugs
|
||||
|
||||
import io.gitlab.arturbosch.detekt.test.assertThat
|
||||
import io.gitlab.arturbosch.detekt.test.compileAndLint
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
internal class MissingPackageDeclarationSpec : Spek({
|
||||
|
||||
describe("MissingPackageDeclaration rule") {
|
||||
|
||||
it("should pass if package declaration is declared") {
|
||||
val code = """
|
||||
package foo.bar
|
||||
|
||||
class C
|
||||
"""
|
||||
val findings = MissingPackageDeclaration().compileAndLint(code)
|
||||
|
||||
assertThat(findings).isEmpty()
|
||||
}
|
||||
|
||||
it("should report if package declaration is missing") {
|
||||
val code = "class C"
|
||||
|
||||
val findings = MissingPackageDeclaration().compileAndLint(code)
|
||||
|
||||
assertThat(findings).hasSize(1)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,11 +11,10 @@ import io.gitlab.arturbosch.detekt.api.Severity
|
||||
import io.gitlab.arturbosch.detekt.api.config
|
||||
import io.gitlab.arturbosch.detekt.api.internal.Configuration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
|
||||
/**
|
||||
* Reports when the package declaration is missing or the file location does not match the declared package.
|
||||
* Reports when the file location does not match the declared package.
|
||||
*/
|
||||
class InvalidPackageDeclaration(config: Config = Config.empty) : Rule(config) {
|
||||
|
||||
@@ -29,21 +28,11 @@ class InvalidPackageDeclaration(config: Config = Config.empty) : Rule(config) {
|
||||
@Configuration("if specified this part of the package structure is ignored")
|
||||
private val rootPackage: String by config("")
|
||||
|
||||
private var packageDeclaration: KtPackageDirective? = null
|
||||
|
||||
override fun visitPackageDirective(directive: KtPackageDirective) {
|
||||
super.visitPackageDirective(directive)
|
||||
packageDeclaration = directive
|
||||
}
|
||||
|
||||
override fun postVisit(root: KtFile) {
|
||||
super.postVisit(root)
|
||||
val packageDeclaration = packageDeclaration
|
||||
val declaredPath = packageDeclaration?.packageNames?.map(KtElement::getText)?.toNormalizedForm()
|
||||
if (declaredPath.isNullOrBlank()) {
|
||||
root.reportInvalidPackageDeclaration("The file does not contain a package declaration.")
|
||||
} else {
|
||||
val normalizedFilePath = root.absolutePath().parent.toNormalizedForm()
|
||||
val declaredPath = directive.packageNames.map(KtElement::getText).toNormalizedForm()
|
||||
if (declaredPath.isNotBlank()) {
|
||||
val normalizedFilePath = directive.containingKtFile.absolutePath().parent.toNormalizedForm()
|
||||
val normalizedRootPackage = packageNameToNormalizedForm(rootPackage)
|
||||
val expectedPath =
|
||||
if (normalizedRootPackage.isBlank()) {
|
||||
@@ -54,16 +43,17 @@ class InvalidPackageDeclaration(config: Config = Config.empty) : Rule(config) {
|
||||
|
||||
val isInRootPackage = expectedPath.isBlank()
|
||||
if (!isInRootPackage && !normalizedFilePath.endsWith(expectedPath)) {
|
||||
packageDeclaration
|
||||
.reportInvalidPackageDeclaration("The package declaration does not match the actual file location.")
|
||||
report(
|
||||
CodeSmell(
|
||||
issue,
|
||||
Entity.from(directive),
|
||||
"The package declaration does not match the actual file location.",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtElement.reportInvalidPackageDeclaration(message: String) {
|
||||
report(CodeSmell(issue, Entity.from(this), message))
|
||||
}
|
||||
|
||||
private fun <T> Iterable<T>.toNormalizedForm() = joinToString("|")
|
||||
|
||||
private fun packageNameToNormalizedForm(packageName: String) = packageName.split('.').toNormalizedForm()
|
||||
|
||||
@@ -28,14 +28,6 @@ internal class InvalidPackageDeclarationSpec : Spek({
|
||||
assertThat(findings).isEmpty()
|
||||
}
|
||||
|
||||
it("should report if package declaration is missing") {
|
||||
val ktFile = compileContentForTest("class C")
|
||||
|
||||
val findings = InvalidPackageDeclaration().lint(ktFile)
|
||||
|
||||
assertThat(findings).hasSize(1)
|
||||
}
|
||||
|
||||
it("should report if package declaration does not match source location") {
|
||||
val source = "package foo\n\nclass C"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user