Skip to content

Commit f08ddb3

Browse files
committed
[Deprecation] Add config ignoreRuleParameterThreshold
This allows deprecation in imports
1 parent 6625e17 commit f08ddb3

File tree

3 files changed

+158
-2
lines changed

3 files changed

+158
-2
lines changed

detekt-core/src/main/resources/default-detekt-config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ potential-bugs:
434434
Deprecation:
435435
active: false
436436
aliases: ['DEPRECATION']
437+
ignoreImport: false
437438
DontDowncastCollectionTypes:
438439
active: false
439440
DoubleMutabilityForCollection:

detekt-rules-errorprone/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/Deprecation.kt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ package io.gitlab.arturbosch.detekt.rules.bugs
33
import io.gitlab.arturbosch.detekt.api.Alias
44
import io.gitlab.arturbosch.detekt.api.CodeSmell
55
import io.gitlab.arturbosch.detekt.api.Config
6+
import io.gitlab.arturbosch.detekt.api.Configuration
67
import io.gitlab.arturbosch.detekt.api.Entity
78
import io.gitlab.arturbosch.detekt.api.RequiresFullAnalysis
89
import io.gitlab.arturbosch.detekt.api.Rule
10+
import io.gitlab.arturbosch.detekt.api.config
911
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
1012
import org.jetbrains.kotlin.diagnostics.Errors
13+
import org.jetbrains.kotlin.psi.KtImportDirective
1114
import org.jetbrains.kotlin.psi.KtNamedDeclaration
15+
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
1216

1317
/**
1418
* Deprecated elements are expected to be removed in the future. Alternatives should be found if possible.
@@ -21,15 +25,30 @@ class Deprecation(config: Config) : Rule(
2125
"Deprecated elements should not be used."
2226
) {
2327

28+
@Configuration("Ignore deprecation in import statements")
29+
private val ignoreImport: Boolean by config(false)
30+
2431
override fun visitElement(element: PsiElement) {
2532
val diagnostic = hasDeprecationCompilerWarnings(element)
2633
if (diagnostic != null) {
27-
val entity = if (element is KtNamedDeclaration) Entity.atName(element) else Entity.from(element)
28-
report(CodeSmell(entity, """${element.text} is deprecated with message "${diagnostic.b}""""))
34+
val entity =
35+
if (element is KtNamedDeclaration) Entity.atName(element) else Entity.from(element)
36+
if (shouldIgnoreThisElement(element)) {
37+
// not reporting for import statements
38+
report(
39+
CodeSmell(
40+
entity,
41+
"""${element.text} is deprecated with message "${diagnostic.b}""""
42+
)
43+
)
44+
}
2945
}
3046
super.visitElement(element)
3147
}
3248

49+
private fun shouldIgnoreThisElement(element: PsiElement) =
50+
!(ignoreImport && element.getParentOfType<KtImportDirective>(true) != null)
51+
3352
private fun hasDeprecationCompilerWarnings(element: PsiElement) =
3453
bindingContext.diagnostics
3554
.forElement(element)

detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DeprecationSpec.kt

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ package io.gitlab.arturbosch.detekt.rules.bugs
22

33
import io.gitlab.arturbosch.detekt.api.Config
44
import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
5+
import io.gitlab.arturbosch.detekt.test.TestConfig
56
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
7+
import io.gitlab.arturbosch.detekt.test.lintWithContext
8+
import io.gitlab.arturbosch.detekt.test.location
69
import org.assertj.core.api.Assertions.assertThat
710
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
11+
import org.junit.jupiter.api.Nested
812
import org.junit.jupiter.api.Test
913

1014
@KotlinCoreEnvironmentTest
@@ -48,4 +52,136 @@ class DeprecationSpec(private val env: KotlinCoreEnvironment) {
4852
""".trimIndent()
4953
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
5054
}
55+
56+
@Test
57+
fun `report when property delegate is deprecated`() {
58+
val stateFile = """
59+
package state
60+
61+
import kotlin.reflect.KProperty
62+
63+
interface State {
64+
val value: Double
65+
}
66+
67+
@Deprecated("Some reason")
68+
operator fun State.getValue(thisObj: Any?, property: KProperty<*>): Double = value
69+
""".trimIndent()
70+
val code = """
71+
import state.State
72+
import state.getValue
73+
fun foo(state: State) {
74+
val d by state
75+
}
76+
""".trimIndent()
77+
assertThat(subject.lintWithContext(env, code, stateFile))
78+
.hasSize(1)
79+
.first()
80+
.extracting {
81+
it.message
82+
}
83+
.isEqualTo("""state is deprecated with message "Some reason"""")
84+
}
85+
86+
@Test
87+
fun `does not report import location`() {
88+
val deprecatedFile = """
89+
package com.example.detekt.featureflag
90+
91+
@Deprecated("Moved to other service")
92+
enum class LegacyFeatureFlags {
93+
FEATURE_A, FEATURE_B,
94+
}
95+
""".trimIndent()
96+
val code = """
97+
import com.example.detekt.featureflag.LegacyFeatureFlags
98+
class FeatureFlagManager {
99+
@Suppress("DEPRECATION")
100+
fun getFeatureFlagValue(featureFlag: LegacyFeatureFlags): Boolean {
101+
return true
102+
}
103+
}
104+
105+
class Manager(private val featureFlagManager: FeatureFlagManager) {
106+
fun doSomething() {
107+
@Suppress("DEPRECATION")
108+
val isFeatureAEnabled =
109+
featureFlagManager.getFeatureFlagValue(LegacyFeatureFlags.FEATURE_A)
110+
}
111+
}
112+
""".trimIndent()
113+
assertThat(subject.lintWithContext(env, code, deprecatedFile))
114+
.hasSize(1)
115+
.first()
116+
.extracting { it.location.source.line }
117+
.isEqualTo(1)
118+
}
119+
120+
@Nested
121+
inner class `With ignore import true` {
122+
private val ignoredImportSubject =
123+
Deprecation(TestConfig(IGNORED_IMPORT to true))
124+
125+
@Test
126+
fun `does not report import location - #7402`() {
127+
val deprecatedFile = """
128+
package com.example.detekt.featureflag
129+
130+
@Deprecated("Moved to other service")
131+
enum class LegacyFeatureFlags {
132+
FEATURE_A, FEATURE_B,
133+
}
134+
""".trimIndent()
135+
val code = """
136+
import com.example.detekt.featureflag.LegacyFeatureFlags
137+
class FeatureFlagManager {
138+
@Suppress("DEPRECATION")
139+
fun getFeatureFlagValue(featureFlag: LegacyFeatureFlags): Boolean {
140+
return true
141+
}
142+
}
143+
144+
class Manager(private val featureFlagManager: FeatureFlagManager) {
145+
fun doSomething() {
146+
@Suppress("DEPRECATION")
147+
val isFeatureAEnabled =
148+
featureFlagManager.getFeatureFlagValue(LegacyFeatureFlags.FEATURE_A)
149+
}
150+
}
151+
""".trimIndent()
152+
assertThat(ignoredImportSubject.lintWithContext(env, code, deprecatedFile))
153+
.isEmpty()
154+
}
155+
156+
@Test
157+
fun `report when property delegate is deprecated`() {
158+
val stateFile = """
159+
package state
160+
import kotlin.reflect.KProperty
161+
interface State {
162+
val value: Double
163+
}
164+
@Deprecated("Some reason")
165+
operator fun State.getValue(thisObj: Any?, property: KProperty<*>): Double = value
166+
""".trimIndent()
167+
val code = """
168+
import state.State
169+
import state.getValue
170+
fun foo(state: State) {
171+
val d by state
172+
}
173+
""".trimIndent()
174+
assertThat(ignoredImportSubject.lintWithContext(env, code, stateFile))
175+
.hasSize(1)
176+
.first()
177+
.extracting {
178+
it.message
179+
}
180+
.isEqualTo("""state is deprecated with message "Some reason"""")
181+
}
182+
}
183+
184+
companion object {
185+
private const val IGNORED_IMPORT = "ignoreImport"
186+
}
51187
}

0 commit comments

Comments
 (0)