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
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.toFirClassLike
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.name.ClassId
@@ -27,6 +28,9 @@ interface FirSymbolProvider {
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 {
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.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.declarations.superConeTypes
import org.jetbrains.kotlin.fir.resolve.toSymbol
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.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
@@ -100,4 +102,11 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority: B
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(
FirImportResolveTransformer(),
FirSupertypeResolverTransformer(),
FirTypeResolveTransformer(),
FirStatusResolveTransformer(),
FirAccessResolveTransformer()
)
fun processFile(firFile: FirFile) {
for (transformer in transformers) {
firFile.transform<FirFile, Nothing?>(transformer, null)
}
}
fun processFiles(files: List<FirFile>) {
for (transformer in transformers) {
for (firFile in files) {
@@ -30,4 +25,4 @@ class FirTotalResolveTransformer {
}
}
}
}
}
@@ -5,68 +5,35 @@
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.expressions.FirAnnotationCall
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.resolve.FirTypeResolver
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.service
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.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
open class FirTypeResolveTransformer(
private val traversedClassifiers: Set<FirMemberDeclaration> = setOf()
) : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
private lateinit var firProvider: FirProvider
open class FirTypeResolveTransformer : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
private lateinit var session: FirSession
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
val session = file.session
firProvider = session.getService(FirProvider::class)
session = file.session
return withScopeCleanup {
towerScope.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)
)
towerScope.addImportingScopes(file, session)
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> {
withScopeCleanup {
regularClass.addTypeParametersScope()
resolveSuperTypesAndExpansions(regularClass)
regularClass.typeParameters.forEach {
it.accept(this, data)
}
}
return withScopeCleanup {
val session = regularClass.session
val firProvider = FirProvider.getInstance(session)
@@ -89,19 +56,11 @@ open class FirTypeResolveTransformer(
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup {
typeAlias.addTypeParametersScope()
resolveSuperTypesAndExpansions(typeAlias)
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> {
return withScopeCleanup {
property.addTypeParametersScope()
@@ -117,112 +76,6 @@ open class FirTypeResolveTransformer(
}
override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
val typeResolver = FirTypeResolver.getInstance(typeRef.session)
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))
}
return FirSpecificTypeResolverTransformer(towerScope, FirPosition.OTHER, session).transformTypeRef(typeRef, data)
}
}
@@ -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
public final class My : R|error: Recursion detected: My| {
public final class My : R|error: Recursion detected: R|My|| {
public constructor(): super<R|My|>()
}
@@ -7,7 +7,7 @@ FILE: fakeRecursiveSupertype.kt
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|>()
}
@@ -1,3 +1,3 @@
FILE: fakeRecursiveTypealias.kt
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) =
acceptChildren(visitor, null)
@Suppress("UNCHECKED_CAST")
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
}
}
@@ -5,8 +5,18 @@
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.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
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.symbols.FirSymbolOwner
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirVisitor
// 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<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
interface FirTypeAlias : FirClassLikeDeclaration, FirSymbolOwner<FirTypeAlias> {
fun replaceExpandTypeRef(typeRef: FirTypeRef): FirTypeAlias
val expandedTypeRef: FirTypeRef
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.Visibility
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.FirRegularClass
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.transformInplace
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.name.Name
open class FirClassImpl(
session: FirSession,
@@ -46,6 +46,11 @@ open class FirClassImpl(
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 {
superTypeRefs.transformInplace(transformer, data)
@@ -55,4 +60,4 @@ open class FirClassImpl(
declarations.transformInplace(transformer, data)
return result
}
}
}
@@ -32,9 +32,14 @@ class FirTypeAliasImpl(
symbol.bind(this)
}
override fun replaceExpandTypeRef(typeRef: FirTypeRef): FirTypeAlias {
expandedTypeRef = typeRef
return this
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
expandedTypeRef = expandedTypeRef.transformSingle(transformer, data)
return super<FirAbstractMemberDeclaration>.transformChildren(transformer, data)
}
}
}
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.visitors
import org.jetbrains.kotlin.fir.FirElement
@Suppress("UNSUPPORTED_FEATURE")
inline class CompositeTransformResult<out T : Any>(val a: Any) {
class CompositeTransformResult<out T : Any>(val a: Any) {
companion object {
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")
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()
baz()
}
}
}
@@ -106,11 +106,11 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
}
val transformer = FirTotalResolveTransformer()
transformer.processFiles(firFiles)
for (file in firFiles) {
transformer.processFile(file)
val firFileDump = StringBuilder().also { file.accept(FirRenderer(it), null) }.toString()
val expectedPath = expectedTxtPath((file.psi as PsiFile).virtualFile)
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
}
}
}
}