Skip to content

Commit

Permalink
Add ignoreOverridden support for BooleanPropertyNaming
Browse files Browse the repository at this point in the history
  • Loading branch information
mhernand40 committed Mar 30, 2022
1 parent dd00f22 commit 25b1ddb
Show file tree
Hide file tree
Showing 3 changed files with 290 additions and 1 deletion.
1 change: 1 addition & 0 deletions detekt-core/src/main/resources/default-detekt-config.yml
Expand Up @@ -284,6 +284,7 @@ naming:
BooleanPropertyNaming:
active: false
allowedPattern: '^(is|has|are)'
ignoreOverridden: false
ClassNaming:
active: true
classPattern: '[A-Z][a-zA-Z0-9]*'
Expand Down
Expand Up @@ -12,6 +12,7 @@ import io.gitlab.arturbosch.detekt.api.internal.Configuration
import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution
import io.gitlab.arturbosch.detekt.rules.fqNameOrNull
import io.gitlab.arturbosch.detekt.rules.identifierName
import io.gitlab.arturbosch.detekt.rules.isOverride
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtProperty
Expand All @@ -35,6 +36,9 @@ class BooleanPropertyNaming(config: Config = Config.empty) : Rule(config) {
@Configuration("naming pattern")
private val allowedPattern: Regex by config("^(is|has|are)", String::toRegex)

@Configuration("ignores properties that have the override modifier")
private val ignoreOverridden: Boolean by config(false)

override val issue = Issue(
javaClass.simpleName, Severity.CodeSmell,
"Boolean property name should follow the naming convention set in the projects configuration.",
Expand Down Expand Up @@ -65,7 +69,7 @@ class BooleanPropertyNaming(config: Config = Config.empty) : Rule(config) {
val isBooleanType =
typeName == KOTLIN_BOOLEAN_TYPE_NAME || typeName == JAVA_BOOLEAN_TYPE_NAME

if (isBooleanType && !name.contains(allowedPattern)) {
if (isBooleanType && !name.contains(allowedPattern) && !isIgnoreOverridden(declaration)) {
report(reportCodeSmell(declaration, name))
}
}
Expand All @@ -89,6 +93,8 @@ class BooleanPropertyNaming(config: Config = Config.empty) : Rule(config) {
.toString()
}

private fun isIgnoreOverridden(declaration: KtCallableDeclaration) = ignoreOverridden && declaration.isOverride()

companion object {
const val KOTLIN_BOOLEAN_TYPE_NAME = "kotlin.Boolean"
const val JAVA_BOOLEAN_TYPE_NAME = "java.lang.Boolean"
Expand Down
Expand Up @@ -26,6 +26,35 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean override`() {
val code = """
interface Test {
val default: Boolean
}
data class TestImpl (override var default: Boolean) : Test
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Kotlin Boolean override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean
}
data class TestImpl (override var default: Boolean) : Test
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean nullable`() {
val code = """data class Test (var default: Boolean?)"""
Expand All @@ -34,6 +63,35 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean nullable override`() {
val code = """
interface Test {
val default: Boolean?
}
data class TestImpl (override var default: Boolean?) : Test
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Kotlin Boolean nullable override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean?
}
data class TestImpl (override var default: Boolean?) : Test
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean initialized`() {
val code = """data class Test (var default: Boolean = false)"""
Expand All @@ -42,6 +100,35 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean initialized override`() {
val code = """
interface Test {
val default: Boolean
}
data class TestImpl (override var default: Boolean = false) : Test
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Kotlin Boolean initialized override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean
}
data class TestImpl (override var default: Boolean = false) : Test
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Java Boolean`() {
val code = """data class Test (var default: java.lang.Boolean)"""
Expand All @@ -50,6 +137,35 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Java Boolean override`() {
val code = """
interface Test {
val default: java.lang.Boolean
}
data class TestImpl (override var default: java.lang.Boolean) : Test
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Java Boolean override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: java.lang.Boolean
}
data class TestImpl (override var default: java.lang.Boolean) : Test
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should not detect primitive types`() {
val code = """data class Test (var count: Int)"""
Expand Down Expand Up @@ -81,6 +197,39 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean override`() {
val code = """
interface Test {
val default: Boolean
}
class TestImpl : Test {
override var default: Boolean = true
}
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Kotlin Boolean override if isIgnoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean
}
class TestImpl : Test {
override var default: Boolean = true
}
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean nullable`() {
val code = """
Expand All @@ -93,6 +242,39 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean nullable override`() {
val code = """
interface Test {
val default: Boolean?
}
class TestImpl : Test {
override var default: Boolean? = null
}
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Kotlin Boolean nullable override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean?
}
class TestImpl : Test {
override var default: Boolean? = null
}
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean initialized`() {
val code = """
Expand All @@ -105,6 +287,39 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Kotlin Boolean initialized override`() {
val code = """
interface Test {
val default: Boolean
}
class TestImpl : Test {
override var default: Boolean = false
}
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Kotlin Boolean initialized override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean
}
class TestImpl : Test {
override var default: Boolean = false
}
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about inferred boolean type`() {
val code = """
Expand All @@ -117,6 +332,39 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about inferred boolean type override`() {
val code = """
interface Test {
val default: Boolean
}
class Test : Test {
override var default = true
}
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about inferred boolean type override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: Boolean
}
class Test : Test {
override var default = true
}
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Java Boolean`() {
val code = """
Expand All @@ -129,6 +377,39 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
assertThat(findings).hasSize(1)
}

@Test
fun `should warn about Java Boolean override`() {
val code = """
interface Test {
val default: java.lang.Boolean
}
class TestImpl : Test {
override var default: java.lang.Boolean = java.lang.Boolean(true)
}
"""
val findings = subject.compileAndLintWithContext(env, code)

assertThat(findings).hasSize(2)
}

@Test
fun `should not warn about Java Boolean override if ignoreOverridden is true`() {
val code = """
interface Test {
val default: java.lang.Boolean
}
class TestImpl : Test {
override var default: java.lang.Boolean = java.lang.Boolean(true)
}
"""
val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true))
val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code)

assertThat(findings).hasSize(1)
}

@Test
fun `should not detect primitive types`() {
val code = """
Expand Down Expand Up @@ -171,3 +452,4 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) {
}

private const val ALLOWED_PATTERN = "allowedPattern"
private const val IGNORE_OVERRIDDEN = "ignoreOverridden"

0 comments on commit 25b1ddb

Please sign in to comment.