From 73539cf3429b1aec6e43d4cb32a1d1917b055d09 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 21 Jul 2021 20:07:32 +0300 Subject: [PATCH] FIR: use symbols as base for OptIn-checkers --- .../expression/FirOptInUsageAccessChecker.kt | 15 +-- .../expression/FirOptInUsageBaseChecker.kt | 93 ++++++++----------- .../FirOptInUsageQualifierChecker.kt | 8 +- .../type/FirOptInUsageTypeRefChecker.kt | 2 +- 4 files changed, 47 insertions(+), 71 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt index f71dc426cfd..35cf9d084ee 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt @@ -8,17 +8,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration -import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference -import org.jetbrains.kotlin.fir.symbols.SymbolInternals -import org.jetbrains.kotlin.fir.symbols.ensureResolved +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() { - @OptIn(SymbolInternals::class) override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { val sourceKind = expression.source?.kind if (sourceKind is FirFakeSourceElementKind.DataClassGeneratedMembers || @@ -26,16 +21,14 @@ object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() { ) return val reference = expression.calleeReference as? FirResolvedNamedReference ?: return val resolvedSymbol = reference.resolvedSymbol - resolvedSymbol.ensureResolved(FirResolvePhase.STATUS) - val fir = resolvedSymbol.fir as? FirAnnotatedDeclaration ?: return with(FirOptInUsageBaseChecker) { - if (expression is FirVariableAssignment && fir is FirProperty) { - val experimentalities = fir.loadExperimentalities(context, fromSetter = true) + + if (expression is FirVariableAssignment && resolvedSymbol is FirPropertySymbol) { + val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true) + loadExperimentalitiesFromTypeArguments(context, expression.typeArguments) reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter) return } - val experimentalities = fir.loadExperimentalities(context, fromSetter = false) + + val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false) + loadExperimentalitiesFromTypeArguments(context, expression.typeArguments) reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt index 7870ffb70cc..c2f8e117c66 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt @@ -27,10 +27,13 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.ensureResolved +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.checkers.OptInNames @@ -71,58 +74,61 @@ object FirOptInUsageBaseChecker { return result } - fun FirAnnotatedDeclaration.loadExperimentalities( + fun FirBasedSymbol<*>.loadExperimentalities( context: CheckerContext, fromSetter: Boolean ): Set = loadExperimentalities( context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter ) @OptIn(SymbolInternals::class) - private fun FirAnnotatedDeclaration.loadExperimentalities( + private fun FirBasedSymbol<*>.loadExperimentalities( context: CheckerContext, knownExperimentalities: SmartSet?, visited: MutableSet, fromSetter: Boolean, ): Set { - if (!visited.add(this)) return emptySet() + ensureResolved(FirResolvePhase.STATUS) + val fir = this.fir as? FirAnnotatedDeclaration ?: return emptySet() + if (!visited.add(fir)) return emptySet() val result = knownExperimentalities ?: SmartSet.create() val session = context.session - if (this is FirCallableDeclaration) { - val parentClass = containingClass()?.toFirRegularClass(session) - if (this.isSubstitutionOrIntersectionOverride) { - val parentClassScope = parentClass?.unsubstitutedScope(context) - if (this is FirSimpleFunction) { - parentClassScope?.processDirectlyOverriddenFunctions(symbol) { - it.fir.loadExperimentalities(context, result, visited, fromSetter = false) + if (fir is FirCallableDeclaration) { + val parentClassSymbol = fir.containingClass()?.toSymbol(session) as? FirRegularClassSymbol + if (fir.isSubstitutionOrIntersectionOverride) { + parentClassSymbol?.ensureResolved(FirResolvePhase.STATUS) + val parentClassScope = parentClassSymbol?.unsubstitutedScope(context) + if (this is FirNamedFunctionSymbol) { + parentClassScope?.processDirectlyOverriddenFunctions(this) { + it.loadExperimentalities(context, result, visited, fromSetter = false) ProcessorAction.NEXT } - } else if (this is FirProperty) { - parentClassScope?.processDirectlyOverriddenProperties(symbol) { - it.fir.loadExperimentalities(context, result, visited, fromSetter) + } else if (this is FirPropertySymbol) { + parentClassScope?.processDirectlyOverriddenProperties(this) { + it.loadExperimentalities(context, result, visited, fromSetter) ProcessorAction.NEXT } } } - if (this !is FirConstructor) { + if (fir !is FirConstructor) { // Note: coneType here crashes on overridden members - returnTypeRef.coneTypeSafe().addExperimentalities(context, result, visited) - receiverTypeRef?.coneTypeSafe().addExperimentalities(context, result, visited) - if (this is FirSimpleFunction) { - valueParameters.forEach { + fir.returnTypeRef.coneTypeSafe().addExperimentalities(context, result, visited) + fir.receiverTypeRef?.coneTypeSafe().addExperimentalities(context, result, visited) + if (fir is FirSimpleFunction) { + fir.valueParameters.forEach { it.returnTypeRef.coneTypeSafe().addExperimentalities(context, result, visited) } } } - parentClass?.loadExperimentalities(context, result, visited, fromSetter = false) - if (fromSetter && this is FirProperty) { - setter?.loadExperimentalities(context, result, visited, fromSetter = false) + parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false) + if (fromSetter && this is FirPropertySymbol) { + setterSymbol?.loadExperimentalities(context, result, visited, fromSetter = false) } - } else if (this is FirRegularClass && !this.isLocal) { - val parentClassSymbol = symbol.outerClassSymbol(context) - parentClassSymbol?.fir?.loadExperimentalities(context, result, visited, fromSetter = false) + } else if (this is FirRegularClassSymbol && fir is FirRegularClass && !fir.isLocal) { + val parentClassSymbol = outerClassSymbol(context) + parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false) } - for (annotation in annotations) { + for (annotation in fir.annotations) { val annotationType = annotation.annotationTypeRef.coneTypeSafe() if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) { result.addIfNotNull( @@ -133,12 +139,12 @@ object FirOptInUsageBaseChecker { } } - if (this is FirTypeAlias) { - expandedTypeRef.coneType.addExperimentalities(context, result, visited) + if (fir is FirTypeAlias) { + fir.expandedTypeRef.coneType.addExperimentalities(context, result, visited) } - if (getAnnotationByClassId(OptInNames.WAS_EXPERIMENTAL_CLASS_ID) != null) { - val accessibility = checkSinceKotlinVersionAccessibility(context) + if (fir.getAnnotationByClassId(OptInNames.WAS_EXPERIMENTAL_CLASS_ID) != null) { + val accessibility = fir.checkSinceKotlinVersionAccessibility(context) if (accessibility is FirSinceKotlinAccessibility.NotAccessibleButWasExperimental) { accessibility.markerClasses.forEach { it.ensureResolved(FirResolvePhase.STATUS) @@ -151,34 +157,17 @@ object FirOptInUsageBaseChecker { return result } - @OptIn(SymbolInternals::class) private fun ConeKotlinType?.addExperimentalities( context: CheckerContext, result: SmartSet, visited: MutableSet = mutableSetOf() ) { - when (this) { - !is ConeClassLikeType -> return - else -> { - val expandedType = fullyExpandedType(context.session) - if (this === expandedType) { - expandedType.lookupTag.toFirRegularClass(context.session)?.loadExperimentalities( - context, result, visited, fromSetter = false - ) - typeArguments.forEach { - if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited) - } - } else { - val symbol = lookupTag.toSymbol(context.session) - if (symbol != null) { - symbol.ensureResolved(FirResolvePhase.STATUS) - symbol.fir.loadExperimentalities(context, result, visited, fromSetter = false) - } - expandedType.typeArguments.forEach { - if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited) - } - } - } + if (this !is ConeClassLikeType) return + lookupTag.toSymbol(context.session)?.loadExperimentalities( + context, result, visited, fromSetter = false + ) + fullyExpandedType(context.session).typeArguments.forEach { + if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageQualifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageQualifierChecker.kt index 2d363854a75..9eb4f34de9e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageQualifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageQualifierChecker.kt @@ -7,19 +7,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier -import org.jetbrains.kotlin.fir.symbols.SymbolInternals -import org.jetbrains.kotlin.fir.symbols.ensureResolved object FirOptInUsageQualifierChecker : FirResolvedQualifierChecker() { - @OptIn(SymbolInternals::class) override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) { val symbol = expression.symbol ?: return - symbol.ensureResolved(FirResolvePhase.STATUS) - val fir = symbol.fir with(FirOptInUsageBaseChecker) { - val experimentalities = fir.loadExperimentalities(context, fromSetter = false) + val experimentalities = symbol.loadExperimentalities(context, fromSetter = false) reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt index ae703b769ef..1a85c4d57dd 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt @@ -43,7 +43,7 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() { } with(FirOptInUsageBaseChecker) { - val experimentalities = symbol.fir.loadExperimentalities(context, fromSetter = false) + + val experimentalities = symbol.loadExperimentalities(context, fromSetter = false) + loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList()) reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter) }