diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeKotlinType.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeKotlinType.kt index b9659631ccf..9dc11c92377 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeKotlinType.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeKotlinType.kt @@ -30,4 +30,10 @@ abstract class ConeKotlinType : ConeKotlinTypeProjection(ProjectionKind.INVARIAN abstract class ConeClassType : ConeKotlinType() { abstract val fqName: ClassId +} + +abstract class ConeAbbreviatedType : ConeClassType() { + abstract val abbreviationFqName: ClassId + + abstract val directExpansion: ConeKotlinType } \ No newline at end of file diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/impl/Impl.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/impl/Impl.kt index 22d5714d71b..cff1f392043 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/impl/Impl.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/impl/Impl.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.types.impl import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.ClassId -class ConeClassTypeImpl( +open class ConeClassTypeImpl( override val fqName: ClassId, override val typeArguments: List ) : ConeClassType() @@ -24,4 +24,13 @@ class ConeKotlinErrorType(val reason: String) : ConeKotlinType() { override fun toString(): String { return "" } +} + +class ConeAbbreviatedTypeImpl( + override val abbreviationFqName: ClassId, + override val typeArguments: List, + override val directExpansion: ConeKotlinType +) : ConeAbbreviatedType() { + override val fqName: ClassId + get() = abbreviationFqName } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt index 35d08bcb2b0..99050ef1fbd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/descriptors/FirTypeResolveTransformer.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.resolve.FirTypeResolver import org.jetbrains.kotlin.fir.scopes.FirScope @@ -59,6 +60,11 @@ class FirTypeResolveTransformer : FirTransformer() { return result } + override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult { + typeAlias.transformChildren(SuperTypeResolver(), null) + return super.transformTypeAlias(typeAlias, data) + } + override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult { val typeResolver = FirTypeResolver.getInstance(type.session) return FirResolvedTypeImpl( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt index 0ab2e3bcda1..527f993f168 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirQualifierResolverImpl.kt @@ -6,10 +6,13 @@ package org.jetbrains.kotlin.fir.resolve.impl import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration +import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeAbbreviatedTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionInImpl import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionOutImpl @@ -19,23 +22,38 @@ import org.jetbrains.kotlin.types.Variance class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver { - private fun FirMemberDeclaration.toConeKotlinType(fqName: ClassId, parts: List): ConeKotlinType? { - return ConeClassTypeImpl(fqName, parts.flatMap { - it.typeArguments.map { - when (it) { - is FirStarProjection -> StarProjection - is FirTypeProjectionWithVariance -> { - val type = (it.type as FirResolvedType).type - when (it.variance) { - Variance.INVARIANT -> type - Variance.IN_VARIANCE -> ConeKotlinTypeProjectionInImpl(type) - Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOutImpl(type) - } + private fun List.toTypeProjections() = flatMap { + it.typeArguments.map { + when (it) { + is FirStarProjection -> StarProjection + is FirTypeProjectionWithVariance -> { + val type = (it.type as FirResolvedType).type + when (it.variance) { + Variance.INVARIANT -> type + Variance.IN_VARIANCE -> ConeKotlinTypeProjectionInImpl(type) + Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOutImpl(type) } - else -> error("!") } + else -> error("!") } - }) + } + } + + private fun FirMemberDeclaration.toConeKotlinType(fqName: ClassId, parts: List): ConeKotlinType? { + return when (this) { + is FirClass -> { + ConeClassTypeImpl(fqName, parts.toTypeProjections()) + } + is FirTypeAlias -> { + ConeAbbreviatedTypeImpl( + abbreviationFqName = fqName, + typeArguments = parts.toTypeProjections(), + directExpansion = (this.abbreviatedType as FirResolvedType).type + ) + + } + else -> error("!") + } } override fun resolveTypeWithPrefix(parts: List, prefix: ClassId): ConeKotlinType? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt index 5d699159f8c..2221a69578b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt @@ -9,10 +9,13 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.types.ConeAbbreviatedType import org.jetbrains.kotlin.fir.types.ConeClassType import org.jetbrains.kotlin.fir.types.FirResolvedType +import org.jetbrains.kotlin.fir.types.coneTypeUnsafe import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -24,15 +27,26 @@ class FirNestedClassifierScope(val classId: ClassId, val session: FirSession) : return firProvider.getFirClassifierByFqName(this) } + private tailrec fun ConeClassType.computePartialExpansion(): ClassId { + return when (this) { + !is ConeAbbreviatedType -> this.fqName + else -> (this.directExpansion as ConeClassType).computePartialExpansion() + } + } + private val superScopes by lazy { val self = classId.getFir() when (self) { is FirClass -> { val superTypes = self.superTypes as List FirCompositeScope(superTypes.mapTo(ArrayList(superTypes.size)) { - FirNestedClassifierScope((it.type as ConeClassType).fqName, session) + FirNestedClassifierScope(it.coneTypeUnsafe().computePartialExpansion(), session) }) } + is FirTypeAlias -> { + val expansionTarget = self.abbreviatedType.coneTypeUnsafe().computePartialExpansion() + FirNestedClassifierScope(expansionTarget, session) + } else -> error("!") } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index 5fad7d96f49..c26b019c0a1 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -393,6 +393,9 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { is ConeKotlinType -> it.asString() } }) + if (this is ConeAbbreviatedType) { + sb.append(" = ${this.directExpansion.asString()}") + } sb.toString() } else -> "Unsupported: $this" diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt index 80f058b4131..40cb3d14bf3 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt @@ -8,9 +8,12 @@ package org.jetbrains.kotlin.fir.declarations.impl import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirTypeAlias +import org.jetbrains.kotlin.fir.transformSingle import org.jetbrains.kotlin.fir.types.FirType +import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.name.Name class FirTypeAliasImpl( @@ -18,5 +21,11 @@ class FirTypeAliasImpl( psi: PsiElement?, name: Name, visibility: Visibility, - override val abbreviatedType: FirType -) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL), FirTypeAlias \ No newline at end of file + override var abbreviatedType: FirType +) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL), FirTypeAlias { + override fun transformChildren(transformer: FirTransformer, data: D): FirElement { + abbreviatedType = abbreviatedType.transformSingle(transformer, data) + + return this + } +} \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirResolvedType.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirResolvedType.kt index 34d089c38e5..9a8e8bdac3d 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirResolvedType.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirResolvedType.kt @@ -13,4 +13,6 @@ interface FirResolvedType : FirTypeWithNullability { override fun accept(visitor: FirVisitor, data: D): R = visitor.visitResolvedType(this, data) -} \ No newline at end of file +} + +inline fun FirType.coneTypeUnsafe() = (this as FirResolvedType).type as T \ No newline at end of file diff --git a/compiler/testData/fir/resolve/NestedOfAliasedType.kt b/compiler/testData/fir/resolve/NestedOfAliasedType.kt new file mode 100644 index 00000000000..2af76b328d1 --- /dev/null +++ b/compiler/testData/fir/resolve/NestedOfAliasedType.kt @@ -0,0 +1,9 @@ +abstract class A { + abstract class Nested +} + +typealias TA = A + +class B : TA() { + class NestedInB : Nested() +} \ No newline at end of file diff --git a/compiler/testData/fir/resolve/NestedOfAliasedType.txt b/compiler/testData/fir/resolve/NestedOfAliasedType.txt new file mode 100644 index 00000000000..c8eb27131ae --- /dev/null +++ b/compiler/testData/fir/resolve/NestedOfAliasedType.txt @@ -0,0 +1,12 @@ +FILE: NestedOfAliasedType.kt + unknown abstract class A() { + unknown abstract class Nested() { + } + + } + unknown final typealias TA = R/.A/ + unknown final class B() : R/.TA = .A/ { + unknown final class NestedInB() : R/.A.Nested/ { + } + + } diff --git a/compiler/testData/fir/resolve/simpleTypeAlias.kt b/compiler/testData/fir/resolve/simpleTypeAlias.kt new file mode 100644 index 00000000000..00b88d1bd87 --- /dev/null +++ b/compiler/testData/fir/resolve/simpleTypeAlias.kt @@ -0,0 +1,5 @@ +interface B + +typealias C = B + +class D : C \ No newline at end of file diff --git a/compiler/testData/fir/resolve/simpleTypeAlias.txt b/compiler/testData/fir/resolve/simpleTypeAlias.txt new file mode 100644 index 00000000000..92a4901f564 --- /dev/null +++ b/compiler/testData/fir/resolve/simpleTypeAlias.txt @@ -0,0 +1,6 @@ +FILE: simpleTypeAlias.kt + unknown final interface B() { + } + unknown final typealias C = R/.B/ + unknown final class D() : R/.C = .B/ { + } diff --git a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index f767a72797a..304383d59e1 100644 --- a/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -31,6 +31,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { doTest(fileName); } + @TestMetadata("NestedOfAliasedType.kt") + public void testNestedOfAliasedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/NestedOfAliasedType.kt"); + doTest(fileName); + } + @TestMetadata("NestedSuperType.kt") public void testNestedSuperType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/NestedSuperType.kt"); @@ -43,6 +49,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { doTest(fileName); } + @TestMetadata("simpleTypeAlias.kt") + public void testSimpleTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/simpleTypeAlias.kt"); + doTest(fileName); + } + @TestMetadata("TwoDeclarationsInSameFile.kt") public void testTwoDeclarationsInSameFile() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt");