FIR: support type alias resolve
This commit is contained in:
@@ -30,4 +30,10 @@ abstract class ConeKotlinType : ConeKotlinTypeProjection(ProjectionKind.INVARIAN
|
|||||||
|
|
||||||
abstract class ConeClassType : ConeKotlinType() {
|
abstract class ConeClassType : ConeKotlinType() {
|
||||||
abstract val fqName: ClassId
|
abstract val fqName: ClassId
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ConeAbbreviatedType : ConeClassType() {
|
||||||
|
abstract val abbreviationFqName: ClassId
|
||||||
|
|
||||||
|
abstract val directExpansion: ConeKotlinType
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.types.impl
|
|||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
class ConeClassTypeImpl(
|
open class ConeClassTypeImpl(
|
||||||
override val fqName: ClassId,
|
override val fqName: ClassId,
|
||||||
override val typeArguments: List<ConeKotlinTypeProjection>
|
override val typeArguments: List<ConeKotlinTypeProjection>
|
||||||
) : ConeClassType()
|
) : ConeClassType()
|
||||||
@@ -24,4 +24,13 @@ class ConeKotlinErrorType(val reason: String) : ConeKotlinType() {
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "<ERROR TYPE: $reason>"
|
return "<ERROR TYPE: $reason>"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConeAbbreviatedTypeImpl(
|
||||||
|
override val abbreviationFqName: ClassId,
|
||||||
|
override val typeArguments: List<ConeKotlinTypeProjection>,
|
||||||
|
override val directExpansion: ConeKotlinType
|
||||||
|
) : ConeAbbreviatedType() {
|
||||||
|
override val fqName: ClassId
|
||||||
|
get() = abbreviationFqName
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirElement
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
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.FirProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
@@ -59,6 +60,11 @@ class FirTypeResolveTransformer : FirTransformer<Nothing?>() {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
|
typeAlias.transformChildren(SuperTypeResolver(), null)
|
||||||
|
return super.transformTypeAlias(typeAlias, data)
|
||||||
|
}
|
||||||
|
|
||||||
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
|
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
|
||||||
val typeResolver = FirTypeResolver.getInstance(type.session)
|
val typeResolver = FirTypeResolver.getInstance(type.session)
|
||||||
return FirResolvedTypeImpl(
|
return FirResolvedTypeImpl(
|
||||||
|
|||||||
+32
-14
@@ -6,10 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve.impl
|
package org.jetbrains.kotlin.fir.resolve.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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.FirMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
|
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
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.ConeClassTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionInImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionInImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionOutImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinTypeProjectionOutImpl
|
||||||
@@ -19,23 +22,38 @@ import org.jetbrains.kotlin.types.Variance
|
|||||||
|
|
||||||
class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
|
class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
|
||||||
|
|
||||||
private fun FirMemberDeclaration.toConeKotlinType(fqName: ClassId, parts: List<FirQualifierPart>): ConeKotlinType? {
|
private fun List<FirQualifierPart>.toTypeProjections() = flatMap {
|
||||||
return ConeClassTypeImpl(fqName, parts.flatMap {
|
it.typeArguments.map {
|
||||||
it.typeArguments.map {
|
when (it) {
|
||||||
when (it) {
|
is FirStarProjection -> StarProjection
|
||||||
is FirStarProjection -> StarProjection
|
is FirTypeProjectionWithVariance -> {
|
||||||
is FirTypeProjectionWithVariance -> {
|
val type = (it.type as FirResolvedType).type
|
||||||
val type = (it.type as FirResolvedType).type
|
when (it.variance) {
|
||||||
when (it.variance) {
|
Variance.INVARIANT -> type
|
||||||
Variance.INVARIANT -> type
|
Variance.IN_VARIANCE -> ConeKotlinTypeProjectionInImpl(type)
|
||||||
Variance.IN_VARIANCE -> ConeKotlinTypeProjectionInImpl(type)
|
Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOutImpl(type)
|
||||||
Variance.OUT_VARIANCE -> ConeKotlinTypeProjectionOutImpl(type)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> error("!")
|
|
||||||
}
|
}
|
||||||
|
else -> error("!")
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirMemberDeclaration.toConeKotlinType(fqName: ClassId, parts: List<FirQualifierPart>): 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<FirQualifierPart>, prefix: ClassId): ConeKotlinType? {
|
override fun resolveTypeWithPrefix(parts: List<FirQualifierPart>, prefix: ClassId): ConeKotlinType? {
|
||||||
|
|||||||
+15
-1
@@ -9,10 +9,13 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
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.resolve.FirProvider
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
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.ConeClassType
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedType
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -24,15 +27,26 @@ class FirNestedClassifierScope(val classId: ClassId, val session: FirSession) :
|
|||||||
return firProvider.getFirClassifierByFqName(this)
|
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 {
|
private val superScopes by lazy {
|
||||||
val self = classId.getFir()
|
val self = classId.getFir()
|
||||||
when (self) {
|
when (self) {
|
||||||
is FirClass -> {
|
is FirClass -> {
|
||||||
val superTypes = self.superTypes as List<FirResolvedType>
|
val superTypes = self.superTypes as List<FirResolvedType>
|
||||||
FirCompositeScope(superTypes.mapTo(ArrayList(superTypes.size)) {
|
FirCompositeScope(superTypes.mapTo(ArrayList(superTypes.size)) {
|
||||||
FirNestedClassifierScope((it.type as ConeClassType).fqName, session)
|
FirNestedClassifierScope(it.coneTypeUnsafe<ConeClassType>().computePartialExpansion(), session)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
is FirTypeAlias -> {
|
||||||
|
val expansionTarget = self.abbreviatedType.coneTypeUnsafe<ConeClassType>().computePartialExpansion()
|
||||||
|
FirNestedClassifierScope(expansionTarget, session)
|
||||||
|
}
|
||||||
else -> error("!")
|
else -> error("!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -393,6 +393,9 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
|||||||
is ConeKotlinType -> it.asString()
|
is ConeKotlinType -> it.asString()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (this is ConeAbbreviatedType) {
|
||||||
|
sb.append(" = ${this.directExpansion.asString()}")
|
||||||
|
}
|
||||||
sb.toString()
|
sb.toString()
|
||||||
}
|
}
|
||||||
else -> "Unsupported: $this"
|
else -> "Unsupported: $this"
|
||||||
|
|||||||
+11
-2
@@ -8,9 +8,12 @@ package org.jetbrains.kotlin.fir.declarations.impl
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
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.types.FirType
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class FirTypeAliasImpl(
|
class FirTypeAliasImpl(
|
||||||
@@ -18,5 +21,11 @@ class FirTypeAliasImpl(
|
|||||||
psi: PsiElement?,
|
psi: PsiElement?,
|
||||||
name: Name,
|
name: Name,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
override val abbreviatedType: FirType
|
override var abbreviatedType: FirType
|
||||||
) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL), FirTypeAlias
|
) : FirAbstractMemberDeclaration(session, psi, name, visibility, Modality.FINAL), FirTypeAlias {
|
||||||
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||||
|
abbreviatedType = abbreviatedType.transformSingle(transformer, data)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,4 +13,6 @@ interface FirResolvedType : FirTypeWithNullability {
|
|||||||
|
|
||||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||||
visitor.visitResolvedType(this, data)
|
visitor.visitResolvedType(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> FirType.coneTypeUnsafe() = (this as FirResolvedType).type as T
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
abstract class A {
|
||||||
|
abstract class Nested
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias TA = A
|
||||||
|
|
||||||
|
class B : TA() {
|
||||||
|
class NestedInB : Nested()
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
FILE: NestedOfAliasedType.kt
|
||||||
|
unknown abstract class A() {
|
||||||
|
unknown abstract class Nested() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
unknown final typealias TA = R/<root>.A/
|
||||||
|
unknown final class B() : R/<root>.TA = <root>.A/ {
|
||||||
|
unknown final class NestedInB() : R/<root>.A.Nested/ {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
interface B
|
||||||
|
|
||||||
|
typealias C = B
|
||||||
|
|
||||||
|
class D : C
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
FILE: simpleTypeAlias.kt
|
||||||
|
unknown final interface B() {
|
||||||
|
}
|
||||||
|
unknown final typealias C = R/<root>.B/
|
||||||
|
unknown final class D() : R/<root>.C = <root>.B/ {
|
||||||
|
}
|
||||||
@@ -31,6 +31,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("NestedSuperType.kt")
|
||||||
public void testNestedSuperType() throws Exception {
|
public void testNestedSuperType() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/NestedSuperType.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/NestedSuperType.kt");
|
||||||
@@ -43,6 +49,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("TwoDeclarationsInSameFile.kt")
|
||||||
public void testTwoDeclarationsInSameFile() throws Exception {
|
public void testTwoDeclarationsInSameFile() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/TwoDeclarationsInSameFile.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user