[FIR JS] Generate dynamic FIRs via DynamicScope
This commit is contained in:
committed by
teamcity
parent
5e97a36680
commit
eaa77b5af6
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideService
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirDynamicMembersStorage
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntersectionOverrideStorage
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirSubstitutionOverrideStorage
|
||||
import org.jetbrains.kotlin.fir.symbols.FirPhaseManager
|
||||
@@ -66,6 +67,7 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
|
||||
register(FirIntersectionOverrideStorage::class, FirIntersectionOverrideStorage(this))
|
||||
register(FirSamConstructorStorage::class, FirSamConstructorStorage(this))
|
||||
register(FirOverrideService::class, FirOverrideService(this))
|
||||
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
|
||||
}
|
||||
|
||||
@OptIn(SessionConfiguration::class)
|
||||
|
||||
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.getOrBuildScopeForIntegerConstantOperatorType
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
@@ -81,6 +78,7 @@ private fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: Scope
|
||||
}
|
||||
}
|
||||
is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession, requiredPhase)
|
||||
is ConeDynamicType -> useSiteSession.dynamicMembersStorage.getDynamicScopeFor(scopeSession)
|
||||
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession, requiredPhase)
|
||||
is ConeIntersectionType -> FirTypeIntersectionScope.prepareIntersectionScope(
|
||||
useSiteSession,
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.DYNAMIC_FQ_NAME
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||
import org.jetbrains.kotlin.fir.caches.createCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirOperationNameConventions
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeDynamicType
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.create
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
@RequiresOptIn(message = "Please, don't create FirDynamicScope-s manually")
|
||||
annotation class FirDynamicScopeConstructor
|
||||
|
||||
class FirDynamicScope @FirDynamicScopeConstructor constructor(
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
) : FirTypeScope() {
|
||||
override fun processDirectOverriddenFunctionsWithBaseScope(
|
||||
functionSymbol: FirNamedFunctionSymbol,
|
||||
processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction = ProcessorAction.NEXT
|
||||
|
||||
override fun processDirectOverriddenPropertiesWithBaseScope(
|
||||
propertySymbol: FirPropertySymbol,
|
||||
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction = ProcessorAction.NEXT
|
||||
|
||||
override fun getCallableNames(): Set<Name> = emptySet()
|
||||
|
||||
override fun getClassifierNames(): Set<Name> = emptySet()
|
||||
|
||||
private val anyTypeScope by lazy {
|
||||
session.builtinTypes.anyType.type.scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(
|
||||
name: Name,
|
||||
processor: (FirNamedFunctionSymbol) -> Unit
|
||||
) {
|
||||
var foundMemberInAny = false
|
||||
|
||||
anyTypeScope?.processFunctionsByName(name) {
|
||||
foundMemberInAny = true
|
||||
processor(it)
|
||||
}
|
||||
|
||||
if (foundMemberInAny) {
|
||||
return
|
||||
}
|
||||
|
||||
session.dynamicMembersStorage.functionsCacheByName.getValue(name, null).also {
|
||||
processor(it.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(
|
||||
name: Name,
|
||||
processor: (FirVariableSymbol<*>) -> Unit
|
||||
) {
|
||||
var foundMemberInAny = false
|
||||
|
||||
anyTypeScope?.processPropertiesByName(name) {
|
||||
foundMemberInAny = true
|
||||
processor(it)
|
||||
}
|
||||
|
||||
if (foundMemberInAny) {
|
||||
return
|
||||
}
|
||||
|
||||
session.dynamicMembersStorage.propertiesCacheByName.getValue(name, null).also {
|
||||
processor(it.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FirDynamicMembersStorage(val session: FirSession) : FirSessionComponent {
|
||||
private val cachesFactory = session.firCachesFactory
|
||||
|
||||
@OptIn(FirDynamicScopeConstructor::class)
|
||||
private val dynamicScopeCacheByScope: FirCache<ScopeSession, FirDynamicScope, Nothing?> =
|
||||
cachesFactory.createCache { it -> FirDynamicScope(session, it) }
|
||||
|
||||
fun getDynamicScopeFor(scopeSession: ScopeSession) = dynamicScopeCacheByScope.getValue(scopeSession, null)
|
||||
|
||||
val functionsCacheByName: FirCache<Name, FirSimpleFunction, Nothing?> =
|
||||
cachesFactory.createCache { name -> buildPseudoFunctionByName(name) }
|
||||
|
||||
val propertiesCacheByName: FirCache<Name, FirProperty, Nothing?> =
|
||||
cachesFactory.createCache { name -> buildPseudoPropertyByName(name) }
|
||||
|
||||
private val dynamicTypeRef = buildResolvedTypeRef {
|
||||
type = ConeDynamicType.create(session)
|
||||
}
|
||||
|
||||
private val anyArrayTypeRef = buildResolvedTypeRef {
|
||||
type = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(StandardClassIds.Array),
|
||||
arrayOf(session.builtinTypes.nullableAnyType.coneType),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildPseudoFunctionByName(name: Name) = buildSimpleFunction {
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.Public,
|
||||
).apply {
|
||||
isInfix = true
|
||||
isOperator = true
|
||||
}
|
||||
|
||||
this.name = name
|
||||
this.symbol = FirNamedFunctionSymbol(CallableId(DYNAMIC_FQ_NAME, this.name))
|
||||
|
||||
moduleData = session.moduleData
|
||||
origin = FirDeclarationOrigin.DynamicScope
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
|
||||
returnTypeRef = if (name in FirOperationNameConventions.ASSIGNMENT_NAMES) {
|
||||
session.builtinTypes.unitType
|
||||
} else {
|
||||
dynamicTypeRef
|
||||
}
|
||||
|
||||
val parameter = buildValueParameter {
|
||||
moduleData = session.moduleData
|
||||
origin = FirDeclarationOrigin.DynamicScope
|
||||
returnTypeRef = anyArrayTypeRef
|
||||
this.name = Name.identifier("args")
|
||||
this.symbol = FirValueParameterSymbol(this.name)
|
||||
isCrossinline = false
|
||||
isNoinline = false
|
||||
isVararg = true
|
||||
}
|
||||
|
||||
valueParameters.add(parameter)
|
||||
}
|
||||
|
||||
private fun buildPseudoPropertyByName(name: Name) = buildProperty {
|
||||
this.name = name
|
||||
this.symbol = FirPropertySymbol(CallableId(DYNAMIC_FQ_NAME, this.name))
|
||||
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.FINAL,
|
||||
EffectiveVisibility.Public,
|
||||
)
|
||||
|
||||
moduleData = session.moduleData
|
||||
origin = FirDeclarationOrigin.DynamicScope
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
returnTypeRef = dynamicTypeRef
|
||||
isVar = true
|
||||
isLocal = false
|
||||
}
|
||||
}
|
||||
|
||||
val FirSession.dynamicMembersStorage: FirDynamicMembersStorage by FirSession.sessionComponentAccessor()
|
||||
@@ -522,6 +522,7 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): Forbidd
|
||||
}
|
||||
}
|
||||
FirDeclarationOrigin.Synthetic -> null
|
||||
FirDeclarationOrigin.DynamicScope -> null
|
||||
FirDeclarationOrigin.RenamedForOverride -> null
|
||||
FirDeclarationOrigin.WrappedIntegerOperator -> null
|
||||
is FirDeclarationOrigin.Plugin -> null // TODO: figure out what to do with plugin generated functions
|
||||
|
||||
@@ -20,6 +20,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
||||
CheckDslScopeViolation,
|
||||
CheckLowPriorityInOverloadResolution,
|
||||
PostponedVariablesInitializerResolutionStage,
|
||||
LowerPriorityIfDynamic,
|
||||
ConstraintSystemForks,
|
||||
CheckIncompatibleTypeVariableUpperBounds,
|
||||
)
|
||||
@@ -53,6 +54,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
||||
EagerResolveOfCallableReferences,
|
||||
CheckLowPriorityInOverloadResolution,
|
||||
PostponedVariablesInitializerResolutionStage,
|
||||
LowerPriorityIfDynamic,
|
||||
ConstraintSystemForks,
|
||||
CheckIncompatibleTypeVariableUpperBounds,
|
||||
)
|
||||
|
||||
+6
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
@@ -79,7 +80,11 @@ fun BodyResolveComponents.mapArguments(
|
||||
|
||||
// If this is an indexed access set operator, it could have default values or a vararg parameter in the middle.
|
||||
// For proper argument mapping, wrap the last one, which is supposed to be the updated value, as a named argument.
|
||||
val isIndexedSetOperator = function is FirSimpleFunction && function.isOperator && function.name == OperatorNameConventions.SET
|
||||
val isIndexedSetOperator = function is FirSimpleFunction
|
||||
&& function.isOperator
|
||||
&& function.name == OperatorNameConventions.SET
|
||||
&& function.origin !is FirDeclarationOrigin.DynamicScope
|
||||
|
||||
if (isIndexedSetOperator &&
|
||||
function.valueParameters.any { it.defaultValue != null || it.isVararg }
|
||||
) {
|
||||
|
||||
@@ -644,6 +644,14 @@ internal object CheckDeprecatedSinceKotlin : ResolutionStage() {
|
||||
}
|
||||
}
|
||||
|
||||
internal object LowerPriorityIfDynamic : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||
if (candidate.symbol.origin is FirDeclarationOrigin.DynamicScope) {
|
||||
candidate.addDiagnostic(LowerPriorityForDynamic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal object ConstraintSystemForks : ResolutionStage() {
|
||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||
if (candidate.system.hasContradiction) return
|
||||
|
||||
+7
-1
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildPlaceholderProjection
|
||||
@@ -33,7 +35,11 @@ internal object MapTypeArguments : ResolutionStage() {
|
||||
|
||||
val owner = candidate.symbol.fir as FirTypeParameterRefsOwner
|
||||
|
||||
if (typeArguments.size == owner.typeParameters.size || callInfo.callKind == CallKind.DelegatingConstructorCall) {
|
||||
if (
|
||||
typeArguments.size == owner.typeParameters.size ||
|
||||
callInfo.callKind == CallKind.DelegatingConstructorCall ||
|
||||
(owner as? FirDeclaration)?.origin is FirDeclarationOrigin.DynamicScope
|
||||
) {
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments)
|
||||
} else {
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(emptyList())
|
||||
|
||||
+2
@@ -89,6 +89,8 @@ class UnsafeCall(val actualType: ConeKotlinType) : ResolutionDiagnostic(UNSAFE_C
|
||||
|
||||
object LowerPriorityToPreserveCompatibilityDiagnostic : ResolutionDiagnostic(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
|
||||
|
||||
object LowerPriorityForDynamic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
|
||||
|
||||
object CandidateChosenUsingOverloadResolutionByLambdaAnnotation : ResolutionDiagnostic(RESOLVED)
|
||||
|
||||
class UnstableSmartCast(val argument: FirExpressionWithSmartcast, val targetType: ConeKotlinType, val isCastToNotNull: Boolean) :
|
||||
|
||||
@@ -12,6 +12,7 @@ sealed class FirDeclarationOrigin(private val displayName: String? = null, val f
|
||||
object BuiltIns : FirDeclarationOrigin()
|
||||
object Java : FirDeclarationOrigin()
|
||||
object Synthetic : FirDeclarationOrigin()
|
||||
object DynamicScope : FirDeclarationOrigin()
|
||||
object SamConstructor : FirDeclarationOrigin()
|
||||
object Enhancement : FirDeclarationOrigin()
|
||||
object ImportedFromObject : FirDeclarationOrigin()
|
||||
|
||||
@@ -32,6 +32,8 @@ object StandardNames {
|
||||
|
||||
@JvmField val CONTEXT_FUNCTION_TYPE_PARAMETER_COUNT_NAME = Name.identifier("count")
|
||||
|
||||
@JvmField val DYNAMIC_FQ_NAME = FqName("<dynamic>")
|
||||
|
||||
@JvmField val COROUTINES_PACKAGE_FQ_NAME = FqName("kotlin.coroutines")
|
||||
|
||||
@JvmField val COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME = FqName("kotlin.coroutines.jvm.internal")
|
||||
|
||||
Reference in New Issue
Block a user