Skip to content

Commit

Permalink
AnnotationSuppressor works with Full Qualified names without type sol…
Browse files Browse the repository at this point in the history
…ving
  • Loading branch information
BraisGabin committed Feb 6, 2022
1 parent ff185b1 commit 1db1b8e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 46 deletions.
@@ -1,11 +1,9 @@
package io.gitlab.arturbosch.detekt.core.suppressors

import io.gitlab.arturbosch.detekt.api.AnnotationExcluder
import io.gitlab.arturbosch.detekt.api.ConfigAware
import io.gitlab.arturbosch.detekt.rules.fqNameOrNull
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext

Expand All @@ -23,43 +21,21 @@ internal fun annotationSuppressorFactory(rule: ConfigAware, bindingContext: Bind
return if (annotations.isNotEmpty()) {
Suppressor { finding ->
val element = finding.entity.ktElement
element != null && annotationSuppressor(element, annotations, bindingContext)
element != null && element.isAnnotatedWith(
AnnotationExcluder(element.containingKtFile, annotations, bindingContext),
)
}
} else {
null
}
}

private fun annotationSuppressor(
element: KtElement,
annotations: List<Regex>,
bindingContext: BindingContext
): Boolean {
return element.isAnnotatedWith(annotations, bindingContext)
}

@Suppress("ReturnCount")
private fun KtElement.isAnnotatedWith(annotationNames: Iterable<Regex>, bindingContext: BindingContext): Boolean {
if (this is KtAnnotated) {
val references = annotationEntries.mapNotNull { it.typeReference }
if (references.any { it.text in annotationNames }) {
return true
} else if (bindingContext != BindingContext.EMPTY) {
if (references.any { it.fqNameOrNull(bindingContext)?.toString() in annotationNames }) {
return true
}
}
private fun KtElement.isAnnotatedWith(excluder: AnnotationExcluder): Boolean {
return if (this is KtAnnotated && excluder.shouldExclude(annotationEntries)) {
true
} else {
getStrictParentOfType<KtAnnotated>()?.isAnnotatedWith(excluder) ?: false
}
return getStrictParentOfType<KtAnnotated>()?.isAnnotatedWith(annotationNames, bindingContext) ?: false
}

private fun KtTypeReference.fqNameOrNull(bindingContext: BindingContext): FqName? {
return bindingContext[BindingContext.TYPE, this]?.fqNameOrNull()
}

private operator fun Iterable<Regex>.contains(a: String?): Boolean {
if (a == null) return false
return any { it.matches(a) }
}

private fun String.qualifiedNameGlobToRegex(): Regex {
Expand Down
Expand Up @@ -14,6 +14,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource

@KotlinCoreEnvironmentTest
class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
Expand Down Expand Up @@ -314,10 +316,14 @@ class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
""".trimIndent()
)

val binding = env.getContextForPaths(listOf(root, *composableFiles))
val bindings = listOf(
env.getContextForPaths(listOf(root, *composableFiles)),
BindingContext.EMPTY,
)

@Test
fun `Just name`() {
@ParameterizedTest
@MethodSource("getBindings")
fun `Just name`(binding: BindingContext) {
val suppressor = annotationSuppressorFactory(
buildConfigAware("ignoreAnnotated" to listOf("Composable")),
binding,
Expand All @@ -328,8 +334,9 @@ class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
assertThat(suppressor.shouldSuppress(buildFinding(ktFunction))).isTrue()
}

@Test
fun `Full qualified name name`() {
@ParameterizedTest
@MethodSource("getBindings")
fun `Full qualified name name`(binding: BindingContext) {
val suppressor = annotationSuppressorFactory(
buildConfigAware("ignoreAnnotated" to listOf("androidx.compose.runtime.Composable")),
binding,
Expand All @@ -340,9 +347,10 @@ class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
assertThat(suppressor.shouldSuppress(buildFinding(ktFunction))).isTrue()
}

@Test
@ParameterizedTest
@MethodSource("getBindings")
@DisplayName("with glob doesn't match because * doesn't match .")
fun withGlobDoesntMatch() {
fun withGlobDoesntMatch(binding: BindingContext) {
val suppressor = annotationSuppressorFactory(
buildConfigAware("ignoreAnnotated" to listOf("*.Composable")),
binding,
Expand All @@ -353,8 +361,9 @@ class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
assertThat(suppressor.shouldSuppress(buildFinding(ktFunction))).isFalse()
}

@Test
fun `With glob2`() {
@ParameterizedTest
@MethodSource("getBindings")
fun `With glob2`(binding: BindingContext) {
val suppressor = annotationSuppressorFactory(
buildConfigAware("ignoreAnnotated" to listOf("**.Composable")),
binding,
Expand All @@ -365,8 +374,9 @@ class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
assertThat(suppressor.shouldSuppress(buildFinding(ktFunction))).isTrue()
}

@Test
fun `With glob3`() {
@ParameterizedTest
@MethodSource("getBindings")
fun `With glob3`(binding: BindingContext) {
val suppressor = annotationSuppressorFactory(
buildConfigAware("ignoreAnnotated" to listOf("Compo*")),
binding,
Expand All @@ -377,8 +387,9 @@ class AnnotationSuppressorSpec(private val env: KotlinCoreEnvironment) {
assertThat(suppressor.shouldSuppress(buildFinding(ktFunction))).isTrue()
}

@Test
fun `With glob4`() {
@ParameterizedTest
@MethodSource("getBindings")
fun `With glob4`(binding: BindingContext) {
val suppressor = annotationSuppressorFactory(
buildConfigAware("ignoreAnnotated" to listOf("*")),
binding,
Expand Down

0 comments on commit 1db1b8e

Please sign in to comment.