FIR: use symbols as base for OptIn-checkers
This commit is contained in:
+4
-11
@@ -8,17 +8,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
|||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
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.FirQualifiedAccess
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
|
||||||
|
|
||||||
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
||||||
@OptIn(SymbolInternals::class)
|
|
||||||
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val sourceKind = expression.source?.kind
|
val sourceKind = expression.source?.kind
|
||||||
if (sourceKind is FirFakeSourceElementKind.DataClassGeneratedMembers ||
|
if (sourceKind is FirFakeSourceElementKind.DataClassGeneratedMembers ||
|
||||||
@@ -26,16 +21,14 @@ object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
|||||||
) return
|
) return
|
||||||
val reference = expression.calleeReference as? FirResolvedNamedReference ?: return
|
val reference = expression.calleeReference as? FirResolvedNamedReference ?: return
|
||||||
val resolvedSymbol = reference.resolvedSymbol
|
val resolvedSymbol = reference.resolvedSymbol
|
||||||
resolvedSymbol.ensureResolved(FirResolvePhase.STATUS)
|
|
||||||
val fir = resolvedSymbol.fir as? FirAnnotatedDeclaration ?: return
|
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
if (expression is FirVariableAssignment && fir is FirProperty) {
|
if (expression is FirVariableAssignment && resolvedSymbol is FirPropertySymbol) {
|
||||||
val experimentalities = fir.loadExperimentalities(context, fromSetter = true) +
|
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true) +
|
||||||
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
||||||
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val experimentalities = fir.loadExperimentalities(context, fromSetter = false) +
|
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false) +
|
||||||
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
||||||
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-52
@@ -27,10 +27,13 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
|
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
|
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
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.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
@@ -71,58 +74,61 @@ object FirOptInUsageBaseChecker {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirAnnotatedDeclaration.loadExperimentalities(
|
fun FirBasedSymbol<*>.loadExperimentalities(
|
||||||
context: CheckerContext, fromSetter: Boolean
|
context: CheckerContext, fromSetter: Boolean
|
||||||
): Set<Experimentality> = loadExperimentalities(
|
): Set<Experimentality> = loadExperimentalities(
|
||||||
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter
|
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
private fun FirAnnotatedDeclaration.loadExperimentalities(
|
private fun FirBasedSymbol<*>.loadExperimentalities(
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
knownExperimentalities: SmartSet<Experimentality>?,
|
knownExperimentalities: SmartSet<Experimentality>?,
|
||||||
visited: MutableSet<FirAnnotatedDeclaration>,
|
visited: MutableSet<FirAnnotatedDeclaration>,
|
||||||
fromSetter: Boolean,
|
fromSetter: Boolean,
|
||||||
): Set<Experimentality> {
|
): Set<Experimentality> {
|
||||||
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 result = knownExperimentalities ?: SmartSet.create()
|
||||||
val session = context.session
|
val session = context.session
|
||||||
if (this is FirCallableDeclaration) {
|
if (fir is FirCallableDeclaration) {
|
||||||
val parentClass = containingClass()?.toFirRegularClass(session)
|
val parentClassSymbol = fir.containingClass()?.toSymbol(session) as? FirRegularClassSymbol
|
||||||
if (this.isSubstitutionOrIntersectionOverride) {
|
if (fir.isSubstitutionOrIntersectionOverride) {
|
||||||
val parentClassScope = parentClass?.unsubstitutedScope(context)
|
parentClassSymbol?.ensureResolved(FirResolvePhase.STATUS)
|
||||||
if (this is FirSimpleFunction) {
|
val parentClassScope = parentClassSymbol?.unsubstitutedScope(context)
|
||||||
parentClassScope?.processDirectlyOverriddenFunctions(symbol) {
|
if (this is FirNamedFunctionSymbol) {
|
||||||
it.fir.loadExperimentalities(context, result, visited, fromSetter = false)
|
parentClassScope?.processDirectlyOverriddenFunctions(this) {
|
||||||
|
it.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
} else if (this is FirProperty) {
|
} else if (this is FirPropertySymbol) {
|
||||||
parentClassScope?.processDirectlyOverriddenProperties(symbol) {
|
parentClassScope?.processDirectlyOverriddenProperties(this) {
|
||||||
it.fir.loadExperimentalities(context, result, visited, fromSetter)
|
it.loadExperimentalities(context, result, visited, fromSetter)
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this !is FirConstructor) {
|
if (fir !is FirConstructor) {
|
||||||
// Note: coneType here crashes on overridden members
|
// Note: coneType here crashes on overridden members
|
||||||
returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
fir.returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
||||||
receiverTypeRef?.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
fir.receiverTypeRef?.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
||||||
if (this is FirSimpleFunction) {
|
if (fir is FirSimpleFunction) {
|
||||||
valueParameters.forEach {
|
fir.valueParameters.forEach {
|
||||||
it.returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
it.returnTypeRef.coneTypeSafe<ConeKotlinType>().addExperimentalities(context, result, visited)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentClass?.loadExperimentalities(context, result, visited, fromSetter = false)
|
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||||
if (fromSetter && this is FirProperty) {
|
if (fromSetter && this is FirPropertySymbol) {
|
||||||
setter?.loadExperimentalities(context, result, visited, fromSetter = false)
|
setterSymbol?.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||||
}
|
}
|
||||||
} else if (this is FirRegularClass && !this.isLocal) {
|
} else if (this is FirRegularClassSymbol && fir is FirRegularClass && !fir.isLocal) {
|
||||||
val parentClassSymbol = symbol.outerClassSymbol(context)
|
val parentClassSymbol = outerClassSymbol(context)
|
||||||
parentClassSymbol?.fir?.loadExperimentalities(context, result, visited, fromSetter = false)
|
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (annotation in annotations) {
|
for (annotation in fir.annotations) {
|
||||||
val annotationType = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()
|
val annotationType = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()
|
||||||
if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) {
|
if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) {
|
||||||
result.addIfNotNull(
|
result.addIfNotNull(
|
||||||
@@ -133,12 +139,12 @@ object FirOptInUsageBaseChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this is FirTypeAlias) {
|
if (fir is FirTypeAlias) {
|
||||||
expandedTypeRef.coneType.addExperimentalities(context, result, visited)
|
fir.expandedTypeRef.coneType.addExperimentalities(context, result, visited)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getAnnotationByClassId(OptInNames.WAS_EXPERIMENTAL_CLASS_ID) != null) {
|
if (fir.getAnnotationByClassId(OptInNames.WAS_EXPERIMENTAL_CLASS_ID) != null) {
|
||||||
val accessibility = checkSinceKotlinVersionAccessibility(context)
|
val accessibility = fir.checkSinceKotlinVersionAccessibility(context)
|
||||||
if (accessibility is FirSinceKotlinAccessibility.NotAccessibleButWasExperimental) {
|
if (accessibility is FirSinceKotlinAccessibility.NotAccessibleButWasExperimental) {
|
||||||
accessibility.markerClasses.forEach {
|
accessibility.markerClasses.forEach {
|
||||||
it.ensureResolved(FirResolvePhase.STATUS)
|
it.ensureResolved(FirResolvePhase.STATUS)
|
||||||
@@ -151,34 +157,17 @@ object FirOptInUsageBaseChecker {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
|
||||||
private fun ConeKotlinType?.addExperimentalities(
|
private fun ConeKotlinType?.addExperimentalities(
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
result: SmartSet<Experimentality>,
|
result: SmartSet<Experimentality>,
|
||||||
visited: MutableSet<FirAnnotatedDeclaration> = mutableSetOf()
|
visited: MutableSet<FirAnnotatedDeclaration> = mutableSetOf()
|
||||||
) {
|
) {
|
||||||
when (this) {
|
if (this !is ConeClassLikeType) return
|
||||||
!is ConeClassLikeType -> return
|
lookupTag.toSymbol(context.session)?.loadExperimentalities(
|
||||||
else -> {
|
context, result, visited, fromSetter = false
|
||||||
val expandedType = fullyExpandedType(context.session)
|
)
|
||||||
if (this === expandedType) {
|
fullyExpandedType(context.session).typeArguments.forEach {
|
||||||
expandedType.lookupTag.toFirRegularClass(context.session)?.loadExperimentalities(
|
if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-7
@@ -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.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
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.expressions.FirResolvedQualifier
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
|
||||||
|
|
||||||
object FirOptInUsageQualifierChecker : FirResolvedQualifierChecker() {
|
object FirOptInUsageQualifierChecker : FirResolvedQualifierChecker() {
|
||||||
@OptIn(SymbolInternals::class)
|
|
||||||
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val symbol = expression.symbol ?: return
|
val symbol = expression.symbol ?: return
|
||||||
symbol.ensureResolved(FirResolvePhase.STATUS)
|
|
||||||
val fir = symbol.fir
|
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
val experimentalities = fir.loadExperimentalities(context, fromSetter = false)
|
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false)
|
||||||
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
val experimentalities = symbol.fir.loadExperimentalities(context, fromSetter = false) +
|
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false) +
|
||||||
loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
|
loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
|
||||||
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user