FIR: add classifiers to local scopes, process local class symbols correctly
This commit is contained in:
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
class Context {
|
||||
lateinit var packageFqName: FqName
|
||||
var className: FqName = FqName.ROOT
|
||||
val currentClassId get() = ClassId(packageFqName, className, false)
|
||||
val currentClassId get() = ClassId(packageFqName, className, firFunctions.isNotEmpty())
|
||||
|
||||
val firFunctions = mutableListOf<FirFunction<*>>()
|
||||
val firFunctionCalls = mutableListOf<FirFunctionCall>()
|
||||
|
||||
@@ -27,7 +27,9 @@ import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.invoke
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
@@ -204,7 +206,14 @@ class FirCallResolver(
|
||||
if (referencedSymbol is FirClassLikeSymbol<*>) {
|
||||
val classId = referencedSymbol.classId
|
||||
return FirResolvedQualifierImpl(nameReference.source, classId.packageFqName, classId.relativeClassName).apply {
|
||||
resultType = typeForQualifier(this)
|
||||
resultType = if (classId.isLocal) {
|
||||
typeForQualifierByDeclaration(referencedSymbol.fir, resultType)
|
||||
?: resultType.resolvedTypeFromPrototype(
|
||||
StandardClassIds.Unit(symbolProvider).constructType(emptyArray(), isNullable = false)
|
||||
)
|
||||
} else {
|
||||
typeForQualifier(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class FirProvider : FirSymbolProvider() {
|
||||
abstract fun getFirClassifierByFqName(fqName: ClassId): FirClassLikeDeclaration<*>?
|
||||
abstract fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration<*>?
|
||||
|
||||
abstract override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>?
|
||||
|
||||
|
||||
@@ -242,26 +242,12 @@ fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifi
|
||||
if (classId != null) {
|
||||
val classSymbol = symbolProvider.getClassLikeSymbolByFqName(classId)!!
|
||||
val declaration = classSymbol.phasedFir
|
||||
if (declaration is FirClass) {
|
||||
if (declaration.classKind == ClassKind.OBJECT) {
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
classSymbol.constructType(emptyArray(), false)
|
||||
)
|
||||
} else if (declaration.classKind == ClassKind.ENUM_ENTRY) {
|
||||
val enumClassSymbol = symbolProvider.getClassLikeSymbolByFqName(classSymbol.classId.outerClassId!!)!!
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
enumClassSymbol.constructType(emptyArray(), false)
|
||||
)
|
||||
} else {
|
||||
if (declaration is FirRegularClass) {
|
||||
val companionObject = declaration.companionObject
|
||||
if (companionObject != null) {
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
companionObject.symbol.constructType(emptyArray(), false)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
typeForQualifierByDeclaration(declaration, resultType)?.let { return it }
|
||||
if (declaration is FirRegularClass && declaration.classKind == ClassKind.ENUM_ENTRY) {
|
||||
val enumClassSymbol = symbolProvider.getClassLikeSymbolByFqName(classSymbol.classId.outerClassId!!)!!
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
enumClassSymbol.constructType(emptyArray(), false)
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO: Handle no value type here
|
||||
@@ -270,6 +256,24 @@ fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifi
|
||||
)
|
||||
}
|
||||
|
||||
internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultType: FirTypeRef): FirTypeRef? {
|
||||
if (declaration is FirRegularClass) {
|
||||
if (declaration.classKind == ClassKind.OBJECT) {
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
declaration.symbol.constructType(emptyArray(), false)
|
||||
)
|
||||
} else {
|
||||
val companionObject = declaration.companionObject
|
||||
if (companionObject != null) {
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
companionObject.symbol.constructType(emptyArray(), false)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
|
||||
val makeNullable: Boolean by lazy {
|
||||
if (access is FirQualifiedAccess && access.safe) {
|
||||
|
||||
@@ -52,8 +52,12 @@ val USE_SITE = scopeSessionKey<FirScope>()
|
||||
data class SubstitutionScopeKey(val type: ConeClassLikeType) : ScopeSessionKey<FirClassSubstitutionScope>() {}
|
||||
|
||||
fun FirRegularClass.buildUseSiteMemberScope(useSiteSession: FirSession, builder: ScopeSession): FirScope? {
|
||||
if (classId.isLocal) {
|
||||
// It's not possible to find local class by symbol
|
||||
return buildDefaultUseSiteMemberScope(useSiteSession, builder)
|
||||
}
|
||||
val symbolProvider = useSiteSession.firSymbolProvider
|
||||
return symbolProvider.getClassUseSiteMemberScope(this.classId, useSiteSession, builder)
|
||||
return symbolProvider.getClassUseSiteMemberScope(classId, useSiteSession, builder)
|
||||
}
|
||||
|
||||
fun FirTypeAlias.buildUseSiteMemberScope(useSiteSession: FirSession, builder: ScopeSession): FirScope? {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.references.impl.FirImplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.buildDefaultUseSiteMemberScope
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
@@ -92,7 +93,12 @@ class ImplicitDispatchReceiverValue(
|
||||
scopeSession: ScopeSession
|
||||
) : ImplicitReceiverValue<FirClassSymbol>(boundSymbol, type, useSiteSession, scopeSession) {
|
||||
val implicitCompanionScope: FirScope? = boundSymbol.fir.companionObject?.let { companionObject ->
|
||||
symbolProvider.getClassUseSiteMemberScope(companionObject.classId, useSiteSession, scopeSession)
|
||||
val companionId = companionObject.classId
|
||||
if (companionId.isLocal) {
|
||||
companionObject.buildDefaultUseSiteMemberScope(useSiteSession, scopeSession)
|
||||
} else {
|
||||
symbolProvider.getClassUseSiteMemberScope(companionId, useSiteSession, scopeSession)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,8 +136,11 @@ class FirProviderImpl(val session: FirSession) : FirProvider() {
|
||||
return state.fileMap[fqName].orEmpty()
|
||||
}
|
||||
|
||||
override fun getFirClassifierByFqName(fqName: ClassId): FirClassLikeDeclaration<*>? {
|
||||
return state.classifierMap[fqName]
|
||||
override fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration<*>? {
|
||||
require(!classId.isLocal) {
|
||||
"Local $classId should never be used to find its corresponding classifier"
|
||||
}
|
||||
return state.classifierMap[classId]
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
|
||||
+1
@@ -134,6 +134,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
|
||||
}
|
||||
|
||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirStatement> {
|
||||
localScopes.lastOrNull()?.storeDeclaration(regularClass)
|
||||
val oldConstructorScope = primaryConstructorParametersScope
|
||||
primaryConstructorParametersScope = null
|
||||
val type = regularClass.defaultType()
|
||||
|
||||
@@ -9,21 +9,20 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.NAME_FOR_BACKING_FIELD
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirLocalScope : FirScope() {
|
||||
|
||||
val properties = mutableMapOf<Name, FirVariableSymbol<*>>()
|
||||
val functions = mutableMapOf<Name, FirFunctionSymbol<*>>()
|
||||
val classes = mutableMapOf<Name, FirClassSymbol>()
|
||||
|
||||
fun storeDeclaration(declaration: FirNamedDeclaration) {
|
||||
when (declaration) {
|
||||
is FirVariable<*> -> properties[declaration.name] = declaration.symbol
|
||||
is FirSimpleFunction -> functions[declaration.name] = declaration.symbol as FirNamedFunctionSymbol
|
||||
is FirRegularClass -> classes[declaration.name] = declaration.symbol
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,17 +31,25 @@ class FirLocalScope : FirScope() {
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val prop = functions[name]
|
||||
if (prop != null) {
|
||||
return processor(prop)
|
||||
val function = functions[name]
|
||||
if (function != null) {
|
||||
return processor(function)
|
||||
}
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val prop = properties[name]
|
||||
if (prop != null) {
|
||||
return processor(prop)
|
||||
val property = properties[name]
|
||||
if (property != null) {
|
||||
return processor(property)
|
||||
}
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
|
||||
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val klass = classes[name]
|
||||
if (klass != null) {
|
||||
return processor(klass)
|
||||
}
|
||||
return ProcessorAction.NONE
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
fun test() {
|
||||
class Local
|
||||
|
||||
val l = Local()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
FILE: localConstructor.kt
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
local final class Local : R|kotlin/Any| {
|
||||
public constructor(): R|Local| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lval l: R|Local| = R|/Local.Local|()
|
||||
}
|
||||
@@ -24,7 +24,7 @@ FILE: problems.kt
|
||||
|
||||
}
|
||||
|
||||
<Unresolved name: Local>#()
|
||||
R|/Local.Local|()
|
||||
}
|
||||
public final val R|kotlin/Any|.bar: R|kotlin/String|
|
||||
public get(): R|kotlin/String| {
|
||||
|
||||
+5
@@ -326,6 +326,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localConstructor.kt")
|
||||
public void testLocalConstructor() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localExtension.kt")
|
||||
public void testLocalExtension() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localExtension.kt");
|
||||
|
||||
@@ -3,7 +3,7 @@ FILE fqName:<root> fileName:/localClassWithOverrides.kt
|
||||
BLOCK_BODY
|
||||
CLASS CLASS name:ALocal modality:ABSTRACT visibility:local superTypes:[kotlin.Any]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.outer.ALocal
|
||||
CONSTRUCTOR visibility:public <> () returnType:IrErrorType [primary]
|
||||
CONSTRUCTOR visibility:public <> () returnType:<root>.outer.ALocal [primary]
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:ALocal modality:ABSTRACT visibility:local superTypes:[kotlin.Any]'
|
||||
@@ -21,11 +21,24 @@ FILE fqName:<root> fileName:/localClassWithOverrides.kt
|
||||
correspondingProperty: PROPERTY name:avar visibility:public modality:ABSTRACT [var]
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.outer.ALocal
|
||||
VALUE_PARAMETER name:<set-?> index:0 type:kotlin.Int
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
CLASS CLASS name:Local modality:FINAL visibility:local superTypes:[IrErrorType]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.outer.Local
|
||||
CONSTRUCTOR visibility:public <> () returnType:IrErrorType [primary]
|
||||
CONSTRUCTOR visibility:public <> () returnType:<root>.outer.Local [primary]
|
||||
BLOCK_BODY
|
||||
ERROR_CALL 'Cannot find delegated constructor call' type=IrErrorType
|
||||
ERROR_CALL 'Cannot find delegated constructor call' type=<root>.outer.Local
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Local modality:FINAL visibility:local superTypes:[IrErrorType]'
|
||||
FUN name:afun visibility:public modality:FINAL <> ($this:<root>.outer.Local) returnType:kotlin.Unit
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.outer.Local
|
||||
|
||||
@@ -33,18 +33,18 @@ class IdeFirProvider(
|
||||
// TODO: invalidation?
|
||||
private val files = mutableMapOf<KtFile, FirFile>()
|
||||
|
||||
override fun getFirClassifierByFqName(fqName: ClassId): FirClassLikeDeclaration<*>? {
|
||||
return cacheProvider.getFirClassifierByFqName(fqName) ?: run {
|
||||
override fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration<*>? {
|
||||
return cacheProvider.getFirClassifierByFqName(classId) ?: run {
|
||||
|
||||
val classes = KotlinFullClassNameIndex.getInstance().get(fqName.asSingleFqName().asString(), project, scope)
|
||||
val classes = KotlinFullClassNameIndex.getInstance().get(classId.asSingleFqName().asString(), project, scope)
|
||||
val ktClass = classes.firstOrNull {
|
||||
fqName.packageFqName == it.containingKtFile.packageFqName
|
||||
classId.packageFqName == it.containingKtFile.packageFqName
|
||||
} ?: return null // TODO: what if two of them?
|
||||
val ktFile = ktClass.containingKtFile
|
||||
|
||||
getOrBuildFile(ktFile)
|
||||
|
||||
cacheProvider.getFirClassifierByFqName(fqName)
|
||||
cacheProvider.getFirClassifierByFqName(classId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user