/
NullableBooleanCheckSpec.kt
140 lines (110 loc) · 4.33 KB
/
NullableBooleanCheckSpec.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package io.gitlab.arturbosch.detekt.rules.style
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
import io.gitlab.arturbosch.detekt.test.compileAndLint
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
@KotlinCoreEnvironmentTest
class NullableBooleanCheckSpec(val env: KotlinCoreEnvironment) {
val subject = NullableBooleanCheck(Config.empty)
/**
* The recommended replacement string for `?: [fallback]`.
*/
private fun replacementForElvis(fallback: Boolean): String {
return if (fallback) "!= false" else "== true"
}
@ParameterizedTest
@ValueSource(booleans = [true, false])
fun `does not report when there is no context`(bool: Boolean) {
val code = """
import kotlin.random.Random
fun nullableBoolean(): Boolean? = true.takeIf { Random.nextBoolean() }
fun foo(): Boolean {
return nullableBoolean() ?: $bool
}
"""
assertThat(subject.compileAndLint(code)).isEmpty()
}
@ParameterizedTest
@ValueSource(booleans = [true, false])
fun `reports elvis in statement`(bool: Boolean) {
val code = """
import kotlin.random.Random
fun nullableBoolean(): Boolean? = true.takeIf { Random.nextBoolean() }
fun foo(): Boolean {
return nullableBoolean() ?: $bool
}
"""
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).hasSize(1)
assertThat(findings).first().extracting { it.message }.isEqualTo(
"The nullable boolean check `nullableBoolean() ?: $bool` should use " +
"`${replacementForElvis(bool)}` rather than `?: $bool`"
)
}
@ParameterizedTest
@ValueSource(booleans = [true, false])
fun `reports elvis in if condition`(bool: Boolean) {
val code = """
import kotlin.random.Random
fun nullableBoolean(): Boolean? = true.takeIf { Random.nextBoolean() }
fun foo() {
if (nullableBoolean() ?: $bool) println("foo")
}
"""
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).hasSize(1)
assertThat(findings).first().extracting { it.message }.isEqualTo(
"The nullable boolean check `nullableBoolean() ?: $bool` should use " +
"`${replacementForElvis(bool)}` rather than `?: $bool`"
)
}
@Test
fun `does not report for non-constant fallback`() {
val code = """
import kotlin.random.Random
fun nullableBoolean(): Boolean? = true.takeIf { Random.nextBoolean() }
fun foo(): Boolean {
return nullableBoolean() ?: Random.nextBoolean()
}
"""
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
@ParameterizedTest
@ValueSource(booleans = [true, false])
fun `does not report elvis for non-boolean statement with boolean default`(bool: Boolean) {
val code = """
import kotlin.random.Random
fun nullableAny(): Any? = Unit.takeIf { Random.nextBoolean() }
fun foo(): Any {
return nullableAny() ?: $bool
}
"""
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
@Test
fun `does not report non-boolean elvis`() {
val code = """
import kotlin.random.Random
fun nullableInt(): Int? = 42.takeIf { Random.nextBoolean() }
fun foo(): Int {
return nullableInt() ?: 0
}
"""
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
@Test
fun `does not report non-elvis binary expression`() {
val code = """
import kotlin.random.Random
fun foo(): Boolean {
return Random.nextBoolean() || false
}
"""
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
}