FIR: support type alias resolve

This commit is contained in:
Mikhail Glukhikh
2018-03-20 18:10:56 +03:00
parent d5463193fd
commit f82ad6ac20
13 changed files with 130 additions and 19 deletions
@@ -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(
@@ -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? {
@@ -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"
@@ -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
+9
View File
@@ -0,0 +1,9 @@
abstract class A {
abstract class Nested
}
typealias TA = A
class B : TA() {
class NestedInB : Nested()
}
+12
View File
@@ -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/ {
}
}
+5
View File
@@ -0,0 +1,5 @@
interface B
typealias C = B
class D : C
+6
View File
@@ -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");