FIR: spread OptIn markers to children except fake override case
This commit implements KT-49001 for FIR
This commit is contained in:
committed by
TeamCityServer
parent
69e06a242a
commit
a76aee9b69
+7
-2
@@ -10,8 +10,11 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
|
||||
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
||||
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -21,14 +24,16 @@ object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
||||
) return
|
||||
val reference = expression.calleeReference as? FirResolvedNamedReference ?: return
|
||||
val resolvedSymbol = reference.resolvedSymbol
|
||||
val dispatchReceiverType =
|
||||
expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }?.typeRef?.coneType?.fullyExpandedType(context.session)
|
||||
with(FirOptInUsageBaseChecker) {
|
||||
if (expression is FirVariableAssignment && resolvedSymbol is FirPropertySymbol) {
|
||||
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true) +
|
||||
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true, dispatchReceiverType) +
|
||||
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
||||
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
|
||||
return
|
||||
}
|
||||
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false) +
|
||||
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType) +
|
||||
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
||||
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
||||
}
|
||||
|
||||
+13
-8
@@ -75,9 +75,9 @@ object FirOptInUsageBaseChecker {
|
||||
}
|
||||
|
||||
fun FirBasedSymbol<*>.loadExperimentalities(
|
||||
context: CheckerContext, fromSetter: Boolean
|
||||
context: CheckerContext, fromSetter: Boolean, dispatchReceiverType: ConeKotlinType?
|
||||
): Set<Experimentality> = loadExperimentalities(
|
||||
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter
|
||||
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter, dispatchReceiverType
|
||||
)
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
@@ -86,6 +86,7 @@ object FirOptInUsageBaseChecker {
|
||||
knownExperimentalities: SmartSet<Experimentality>?,
|
||||
visited: MutableSet<FirAnnotatedDeclaration>,
|
||||
fromSetter: Boolean,
|
||||
dispatchReceiverType: ConeKotlinType?,
|
||||
): Set<Experimentality> {
|
||||
ensureResolved(FirResolvePhase.STATUS)
|
||||
val fir = this.fir as? FirAnnotatedDeclaration ?: return emptySet()
|
||||
@@ -99,12 +100,12 @@ object FirOptInUsageBaseChecker {
|
||||
val parentClassScope = parentClassSymbol?.unsubstitutedScope(context)
|
||||
if (this is FirNamedFunctionSymbol) {
|
||||
parentClassScope?.processDirectlyOverriddenFunctions(this) {
|
||||
it.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||
it.loadExperimentalities(context, result, visited, fromSetter = false, dispatchReceiverType = null)
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
} else if (this is FirPropertySymbol) {
|
||||
parentClassScope?.processDirectlyOverriddenProperties(this) {
|
||||
it.loadExperimentalities(context, result, visited, fromSetter)
|
||||
it.loadExperimentalities(context, result, visited, fromSetter, dispatchReceiverType = null)
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
@@ -119,13 +120,17 @@ object FirOptInUsageBaseChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||
if (dispatchReceiverType == null) {
|
||||
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false, dispatchReceiverType = null)
|
||||
} else {
|
||||
dispatchReceiverType.addExperimentalities(context, result, visited)
|
||||
}
|
||||
if (fromSetter && this is FirPropertySymbol) {
|
||||
setterSymbol?.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||
setterSymbol?.loadExperimentalities(context, result, visited, fromSetter = false, dispatchReceiverType)
|
||||
}
|
||||
} else if (this is FirRegularClassSymbol && fir is FirRegularClass && !fir.isLocal) {
|
||||
val parentClassSymbol = outerClassSymbol(context)
|
||||
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false)
|
||||
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false, dispatchReceiverType = null)
|
||||
}
|
||||
|
||||
for (annotation in fir.annotations) {
|
||||
@@ -164,7 +169,7 @@ object FirOptInUsageBaseChecker {
|
||||
) {
|
||||
if (this !is ConeClassLikeType) return
|
||||
lookupTag.toSymbol(context.session)?.loadExperimentalities(
|
||||
context, result, visited, fromSetter = false
|
||||
context, result, visited, fromSetter = false, dispatchReceiverType = null
|
||||
)
|
||||
fullyExpandedType(context.session).typeArguments.forEach {
|
||||
if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited)
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ object FirOptInUsageQualifierChecker : FirResolvedQualifierChecker() {
|
||||
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val symbol = expression.symbol ?: return
|
||||
with(FirOptInUsageBaseChecker) {
|
||||
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false)
|
||||
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType = null)
|
||||
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
|
||||
}
|
||||
|
||||
with(FirOptInUsageBaseChecker) {
|
||||
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false) +
|
||||
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType = null) +
|
||||
loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
|
||||
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
||||
}
|
||||
|
||||
+1
-1
@@ -55,4 +55,4 @@ fun use1() {
|
||||
C.D.<!OPT_IN_USAGE!>E<!>.<!OPT_IN_USAGE!>F<!>()
|
||||
}
|
||||
|
||||
fun use2(f: <!OPT_IN_USAGE!>C.D.E.F<!>) = <!OPT_IN_USAGE!>f<!>.hashCode()
|
||||
fun use2(f: <!OPT_IN_USAGE!>C.D.E.F<!>) = <!OPT_IN_USAGE!>f<!>.<!OPT_IN_USAGE!>hashCode<!>()
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ interface NotExperimentalExtension : ExperimentalType {
|
||||
|
||||
fun use(arg: NotExperimentalExtension) {
|
||||
arg.foo()
|
||||
arg.<!OPT_IN_USAGE_ERROR!>bar<!>()
|
||||
arg.bar()
|
||||
}
|
||||
|
||||
@Marker
|
||||
@@ -120,5 +120,5 @@ fun operatorContainerUsage(s: String, a: AnotherContainer) {
|
||||
val res1 = s <!OPT_IN_USAGE_ERROR!>-<!> s
|
||||
val res2 = <!OPT_IN_USAGE_ERROR!>s<!>()
|
||||
val res3 = <!OPT_IN_USAGE_ERROR!>res1<!> <!OPT_IN_USAGE_ERROR!>><!> <!OPT_IN_USAGE_ERROR!>res2<!>
|
||||
<!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>for (c in a) {}<!>
|
||||
<!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>for (c in a) {}<!>
|
||||
}
|
||||
+2
-2
@@ -49,7 +49,7 @@ interface NotExperimentalExtension : ExperimentalType {
|
||||
|
||||
fun use(arg: NotExperimentalExtension) {
|
||||
arg.foo()
|
||||
arg.<!OPT_IN_USAGE_ERROR!>bar<!>()
|
||||
arg.bar()
|
||||
}
|
||||
|
||||
@Marker
|
||||
@@ -120,5 +120,5 @@ fun operatorContainerUsage(s: String, a: AnotherContainer) {
|
||||
val res1 = s <!OPT_IN_USAGE_ERROR!>-<!> s
|
||||
val res2 = <!OPT_IN_USAGE_ERROR!>s<!>()
|
||||
val res3 = <!OPT_IN_USAGE_ERROR!>res1<!> <!OPT_IN_USAGE_ERROR!>><!> <!OPT_IN_USAGE_ERROR!>res2<!>
|
||||
<!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>for (c in a) {}<!>
|
||||
<!OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR, OPT_IN_USAGE_ERROR!>for (c in a) {}<!>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user