FIR: resolve constructors via type-aliases

This commit is contained in:
Simon Ogorodnik
2019-04-18 18:18:32 +03:00
committed by Mikhail Glukhikh
parent aa077b42e9
commit e6ab38a583
7 changed files with 130 additions and 30 deletions
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.classId
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.declarations.superConeTypes
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.service
@@ -59,6 +56,13 @@ fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession, builder: Scope
return symbolProvider.getClassUseSiteMemberScope(this.classId, useSiteSession, builder)!!
}
fun FirTypeAlias.buildUseSiteScope(useSiteSession: FirSession, builder: ScopeSession): FirScope? {
val type = expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>()
return type.scope(useSiteSession, builder)?.let {
type.wrapSubstitutionScopeIfNeed(useSiteSession, it, this, builder)
}
}
fun FirRegularClass.buildDefaultUseSiteScope(useSiteSession: FirSession, builder: ScopeSession): FirScope {
return builder.getOrBuild(symbol, USE_SITE) {
val superTypeScope = FirCompositeScope(mutableListOf())
@@ -81,13 +85,13 @@ fun FirRegularClass.buildDefaultUseSiteScope(useSiteSession: FirSession, builder
private fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
session: FirSession,
useSiteScope: FirScope,
regularClass: FirRegularClass,
declaration: FirClassLikeDeclaration,
builder: ScopeSession
): FirScope {
if (this.typeArguments.isEmpty()) return useSiteScope
return builder.getOrBuild(regularClass.symbol, SubstitutionScopeKey(this)) {
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) {
@Suppress("UNCHECKED_CAST")
val substitution = regularClass.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
val substitution = declaration.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type
}.filter { (_, type) -> type != null }.toMap() as Map<ConeTypeParameterSymbol, ConeKotlinType>
@@ -7,7 +7,19 @@ package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.ConeAbbreviatedType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun MutableList<FirScope>.addImportingScopes(file: FirFile, session: FirSession) {
this += listOf(
@@ -24,3 +36,51 @@ fun MutableList<FirScope>.addImportingScopes(file: FirFile, session: FirSession)
fun FirCompositeScope.addImportingScopes(file: FirFile, session: FirSession) {
scopes.addImportingScopes(file, session)
}
private fun finalExpansionName(symbol: FirTypeAliasSymbol, session: FirSession): Name? {
val expandedType = symbol.fir.expandedTypeRef.coneTypeUnsafe<ConeClassLikeType>()
return when (expandedType) {
is ConeAbbreviatedType ->
expandedType.abbreviationLookupTag.toSymbol(session)?.safeAs<FirTypeAliasSymbol>()?.let {
finalExpansionName(it, session)
}
else -> expandedType.lookupTag.classId.shortClassName
}
}
fun processConstructors(
matchedSymbol: ConeClassLikeSymbol?,
processor: (ConeFunctionSymbol) -> ProcessorAction,
session: FirSession,
scopeSession: ScopeSession,
name: Name
): ProcessorAction {
try {
if (matchedSymbol != null) {
val scope = when (matchedSymbol) {
is FirTypeAliasSymbol -> matchedSymbol.fir.buildUseSiteScope(session, scopeSession)
is FirClassSymbol -> matchedSymbol.fir.buildUseSiteScope(session, scopeSession)
else -> null
}
val constructorName = when (matchedSymbol) {
is FirTypeAliasSymbol -> finalExpansionName(matchedSymbol, session) ?: return ProcessorAction.NEXT
else -> name
}
//TODO: why don't we use declared member scope at this point?
if (scope != null && scope.processFunctionsByName(
constructorName,
processor
) == ProcessorAction.STOP
) {
return ProcessorAction.STOP
}
}
return ProcessorAction.NEXT
} catch (e: Throwable) {
throw RuntimeException("While processing constructors", e)
}
}
@@ -8,14 +8,10 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope
import org.jetbrains.kotlin.fir.resolve.calls.TowerScopeLevel
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.ConeVariableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.scopes.processConstructors
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -55,18 +51,18 @@ abstract class FirAbstractImportingScope(session: FirSession, lookupInFir: Boole
}
} else {
val matchedClass = provider.getClassLikeSymbolByFqName(ClassId(import.packageFqName, name))
if (matchedClass != null && matchedClass is FirClassSymbol) {
//TODO: why don't we use declared member scope at this point?
if (matchedClass.fir.buildUseSiteScope(session, scopeCache).processFunctionsByName(
name,
processor
) == ProcessorAction.STOP
) {
return ProcessorAction.STOP
}
if (processConstructors(
matchedClass,
processor,
session,
scopeCache,
name
).stop()
) {
return ProcessorAction.STOP
}
val symbols = provider.getTopLevelCallableSymbols(callableId.packageName, callableId.callableName)
for (symbol in symbols) {
@@ -8,14 +8,13 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.STOP
import org.jetbrains.kotlin.fir.scopes.processConstructors
import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.ConePropertySymbol
import org.jetbrains.kotlin.fir.symbols.ConeVariableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -29,11 +28,15 @@ class FirTopLevelDeclaredMemberScope(
override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction {
val matchedClass = provider.getClassLikeSymbolByFqName(ClassId(packageFqName, name))
if (matchedClass != null && matchedClass is FirClassSymbol) {
// TODO: why don't we use declared member scope at this point?
if (matchedClass.fir.buildUseSiteScope(session, ScopeSession()).processFunctionsByName(name, processor) == STOP) {
return STOP
}
if (processConstructors(
matchedClass,
processor,
session,
ScopeSession(),
name
).stop()
) {
return ProcessorAction.STOP
}
val symbols = provider.getTopLevelCallableSymbols(packageFqName, name)
for (symbol in symbols) {
@@ -0,0 +1,13 @@
class A(i: Int)
typealias AA = A
class B<T>(t: T)
typealias BB<U> = B<U>
fun main() {
val x = AA(1)
val y = BB<String>("bb")
}
@@ -0,0 +1,19 @@
FILE: typeAliasConstructor.kt
public final class A : R|kotlin/Any| {
public constructor(i: R|kotlin/Int|): R|A| {
super<R|kotlin/Any|>()
}
}
public final typealias AA = R|A|
public final class B<T> : R|kotlin/Any| {
public constructor<T>(t: R|T|): R|B<T>| {
super<R|kotlin/Any|>()
}
}
public final typealias BB<U> = R|B<U>|
public final fun main(): R|kotlin/Unit| {
lval x: R|A| = R|/A.A|(Int(1))
lval y: <ERROR TYPE REF: Inapplicable(INAPPLICABLE): [/B.B]> = <Inapplicable(INAPPLICABLE): [/B.B]>#<R|kotlin/String|>(String(bb))
}
@@ -262,6 +262,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/this.kt");
}
@TestMetadata("typeAliasConstructor.kt")
public void testTypeAliasConstructor() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/typeAliasConstructor.kt");
}
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/vararg.kt");