/
LateinitUsage.kt
76 lines (65 loc) · 2.73 KB
/
LateinitUsage.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package io.gitlab.arturbosch.detekt.rules.bugs
import io.gitlab.arturbosch.detekt.api.AnnotationExcluder
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 io.gitlab.arturbosch.detekt.api.config
import io.gitlab.arturbosch.detekt.api.internal.Configuration
import io.gitlab.arturbosch.detekt.rules.isLateinit
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.containingClass
/**
* Turn on this rule to flag usages of the lateinit modifier.
*
* Using lateinit for property initialization can be error-prone and the actual initialization is not
* guaranteed. Try using constructor injection or delegation to initialize properties.
*
* <noncompliant>
* class Foo {
* private lateinit var i1: Int
* lateinit var i2: Int
* }
* </noncompliant>
*/
@Suppress("ViolatesTypeResolutionRequirements")
class LateinitUsage(config: Config = Config.empty) : Rule(config) {
override val issue = Issue(
javaClass.simpleName,
Severity.Defect,
"Usage of `lateinit` detected. Using `lateinit` for property initialization " +
"is error prone, try using constructor injection or delegation.",
Debt.TWENTY_MINS
)
@Configuration("Allows you to provide a list of annotations that disable this check.")
@Deprecated("Use `ignoreAnnotated` instead")
private val excludeAnnotatedProperties: List<Regex> by config(emptyList<String>()) { list ->
list.map { it.replace(".", "\\.").replace("*", ".*").toRegex() }
}
@Configuration("Allows you to disable the rule for a list of classes")
private val ignoreOnClassesPattern: Regex by config("", String::toRegex)
private var properties = mutableListOf<KtProperty>()
override fun visitProperty(property: KtProperty) {
if (property.isLateinit()) {
properties.add(property)
}
}
override fun visit(root: KtFile) {
properties = mutableListOf()
super.visit(root)
val annotationExcluder = AnnotationExcluder(
root,
@Suppress("DEPRECATION") excludeAnnotatedProperties,
bindingContext,
)
properties.filterNot { annotationExcluder.shouldExclude(it.annotationEntries) }
.filterNot { it.containingClass()?.name?.matches(ignoreOnClassesPattern) == true }
.forEach {
report(CodeSmell(issue, Entity.from(it), "Usages of lateinit should be avoided."))
}
}
}