Extract supertypes resolution into a separate FIR phase

This commit is contained in:
Denis Zharkov
2019-03-11 11:53:11 +03:00
parent 3f4c5c8d53
commit 92defc2ae3
18 changed files with 340 additions and 179 deletions
@@ -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>()
} }
@@ -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)
}
}
} }
@@ -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()
}
}
@@ -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)
@@ -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 {
} }
} }
} }
} }
@@ -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
} }
@@ -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
} }
} }
@@ -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)
} }
} }
@@ -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
View File
@@ -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)
} }
} }
} }