io.gitlab.arturbosch.detekt.rules.style.NestedClassesVisibility.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of detekt-rules-style Show documentation
Show all versions of detekt-rules-style Show documentation
Static code analysis for Kotlin
The newest version!
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.internal.ActiveByDefault
import io.gitlab.arturbosch.detekt.rules.isInternal
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtEnumEntry
/**
* Nested classes inherit their visibility from the parent class
* and are often used to implement functionality local to the class it is nested in.
* These nested classes can't have a higher visibility than their parent.
* However, the visibility can be further restricted by using a private modifier for instance.
* In internal classes the _explicit_ public modifier for nested classes is misleading and thus unnecessary,
* because the nested class still has an internal visibility.
*
*
* internal class Outer {
* // explicit public modifier still results in an internal nested class
* public class Nested
* }
*
*
*
* internal class Outer {
* class Nested1
* internal class Nested2
* }
*
*/
@ActiveByDefault(since = "1.16.0")
class NestedClassesVisibility(config: Config = Config.empty) : Rule(config) {
override val issue: Issue = Issue(
"NestedClassesVisibility",
Severity.Style,
"The explicit public modifier still results in an internal nested class.",
Debt.FIVE_MINS
)
override fun visitClass(klass: KtClass) {
if (!klass.isInterface() && klass.isTopLevel() && klass.isInternal()) {
checkDeclarations(klass)
}
}
private fun checkDeclarations(klass: KtClass) {
klass.declarations
.filterIsInstance()
.filter { it.hasModifier(KtTokens.PUBLIC_KEYWORD) && it.isNoEnum() && it.isNoCompanionObj() }
.forEach { report(CodeSmell(issue, Entity.from(it), issue.description)) }
}
private fun KtClassOrObject.isNoEnum() = !this.hasModifier(KtTokens.ENUM_KEYWORD) && this !is KtEnumEntry
private fun KtClassOrObject.isNoCompanionObj() = !this.hasModifier(KtTokens.COMPANION_KEYWORD)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy