diff --git a/compiler/fir/psi2fir/testData/rawBuilder/declarations/noPrimaryConstructor.txt b/compiler/fir/psi2fir/testData/rawBuilder/declarations/noPrimaryConstructor.txt index 87326547019..2b77642a323 100644 --- a/compiler/fir/psi2fir/testData/rawBuilder/declarations/noPrimaryConstructor.txt +++ b/compiler/fir/psi2fir/testData/rawBuilder/declarations/noPrimaryConstructor.txt @@ -7,6 +7,6 @@ FILE: noPrimaryConstructor.kt this#.x# = x# } - public? constructor(): this(String()) + public? constructor(): this(String()) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt index 7e33a9c61dd..7bd7f4e1490 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt @@ -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( } fun ConeKotlinType.scope(useSiteSession: FirSession): FirScope { - when (this) { - is ConeClassTypeImpl -> return (this.lookupTag.toSymbol(useSiteSession) as FirBasedSymbol).fir.buildUseSiteScope( + return when (this) { + is ConeAbbreviatedType -> directExpansion.scope(useSiteSession) + is ConeClassLikeType -> (this.lookupTag.toSymbol(useSiteSession) as FirBasedSymbol).fir.buildUseSiteScope( useSiteSession ) else -> error("Failed type ${this}") } } + + inline fun 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 { 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 withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T { val sizeBefore = scopes.size @@ -133,6 +159,8 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer( val scopes = mutableListOf() val localScopes = mutableListOf() + val labels = LinkedHashMultimap.create() + enum class CandidateApplicability { HIDDEN, PARAMETER_MAPPING_ERROR, @@ -416,6 +444,15 @@ class FirBodyResolveTransformer(val session: FirSession) : FirTransformer( data: Any? ): CompositeTransformResult { + 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( override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult { + val receiverTypeRef = namedFunction.receiverTypeRef + fun transform(): CompositeTransformResult { + 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 { diff --git a/compiler/fir/resolve/testData/resolve/expresssions/this.kt b/compiler/fir/resolve/testData/resolve/expresssions/this.kt new file mode 100644 index 00000000000..4975a819e8e --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/this.kt @@ -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 +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/expresssions/this.txt b/compiler/fir/resolve/testData/resolve/expresssions/this.txt new file mode 100644 index 00000000000..5368ff92f25 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/this.txt @@ -0,0 +1,25 @@ +FILE: this.kt + public final class Bar { + public constructor(): super() + + } + public final class Foo { + public constructor(): super() + + 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 + } + + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index b9be58bfca1..7b133283060 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -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");