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.analysis.diagnostics.DiagnosticReporter
|
||||||
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.expressions.impl.FirNoReceiverExpression
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
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.symbols.impl.FirPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
|
||||||
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() {
|
||||||
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
@@ -21,14 +24,16 @@ 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
|
||||||
|
val dispatchReceiverType =
|
||||||
|
expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }?.typeRef?.coneType?.fullyExpandedType(context.session)
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
if (expression is FirVariableAssignment && resolvedSymbol is FirPropertySymbol) {
|
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)
|
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
||||||
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false) +
|
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType) +
|
||||||
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
|
||||||
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-8
@@ -75,9 +75,9 @@ object FirOptInUsageBaseChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun FirBasedSymbol<*>.loadExperimentalities(
|
fun FirBasedSymbol<*>.loadExperimentalities(
|
||||||
context: CheckerContext, fromSetter: Boolean
|
context: CheckerContext, fromSetter: Boolean, dispatchReceiverType: ConeKotlinType?
|
||||||
): Set<Experimentality> = loadExperimentalities(
|
): Set<Experimentality> = loadExperimentalities(
|
||||||
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter
|
context, knownExperimentalities = null, visited = mutableSetOf(), fromSetter, dispatchReceiverType
|
||||||
)
|
)
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
@@ -86,6 +86,7 @@ object FirOptInUsageBaseChecker {
|
|||||||
knownExperimentalities: SmartSet<Experimentality>?,
|
knownExperimentalities: SmartSet<Experimentality>?,
|
||||||
visited: MutableSet<FirAnnotatedDeclaration>,
|
visited: MutableSet<FirAnnotatedDeclaration>,
|
||||||
fromSetter: Boolean,
|
fromSetter: Boolean,
|
||||||
|
dispatchReceiverType: ConeKotlinType?,
|
||||||
): Set<Experimentality> {
|
): Set<Experimentality> {
|
||||||
ensureResolved(FirResolvePhase.STATUS)
|
ensureResolved(FirResolvePhase.STATUS)
|
||||||
val fir = this.fir as? FirAnnotatedDeclaration ?: return emptySet()
|
val fir = this.fir as? FirAnnotatedDeclaration ?: return emptySet()
|
||||||
@@ -99,12 +100,12 @@ object FirOptInUsageBaseChecker {
|
|||||||
val parentClassScope = parentClassSymbol?.unsubstitutedScope(context)
|
val parentClassScope = parentClassSymbol?.unsubstitutedScope(context)
|
||||||
if (this is FirNamedFunctionSymbol) {
|
if (this is FirNamedFunctionSymbol) {
|
||||||
parentClassScope?.processDirectlyOverriddenFunctions(this) {
|
parentClassScope?.processDirectlyOverriddenFunctions(this) {
|
||||||
it.loadExperimentalities(context, result, visited, fromSetter = false)
|
it.loadExperimentalities(context, result, visited, fromSetter = false, dispatchReceiverType = null)
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
} else if (this is FirPropertySymbol) {
|
} else if (this is FirPropertySymbol) {
|
||||||
parentClassScope?.processDirectlyOverriddenProperties(this) {
|
parentClassScope?.processDirectlyOverriddenProperties(this) {
|
||||||
it.loadExperimentalities(context, result, visited, fromSetter)
|
it.loadExperimentalities(context, result, visited, fromSetter, dispatchReceiverType = null)
|
||||||
ProcessorAction.NEXT
|
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) {
|
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) {
|
} else if (this is FirRegularClassSymbol && fir is FirRegularClass && !fir.isLocal) {
|
||||||
val parentClassSymbol = outerClassSymbol(context)
|
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) {
|
for (annotation in fir.annotations) {
|
||||||
@@ -164,7 +169,7 @@ object FirOptInUsageBaseChecker {
|
|||||||
) {
|
) {
|
||||||
if (this !is ConeClassLikeType) return
|
if (this !is ConeClassLikeType) return
|
||||||
lookupTag.toSymbol(context.session)?.loadExperimentalities(
|
lookupTag.toSymbol(context.session)?.loadExperimentalities(
|
||||||
context, result, visited, fromSetter = false
|
context, result, visited, fromSetter = false, dispatchReceiverType = null
|
||||||
)
|
)
|
||||||
fullyExpandedType(context.session).typeArguments.forEach {
|
fullyExpandedType(context.session).typeArguments.forEach {
|
||||||
if (!it.isStarProjection) it.type?.addExperimentalities(context, result, visited)
|
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) {
|
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val symbol = expression.symbol ?: return
|
val symbol = expression.symbol ?: return
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false)
|
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType = null)
|
||||||
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with(FirOptInUsageBaseChecker) {
|
with(FirOptInUsageBaseChecker) {
|
||||||
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false) +
|
val experimentalities = symbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType = null) +
|
||||||
loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
|
loadExperimentalitiesFromConeArguments(context, coneType.typeArguments.toList())
|
||||||
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
reportNotAcceptedExperimentalities(experimentalities, typeRef, context, reporter)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -55,4 +55,4 @@ fun use1() {
|
|||||||
C.D.<!OPT_IN_USAGE!>E<!>.<!OPT_IN_USAGE!>F<!>()
|
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) {
|
fun use(arg: NotExperimentalExtension) {
|
||||||
arg.foo()
|
arg.foo()
|
||||||
arg.<!OPT_IN_USAGE_ERROR!>bar<!>()
|
arg.bar()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Marker
|
@Marker
|
||||||
@@ -120,5 +120,5 @@ fun operatorContainerUsage(s: String, a: AnotherContainer) {
|
|||||||
val res1 = s <!OPT_IN_USAGE_ERROR!>-<!> s
|
val res1 = s <!OPT_IN_USAGE_ERROR!>-<!> s
|
||||||
val res2 = <!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<!>
|
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) {
|
fun use(arg: NotExperimentalExtension) {
|
||||||
arg.foo()
|
arg.foo()
|
||||||
arg.<!OPT_IN_USAGE_ERROR!>bar<!>()
|
arg.bar()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Marker
|
@Marker
|
||||||
@@ -120,5 +120,5 @@ fun operatorContainerUsage(s: String, a: AnotherContainer) {
|
|||||||
val res1 = s <!OPT_IN_USAGE_ERROR!>-<!> s
|
val res1 = s <!OPT_IN_USAGE_ERROR!>-<!> s
|
||||||
val res2 = <!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<!>
|
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