Skip to content

Commit

Permalink
Fix incomplete requireRootInDeclaration check in `InvalidPackageDec…
Browse files Browse the repository at this point in the history
…laration` (#6045)
  • Loading branch information
cketti committed Apr 29, 2023
1 parent df82521 commit 704ca20
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 14 deletions.
Expand Up @@ -11,6 +11,7 @@ import io.gitlab.arturbosch.detekt.api.Severity
import io.gitlab.arturbosch.detekt.api.config
import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault
import io.gitlab.arturbosch.detekt.api.internal.Configuration
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtPackageDirective

Expand All @@ -37,24 +38,19 @@ class InvalidPackageDeclaration(config: Config = Config.empty) : Rule(config) {

override fun visitPackageDirective(directive: KtPackageDirective) {
super.visitPackageDirective(directive)
val declaredPath = directive.packageNames.map(KtElement::getText).toNormalizedForm()
if (declaredPath.isNotBlank()) {
val normalizedFilePath = directive.containingKtFile.absolutePath().parent.toNormalizedForm()
val normalizedRootPackage = packageNameToNormalizedForm(rootPackage)
if (requireRootInDeclaration && !declaredPath.startsWith(normalizedRootPackage)) {
val packageName = directive.fqName
if (!packageName.isRoot) {
val rootPackageName = FqName(rootPackage)
if (requireRootInDeclaration && !packageName.startsWith(rootPackageName)) {
directive.reportInvalidPackageDeclaration("The package declaration is missing the root package")
return
}

val expectedPath =
if (normalizedRootPackage.isBlank()) {
declaredPath
} else {
declaredPath.substringAfter(normalizedRootPackage)
}
val normalizedFilePath = directive.containingKtFile.absolutePath().parent.toNormalizedForm()
val expectedPath = packageName.withoutPrefix(rootPackageName).toNormalizedForm()

val isInRootPackage = expectedPath.isBlank()
if (!isInRootPackage && !normalizedFilePath.endsWith(expectedPath)) {
val isInRootPackage = expectedPath.isEmpty()
if (!isInRootPackage && !normalizedFilePath.endsWith("|$expectedPath")) {
directive.reportInvalidPackageDeclaration(
"The package declaration does not match the actual file location."
)
Expand All @@ -68,5 +64,20 @@ class InvalidPackageDeclaration(config: Config = Config.empty) : Rule(config) {

private fun <T> Iterable<T>.toNormalizedForm() = joinToString("|")

private fun packageNameToNormalizedForm(packageName: String) = packageName.split('.').toNormalizedForm()
private fun FqName.startsWith(other: FqName): Boolean {
val segments = pathSegments()
val otherSegments = other.pathSegments()
return if (otherSegments.size <= segments.size) {
otherSegments.indices.all { index -> segments[index] == otherSegments[index] }
} else {
false
}
}

private fun FqName.withoutPrefix(prefix: FqName): List<String> {
val dropCount = if (startsWith(prefix)) prefix.pathSegments().size else 0
return pathSegments()
.drop(dropCount)
.map { segmentName -> segmentName.asString() }
}
}
Expand Up @@ -167,6 +167,20 @@ class InvalidPackageDeclarationSpec {

assertThat(findings).hasSize(1)
}

@Test
fun `should report if declaration only shares a prefix with root package`() {
val source = """
package com.example_extra
class C
""".trimIndent()

val ktFile = compileContentForTest(source, createPath("src/com/example_extra/File.kt"))
val findings = InvalidPackageDeclaration(config).lint(ktFile)

assertThat(findings).hasSize(1)
}
}
}

Expand Down

0 comments on commit 704ca20

Please sign in to comment.