FIR: Support this resolve

This commit is contained in:
Simon Ogorodnik
2019-03-07 16:01:22 +03:00
parent 9dc6d93070
commit 3867b255f2
5 changed files with 96 additions and 13 deletions
@@ -7,6 +7,6 @@ FILE: noPrimaryConstructor.kt
this#.x# = x#
}
public? constructor(): this<NoPrimary>(String())
public? constructor(): this<R|NoPrimary|>(String())
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import com.google.common.collect.LinkedHashMultimap
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
@@ -27,6 +28,7 @@ import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.name.Name
@@ -103,21 +105,45 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
}
fun ConeKotlinType.scope(useSiteSession: FirSession): FirScope {
when (this) {
is ConeClassTypeImpl -> return (this.lookupTag.toSymbol(useSiteSession) as FirBasedSymbol<FirRegularClass>).fir.buildUseSiteScope(
return when (this) {
is ConeAbbreviatedType -> directExpansion.scope(useSiteSession)
is ConeClassLikeType -> (this.lookupTag.toSymbol(useSiteSession) as FirBasedSymbol<FirRegularClass>).fir.buildUseSiteScope(
useSiteSession
)
else -> error("Failed type ${this}")
}
}
inline fun <T> withLabel(labelName: Name, type: ConeKotlinType, block: () -> T): T {
labels.put(labelName, type)
val result = block()
labels.remove(labelName, type)
return result
}
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup(scopes) {
scopes += regularClass.buildUseSiteScope()
super.transformRegularClass(regularClass, data)
withLabel(regularClass.name, regularClass.defaultType()) {
super.transformRegularClass(regularClass, data)
}
}
}
private fun FirRegularClass.defaultType(): ConeClassTypeImpl {
return ConeClassTypeImpl(
symbol.toLookupTag(),
typeParameters.map {
ConeTypeParameterTypeImpl(
it.symbol.toLookupTag(),
isNullable = false
)
}.toTypedArray(),
isNullable = false
)
}
protected inline fun <T> withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T {
val sizeBefore = scopes.size
@@ -133,6 +159,8 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
val scopes = mutableListOf<FirScope>()
val localScopes = mutableListOf<FirLocalScope>()
val labels = LinkedHashMultimap.create<Name, ConeKotlinType>()
enum class CandidateApplicability {
HIDDEN,
PARAMETER_MAPPING_ERROR,
@@ -416,6 +444,15 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
data: Any?
): CompositeTransformResult<FirStatement> {
when (val callee = qualifiedAccessExpression.calleeReference) {
is FirThisReference -> {
val labelName = callee.labelName
val types = if (labelName == null) labels.values() else labels[Name.identifier(labelName)]
val type = types.lastOrNull() ?: ConeKotlinErrorType("Unresolved this@$labelName")
bindingContext[qualifiedAccessExpression] = FirResolvedTypeRefImpl(session, null, type, false, emptyList())
}
}
val callee = qualifiedAccessExpression.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccessExpression.compose()
qualifiedAccessExpression.explicitReceiver?.visitNoTransform(this, null)
@@ -574,19 +611,26 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>(
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
val receiverTypeRef = namedFunction.receiverTypeRef
fun transform(): CompositeTransformResult<FirDeclaration> {
localScopes.lastOrNull()?.storeDeclaration(namedFunction)
return withScopeCleanup(scopes) {
scopes.addIfNotNull(receiverTypeRef?.coneTypeSafe()?.scope(session))
val body = namedFunction.body
if (namedFunction.returnTypeRef is FirImplicitTypeRef && body != null) {
body.visitNoTransform(this, namedFunction.returnTypeRef)
namedFunction.transformReturnTypeRef(this, body.resultType)
}
localScopes.lastOrNull()?.storeDeclaration(namedFunction)
return withScopeCleanup(scopes) {
scopes.addIfNotNull(namedFunction.receiverTypeRef?.coneTypeSafe()?.scope(session))
val body = namedFunction.body
if (namedFunction.returnTypeRef is FirImplicitTypeRef && body != null) {
body.visitNoTransform(this, namedFunction.returnTypeRef)
namedFunction.transformReturnTypeRef(this, body.resultType)
super.transformNamedFunction(namedFunction, data)
}
super.transformNamedFunction(namedFunction, data)
}
return if (receiverTypeRef != null) {
withLabel(namedFunction.name, receiverTypeRef.coneTypeUnsafe()) { transform() }
} else {
transform()
}
}
override fun transformVariable(variable: FirVariable, data: Any?): CompositeTransformResult<FirDeclaration> {
@@ -0,0 +1,9 @@
class Bar
class Foo {
fun bar() = this
fun Bar.buz() = this
fun Bar.foo() = this@Foo
fun Bar.foobar() = this@foobar
}
@@ -0,0 +1,25 @@
FILE: this.kt
public final class Bar {
public constructor(): super<R|kotlin/Any|>()
}
public final class Foo {
public constructor(): super<R|kotlin/Any|>()
public final function bar(): R|Foo| {
return@@@bar this#
}
public final function buz R|Bar|.(): R|Bar| {
return@@@buz this#
}
public final function foo R|Bar|.(): R|Foo| {
return@@@foo this@Foo
}
public final function foobar R|Bar|.(): R|Bar| {
return@@@foobar this@foobar
}
}
@@ -164,6 +164,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/simple.kt");
}
@TestMetadata("this.kt")
public void testThis() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/this.kt");
}
@TestMetadata("when.kt")
public void testWhen() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/when.kt");