Extract supertypes resolution into a separate FIR phase
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve
|
package org.jetbrains.kotlin.fir.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.toFirClassLike
|
||||||
import org.jetbrains.kotlin.fir.service
|
import org.jetbrains.kotlin.fir.service
|
||||||
import org.jetbrains.kotlin.fir.symbols.*
|
import org.jetbrains.kotlin.fir.symbols.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -27,6 +28,9 @@ interface FirSymbolProvider {
|
|||||||
|
|
||||||
fun getPackage(fqName: FqName): FqName? // TODO: Replace to symbol sometime
|
fun getPackage(fqName: FqName): FqName? // TODO: Replace to symbol sometime
|
||||||
|
|
||||||
|
// TODO: should not retrieve session through the FirElement::session
|
||||||
|
fun getSessionForClass(classId: ClassId): FirSession? = getClassLikeSymbolByFqName(classId)?.toFirClassLike()?.session
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(session: FirSession) = session.service<FirSymbolProvider>()
|
fun getInstance(session: FirSession) = session.service<FirSymbolProvider>()
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -7,11 +7,13 @@ package org.jetbrains.kotlin.fir.resolve.transformers
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
||||||
import org.jetbrains.kotlin.fir.declarations.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
@@ -100,4 +102,11 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority: B
|
|||||||
else -> error("?!id:1")
|
else -> error("?!id:1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun FirMemberDeclaration.addTypeParametersScope() {
|
||||||
|
val scopes = towerScope.scopes
|
||||||
|
if (typeParameters.isNotEmpty()) {
|
||||||
|
scopes += FirMemberTypeParameterScope(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirResolvedFunctionTypeRefImpl
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.compose
|
||||||
|
|
||||||
|
class FirSpecificTypeResolverTransformer(
|
||||||
|
private val towerScope: FirScope,
|
||||||
|
private val position: FirPosition,
|
||||||
|
private val session: FirSession
|
||||||
|
) : FirAbstractTreeTransformer() {
|
||||||
|
override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||||
|
val typeResolver = FirTypeResolver.getInstance(session)
|
||||||
|
typeRef.transformChildren(FirSpecificTypeResolverTransformer(towerScope, FirPosition.OTHER, session), null)
|
||||||
|
return transformType(typeRef, typeResolver.resolveType(typeRef, towerScope, position))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||||
|
val typeResolver = FirTypeResolver.getInstance(functionTypeRef.session)
|
||||||
|
functionTypeRef.transformChildren(this, data)
|
||||||
|
return FirResolvedFunctionTypeRefImpl(
|
||||||
|
functionTypeRef.psi,
|
||||||
|
functionTypeRef.session,
|
||||||
|
functionTypeRef.isMarkedNullable,
|
||||||
|
functionTypeRef.annotations as MutableList<FirAnnotationCall>,
|
||||||
|
functionTypeRef.receiverTypeRef,
|
||||||
|
functionTypeRef.valueParameters as MutableList<FirValueParameter>,
|
||||||
|
functionTypeRef.returnTypeRef,
|
||||||
|
typeResolver.resolveType(functionTypeRef, towerScope, position)
|
||||||
|
).compose()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType): CompositeTransformResult<FirTypeRef> {
|
||||||
|
return FirResolvedTypeRefImpl(
|
||||||
|
typeRef.session,
|
||||||
|
typeRef.psi,
|
||||||
|
resolvedType,
|
||||||
|
false,
|
||||||
|
typeRef.annotations
|
||||||
|
).compose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||||
|
return resolvedTypeRef.compose()
|
||||||
|
}
|
||||||
|
}
|
||||||
+189
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
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.FirSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.addImportingScopes
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.compose
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
|
class FirSupertypeResolverTransformer : FirAbstractTreeTransformer() {
|
||||||
|
private lateinit var firSession: FirSession
|
||||||
|
private val currentlyComputing: MutableSet<ClassId> = mutableSetOf()
|
||||||
|
private val fullyComputed: MutableSet<ClassId> = mutableSetOf()
|
||||||
|
|
||||||
|
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
|
||||||
|
firSession = file.session
|
||||||
|
return super.transformFile(file, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
|
val transformedClass = resolveSupertypesOrExpansions(regularClass) as? FirRegularClass ?: regularClass
|
||||||
|
|
||||||
|
// resolve supertypes for nested classes
|
||||||
|
return super.transformRegularClass(transformedClass, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
|
return resolveSupertypesOrExpansions(typeAlias).compose()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveSupertypesOrExpansions(classLikeDeclaration: FirClassLikeDeclaration): FirDeclaration {
|
||||||
|
val classId = classLikeDeclaration.symbol.classId
|
||||||
|
|
||||||
|
if (classId in fullyComputed) return classLikeDeclaration
|
||||||
|
|
||||||
|
val firFile = firSession.getService(FirProvider::class).getFirClassifierContainerFile(classId)
|
||||||
|
|
||||||
|
val visitor = ResolveSuperTypesTask(firSession, classId, firFile, currentlyComputing, fullyComputed)
|
||||||
|
firFile.accept(visitor, null).single
|
||||||
|
|
||||||
|
return visitor.resultingClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ResolveSuperTypesTask(
|
||||||
|
private val session: FirSession,
|
||||||
|
private val requestedClassId: ClassId,
|
||||||
|
file: FirFile,
|
||||||
|
private val currentlyComputing: MutableSet<ClassId>,
|
||||||
|
private val fullyComputed: MutableSet<ClassId>
|
||||||
|
) : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
|
||||||
|
|
||||||
|
lateinit var resultingClass: FirDeclaration
|
||||||
|
|
||||||
|
init {
|
||||||
|
towerScope.addImportingScopes(file, session)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
|
val classId = regularClass.classId
|
||||||
|
if (!isOuterClass(classId, requestedClassId)) return regularClass.compose()
|
||||||
|
val transformedClass = withScopeCleanup {
|
||||||
|
if (classId in fullyComputed) return@withScopeCleanup regularClass
|
||||||
|
|
||||||
|
regularClass.addTypeParametersScope()
|
||||||
|
|
||||||
|
val transformer = FirSpecificTypeResolverTransformer(towerScope, FirPosition.SUPER_TYPE_OR_EXPANSION, session)
|
||||||
|
val resolvedTypesRefs = regularClass.superTypeRefs.map { transformer.transformTypeRef(it, data).single }
|
||||||
|
|
||||||
|
val resultingTypeRefs = resolveLoops(classId, resolvedTypesRefs)
|
||||||
|
regularClass.replaceSupertypes(resultingTypeRefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classId == requestedClassId) {
|
||||||
|
resultingClass = transformedClass
|
||||||
|
return transformedClass.compose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolveNestedClassesSupertypes(transformedClass, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
|
val classId = typeAlias.symbol.classId
|
||||||
|
// nested type aliases
|
||||||
|
if (requestedClassId != classId || classId in fullyComputed) return typeAlias.compose()
|
||||||
|
|
||||||
|
return withScopeCleanup {
|
||||||
|
typeAlias.addTypeParametersScope()
|
||||||
|
|
||||||
|
val transformer = FirSpecificTypeResolverTransformer(towerScope, FirPosition.SUPER_TYPE_OR_EXPANSION, session)
|
||||||
|
val resolvedTypesRef = transformer.transformTypeRef(typeAlias.expandedTypeRef, data).single
|
||||||
|
val resultingTypeRef = resolveLoops(classId, listOf(resolvedTypesRef)).firstOrNull()
|
||||||
|
|
||||||
|
typeAlias.replaceExpandTypeRef(resultingTypeRef ?: resolvedTypesRef).also {
|
||||||
|
resultingClass = it
|
||||||
|
}
|
||||||
|
}.compose()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveLoops(
|
||||||
|
classId: ClassId,
|
||||||
|
resolvedTypesRefs: List<FirTypeRef>
|
||||||
|
): List<FirTypeRef> {
|
||||||
|
currentlyComputing.add(classId)
|
||||||
|
|
||||||
|
val resultingTypeRefs = mutableListOf<FirTypeRef>()
|
||||||
|
for (superTypeRef in resolvedTypesRefs) {
|
||||||
|
val resolvedType = superTypeRef.coneTypeSafe<ConeClassLikeType>() ?: continue
|
||||||
|
val superTypeClassId = resolvedType.lookupTag.classId
|
||||||
|
|
||||||
|
if (superTypeClassId.outerClasses().any(currentlyComputing::contains)) {
|
||||||
|
resultingTypeRefs.add(
|
||||||
|
FirErrorTypeRefImpl(session, superTypeRef.psi, "Recursion detected: ${superTypeRef.render()}")
|
||||||
|
)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val sessionForSupertype = session.getService(FirSymbolProvider::class).getSessionForClass(superTypeClassId) ?: continue
|
||||||
|
val provider = sessionForSupertype.getService(FirProvider::class)
|
||||||
|
|
||||||
|
val firClassForSupertype =
|
||||||
|
sessionForSupertype
|
||||||
|
.getService(FirSymbolProvider::class)
|
||||||
|
.getClassLikeSymbolByFqName(superTypeClassId)
|
||||||
|
?.toFirClassLike() as? FirClass
|
||||||
|
|
||||||
|
// TODO: this if is a temporary hack for built-in types (because we can't load file for them)
|
||||||
|
if (firClassForSupertype == null || firClassForSupertype.superTypeRefs.any { it !is FirResolvedTypeRef }) {
|
||||||
|
val firForSuperClassFile = provider.getFirClassifierContainerFile(superTypeClassId)
|
||||||
|
|
||||||
|
ResolveSuperTypesTask(
|
||||||
|
sessionForSupertype, superTypeClassId, firForSuperClassFile,
|
||||||
|
currentlyComputing, fullyComputed
|
||||||
|
).transformFile(firForSuperClassFile, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
resultingTypeRefs.add(superTypeRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
fullyComputed.add(classId)
|
||||||
|
currentlyComputing.remove(classId)
|
||||||
|
return resultingTypeRefs
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveNestedClassesSupertypes(
|
||||||
|
regularClass: FirRegularClass,
|
||||||
|
data: Nothing?
|
||||||
|
): CompositeTransformResult<FirDeclaration> {
|
||||||
|
return withScopeCleanup {
|
||||||
|
val session = regularClass.session
|
||||||
|
val firProvider = FirProvider.getInstance(session)
|
||||||
|
val classId = regularClass.symbol.classId
|
||||||
|
lookupSuperTypes(regularClass, lookupInterfaces = false, deep = true, useSiteSession = session)
|
||||||
|
.asReversed().mapTo(towerScope.scopes) {
|
||||||
|
FirNestedClassifierScope(it.lookupTag.classId, FirSymbolProvider.getInstance(session))
|
||||||
|
}
|
||||||
|
val companionObjects = regularClass.declarations.filterIsInstance<FirRegularClass>().filter { it.isCompanion }
|
||||||
|
for (companionObject in companionObjects) {
|
||||||
|
towerScope.scopes += FirNestedClassifierScope(companionObject.symbol.classId, firProvider)
|
||||||
|
}
|
||||||
|
towerScope.scopes += FirNestedClassifierScope(classId, firProvider)
|
||||||
|
regularClass.addTypeParametersScope()
|
||||||
|
|
||||||
|
super.transformRegularClass(regularClass, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isOuterClass(outerCandidate: ClassId, innerCandidate: ClassId) =
|
||||||
|
innerCandidate.outerClasses().any { outerCandidate == it }
|
||||||
|
|
||||||
|
private fun ClassId.outerClasses() = generateSequence(this, ClassId::getOuterClassId)
|
||||||
+2
-7
@@ -12,17 +12,12 @@ class FirTotalResolveTransformer {
|
|||||||
|
|
||||||
val transformers: List<FirTransformer<Nothing?>> = listOf(
|
val transformers: List<FirTransformer<Nothing?>> = listOf(
|
||||||
FirImportResolveTransformer(),
|
FirImportResolveTransformer(),
|
||||||
|
FirSupertypeResolverTransformer(),
|
||||||
FirTypeResolveTransformer(),
|
FirTypeResolveTransformer(),
|
||||||
FirStatusResolveTransformer(),
|
FirStatusResolveTransformer(),
|
||||||
FirAccessResolveTransformer()
|
FirAccessResolveTransformer()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun processFile(firFile: FirFile) {
|
|
||||||
for (transformer in transformers) {
|
|
||||||
firFile.transform<FirFile, Nothing?>(transformer, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun processFiles(files: List<FirFile>) {
|
fun processFiles(files: List<FirFile>) {
|
||||||
for (transformer in transformers) {
|
for (transformer in transformers) {
|
||||||
for (firFile in files) {
|
for (firFile in files) {
|
||||||
@@ -30,4 +25,4 @@ class FirTotalResolveTransformer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-156
@@ -5,68 +5,35 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
|
||||||
import org.jetbrains.kotlin.fir.render
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.addImportingScopes
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||||
import org.jetbrains.kotlin.fir.service
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.transformSingle
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedFunctionTypeRefImpl
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.compose
|
|
||||||
|
|
||||||
open class FirTypeResolveTransformer(
|
open class FirTypeResolveTransformer : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
|
||||||
private val traversedClassifiers: Set<FirMemberDeclaration> = setOf()
|
private lateinit var session: FirSession
|
||||||
) : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
|
|
||||||
private lateinit var firProvider: FirProvider
|
|
||||||
|
|
||||||
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
|
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
|
||||||
val session = file.session
|
session = file.session
|
||||||
firProvider = session.getService(FirProvider::class)
|
|
||||||
return withScopeCleanup {
|
return withScopeCleanup {
|
||||||
towerScope.scopes += listOf(
|
towerScope.addImportingScopes(file, session)
|
||||||
// from low priority to high priority
|
|
||||||
FirDefaultStarImportingScope(session),
|
|
||||||
FirExplicitStarImportingScope(file.imports, session),
|
|
||||||
FirDefaultSimpleImportingScope(session),
|
|
||||||
FirSelfImportingScope(file.packageFqName, session),
|
|
||||||
// TODO: explicit simple importing scope should have highest priority (higher than inner scopes added in process)
|
|
||||||
FirExplicitSimpleImportingScope(file.imports, session)
|
|
||||||
)
|
|
||||||
super.transformFile(file, data)
|
super.transformFile(file, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveSuperTypesAndExpansions(element: FirMemberDeclaration) {
|
|
||||||
try {
|
|
||||||
element.transformChildren(SuperTypeResolver(traversedClassifiers + listOfNotNull(element)), null)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
class SuperTypeResolveException(cause: Exception) : Exception(element.render(), cause)
|
|
||||||
throw SuperTypeResolveException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
withScopeCleanup {
|
withScopeCleanup {
|
||||||
regularClass.addTypeParametersScope()
|
regularClass.addTypeParametersScope()
|
||||||
resolveSuperTypesAndExpansions(regularClass)
|
|
||||||
regularClass.typeParameters.forEach {
|
regularClass.typeParameters.forEach {
|
||||||
it.accept(this, data)
|
it.accept(this, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return withScopeCleanup {
|
return withScopeCleanup {
|
||||||
val session = regularClass.session
|
val session = regularClass.session
|
||||||
val firProvider = FirProvider.getInstance(session)
|
val firProvider = FirProvider.getInstance(session)
|
||||||
@@ -89,19 +56,11 @@ open class FirTypeResolveTransformer(
|
|||||||
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
return withScopeCleanup {
|
return withScopeCleanup {
|
||||||
typeAlias.addTypeParametersScope()
|
typeAlias.addTypeParametersScope()
|
||||||
resolveSuperTypesAndExpansions(typeAlias)
|
|
||||||
super.transformTypeAlias(typeAlias, data)
|
super.transformTypeAlias(typeAlias, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun FirMemberDeclaration.addTypeParametersScope() {
|
|
||||||
val scopes = towerScope.scopes
|
|
||||||
if (typeParameters.isNotEmpty()) {
|
|
||||||
scopes += FirMemberTypeParameterScope(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformProperty(property: FirProperty, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
override fun transformProperty(property: FirProperty, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||||
return withScopeCleanup {
|
return withScopeCleanup {
|
||||||
property.addTypeParametersScope()
|
property.addTypeParametersScope()
|
||||||
@@ -117,112 +76,6 @@ open class FirTypeResolveTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||||
val typeResolver = FirTypeResolver.getInstance(typeRef.session)
|
return FirSpecificTypeResolverTransformer(towerScope, FirPosition.OTHER, session).transformTypeRef(typeRef, data)
|
||||||
typeRef.transformChildren(this, null)
|
|
||||||
return transformType(typeRef, typeResolver.resolveType(typeRef, towerScope, position = FirPosition.OTHER))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
|
||||||
val typeResolver = FirTypeResolver.getInstance(functionTypeRef.session)
|
|
||||||
functionTypeRef.transformChildren(this, data)
|
|
||||||
return FirResolvedFunctionTypeRefImpl(
|
|
||||||
functionTypeRef.psi,
|
|
||||||
functionTypeRef.session,
|
|
||||||
functionTypeRef.isMarkedNullable,
|
|
||||||
functionTypeRef.annotations as MutableList<FirAnnotationCall>,
|
|
||||||
functionTypeRef.receiverTypeRef,
|
|
||||||
functionTypeRef.valueParameters as MutableList<FirValueParameter>,
|
|
||||||
functionTypeRef.returnTypeRef,
|
|
||||||
typeResolver.resolveType(functionTypeRef, towerScope, FirPosition.OTHER)
|
|
||||||
).compose()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType): CompositeTransformResult<FirTypeRef> {
|
|
||||||
return FirResolvedTypeRefImpl(
|
|
||||||
typeRef.session,
|
|
||||||
typeRef.psi,
|
|
||||||
resolvedType,
|
|
||||||
false,
|
|
||||||
typeRef.annotations
|
|
||||||
).compose()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
|
||||||
return resolvedTypeRef.compose()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformValueParameter(valueParameter: FirValueParameter, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
|
||||||
return valueParameter.also { it.transformChildren(this, data) }.compose()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun transformTypeProjectionWithVariance(
|
|
||||||
typeProjectionWithVariance: FirTypeProjectionWithVariance,
|
|
||||||
data: Nothing?
|
|
||||||
): CompositeTransformResult<FirTypeProjection> {
|
|
||||||
typeProjectionWithVariance.transformChildren(this, data)
|
|
||||||
return typeProjectionWithVariance.compose()
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SuperTypeResolveTransformer(
|
|
||||||
val elementIterator: Iterator<FirElement>,
|
|
||||||
traversedClassifiers: Set<FirMemberDeclaration>
|
|
||||||
) : FirTypeResolveTransformer(traversedClassifiers) {
|
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
|
||||||
if (elementIterator.hasNext()) elementIterator.next().transformSingle(this, data)
|
|
||||||
return element.compose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class SuperTypeResolver(val traversedClassifiers: Set<FirMemberDeclaration>) : FirTransformer<Nothing?>() {
|
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
|
||||||
return element.compose()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun walkSymbols(symbol: ConeClassifierSymbol) {
|
|
||||||
if (symbol !is ConeClassLikeSymbol || symbol !is FirBasedSymbol<*>) return
|
|
||||||
val classId = symbol.classId
|
|
||||||
val classes = generateSequence(classId) { it.outerClassId }.toList().asReversed()
|
|
||||||
|
|
||||||
val fir = symbol.fir
|
|
||||||
if (fir is FirTypeAlias) {
|
|
||||||
if (fir.expandedTypeRef is FirResolvedTypeRef) return
|
|
||||||
} else if (fir is FirClass) {
|
|
||||||
if (fir.superTypeRefs.all { it is FirResolvedTypeRef }) return
|
|
||||||
}
|
|
||||||
|
|
||||||
val firProvider = fir.session.service<FirProvider>()
|
|
||||||
val file = firProvider.getFirClassifierContainerFile(classes.first())
|
|
||||||
|
|
||||||
val firElementsToVisit = classes.asSequence().map {
|
|
||||||
firProvider.getFirClassifierByFqName(it)!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val transformer = SuperTypeResolveTransformer(
|
|
||||||
firElementsToVisit.iterator(), traversedClassifiers
|
|
||||||
)
|
|
||||||
file.transformSingle(transformer, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
|
||||||
val typeResolver = FirTypeResolver.getInstance(typeRef.session)
|
|
||||||
val symbol = typeResolver.resolveToSymbol(typeRef, towerScope, position = FirPosition.SUPER_TYPE_OR_EXPANSION)
|
|
||||||
val myTransformer = this@FirTypeResolveTransformer
|
|
||||||
|
|
||||||
if (symbol != null) {
|
|
||||||
if (symbol is AbstractFirBasedSymbol<*> && symbol.fir in traversedClassifiers) {
|
|
||||||
return FirErrorTypeRefImpl(typeRef.session, typeRef.psi, "Recursion detected: ${typeRef.render()}").compose()
|
|
||||||
} else {
|
|
||||||
walkSymbols(symbol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeRef !is FirUserTypeRef) return typeRef.transform(myTransformer, data)
|
|
||||||
|
|
||||||
|
|
||||||
typeRef.transformChildren(myTransformer, null)
|
|
||||||
return myTransformer.transformType(typeRef, typeResolver.resolveUserType(typeRef, symbol, towerScope))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.scopes
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||||
|
|
||||||
|
fun FirCompositeScope.addImportingScopes(file: FirFile, session: FirSession) {
|
||||||
|
scopes += listOf(
|
||||||
|
// from low priority to high priority
|
||||||
|
FirDefaultStarImportingScope(session),
|
||||||
|
FirExplicitStarImportingScope(file.imports, session),
|
||||||
|
FirDefaultSimpleImportingScope(session),
|
||||||
|
FirSelfImportingScope(file.packageFqName, session),
|
||||||
|
// TODO: explicit simple importing scope should have highest priority (higher than inner scopes added in process)
|
||||||
|
FirExplicitSimpleImportingScope(file.imports, session)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
FILE: fakeRecursiveSupertype.kt
|
FILE: fakeRecursiveSupertype.kt
|
||||||
public final class My : R|error: Recursion detected: My| {
|
public final class My : R|error: Recursion detected: R|My|| {
|
||||||
public constructor(): super<R|My|>()
|
public constructor(): super<R|My|>()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ FILE: fakeRecursiveSupertype.kt
|
|||||||
public constructor(): super<R|His|>()
|
public constructor(): super<R|His|>()
|
||||||
|
|
||||||
}
|
}
|
||||||
public final class His : R|error: Recursion detected: Your| {
|
public final class His : R|error: Recursion detected: R|Your|| {
|
||||||
public constructor(): super<R|Your|>()
|
public constructor(): super<R|Your|>()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
FILE: fakeRecursiveTypealias.kt
|
FILE: fakeRecursiveTypealias.kt
|
||||||
public final typealias My = R|error: Symbol not found, for `incorrect.directory.My`|
|
public final typealias My = R|error: Symbol not found, for `incorrect.directory.My`|
|
||||||
public final typealias Your = R|error: Recursion detected: Your|
|
public final typealias Your = R|error: Recursion detected: R|Your||
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ interface FirElement {
|
|||||||
fun acceptChildren(visitor: FirVisitorVoid) =
|
fun acceptChildren(visitor: FirVisitorVoid) =
|
||||||
acceptChildren(visitor, null)
|
acceptChildren(visitor, null)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <E : FirElement, D> transform(visitor: FirTransformer<D>, data: D): CompositeTransformResult<E> =
|
fun <E : FirElement, D> transform(visitor: FirTransformer<D>, data: D): CompositeTransformResult<E> =
|
||||||
CompositeTransformResult(accept(visitor, data))
|
accept(visitor, data) as CompositeTransformResult<E>
|
||||||
|
|
||||||
fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement = this
|
fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement = this
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -5,8 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.declarations
|
package org.jetbrains.kotlin.fir.declarations
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
|
|
||||||
interface FirClassLikeDeclaration : FirMemberDeclaration {
|
interface FirClassLikeDeclaration : FirMemberDeclaration {
|
||||||
val symbol: ConeClassifierSymbol
|
val symbol: ConeClassLikeSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ConeClassifierSymbol.toFirClassLike(): FirClassLikeDeclaration? =
|
||||||
|
when (this) {
|
||||||
|
is FirClassSymbol -> this.fir
|
||||||
|
is FirTypeAliasSymbol -> this.fir
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.BaseTransformedType
|
|||||||
import org.jetbrains.kotlin.fir.VisitedSupertype
|
import org.jetbrains.kotlin.fir.VisitedSupertype
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirSymbolOwner
|
import org.jetbrains.kotlin.fir.symbols.FirSymbolOwner
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
|
||||||
// May be all containers should be properties and not base classes
|
// May be all containers should be properties and not base classes
|
||||||
@@ -32,4 +33,8 @@ interface FirRegularClass : FirClass, @VisitedSupertype FirClassLikeDeclaration,
|
|||||||
super<FirClassLikeDeclaration>.acceptChildren(visitor, data)
|
super<FirClassLikeDeclaration>.acceptChildren(visitor, data)
|
||||||
super<FirClass>.acceptChildren(visitor, data)
|
super<FirClass>.acceptChildren(visitor, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun replaceSupertypes(newSupertypes: List<FirTypeRef>): FirRegularClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val FirRegularClass.classId get() = symbol.classId
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
|||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
|
||||||
interface FirTypeAlias : FirClassLikeDeclaration, FirSymbolOwner<FirTypeAlias> {
|
interface FirTypeAlias : FirClassLikeDeclaration, FirSymbolOwner<FirTypeAlias> {
|
||||||
|
fun replaceExpandTypeRef(typeRef: FirTypeRef): FirTypeAlias
|
||||||
|
|
||||||
val expandedTypeRef: FirTypeRef
|
val expandedTypeRef: FirTypeRef
|
||||||
|
|
||||||
override val symbol: FirTypeAliasSymbol
|
override val symbol: FirTypeAliasSymbol
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
|||||||
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.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.transformInplace
|
import org.jetbrains.kotlin.fir.transformInplace
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
open class FirClassImpl(
|
open class FirClassImpl(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
@@ -46,6 +46,11 @@ open class FirClassImpl(
|
|||||||
|
|
||||||
override val declarations = mutableListOf<FirDeclaration>()
|
override val declarations = mutableListOf<FirDeclaration>()
|
||||||
|
|
||||||
|
override fun replaceSupertypes(newSupertypes: List<FirTypeRef>): FirRegularClass {
|
||||||
|
superTypeRefs.clear()
|
||||||
|
superTypeRefs.addAll(newSupertypes)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirRegularClass {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirRegularClass {
|
||||||
superTypeRefs.transformInplace(transformer, data)
|
superTypeRefs.transformInplace(transformer, data)
|
||||||
@@ -55,4 +60,4 @@ open class FirClassImpl(
|
|||||||
declarations.transformInplace(transformer, data)
|
declarations.transformInplace(transformer, data)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -32,9 +32,14 @@ class FirTypeAliasImpl(
|
|||||||
symbol.bind(this)
|
symbol.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun replaceExpandTypeRef(typeRef: FirTypeRef): FirTypeAlias {
|
||||||
|
expandedTypeRef = typeRef
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||||
expandedTypeRef = expandedTypeRef.transformSingle(transformer, data)
|
expandedTypeRef = expandedTypeRef.transformSingle(transformer, data)
|
||||||
|
|
||||||
return super<FirAbstractMemberDeclaration>.transformChildren(transformer, data)
|
return super<FirAbstractMemberDeclaration>.transformChildren(transformer, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.visitors
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
|
||||||
@Suppress("UNSUPPORTED_FEATURE")
|
class CompositeTransformResult<out T : Any>(val a: Any) {
|
||||||
inline class CompositeTransformResult<out T : Any>(val a: Any) {
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <T : Any> empty() = CompositeTransformResult<T>(emptyList<T>())
|
fun <T : Any> empty() = CompositeTransformResult<T>(emptyList<T>())
|
||||||
@@ -33,4 +32,4 @@ inline class CompositeTransformResult<out T : Any>(val a: Any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <T : FirElement> T.compose() = CompositeTransformResult.single(this)
|
inline fun <T : FirElement> T.compose() = CompositeTransformResult.single(this)
|
||||||
|
|||||||
+1
-1
@@ -24,4 +24,4 @@ class D : A() {
|
|||||||
bar()
|
bar()
|
||||||
baz()
|
baz()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,11 +106,11 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val transformer = FirTotalResolveTransformer()
|
val transformer = FirTotalResolveTransformer()
|
||||||
|
transformer.processFiles(firFiles)
|
||||||
for (file in firFiles) {
|
for (file in firFiles) {
|
||||||
transformer.processFile(file)
|
|
||||||
val firFileDump = StringBuilder().also { file.accept(FirRenderer(it), null) }.toString()
|
val firFileDump = StringBuilder().also { file.accept(FirRenderer(it), null) }.toString()
|
||||||
val expectedPath = expectedTxtPath((file.psi as PsiFile).virtualFile)
|
val expectedPath = expectedTxtPath((file.psi as PsiFile).virtualFile)
|
||||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user