
io.gitlab.arturbosch.detekt.rules.style.ForbiddenPublicDataClass.kt Maven / Gradle / Ivy
package io.gitlab.arturbosch.detekt.rules.style
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 io.gitlab.arturbosch.detekt.api.config
import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault
import io.gitlab.arturbosch.detekt.api.internal.Configuration
import io.gitlab.arturbosch.detekt.api.simplePatternToRegex
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierTypeOrDefault
/**
* The data classes are bad for the binary compatibility in public APIs. Avoid to use it.
*
* This rule is aimed to library maintainers. If you are developing a final application you don't need to care about
* this issue.
*
* More info: https://jakewharton.com/public-api-challenges-in-kotlin/
*
*
* data class C(val a: String) // violation: public data class
*
*
*
* internal data class C(val a: String)
*
*/
@ActiveByDefault(since = "1.16.0")
class ForbiddenPublicDataClass(config: Config = Config.empty) : Rule(config) {
override val issue = Issue(
javaClass.simpleName,
Severity.Style,
"The data classes are bad for the binary compatibility in public APIs. Avoid to use it.",
Debt.TWENTY_MINS
)
@Configuration("ignores classes in the specified packages.")
private val ignorePackages: List by config(listOf("*.internal", "*.internal.*")) { packages ->
packages.distinct().map(String::simplePatternToRegex)
}
override fun visitClass(klass: KtClass) {
val packageName = klass.containingKtFile.packageDirective?.packageNameExpression?.text
if (packageName != null && ignorePackages.any { it.matches(packageName) }) {
return
}
val isPublicOrProtected = klass.visibilityModifierTypeOrDefault().let { visibility ->
visibility != KtTokens.INTERNAL_KEYWORD && visibility != KtTokens.PRIVATE_KEYWORD
}
if (isPublicOrProtected) {
if (klass.isData()) {
report(CodeSmell(issue, Entity.from(klass.nameIdentifier ?: klass), ""))
}
super.visitClass(klass)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy