Skip to content

Commit e2df0c8

Browse files
authored
DataClassesRule shouldn't trigger when no property in constructor (#671)
* DataClassesRule shouldn't trigger when no property in constructor ### What's done: Fixed bug, added test, added logic for empty class and class with property
1 parent ac8bcb0 commit e2df0c8

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/DataClassesRule.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ import com.pinterest.ktlint.core.ast.ElementType.FUN
1818
import com.pinterest.ktlint.core.ast.ElementType.INNER_KEYWORD
1919
import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST
2020
import com.pinterest.ktlint.core.ast.ElementType.OPEN_KEYWORD
21+
import com.pinterest.ktlint.core.ast.ElementType.PRIMARY_CONSTRUCTOR
2122
import com.pinterest.ktlint.core.ast.ElementType.PROPERTY
2223
import com.pinterest.ktlint.core.ast.ElementType.PROPERTY_ACCESSOR
2324
import com.pinterest.ktlint.core.ast.ElementType.SEALED_KEYWORD
2425
import com.pinterest.ktlint.core.ast.ElementType.SUPER_TYPE_LIST
2526
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
2627
import org.jetbrains.kotlin.psi.KtClass
28+
import org.jetbrains.kotlin.psi.KtClassBody
2729
import org.jetbrains.kotlin.psi.KtExpression
30+
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
2831

2932
/**
3033
* This rule checks if class can be made as data class
@@ -59,8 +62,18 @@ class DataClassesRule(private val configRule: List<RulesConfig>) : Rule("data-cl
5962
USE_DATA_CLASS.warn(configRule, emitWarn, isFixMode, "${(node.psi as KtClass).name}", node.startOffset, node)
6063
}
6164

62-
@Suppress("UnsafeCallOnNullableType", "FUNCTION_BOOLEAN_PREFIX")
65+
@Suppress("UnsafeCallOnNullableType", "FUNCTION_BOOLEAN_PREFIX", "ComplexMethod")
6366
private fun ASTNode.canBeDataClass(): Boolean {
67+
val isNotPropertyInClassBody = findChildByType(CLASS_BODY)?.let { (it.psi as KtClassBody).properties.isEmpty() } ?: true
68+
val hasPropertyInConstructor = findChildByType(PRIMARY_CONSTRUCTOR)
69+
?.let { constructor ->
70+
(constructor.psi as KtPrimaryConstructor)
71+
.valueParameters
72+
.run { isNotEmpty() && all { it.hasValOrVar() } }
73+
} ?: false
74+
if (isNotPropertyInClassBody && !hasPropertyInConstructor) {
75+
return false
76+
}
6477
val classBody = getFirstChildWithType(CLASS_BODY)
6578
if (hasChildOfType(MODIFIER_LIST)) {
6679
val list = getFirstChildWithType(MODIFIER_LIST)!!

diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/DataClassesRuleWarnTest.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,56 @@ class DataClassesRuleWarnTest : LintTestBase(::DataClassesRule) {
9696
""".trimMargin()
9797
)
9898
}
99+
100+
@Test
101+
@Tag(USE_DATA_CLASS)
102+
fun `should not trigger on classes with no property in constructor`() {
103+
lintMethod(
104+
"""
105+
|class B(map: Map<Int,Int>) {}
106+
|
107+
|class Ab(val map: Map<Int, Int>, map: Map<Int, Int>) {}
108+
|
109+
|class A(val map: Map<Int, Int>) {}
110+
|
111+
""".trimMargin(),
112+
LintError(5, 1, ruleId, "${Warnings.USE_DATA_CLASS.warnText()} A")
113+
)
114+
}
115+
116+
@Test
117+
@Tag(USE_DATA_CLASS)
118+
fun `should not trigger on empty class`() {
119+
lintMethod(
120+
"""
121+
|class B() {}
122+
|
123+
|class Ab{}
124+
|
125+
""".trimMargin()
126+
)
127+
}
128+
129+
@Test
130+
@Tag(USE_DATA_CLASS)
131+
fun `should trigger on class without constructor but with property`() {
132+
lintMethod(
133+
"""
134+
|class B() {
135+
| val q = 10
136+
|}
137+
|
138+
|class Ab {
139+
| val qw = 10
140+
|}
141+
|
142+
|class Ba {
143+
| val q = 10
144+
| fun foo() = 10
145+
|}
146+
""".trimMargin(),
147+
LintError(1, 1, ruleId, "${Warnings.USE_DATA_CLASS.warnText()} B"),
148+
LintError(5, 1, ruleId, "${Warnings.USE_DATA_CLASS.warnText()} Ab")
149+
)
150+
}
99151
}

0 commit comments

Comments
 (0)