forked from detekt/detekt
/
MandatoryBracesIfStatements.kt
65 lines (57 loc) · 2.38 KB
/
MandatoryBracesIfStatements.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
package io.gitlab.arturbosch.detekt.rules.style.optional
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 org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.kotlin.psi.psiUtil.siblings
/**
* This rule detects multi-line `if` statements which do not have braces.
* Adding braces would improve readability and avoid possible errors.
*
* <noncompliant>
* val i = 1
* if (i > 0)
* println(i)
* </noncompliant>
*
* <compliant>
* val x = if (condition) 5 else 4
* </compliant>
*/
class MandatoryBracesIfStatements(config: Config = Config.empty) : Rule(config) {
override val issue = Issue(
"MandatoryBracesIfStatements",
Severity.Style,
"Multi-line if statement was found that does not have braces. " +
"These braces should be added to improve readability.",
Debt.FIVE_MINS
)
override fun visitIfExpression(expression: KtIfExpression) {
super.visitIfExpression(expression)
val thenExpression = expression.then ?: return
if (thenExpression !is KtBlockExpression && hasNewLineAfter(expression.rightParenthesis)) {
report(CodeSmell(issue, Entity.from(expression.ifKeyword), issue.description))
}
val elseExpression = expression.`else` ?: return
if (mustBeOnSameLine(elseExpression) && hasNewLineAfter(expression.elseKeyword)) {
report(CodeSmell(issue, Entity.from(expression.elseKeyword ?: elseExpression), issue.description))
}
}
private fun hasNewLineAfter(element: PsiElement?): Boolean {
if (element == null) return false
return element
.siblings(forward = true, withItself = false)
.takeWhile { it.text != "else" }
.any { it.textContains('\n') }
}
private fun mustBeOnSameLine(expression: KtExpression): Boolean =
expression !is KtIfExpression && expression !is KtBlockExpression && expression !is KtWhenExpression
}