[FIR] KT-44939: report REDUNDANT_VISIBILITY for explicit public overriding public
This commit is contained in:
+6
@@ -2273,6 +2273,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantSingleExpressionStringTemplateChecker.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RedundantVisibilityDueToOverride.kt")
|
||||
public void testRedundantVisibilityDueToOverride() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityDueToOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RedundantVisibilityModifierChecker.kt")
|
||||
public void testRedundantVisibilityModifierChecker() throws Exception {
|
||||
|
||||
+5
@@ -1990,6 +1990,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantSingleExpressionStringTemplateChecker.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("RedundantVisibilityDueToOverride.kt")
|
||||
public void testRedundantVisibilityDueToOverride() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityDueToOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("RedundantVisibilityModifierChecker.kt")
|
||||
public void testRedundantVisibilityModifierChecker() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierChecker.kt");
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
FILE: RedundantVisibilityDueToOverride.kt
|
||||
public abstract class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public open var attribute: R|kotlin/String| = String(a)
|
||||
public get(): R|kotlin/String|
|
||||
protected set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public final class C1 : R|A| {
|
||||
public constructor(): R|C1| {
|
||||
super<R|A|>()
|
||||
}
|
||||
|
||||
public final override var attribute: R|kotlin/String| = this@R|/C1|.super<R|A|>.R|/A.attribute|
|
||||
public get(): R|kotlin/String|
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract class B2 : R|A| {
|
||||
public constructor(): R|B2| {
|
||||
super<R|A|>()
|
||||
}
|
||||
|
||||
public open override var attribute: R|kotlin/String| = String(b)
|
||||
public get(): R|kotlin/String|
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public final class C2 : R|B2| {
|
||||
public constructor(): R|C2| {
|
||||
super<R|B2|>()
|
||||
}
|
||||
|
||||
public final override var attribute: R|kotlin/String| = this@R|/C2|.super<R|B2|>.R|/B2.attribute|
|
||||
public get(): R|kotlin/String|
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
abstract class A {
|
||||
open var attribute = "a"
|
||||
protected set
|
||||
}
|
||||
|
||||
class C1 : A() {
|
||||
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> override var attribute = super.attribute
|
||||
public set
|
||||
}
|
||||
|
||||
abstract class B2 : A() {
|
||||
override var attribute = "b"
|
||||
public set
|
||||
}
|
||||
|
||||
class C2 : B2() {
|
||||
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> override var attribute = super.attribute
|
||||
}
|
||||
+6
@@ -2273,6 +2273,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantSingleExpressionStringTemplateChecker.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RedundantVisibilityDueToOverride.kt")
|
||||
public void testRedundantVisibilityDueToOverride() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityDueToOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RedundantVisibilityModifierChecker.kt")
|
||||
public void testRedundantVisibilityModifierChecker() throws Exception {
|
||||
|
||||
+6
@@ -2273,6 +2273,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantSingleExpressionStringTemplateChecker.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RedundantVisibilityDueToOverride.kt")
|
||||
public void testRedundantVisibilityDueToOverride() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityDueToOverride.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RedundantVisibilityModifierChecker.kt")
|
||||
public void testRedundantVisibilityModifierChecker() throws Exception {
|
||||
|
||||
+34
-11
@@ -21,6 +21,14 @@ import org.jetbrains.kotlin.fir.analysis.checkers.toVisibilityOrNull
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isSealed
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
@@ -45,24 +53,39 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
|
||||
val implicitVisibility = element.implicitVisibility(context)
|
||||
val containingMemberDeclaration = context.findClosest<FirMemberDeclaration>()
|
||||
require(containingMemberDeclaration is FirDeclaration?)
|
||||
|
||||
val isHidden = explicitVisibility.isEffectivelyHiddenBy(containingMemberDeclaration)
|
||||
|
||||
val redundantVisibility = when {
|
||||
explicitVisibility == implicitVisibility -> implicitVisibility
|
||||
explicitVisibility.isEffectivelyHiddenBy(containingMemberDeclaration) -> explicitVisibility
|
||||
else -> return
|
||||
if (explicitVisibility != implicitVisibility && !isHidden) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
redundantVisibility == Visibilities.Public
|
||||
&& element is FirProperty
|
||||
&& source.treeStructure.overrideModifier(source.lighterASTNode) != null
|
||||
&& element.isVar
|
||||
&& element.setter?.visibility == Visibilities.Public
|
||||
) return
|
||||
if (element.isPublicOverriddenWithNonPublicBase(containingMemberDeclaration, context)) {
|
||||
return
|
||||
}
|
||||
|
||||
reporter.reportOn(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER, context)
|
||||
}
|
||||
|
||||
private fun FirDeclaration.isPublicOverriddenWithNonPublicBase(
|
||||
container: FirMemberDeclaration?,
|
||||
context: CheckerContext,
|
||||
): Boolean {
|
||||
if (container !is FirClass) {
|
||||
return false
|
||||
}
|
||||
|
||||
val scope = container.unsubstitutedScope(context.session, ScopeSession(), false)
|
||||
|
||||
val overridden = when (this) {
|
||||
is FirProperty -> scope.getDirectOverriddenProperties(symbol)
|
||||
is FirSimpleFunction -> scope.getDirectOverriddenFunctions(symbol)
|
||||
else -> return false
|
||||
}
|
||||
|
||||
return overridden.any { it.visibility != Visibilities.Public }
|
||||
}
|
||||
|
||||
private fun Visibility?.isEffectivelyHiddenBy(declaration: FirMemberDeclaration?): Boolean {
|
||||
val containerVisibility = declaration?.effectiveVisibility?.toVisibility() ?: return false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user