FIR: implement early type alias expansion
This commit is contained in:
committed by
Mikhail Glukhikh
parent
d15fb1963b
commit
25ae12fe07
+26
-8
@@ -8,9 +8,12 @@ package org.jetbrains.kotlin.descriptors
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl
|
||||
@@ -21,8 +24,6 @@ import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
fun FirElement.render(): String = buildString { this@render.accept(FirRenderer(this)) }
|
||||
|
||||
class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransformer<Nothing?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
return if (superTypesOnly) {
|
||||
@@ -94,11 +95,15 @@ class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransf
|
||||
|
||||
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
|
||||
val typeResolver = FirTypeResolver.getInstance(type.session)
|
||||
type.transformChildren(this, data)
|
||||
type.transformChildren(this, null)
|
||||
return transformType(type, typeResolver.resolveType(type, scope))
|
||||
}
|
||||
|
||||
private fun transformType(type: FirType, resolvedType: ConeKotlinType): CompositeTransformResult<FirType> {
|
||||
return FirResolvedTypeImpl(
|
||||
type.session,
|
||||
type.psi,
|
||||
typeResolver.resolveType(type, scope),
|
||||
resolvedType,
|
||||
false,
|
||||
type.annotations
|
||||
).compose()
|
||||
@@ -109,16 +114,27 @@ class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransf
|
||||
}
|
||||
|
||||
|
||||
override fun transformTypeProjectionWithVariance(
|
||||
typeProjectionWithVariance: FirTypeProjectionWithVariance,
|
||||
data: Nothing?
|
||||
): CompositeTransformResult<FirTypeProjection> {
|
||||
typeProjectionWithVariance.transformChildren(this, data)
|
||||
return typeProjectionWithVariance.compose()
|
||||
}
|
||||
|
||||
private inner class SuperTypeResolver : FirTransformer<Nothing?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
|
||||
val transformedType = this@FirTypeResolveTransformer.transformType(type, data).single as FirResolvedType
|
||||
val typeResolver = FirTypeResolver.getInstance(type.session)
|
||||
val symbol = typeResolver.resolveToSymbol(type, scope)
|
||||
val myTransformer = this@FirTypeResolveTransformer
|
||||
|
||||
val classId = (transformedType.type as? ConeClassLikeType)?.symbol?.classId ?: return transformedType.compose()
|
||||
val firProvider = FirProvider.getInstance(transformedType.session)
|
||||
if (type !is FirUserType) return myTransformer.transformType(type, data)
|
||||
val classId = (symbol as? ConeClassLikeSymbol)?.classId ?: return myTransformer.transformType(type, data)
|
||||
val firProvider = FirProvider.getInstance(type.session)
|
||||
|
||||
val classes = generateSequence(classId) { it.outerClassId }.toList()
|
||||
|
||||
@@ -132,7 +148,9 @@ class FirTypeResolveTransformer(val superTypesOnly: Boolean = false) : FirTransf
|
||||
firProvider.getFirClassifierByFqName(it)!!.transformSingle(transformer, data)
|
||||
}
|
||||
|
||||
return transformedType.compose()
|
||||
|
||||
type.transformChildren(myTransformer, null)
|
||||
return myTransformer.transformType(type, typeResolver.resolveUserType(type, symbol, scope))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -18,7 +19,7 @@ interface FirProvider {
|
||||
|
||||
fun getFirClassifierContainerFile(fqName: ClassId): FirFile
|
||||
|
||||
fun getFirClassifierBySymbol(symbol: ConeSymbol): FirMemberDeclaration?
|
||||
fun getFirClassifierBySymbol(symbol: ConeSymbol): FirNamedDeclaration?
|
||||
|
||||
companion object {
|
||||
fun getInstance(session: FirSession): FirProvider = session.service()
|
||||
|
||||
@@ -7,15 +7,16 @@ package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirQualifierPart
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
interface FirQualifierResolver {
|
||||
fun resolveTypeWithPrefix(parts: List<FirQualifierPart>, prefix: ClassId): ConeKotlinType?
|
||||
fun resolveSymbolWithPrefix(parts: List<FirQualifierPart>, prefix: ClassId): ConeSymbol?
|
||||
|
||||
fun resolveType(parts: List<FirQualifierPart>): ConeKotlinType?
|
||||
fun resolveSymbol(parts: List<FirQualifierPart>): ConeSymbol?
|
||||
|
||||
companion object {
|
||||
fun getInstance(session: FirSession): FirQualifierResolver = session.service()
|
||||
|
||||
@@ -8,14 +8,19 @@ package org.jetbrains.kotlin.fir.resolve
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirUserType
|
||||
|
||||
interface FirTypeResolver {
|
||||
|
||||
fun resolveType(type: FirType, scope: FirScope): ConeKotlinType
|
||||
fun resolveToSymbol(type: FirType, scope: FirScope): ConeSymbol?
|
||||
|
||||
companion object {
|
||||
fun getInstance(session: FirSession): FirTypeResolver = session.service()
|
||||
}
|
||||
|
||||
fun resolveUserType(type: FirUserType, symbol: ConeSymbol?, scope: FirScope): ConeKotlinType
|
||||
}
|
||||
@@ -17,9 +17,9 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class FirProviderImpl(val session: FirSession) : FirProvider {
|
||||
override fun getFirClassifierBySymbol(symbol: ConeSymbol): FirMemberDeclaration? {
|
||||
override fun getFirClassifierBySymbol(symbol: ConeSymbol): FirNamedDeclaration? {
|
||||
return when(symbol) {
|
||||
is FirBasedSymbol<*> -> symbol.fir as? FirMemberDeclaration
|
||||
is FirBasedSymbol<*> -> symbol.fir as? FirNamedDeclaration
|
||||
is ConeClassLikeSymbol -> getFirClassifierByFqName(symbol.classId)
|
||||
else -> error("!")
|
||||
}
|
||||
|
||||
+7
-41
@@ -11,6 +11,8 @@ 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.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.toSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
@@ -20,43 +22,7 @@ import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
|
||||
|
||||
private fun List<FirQualifierPart>.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("!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirMemberDeclaration.toConeKotlinType(fqName: ClassId, parts: List<FirQualifierPart>): ConeKotlinType? {
|
||||
return when (this) {
|
||||
is FirClass -> {
|
||||
ConeClassTypeImpl(fqName.toSymbol(), parts.toTypeProjections())
|
||||
}
|
||||
is FirTypeAlias -> {
|
||||
val expansion = expandedType.coneTypeSafe<ConeClassLikeType>()
|
||||
?: return ConeKotlinErrorType("Couldn't resolve expansion")
|
||||
|
||||
ConeAbbreviatedTypeImpl(
|
||||
abbreviationSymbol = fqName.toSymbol(),
|
||||
typeArguments = parts.toTypeProjections(),
|
||||
directExpansion = expansion
|
||||
)
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveTypeWithPrefix(parts: List<FirQualifierPart>, prefix: ClassId): ConeKotlinType? {
|
||||
override fun resolveSymbolWithPrefix(parts: List<FirQualifierPart>, prefix: ClassId): ConeSymbol? {
|
||||
val firProvider = FirProvider.getInstance(session)
|
||||
|
||||
val fqName = ClassId(
|
||||
@@ -64,12 +30,12 @@ class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
|
||||
parts.drop(1).fold(prefix.relativeClassName) { prefix, suffix -> prefix.child(suffix.name) },
|
||||
false
|
||||
)
|
||||
val foundClassifier = firProvider.getFirClassifierByFqName(fqName)
|
||||
firProvider.getFirClassifierByFqName(fqName) ?: return null
|
||||
|
||||
return foundClassifier?.toConeKotlinType(fqName, parts)
|
||||
return ConeClassLikeSymbol(fqName)
|
||||
}
|
||||
|
||||
override fun resolveType(parts: List<FirQualifierPart>): ConeKotlinType? {
|
||||
override fun resolveSymbol(parts: List<FirQualifierPart>): ConeSymbol? {
|
||||
val firProvider = FirProvider.getInstance(session)
|
||||
|
||||
if (parts.isNotEmpty()) {
|
||||
@@ -84,7 +50,7 @@ class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
|
||||
val foundClassifier = firProvider.getFirClassifierByFqName(fqName)
|
||||
|
||||
if (foundClassifier != null) {
|
||||
return foundClassifier.toConeKotlinType(fqName, parts)
|
||||
return ConeClassLikeSymbol(fqName)
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
+77
-10
@@ -5,40 +5,107 @@
|
||||
|
||||
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.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinErrorType
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class FirTypeResolverImpl : FirTypeResolver {
|
||||
override fun resolveType(type: FirType, scope: FirScope): ConeKotlinType {
|
||||
|
||||
|
||||
private fun List<FirQualifierPart>.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("!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeSymbol.toConeKotlinType(parts: List<FirQualifierPart>, session: FirSession): ConeKotlinType? {
|
||||
val firProvider = FirProvider.getInstance(session)
|
||||
val fir = firProvider.getFirClassifierBySymbol(this) ?: return null
|
||||
return when (fir) {
|
||||
is FirTypeParameter -> {
|
||||
ConeTypeParameterTypeImpl(this as ConeTypeParameterSymbol)
|
||||
}
|
||||
is FirClass -> {
|
||||
ConeClassTypeImpl(this as ConeClassLikeSymbol, parts.toTypeProjections())
|
||||
}
|
||||
is FirTypeAlias -> {
|
||||
val coneTypeSafe = fir.expandedType.coneTypeSafe<ConeClassLikeType>()
|
||||
val expansion = if (coneTypeSafe != null) coneTypeSafe else {
|
||||
return ConeKotlinErrorType("Couldn't resolve expansion")
|
||||
}
|
||||
|
||||
ConeAbbreviatedTypeImpl(
|
||||
abbreviationSymbol = this as ConeClassLikeSymbol,
|
||||
typeArguments = parts.toTypeProjections(),
|
||||
directExpansion = expansion
|
||||
)
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveToSymbol(type: FirType, scope: FirScope): ConeSymbol? {
|
||||
return when (type) {
|
||||
is FirResolvedType -> type.type
|
||||
is FirResolvedType -> type.coneTypeSafe<ConeSymbolBasedType>()?.symbol
|
||||
is FirUserType -> {
|
||||
|
||||
val qualifierResolver = FirQualifierResolver.getInstance(type.session)
|
||||
|
||||
var resolvedType: ConeKotlinType? = null
|
||||
var resolvedSymbol: ConeSymbol? = null
|
||||
scope.processClassifiersByName(type.qualifier.first().name) { symbol ->
|
||||
resolvedType = when (symbol) {
|
||||
resolvedSymbol = when (symbol) {
|
||||
is ConeClassLikeSymbol -> {
|
||||
qualifierResolver.resolveTypeWithPrefix(type.qualifier, symbol.classId)
|
||||
qualifierResolver.resolveSymbolWithPrefix(type.qualifier, symbol.classId)
|
||||
}
|
||||
is ConeTypeParameterSymbol -> {
|
||||
assert(type.qualifier.size == 1)
|
||||
ConeTypeParameterTypeImpl(symbol)
|
||||
symbol
|
||||
}
|
||||
else -> error("!")
|
||||
}
|
||||
resolvedType == null
|
||||
resolvedSymbol == null
|
||||
}
|
||||
|
||||
// TODO: Imports
|
||||
resolvedType ?: qualifierResolver.resolveType(type.qualifier) ?: ConeKotlinErrorType("Failed to resolve qualified type")
|
||||
resolvedSymbol ?: qualifierResolver.resolveSymbol(type.qualifier)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveUserType(type: FirUserType, symbol: ConeSymbol?, scope: FirScope): ConeKotlinType {
|
||||
symbol ?: return ConeKotlinErrorType("Symbol not found")
|
||||
return symbol.toConeKotlinType(type.qualifier, type.session) ?: ConeKotlinErrorType("Failed to resolve qualified type")
|
||||
}
|
||||
|
||||
override fun resolveType(type: FirType, scope: FirScope): ConeKotlinType {
|
||||
return when (type) {
|
||||
is FirResolvedType -> type.type
|
||||
is FirUserType -> {
|
||||
resolveUserType(type, resolveToSymbol(type, scope), scope)
|
||||
}
|
||||
is FirErrorType -> {
|
||||
ConeKotlinErrorType(type.reason)
|
||||
|
||||
@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
fun FirElement.render(): String = buildString { this@render.accept(FirRenderer(this)) }
|
||||
|
||||
class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
||||
private val printer = Printer(builder)
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package b
|
||||
|
||||
class A
|
||||
|
||||
typealias TA = A
|
||||
|
||||
// analyzePriority: 1
|
||||
@@ -0,0 +1,7 @@
|
||||
package a
|
||||
|
||||
import b.TA
|
||||
|
||||
class MyClass : TA
|
||||
|
||||
// analyzePriority: 0
|
||||
@@ -0,0 +1,3 @@
|
||||
FILE: TypeAliasExpansion.kt
|
||||
(resolved) public? final class MyClass() : R/b/TA = b/A/ {
|
||||
}
|
||||
+9
-9
@@ -1,27 +1,27 @@
|
||||
FILE: simpleClass.kt
|
||||
(resolved) public? abstract interface SomeInterface() {
|
||||
public? final? function foo(x: R/error: Failed to resolve qualified type/, y: R/error: Failed to resolve qualified type/): R/error: Failed to resolve qualified type/
|
||||
public? final? function foo(x: R/error: Symbol not found/, y: R/error: Symbol not found/): R/error: Symbol not found/
|
||||
|
||||
public? final? property bar(val): R/error: Failed to resolve qualified type/
|
||||
public? get(): R/error: Failed to resolve qualified type/
|
||||
public? final? property bar(val): R/error: Symbol not found/
|
||||
public? get(): R/error: Symbol not found/
|
||||
|
||||
}
|
||||
(resolved) public? final class SomeClass() : R/SomeInterface/ {
|
||||
private final? property baz(val): R/error: Not supported: FirImplicitTypeImpl/ = STUB
|
||||
public? get(): R/error: Not supported: FirImplicitTypeImpl/
|
||||
|
||||
public? open? override function foo(x: R/error: Failed to resolve qualified type/, y: R/error: Failed to resolve qualified type/): R/error: Failed to resolve qualified type/ {
|
||||
public? open? override function foo(x: R/error: Symbol not found/, y: R/error: Symbol not found/): R/error: Symbol not found/ {
|
||||
}
|
||||
|
||||
public? open? override property bar(var): R/error: Failed to resolve qualified type/
|
||||
public? open? override property bar(var): R/error: Symbol not found/
|
||||
public? get(): R/error: Not supported: FirImplicitTypeImpl/ {
|
||||
STUB
|
||||
}
|
||||
public? set(value: R/error: Failed to resolve qualified type/): R/error: Not supported: FirImplicitTypeImpl/ {
|
||||
public? set(value: R/error: Symbol not found/): R/error: Not supported: FirImplicitTypeImpl/ {
|
||||
}
|
||||
|
||||
public? final? property fau(var): R/error: Failed to resolve qualified type/
|
||||
public? get(): R/error: Failed to resolve qualified type/
|
||||
public? set(value: R/error: Failed to resolve qualified type/): R/kotlin/Unit/
|
||||
public? final? property fau(var): R/error: Symbol not found/
|
||||
public? get(): R/error: Symbol not found/
|
||||
public? set(value: R/error: Symbol not found/): R/kotlin/Unit/
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,6 +2,6 @@ open class A
|
||||
|
||||
interface B<S, T : A>
|
||||
|
||||
typealias C<T> = B<T, A>
|
||||
|
||||
class D : C<A>
|
||||
|
||||
typealias C<T> = B<T, A>
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@ FILE: typeAliasWithGeneric.kt
|
||||
}
|
||||
(resolved) <(resolved) S, (resolved) T : R/A/> public? abstract interface B() {
|
||||
}
|
||||
(resolved) <(resolved) T> public? final typealias C = R/B<T, A>/
|
||||
(resolved) public? final class D() : R/C<A> = B<T, A>/ {
|
||||
}
|
||||
(resolved) <(resolved) T> public? final typealias C = R/B<T, A>/
|
||||
|
||||
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.fir
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.descriptors.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirQualifierResolverImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirTypeResolverImpl
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
|
||||
@@ -24,20 +26,7 @@ abstract class AbstractFirResolveTestCase : KotlinTestWithEnvironment() {
|
||||
return createEnvironmentWithMockJdk(ConfigurationKind.JDK_NO_RUNTIME)
|
||||
}
|
||||
|
||||
fun doTest(path: String) {
|
||||
val file = File(path)
|
||||
|
||||
val allFiles = listOf(file) + file.parentFile.listFiles { sibling ->
|
||||
sibling.name.removePrefix(file.nameWithoutExtension).removeSuffix(file.extension).matches("\\.[0-9]+\\.".toRegex())
|
||||
}
|
||||
|
||||
|
||||
val ktFiles = allFiles.map {
|
||||
val text = KotlinTestUtils.doLoadFile(it)
|
||||
KotlinTestUtils.createFile(it.name, text, project)
|
||||
|
||||
}
|
||||
|
||||
fun doCreateAndProcessFir(ktFiles: List<KtFile>): List<FirFile> {
|
||||
val session = object : FirSessionBase() {
|
||||
init {
|
||||
registerComponent(FirProvider::class, FirProviderImpl(this))
|
||||
@@ -57,6 +46,31 @@ abstract class AbstractFirResolveTestCase : KotlinTestWithEnvironment() {
|
||||
transformer.processFiles(it)
|
||||
}
|
||||
|
||||
return firFiles
|
||||
}
|
||||
|
||||
|
||||
fun doTest(path: String) {
|
||||
val file = File(path)
|
||||
|
||||
val allFiles = listOf(file) + file.parentFile.listFiles { sibling ->
|
||||
sibling.name.removePrefix(file.nameWithoutExtension).removeSuffix(file.extension).matches("\\.[0-9]+\\.".toRegex())
|
||||
}
|
||||
|
||||
val ktFiles =
|
||||
allFiles.map {
|
||||
val text = KotlinTestUtils.doLoadFile(it)
|
||||
it.name to text
|
||||
}
|
||||
.sortedBy { (_, text) ->
|
||||
KotlinTestUtils.parseDirectives(text)["analyzePriority"]?.toInt()
|
||||
}
|
||||
.map { (name, text) ->
|
||||
KotlinTestUtils.createFile(name, text, project)
|
||||
}
|
||||
|
||||
val firFiles = doCreateAndProcessFir(ktFiles)
|
||||
|
||||
val firFileDump = StringBuilder().also { firFiles.first().accept(FirRenderer(it), null) }.toString()
|
||||
val expectedPath = path.replace(".kt", ".txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||
|
||||
@@ -110,5 +110,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/simpleImportOuter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TypeAliasExpansion.kt")
|
||||
public void testTypeAliasExpansion() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/TypeAliasExpansion.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user