/
ConfigAssert.kt
85 lines (72 loc) · 3.09 KB
/
ConfigAssert.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
77
78
79
80
81
82
83
84
85
package io.gitlab.arturbosch.detekt.generator.config
import io.gitlab.arturbosch.detekt.api.BaseRule
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Rule
import io.gitlab.arturbosch.detekt.api.RuleSetProvider
import io.gitlab.arturbosch.detekt.api.internal.DefaultRuleSetProvider
import io.gitlab.arturbosch.detekt.core.config.YamlConfig
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.fail
import org.reflections.Reflections
import java.lang.reflect.Modifier
class ConfigAssert(
private val config: Config,
private val name: String,
private val packageName: String
) {
private val allowedOptions = setOf(
Config.ACTIVE_KEY,
Config.EXCLUDES_KEY,
Config.INCLUDES_KEY,
Config.AUTO_CORRECT_KEY,
"android"
)
fun assert() {
val ymlDeclarations = getYmlRuleConfig().properties.filter { it.key !in allowedOptions }
assertThat(ymlDeclarations).isNotEmpty
checkRulesDefinedByRuleSetProvider()
val ruleClasses = getRuleClassesInPackage()
val foundRulesClassNames = ruleClasses.map { it.simpleName }
val ruleNamesInConfig = ymlDeclarations.keys
assertThat(foundRulesClassNames).containsExactlyInAnyOrderElementsOf(ruleNamesInConfig)
checkRules(ruleClasses, ymlDeclarations)
}
private fun checkRules(ruleClasses: List<Class<out Rule>>, ymlDeclarations: Map<String, Any>) {
for (ruleClass in ruleClasses) {
val ymlDeclaration = ymlDeclarations.filter { it.key == ruleClass.simpleName }
if (ymlDeclaration.keys.size != 1) {
fail<String>("${ruleClass.simpleName} rule is not correctly defined in detekt-default-config.yml")
}
}
}
private fun checkRulesDefinedByRuleSetProvider() {
getRulesDefinedByRuleSet().forEach(::verifyIssueIdMatchesName)
}
private fun verifyIssueIdMatchesName(rule: BaseRule) {
val clazz = rule::class.java
assertThat(rule.ruleId)
.withFailMessage { "rule $clazz declares the rule id ${rule.ruleId} instead of ${clazz.simpleName}" }
.isEqualTo(clazz.simpleName)
}
private fun getYmlRuleConfig() = config.subConfig(name) as? YamlConfig
?: error("yaml config expected but got ${config.javaClass}")
private fun getRulesDefinedByRuleSet(): List<BaseRule> {
return getRuleSetProviderInPackageOrNull()
?.instance(Config.empty)
?.rules
.orEmpty()
}
private fun getRuleSetProviderInPackageOrNull(): RuleSetProvider? = Reflections(packageName)
.getSubTypesOf(DefaultRuleSetProvider::class.java)
.firstOrNull()
?.getDeclaredConstructor()
?.newInstance()
private fun getRuleClassesInPackage(): List<Class<out Rule>> {
return Reflections(packageName)
.getSubTypesOf(Rule::class.java)
.filter { rule ->
!Modifier.isAbstract(rule.modifiers) &&
rule.annotations.none { it.annotationClass == Deprecated::class }
}
}
}