[FIR] KT-49265: Fix implicit visibility checks

This commit is contained in:
Nikolay Lunyak
2021-10-19 18:57:22 +03:00
committed by teamcityserver
parent 8b859e6558
commit 8d647fa016
10 changed files with 535 additions and 96 deletions
@@ -2285,6 +2285,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierChecker.kt");
}
@Test
@TestMetadata("RedundantVisibilityModifierCheckerForInnerComponents.kt")
public void testRedundantVisibilityModifierCheckerForInnerComponents() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierCheckerForInnerComponents.kt");
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment")
@TestDataPath("$PROJECT_ROOT")
@@ -2000,6 +2000,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierChecker.kt");
}
@TestMetadata("RedundantVisibilityModifierCheckerForInnerComponents.kt")
public void testRedundantVisibilityModifierCheckerForInnerComponents() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierCheckerForInnerComponents.kt");
}
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -5,12 +5,12 @@ abstract class A {
class C1 : A() {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> override var attribute = super.attribute
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set
public set
}
abstract class B2 : A() {
override var attribute = "b"
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set
public set
}
class C2 : B2() {
@@ -0,0 +1,153 @@
FILE: RedundantVisibilityModifierCheckerForInnerComponents.kt
public abstract class Foo : R|kotlin/Any| {
public constructor(): R|Foo| {
super<R|kotlin/Any|>()
}
public abstract var id: R|kotlin/Int|
public get(): R|kotlin/Int|
protected set(value: R|kotlin/Int|): R|kotlin/Unit|
protected open val a: R|kotlin/String| = String(test)
protected get(): R|kotlin/String|
}
public final class Bar : R|Foo| {
public constructor(): R|Bar| {
super<R|Foo|>()
}
public final override var id: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
public set(value: R|kotlin/Int|): R|kotlin/Unit|
public final override val a: R|kotlin/String| = String(rest)
public get(): R|kotlin/String|
}
public abstract class A1 : R|kotlin/Any| {
public constructor(): R|A1| {
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|A1| {
public constructor(): R|C1| {
super<R|A1|>()
}
public final override var attribute: R|kotlin/String| = this@R|/C1|.super<R|A1|>.R|/A1.attribute|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
}
public final fun test1(): R|kotlin/Unit| {
R|/C1.C1|().R|/C1.attribute| = String(c)
}
public abstract class A2 : R|kotlin/Any| {
public constructor(): R|A2| {
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 C2 : R|A2| {
public constructor(): R|C2| {
super<R|A2|>()
}
public final override var attribute: R|kotlin/String| = this@R|/C2|.super<R|A2|>.R|/A2.attribute|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
}
public abstract class A3 : R|kotlin/Any| {
public constructor(): R|A3| {
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 abstract class B3 : R|A3| {
public constructor(): R|B3| {
super<R|A3|>()
}
public open override var attribute: R|kotlin/String| = String(b)
public get(): R|kotlin/String|
protected set(value: R|kotlin/String|): R|kotlin/Unit|
}
public final class C3 : R|B3| {
public constructor(): R|C3| {
super<R|B3|>()
}
public final override var attribute: R|kotlin/String| = this@R|/C3|.super<R|B3|>.R|/B3.attribute|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
}
public abstract class A4 : R|kotlin/Any| {
public constructor(): R|A4| {
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 abstract class B4 : R|A4| {
public constructor(): R|B4| {
super<R|A4|>()
}
public open override var attribute: R|kotlin/String| = String(b)
public get(): R|kotlin/String|
protected set(value: R|kotlin/String|): R|kotlin/Unit|
}
public final class C4 : R|B4| {
public constructor(): R|C4| {
super<R|B4|>()
}
public final override var attribute: R|kotlin/String| = this@R|/C4|.super<R|B4|>.R|/B4.attribute|
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
}
public abstract class A5 : R|kotlin/Any| {
public constructor(): R|A5| {
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 B5 : R|A5| {
public constructor(): R|B5| {
super<R|A5|>()
}
public final override var attribute: R|kotlin/String| = String(b)
public get(): R|kotlin/String|
protected set(value: R|kotlin/String|): R|kotlin/Unit|
}
public final fun test5(): R|kotlin/Unit| {
R|/B5.B5|().R|/B5.attribute| = String(c)
}
@@ -0,0 +1,77 @@
abstract class Foo {
abstract var id: Int
protected set
protected open val a = "test"
}
class Bar : Foo() {
override var id: Int = 1
public set
public override val a = "rest"
}
abstract class A1 {
open var attribute = "a"
protected set
}
class C1 : A1() {
public override var attribute = super.attribute
}
fun test1() {
C1().attribute = "c"
}
abstract class A2 {
open var attribute = "a"
protected set
}
class C2 : A2() {
public override var attribute = super.attribute
set
}
abstract class A3 {
open var attribute = "a"
protected set
}
abstract class B3 : A3() {
override var attribute = "b"
}
class C3 : B3() {
public override var attribute = super.attribute
}
abstract class A4 {
open var attribute = "a"
protected set
}
abstract class B4 : A4() {
override var attribute = "b"
set
}
class C4 : B4() {
public override var attribute = super.attribute
}
abstract class A5 {
open var attribute = "a"
protected set
}
class B5 : A5() {
override var attribute = "b"
set
}
fun test5() {
<!INVISIBLE_SETTER!>B5().attribute<!> = "c"
}
@@ -2285,6 +2285,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierChecker.kt");
}
@Test
@TestMetadata("RedundantVisibilityModifierCheckerForInnerComponents.kt")
public void testRedundantVisibilityModifierCheckerForInnerComponents() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierCheckerForInnerComponents.kt");
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment")
@TestDataPath("$PROJECT_ROOT")
@@ -2285,6 +2285,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierChecker.kt");
}
@Test
@TestMetadata("RedundantVisibilityModifierCheckerForInnerComponents.kt")
public void testRedundantVisibilityModifierCheckerForInnerComponents() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/RedundantVisibilityModifierCheckerForInnerComponents.kt");
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/extendedCheckers/canBeReplacedWithOperatorAssignment")
@TestDataPath("$PROJECT_ROOT")
@@ -5,22 +5,17 @@
package org.jetbrains.kotlin.fir.analysis.checkers.extended
import org.jetbrains.kotlin.KtFakeSourceElement
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.overrideModifier
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.diagnostics.visibilityModifier
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirDeclarationSyntaxChecker
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.*
@@ -28,10 +23,8 @@ 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.scopes.*
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -44,50 +37,136 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (element is FirConstructor && source.kind is KtFakeSourceElementKind) return
if (source.kind is KtFakeSourceElementKind) return
if (
element !is FirMemberDeclaration
&& !(element is FirPropertyAccessor && element.visibility == context.containingPropertyVisibility)
) return
if (element is FirPropertyAccessor) {
return
}
val visibilityModifier = source.treeStructure.visibilityModifier(source.lighterASTNode)
val explicitVisibility = (visibilityModifier?.tokenType as? KtModifierKeywordToken)?.toVisibilityOrNull()
val implicitVisibility = element.implicitVisibility(context)
val containingMemberDeclaration = context.findClosest<FirMemberDeclaration>()
if (element is FirConstructor && element.source?.kind is KtFakeSourceElementKind) {
return
}
when (element) {
is FirProperty -> checkPropertyAndReport(element, context, reporter)
else -> checkElementAndReport(element, context, reporter)
}
}
private fun checkPropertyAndReport(
property: FirProperty,
context: CheckerContext,
reporter: DiagnosticReporter
) {
var setterImplicitVisibility: Visibility? = null
context.withDeclaration(property) {
property.setter?.let { setter ->
val visibility = setter.implicitVisibility(it)
setterImplicitVisibility = visibility
checkElementAndReport(setter, visibility, property, it, reporter)
}
property.getter?.let { getter ->
checkElementAndReport(getter, property, it, reporter)
}
property.backingField?.let { field ->
checkElementAndReport(field, property, it, reporter)
}
}
if (property.canMakeSetterMoreAccessible(setterImplicitVisibility)) {
return
}
checkElementAndReport(property, context, reporter)
}
private fun checkElementAndReport(
element: FirDeclaration,
context: CheckerContext,
reporter: DiagnosticReporter
) = checkElementAndReport(
element,
context.findClosest(),
context,
reporter
)
private fun checkElementAndReport(
element: FirDeclaration,
containingMemberDeclaration: FirMemberDeclaration?,
context: CheckerContext,
reporter: DiagnosticReporter
) = checkElementAndReport(
element,
element.implicitVisibility(context),
containingMemberDeclaration,
context,
reporter
)
private fun checkElementAndReport(
element: FirDeclaration,
implicitVisibility: Visibility,
containingMemberDeclaration: FirMemberDeclaration?,
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (element.source?.kind is KtFakeSourceElementKind) {
return
}
val isAccessorWithSameVisibility = element is FirPropertyAccessor
&& element.visibility == context.containingPropertyVisibility
if (element !is FirMemberDeclaration && !isAccessorWithSameVisibility) {
return
}
val explicitVisibility = element.source?.explicitVisibility
val isHidden = explicitVisibility.isEffectivelyHiddenBy(containingMemberDeclaration)
if (explicitVisibility != implicitVisibility && !isHidden) {
return
}
if (element.isPublicOverriddenWithNonPublicBase(containingMemberDeclaration, context)) {
return
}
reporter.reportOn(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER, context)
reporter.reportOn(element.source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER, context)
}
private fun FirDeclaration.isPublicOverriddenWithNonPublicBase(
container: FirMemberDeclaration?,
context: CheckerContext,
): Boolean {
if (container !is FirClass) {
private fun FirProperty.canMakeSetterMoreAccessible(setterImplicitVisibility: Visibility?): Boolean {
if (!isOverride) {
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
if (!hasSetterWithImplicitVisibility) {
return false
}
return overridden.any { it.visibility != Visibilities.Public }
if (setterImplicitVisibility == null) {
return false
}
return setterImplicitVisibility != visibility
}
private val FirProperty.hasSetterWithImplicitVisibility: Boolean
get() {
val theSetter = setter ?: return false
if (source?.lighterASTNode == theSetter.source?.lighterASTNode) {
return true
}
val theSource = theSetter.source ?: return true
return theSource.explicitVisibility == null
}
private val KtSourceElement.explicitVisibility: Visibility?
get() {
val visibilityModifier = treeStructure.visibilityModifier(lighterASTNode)
return (visibilityModifier?.tokenType as? KtModifierKeywordToken)?.toVisibilityOrNull()
}
private fun Visibility?.isEffectivelyHiddenBy(declaration: FirMemberDeclaration?): Boolean {
val containerVisibility = declaration?.effectiveVisibility?.toVisibility() ?: return false
@@ -101,7 +180,11 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
private fun FirDeclaration.implicitVisibility(context: CheckerContext): Visibility {
return when {
this is FirPropertyAccessor && isSetter && status.isOverride -> this.visibility
this is FirPropertyAccessor
&& isSetter
&& context.containingDeclarations.size >= 2
&& context.containingDeclarations.asReversed()[1] is FirClass
&& propertySymbol?.isOverride == true -> findPropertyAccessorVisibility(this, context)
this is FirPropertyAccessor -> {
context.findClosest<FirProperty>()?.visibility ?: Visibilities.DEFAULT_VISIBILITY
@@ -123,23 +206,79 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
&& context.containingDeclarations.last() is FirClass
&& this.isOverride -> findFunctionVisibility(this, context)
this is FirProperty
&& context.containingDeclarations.last() is FirClass
&& this.isOverride -> findPropertyVisibility(this, context)
else -> Visibilities.DEFAULT_VISIBILITY
}
}
private fun findBiggestVisibility(
processSymbols: ((FirCallableSymbol<*>) -> ProcessorAction) -> Unit
): Visibility {
var current: Visibility = Visibilities.Private
processSymbols {
val difference = Visibilities.compare(current, it.visibility)
if (difference != null && difference < 0) {
current = it.visibility
}
ProcessorAction.NEXT
}
return current
}
private fun findPropertyAccessorVisibility(accessor: FirPropertyAccessor, context: CheckerContext): Visibility {
val containingClass = context.findClosestClassOrObject()?.symbol ?: return Visibilities.Public
val propertySymbol = accessor.propertySymbol ?: return Visibilities.Public
val scope = containingClass.unsubstitutedScope(
context.sessionHolder.session,
context.sessionHolder.scopeSession,
withForcedTypeCalculator = false
)
return findBiggestVisibility { checkVisibility ->
scope.processPropertiesByName(propertySymbol.name) {}
scope.processOverriddenProperties(propertySymbol) { property ->
val setter = property.setterSymbol ?: return@processOverriddenProperties ProcessorAction.NEXT
checkVisibility(setter)
}
}
}
private fun findPropertyVisibility(property: FirProperty, context: CheckerContext): Visibility {
val containingClass = context.findClosestClassOrObject()?.symbol ?: return Visibilities.Public
val scope = containingClass.unsubstitutedScope(
context.sessionHolder.session,
context.sessionHolder.scopeSession,
withForcedTypeCalculator = false
)
return findBiggestVisibility {
scope.processPropertiesByName(property.symbol.name) {}
scope.processOverriddenProperties(property.symbol, it)
}
}
private fun findFunctionVisibility(function: FirSimpleFunction, context: CheckerContext): Visibility {
val currentClassSymbol = context.findClosestClassOrObject()?.symbol ?: return Visibilities.Unknown
val overriddenFunctions = function.overriddenFunctions(currentClassSymbol, context)
var visibility: Visibility = Visibilities.Private
for (func in overriddenFunctions) {
val currentVisibility = func.visibility
val compareResult = Visibilities.compare(currentVisibility, visibility)
if (compareResult != null && compareResult > 0) {
visibility = currentVisibility
}
}
return visibility
val scope = currentClassSymbol.unsubstitutedScope(
context.sessionHolder.session,
context.sessionHolder.scopeSession,
withForcedTypeCalculator = false
)
return findBiggestVisibility {
scope.processFunctionsByName(function.symbol.name) {}
scope.processOverriddenFunctions(function.symbol, it)
}
}
private val CheckerContext.containingPropertyVisibility
@@ -442,10 +442,17 @@ abstract class AbstractFirStatusResolveTransformer(
private fun transformPropertyAccessor(
propertyAccessor: FirPropertyAccessor,
containingProperty: FirProperty,
overriddenStatuses: List<FirResolvedDeclarationStatus> = emptyList(),
) {
propertyAccessor.transformStatus(
this,
statusResolver.resolveStatus(propertyAccessor, containingClass, containingProperty, isLocal = false)
statusResolver.resolveStatus(
propertyAccessor,
containingClass,
containingProperty,
isLocal = false,
overriddenStatuses,
)
)
propertyAccessor.transformValueParameters(this, null)
@@ -474,10 +481,25 @@ abstract class AbstractFirStatusResolveTransformer(
property: FirProperty,
data: FirResolvedDeclarationStatus?
): FirStatement {
property.transformStatus(this, statusResolver.resolveStatus(property, containingClass, isLocal = false))
val overridden = statusResolver.getOverriddenProperties(property, containingClass)
val overriddenProperties = overridden.map {
it.ensureResolved(FirResolvePhase.STATUS)
it.status as FirResolvedDeclarationStatus
}
val overriddenSetters = overridden.mapNotNull {
it.setter?.ensureResolved(FirResolvePhase.STATUS)
it.setter?.status as? FirResolvedDeclarationStatus
}
property.transformStatus(
this,
statusResolver.resolveStatus(property, containingClass, false, overriddenProperties)
)
property.getter?.let { transformPropertyAccessor(it, property) }
property.setter?.let { transformPropertyAccessor(it, property) }
property.setter?.let { transformPropertyAccessor(it, property, overriddenSetters) }
property.backingField?.let {
it.transformStatus(
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
@@ -14,9 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.extensions.FirStatusTransformerExtension
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.statusTransformerExtensions
import org.jetbrains.kotlin.fir.extensions.*
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
@@ -83,43 +81,69 @@ class FirStatusResolver(
}
@OptIn(ExperimentalStdlibApi::class)
fun resolveStatus(property: FirProperty, containingClass: FirClass?, isLocal: Boolean): FirResolvedDeclarationStatus {
val status = property.applyExtensionTransformers { transformStatus(it, property, containingClass, isLocal) }
return resolveStatus(property, status, containingClass, null, isLocal) l@{
if (containingClass == null) return@l emptyList()
@Suppress("RemoveExplicitTypeArguments") // Workaround for KT-42175
buildList<FirProperty> {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
scope.processPropertiesByName(property.name) {}
scope.processDirectOverriddenPropertiesWithBaseScope(property.symbol) { symbol, _ ->
this += symbol.fir
ProcessorAction.NEXT
}
}.map {
fun getOverriddenProperties(
property: FirProperty,
containingClass: FirClass?,
): List<FirProperty> {
if (containingClass == null) {
return emptyList()
}
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
return buildList {
scope.processPropertiesByName(property.name) {}
scope.processDirectOverriddenPropertiesWithBaseScope(property.symbol) { symbol, _ ->
this += symbol.fir
ProcessorAction.NEXT
}
}
}
@OptIn(ExperimentalStdlibApi::class)
fun resolveStatus(
property: FirProperty,
containingClass: FirClass?,
isLocal: Boolean,
overriddenStatuses: List<FirResolvedDeclarationStatus>? = null,
): FirResolvedDeclarationStatus {
val statuses = overriddenStatuses ?: getOverriddenProperties(property, containingClass)
.map {
it.ensureResolved(FirResolvePhase.STATUS)
it.status as FirResolvedDeclarationStatus
}
val status = property.applyExtensionTransformers { transformStatus(it, property, containingClass, isLocal) }
return resolveStatus(property, status, containingClass, null, isLocal, statuses)
}
private fun getOverriddenStatuses(
function: FirSimpleFunction,
containingClass: FirClass?
): List<FirResolvedDeclarationStatus> {
if (containingClass == null) {
return emptyList()
}
@Suppress("RemoveExplicitTypeArguments") // Workaround for KT-42175
return buildList<FirCallableDeclaration> {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
val symbol = function.symbol
scope.processFunctionsByName(function.name) {}
scope.processDirectOverriddenFunctionsWithBaseScope(symbol) { overriddenSymbol, _ ->
this += overriddenSymbol.fir
ProcessorAction.NEXT
}
}.mapNotNull {
it.status as? FirResolvedDeclarationStatus
}
}
@OptIn(ExperimentalStdlibApi::class)
fun resolveStatus(function: FirSimpleFunction, containingClass: FirClass?, isLocal: Boolean): FirResolvedDeclarationStatus {
val status = function.applyExtensionTransformers { transformStatus(it, function, containingClass, isLocal) }
return resolveStatus(function, status, containingClass, null, isLocal) l@{
if (containingClass == null) return@l emptyList()
@Suppress("RemoveExplicitTypeArguments") // Workaround for KT-42175
buildList<FirCallableDeclaration> {
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
val symbol = function.symbol
scope.processFunctionsByName(function.name) {}
scope.processDirectOverriddenFunctionsWithBaseScope(symbol) { overriddenSymbol, _ ->
this += overriddenSymbol.fir
ProcessorAction.NEXT
}
}.mapNotNull {
it.status as? FirResolvedDeclarationStatus
}
}
val overriddenStatuses = getOverriddenStatuses(function, containingClass)
return resolveStatus(function, status, containingClass, null, isLocal, overriddenStatuses)
}
fun resolveStatus(
@@ -128,7 +152,7 @@ class FirStatusResolver(
isLocal: Boolean
): FirResolvedDeclarationStatus {
val status = regularClass.applyExtensionTransformers { transformStatus(it, regularClass, containingClass, isLocal) }
return resolveStatus(regularClass, status, containingClass, null, isLocal) { emptyList() }
return resolveStatus(regularClass, status, containingClass, null, isLocal, emptyList())
}
fun resolveStatus(
@@ -137,28 +161,29 @@ class FirStatusResolver(
isLocal: Boolean
): FirResolvedDeclarationStatus {
val status = typeAlias.applyExtensionTransformers { transformStatus(it, typeAlias, containingClass, isLocal) }
return resolveStatus(typeAlias, status, containingClass, null, isLocal) { emptyList() }
return resolveStatus(typeAlias, status, containingClass, null, isLocal, emptyList())
}
fun resolveStatus(
propertyAccessor: FirPropertyAccessor,
containingClass: FirClass?,
containingProperty: FirProperty?,
isLocal: Boolean
isLocal: Boolean,
overriddenStatuses: List<FirResolvedDeclarationStatus> = emptyList(),
): FirResolvedDeclarationStatus {
val status = propertyAccessor.applyExtensionTransformers {
transformStatus(it, propertyAccessor, containingClass, containingProperty, isLocal)
}
return resolveStatus(propertyAccessor, status, containingClass, containingProperty, isLocal) { emptyList() }
return resolveStatus(propertyAccessor, status, containingClass, containingProperty, isLocal, overriddenStatuses)
}
fun resolveStatus(constructor: FirConstructor, containingClass: FirClass?, isLocal: Boolean): FirResolvedDeclarationStatus {
val status = constructor.applyExtensionTransformers { transformStatus(it, constructor, containingClass, isLocal) }
return resolveStatus(constructor, status, containingClass, null, isLocal) { emptyList() }
return resolveStatus(constructor, status, containingClass, null, isLocal, emptyList())
}
fun resolveStatus(field: FirField, containingClass: FirClass?, isLocal: Boolean): FirResolvedDeclarationStatus {
return resolveStatus(field, field.status, containingClass, null, isLocal) { emptyList() }
return resolveStatus(field, field.status, containingClass, null, isLocal, emptyList())
}
fun resolveStatus(
@@ -167,27 +192,27 @@ class FirStatusResolver(
isLocal: Boolean
): FirResolvedDeclarationStatus {
val status = backingField.applyExtensionTransformers { transformStatus(it, backingField, containingClass, isLocal) }
return resolveStatus(backingField, status, containingClass, null, isLocal) { emptyList() }
return resolveStatus(backingField, status, containingClass, null, isLocal, emptyList())
}
fun resolveStatus(enumEntry: FirEnumEntry, containingClass: FirClass?, isLocal: Boolean): FirResolvedDeclarationStatus {
val status = enumEntry.applyExtensionTransformers { transformStatus(it, enumEntry, containingClass, isLocal) }
return resolveStatus(enumEntry, status, containingClass, null, isLocal) { emptyList() }
return resolveStatus(enumEntry, status, containingClass, null, isLocal, emptyList())
}
private inline fun resolveStatus(
private fun resolveStatus(
declaration: FirDeclaration,
status: FirDeclarationStatus,
containingClass: FirClass?,
containingProperty: FirProperty?,
isLocal: Boolean,
overriddenExtractor: () -> List<FirResolvedDeclarationStatus>
overriddenStatuses: List<FirResolvedDeclarationStatus>
): FirResolvedDeclarationStatus {
if (status is FirResolvedDeclarationStatus) return status
require(status is FirDeclarationStatusImpl)
@Suppress("UNCHECKED_CAST")
val overriddenStatuses = overriddenExtractor() as List<FirResolvedDeclarationStatusImpl>
overriddenStatuses as List<FirResolvedDeclarationStatusImpl>
val visibility = when (status.visibility) {
Visibilities.Unknown -> when {
isLocal -> Visibilities.Local