/
KtLintMultiRule.kt
126 lines (118 loc) · 4.68 KB
/
KtLintMultiRule.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package io.gitlab.arturbosch.detekt.formatting
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Rule
import io.gitlab.arturbosch.detekt.formatting.wrappers.*
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.impl.source.JavaDummyElement
import org.jetbrains.kotlin.com.intellij.psi.impl.source.JavaDummyHolder
import org.jetbrains.kotlin.psi.KtFile
import java.util.LinkedList
/**
* Runs all KtLint rules.
*/
class KtLintMultiRule(config: Config = Config.empty) :
@Suppress("DEPRECATION")
io.gitlab.arturbosch.detekt.api.MultiRule() {
override val rules: List<Rule> = listOf(
// Wrappers for ktlint-ruleset-standard rules. Enabled by default.
AnnotationOnSeparateLine(config),
AnnotationSpacing(config),
ArgumentListWrapping(config),
ChainWrapping(config),
CommentSpacing(config),
EnumEntryNameCase(config),
Filename(config),
FinalNewline(config),
ImportOrdering(config),
Indentation(config),
MaximumLineLength(config),
ModifierOrdering(config),
MultiLineIfElse(config),
NoBlankLineBeforeRbrace(config),
NoBlankLinesInChainedMethodCalls(config),
NoConsecutiveBlankLines(config),
NoEmptyClassBody(config),
NoEmptyFirstLineInMethodBlock(config),
NoLineBreakAfterElse(config),
NoLineBreakBeforeAssignment(config),
NoMultipleSpaces(config),
NoSemicolons(config),
NoTrailingSpaces(config),
NoUnitReturn(config),
NoUnusedImports(config),
NoWildcardImports(config),
PackageName(config),
ParameterListWrapping(config),
SpacingAroundAngleBrackets(config),
SpacingAroundColon(config),
SpacingAroundComma(config),
SpacingAroundCurly(config),
SpacingAroundDot(config),
SpacingAroundDoubleColon(config),
SpacingAroundKeyword(config),
SpacingAroundOperators(config),
SpacingAroundParens(config),
SpacingAroundRangeOperator(config),
SpacingAroundUnaryOperator(config),
SpacingBetweenDeclarationsWithAnnotations(config),
SpacingBetweenDeclarationsWithComments(config),
StringTemplate(config),
TrailingCommaOnCallSite(config), // in standard ruleset but not enabled by default
TrailingCommaOnDeclarationSite(config), // in standard ruleset but not enabled by default
Wrapping(config),
// Wrappers for ktlint-ruleset-experimental rules. Disabled by default.
BlockCommentInitialStarAlignment(config),
CommentWrapping(config),
DiscouragedCommentLocation(config),
FunctionReturnTypeSpacing(config),
FunKeywordSpacing(config),
FunctionSignature(config),
FunctionStartOfBodySpacing(config),
FunctionTypeReferenceSpacing(config),
KdocWrapping(config),
ModifierListSpacing(config),
NullableTypeSpacing(config),
ParameterListSpacing(config),
SpacingBetweenFunctionNameAndOpeningParenthesis(config),
TypeArgumentListSpacing(config),
TypeParameterListSpacing(config),
UnnecessaryParenthesesBeforeTrailingLambda(config),
)
override fun visit(root: KtFile) {
val sortedRules = getSortedRules()
sortedRules.forEach { it.visit(root) }
root.node.visitTokens { node ->
sortedRules.forEach { it.apply(node) }
}
}
internal fun getSortedRules(): List<FormattingRule> {
val runFirstOnRoot = mutableListOf<FormattingRule>()
val other = mutableListOf<FormattingRule>()
val runLastOnRoot = mutableListOf<FormattingRule>()
val runLast = mutableListOf<FormattingRule>()
for (rule in activeRules.filterIsInstance<FormattingRule>()) {
when {
rule.runOnRootNodeOnly && rule.runAsLateAsPossible -> runLastOnRoot.add(rule)
rule.runOnRootNodeOnly -> runFirstOnRoot.add(rule)
rule.runAsLateAsPossible -> runLast.add(rule)
else -> other.add(rule)
}
}
return LinkedList<FormattingRule>().apply {
addAll(runFirstOnRoot)
addAll(other)
addAll(runLastOnRoot)
addAll(runLast)
}
}
private fun ASTNode.visitTokens(currentNode: (ASTNode) -> Unit) {
if (this.isNoFakeElement()) {
currentNode(this)
}
getChildren(null).forEach { it.visitTokens(currentNode) }
}
private fun ASTNode.isNoFakeElement(): Boolean {
val parent = this.psi?.parent
return parent !is JavaDummyHolder && parent !is JavaDummyElement
}
}