FIR: Resolve local callables

This commit is contained in:
Simon Ogorodnik
2019-03-07 15:14:04 +03:00
parent 61eb19fbbf
commit 9dc6d93070
15 changed files with 124 additions and 48 deletions
@@ -14,7 +14,11 @@ import org.jetbrains.kotlin.name.Name
data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) { data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) {
val classId: ClassId? get() = className?.let { ClassId(packageName, it, false) } val classId: ClassId? get() = className?.let { ClassId(packageName, it, false) }
constructor(packageName: FqName, callableName: Name): this(packageName, null, callableName) constructor(packageName: FqName, callableName: Name) : this(packageName, null, callableName)
@Deprecated("TODO: Better solution for local callables?")
constructor(callableName: Name) : this(FqName.topLevel(Name.special("<local>")), null, callableName)
override fun toString(): String { override fun toString(): String {
return buildString { return buildString {
@@ -445,9 +445,12 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
val currentClassId get() = ClassId(packageFqName, className, false) val currentClassId get() = ClassId(packageFqName, className, false)
fun callableIdForName(name: Name) = fun callableIdForName(name: Name, local: Boolean = false) =
if (className == FqName.ROOT) CallableId(packageFqName, name) when {
else CallableId(packageFqName, className, name) local -> CallableId(name)
className == FqName.ROOT -> CallableId(packageFqName, name)
else -> CallableId(packageFqName, className, name)
}
fun callableIdForClassConstructor() = fun callableIdForClassConstructor() =
if (className == FqName.ROOT) CallableId(packageFqName, Name.special("<anonymous-init>")) if (className == FqName.ROOT) CallableId(packageFqName, Name.special("<anonymous-init>"))
@@ -561,10 +564,11 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
val firFunction = if (function.name == null) { val firFunction = if (function.name == null) {
FirAnonymousFunctionImpl(session, function, returnType, receiverType) FirAnonymousFunctionImpl(session, function, returnType, receiverType)
} else { } else {
FirMemberFunctionImpl( FirMemberFunctionImpl(
session, session,
function, function,
FirFunctionSymbol(callableIdForName(function.nameAsSafeName)), FirFunctionSymbol(callableIdForName(function.nameAsSafeName, function.isLocal)),
function.nameAsSafeName, function.nameAsSafeName,
function.visibility, function.visibility,
function.modality, function.modality,
@@ -44,7 +44,7 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
} }
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> { override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
return withScopeCleanup { return withScopeCleanup(scopes) {
scopes += FirTopLevelDeclaredMemberScope(file, session) scopes += FirTopLevelDeclaredMemberScope(file, session)
super.transformFile(file, data) super.transformFile(file, data)
} }
@@ -57,6 +57,19 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
return data.compose() return data.compose()
} }
override fun transformFunction(function: FirFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup(localScopes) {
localScopes += FirLocalScope()
super.transformFunction(function, data)
}
}
override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): CompositeTransformResult<FirDeclaration> {
localScopes.lastOrNull()?.storeDeclaration(valueParameter)
return super.transformValueParameter(valueParameter, data)
}
private fun ConeClassLikeType.buildSubstitutionScope( private fun ConeClassLikeType.buildSubstitutionScope(
useSiteSession: FirSession, useSiteSession: FirSession,
@@ -99,14 +112,14 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
} }
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> { override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup { return withScopeCleanup(scopes) {
scopes += regularClass.buildUseSiteScope() scopes += regularClass.buildUseSiteScope()
super.transformRegularClass(regularClass, data) super.transformRegularClass(regularClass, data)
} }
} }
protected inline fun <T> withScopeCleanup(crossinline l: () -> T): T { protected inline fun <T> withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T {
val sizeBefore = scopes.size val sizeBefore = scopes.size
val result = l() val result = l()
val size = scopes.size val size = scopes.size
@@ -118,7 +131,7 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
} }
val scopes = mutableListOf<FirScope>() val scopes = mutableListOf<FirScope>()
val localScopes = mutableListOf<FirScope>() val localScopes = mutableListOf<FirLocalScope>()
enum class CandidateApplicability { enum class CandidateApplicability {
HIDDEN, HIDDEN,
@@ -215,7 +228,7 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
} }
override fun consumeCandidate(group: Int, symbol: ConeCallableSymbol) { override fun consumeCandidate(group: Int, symbol: ConeCallableSymbol) {
if (symbol !is ConePropertySymbol) return if (symbol !is ConeVariableSymbol) return
if (symbol.callableId.callableName != name) return if (symbol.callableId.callableName != name) return
super.consumeCandidate(group, symbol) super.consumeCandidate(group, symbol)
} }
@@ -562,7 +575,8 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> { override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup { localScopes.lastOrNull()?.storeDeclaration(namedFunction)
return withScopeCleanup(scopes) {
scopes.addIfNotNull(namedFunction.receiverTypeRef?.coneTypeSafe()?.scope(session)) scopes.addIfNotNull(namedFunction.receiverTypeRef?.coneTypeSafe()?.scope(session))
val body = namedFunction.body val body = namedFunction.body
if (namedFunction.returnTypeRef is FirImplicitTypeRef && body != null) { if (namedFunction.returnTypeRef is FirImplicitTypeRef && body != null) {
@@ -586,6 +600,9 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
} }
} }
} }
if (variable !is FirProperty) {
localScopes.last().storeDeclaration(variable)
}
return super.transformVariable(variable, data) return super.transformVariable(variable, data)
} }
@@ -5,38 +5,40 @@
package org.jetbrains.kotlin.fir.scopes.impl package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
import org.jetbrains.kotlin.fir.expressions.FirVariable import org.jetbrains.kotlin.fir.expressions.FirVariable
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol 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.name.Name import org.jetbrains.kotlin.name.Name
//class FirLocalScope : FirScope { class FirLocalScope : FirScope {
//
// val properties = mutableMapOf<Name, FirVariable>() val properties = mutableMapOf<Name, ConeVariableSymbol>()
// val functions = mutableMapOf<Name, FirNamedFunction>() val functions = mutableMapOf<Name, ConeFunctionSymbol>()
//
// fun storeDeclaration(declaration: FirNamedDeclaration) { fun storeDeclaration(declaration: FirNamedDeclaration) {
// when (declaration) { when (declaration) {
// is FirVariable -> properties[declaration.name] = declaration is FirVariable -> properties[declaration.name] = declaration.symbol
// is FirNamedFunction -> functions[declaration.name] = declaration is FirNamedFunction -> functions[declaration.name] = declaration.symbol
// }
// } }
// }
// override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction {
// override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction { val prop = functions[name]
// return super.processFunctionsByName(name, processor) if (prop != null) {
// } return processor(prop)
// }
// override fun processPropertiesByName(name: Name, processor: (ConePropertySymbol) -> ProcessorAction): ProcessorAction { return ProcessorAction.NEXT
// val prop = properties[name] }
// if (prop != null) {
// return processor() override fun processPropertiesByName(name: Name, processor: (ConeVariableSymbol) -> ProcessorAction): ProcessorAction {
// } val prop = properties[name]
// return ProcessorAction.NEXT if (prop != null) {
// } return processor(prop)
//} }
return ProcessorAction.NEXT
}
}
+2 -2
View File
@@ -7,9 +7,9 @@ FILE: derivedClass.kt
} }
<T : R|kotlin/Any|> public final class Derived : R|Base<T>| { <T : R|kotlin/Any|> public final class Derived : R|Base<T>| {
public constructor(x: R|T|): super<R|Base<T>|>(R|/Base.x|) public constructor(x: R|T|): super<R|Base<T>|>(R|<local>/x|)
} }
<T : R|kotlin/Any|> public final function create(x: R|T|): R|Derived<T>| { <T : R|kotlin/Any|> public final function create(x: R|T|): R|Derived<T>| {
return@@@create <Unresolved name: Derived>#(<Unresolved name: x>#) return@@@create <Unresolved name: Derived>#(R|<local>/x|)
} }
+1 -1
View File
@@ -28,7 +28,7 @@ FILE: enum.kt
public constructor(): super<R|SomeEnum|>(<Unresolved name: O2>#) public constructor(): super<R|SomeEnum|>(<Unresolved name: O2>#)
public final override function check(y: R|Some|): R|kotlin/Boolean| { public final override function check(y: R|Some|): R|kotlin/Boolean| {
return@@@check ==(<Unresolved name: y>#, <Unresolved name: O2>#) return@@@check ==(R|<local>/y|, <Unresolved name: O2>#)
} }
} }
@@ -30,3 +30,28 @@ fun bar() {
fun buz() { fun buz() {
bar() bar()
} }
fun f() {
val a = 10
val b = a
val d = ""
val c = c
abc()
fun bcd() {}
fun abc() {
val a = d
val b = a
bcd()
fun dcb() {}
dcb()
}
dcb()
abc()
}
@@ -45,3 +45,25 @@ FILE: access.kt
public final function buz(): R|kotlin/Unit| { public final function buz(): R|kotlin/Unit| {
R|/bar|() R|/bar|()
} }
public final function f(): R|kotlin/Unit| {
val a: R|kotlin/Int| = Int(10)
val b: R|kotlin/Int| = R|<local>/a|
val d: R|kotlin/String| = String()
val c: <ERROR TYPE: Unresolved name: c> = <Unresolved name: c>#
<Unresolved name: abc>#()
public final function bcd(): R|kotlin/Unit| {
}
public final function abc(): R|kotlin/Unit| {
val a: R|kotlin/String| = R|<local>/d|
val b: R|kotlin/String| = R|<local>/a|
R|<local>/bcd|()
public final function dcb(): R|kotlin/Unit| {
}
R|<local>/dcb|()
}
<Unresolved name: dcb>#()
R|<local>/abc|()
}
@@ -4,7 +4,7 @@ FILE: noPrimaryConstructor.kt
public get(): R|kotlin/String| public get(): R|kotlin/String|
public constructor(x: R|kotlin/String|): super<R|kotlin/Any|>() { public constructor(x: R|kotlin/String|): super<R|kotlin/Any|>() {
this#.R|/NoPrimary.x| = R|/NoPrimary.x| this#.x# = R|<local>/x|
} }
public constructor(): this<R|NoPrimary|>(String()) public constructor(): this<R|NoPrimary|>(String())
@@ -13,7 +13,7 @@ FILE: simpleClass.kt
private get(): <implicit> private get(): <implicit>
public final override function foo(x: R|kotlin/Int|, y: R|kotlin/String|): R|kotlin/String| { public final override function foo(x: R|kotlin/Int|, y: R|kotlin/String|): R|kotlin/String| {
return@@@foo <Unresolved name: plus>#(<Unresolved name: plus>#(<Unresolved name: y>#, <Unresolved name: x>#), R|/SomeClass.baz|) return@@@foo <Unresolved name: plus>#(<Unresolved name: plus>#(R|<local>/y|, R|<local>/x|), R|/SomeClass.baz|)
} }
public final override property bar(var): R|kotlin/Boolean| public final override property bar(var): R|kotlin/Boolean|
+1 -1
View File
@@ -5,7 +5,7 @@ FILE: functionTypes.kt
<T, R> public final function simpleMap R|kotlin/collections/List<T>|.(f: R|kotlin/Function1|): R|R| { <T, R> public final function simpleMap R|kotlin/collections/List<T>|.(f: R|kotlin/Function1|): R|R| {
} }
<T> public final function simpleWith(t: R|T|, f: R|kotlin/Function1|): R|kotlin/Unit| { <T> public final function simpleWith(t: R|T|, f: R|kotlin/Function1|): R|kotlin/Unit| {
return@@@simpleWith <Unresolved name: t>#.<Unresolved name: f>#() return@@@simpleWith R|<local>/t|.<Unresolved name: f>#()
} }
<T, R> public abstract interface KMutableProperty1 : R|KProperty1<T, R>|, R|KMutableProperty<R>| { <T, R> public abstract interface KMutableProperty1 : R|KProperty1<T, R>|, R|KMutableProperty<R>| {
} }
+1 -1
View File
@@ -10,7 +10,7 @@ FILE: nestedClass.kt
public constructor(): super<R|kotlin/Any|>() public constructor(): super<R|kotlin/Any|>()
public final class Derived : R|Base| { public final class Derived : R|Base| {
public constructor(s: R|kotlin/String|): super<R|Base|>(R|/Base.s|) public constructor(s: R|kotlin/String|): super<R|Base|>(R|<local>/s|)
} }
@@ -3,7 +3,7 @@ FILE: simpleFakeOverride.kt
public constructor(): super<R|kotlin/Any|>() public constructor(): super<R|kotlin/Any|>()
public final function foo(t: R|T|): R|T| { public final function foo(t: R|T|): R|T| {
return@@@foo <Unresolved name: t># return@@@foo R|<local>/t|
} }
} }
+1 -1
View File
@@ -13,7 +13,7 @@ FILE: simpleClass.kt
private get(): <implicit> private get(): <implicit>
public final override function foo(x: R|kotlin/Int|, y: R|kotlin/String|): R|kotlin/String| { public final override function foo(x: R|kotlin/Int|, y: R|kotlin/String|): R|kotlin/String| {
return@@@foo <Unresolved name: plus>#(<Unresolved name: plus>#(<Unresolved name: y>#, <Unresolved name: x>#), R|/SomeClass.baz|) return@@@foo <Unresolved name: plus>#(<Unresolved name: plus>#(R|<local>/y|, R|<local>/x|), R|/SomeClass.baz|)
} }
public final override property bar(var): R|kotlin/Boolean| public final override property bar(var): R|kotlin/Boolean|
@@ -16,5 +16,7 @@ import org.jetbrains.kotlin.name.Name
class FirPropertySymbol(callableId: CallableId) : FirVariableSymbol(callableId), ConePropertySymbol class FirPropertySymbol(callableId: CallableId) : FirVariableSymbol(callableId), ConePropertySymbol
open class FirVariableSymbol(override val callableId: CallableId) : ConeVariableSymbol, AbstractFirBasedSymbol<FirCallableDeclaration>() { open class FirVariableSymbol(override val callableId: CallableId) : ConeVariableSymbol, AbstractFirBasedSymbol<FirCallableDeclaration>() {
constructor(name: Name) : this(CallableId(FqName("var"), name)) // TODO?
@Deprecated("TODO: Better solution for local vars?")
constructor(name: Name) : this(CallableId(name)) // TODO?
} }