diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt index 78773772890..2ed4a6a8d72 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/FirSymbolProvider.kt @@ -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() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractTreeTransformerWithSuperTypes.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractTreeTransformerWithSuperTypes.kt index 362fe45a27c..bbc833956ac 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractTreeTransformerWithSuperTypes.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractTreeTransformerWithSuperTypes.kt @@ -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) + } + } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt new file mode 100644 index 00000000000..c1c43c55932 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSpecificTypeResolverTransformer.kt @@ -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 { + 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 { + val typeResolver = FirTypeResolver.getInstance(functionTypeRef.session) + functionTypeRef.transformChildren(this, data) + return FirResolvedFunctionTypeRefImpl( + functionTypeRef.psi, + functionTypeRef.session, + functionTypeRef.isMarkedNullable, + functionTypeRef.annotations as MutableList, + functionTypeRef.receiverTypeRef, + functionTypeRef.valueParameters as MutableList, + functionTypeRef.returnTypeRef, + typeResolver.resolveType(functionTypeRef, towerScope, position) + ).compose() + } + + private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType): CompositeTransformResult { + return FirResolvedTypeRefImpl( + typeRef.session, + typeRef.psi, + resolvedType, + false, + typeRef.annotations + ).compose() + } + + override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): CompositeTransformResult { + return resolvedTypeRef.compose() + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt new file mode 100644 index 00000000000..7bab2463037 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypeResolverTransformer.kt @@ -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 = mutableSetOf() + private val fullyComputed: MutableSet = mutableSetOf() + + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + firSession = file.session + return super.transformFile(file, data) + } + + override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult { + 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 { + 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, + private val fullyComputed: MutableSet + ) : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) { + + lateinit var resultingClass: FirDeclaration + + init { + towerScope.addImportingScopes(file, session) + } + + override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult { + 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 { + 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 + ): List { + currentlyComputing.add(classId) + + val resultingTypeRefs = mutableListOf() + for (superTypeRef in resolvedTypesRefs) { + val resolvedType = superTypeRef.coneTypeSafe() ?: 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 { + 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().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) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveTransformer.kt index 134335b5b4f..d05bd80e232 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveTransformer.kt @@ -12,17 +12,12 @@ class FirTotalResolveTransformer { val transformers: List> = listOf( FirImportResolveTransformer(), + FirSupertypeResolverTransformer(), FirTypeResolveTransformer(), FirStatusResolveTransformer(), FirAccessResolveTransformer() ) - fun processFile(firFile: FirFile) { - for (transformer in transformers) { - firFile.transform(transformer, null) - } - } - fun processFiles(files: List) { for (transformer in transformers) { for (firFile in files) { @@ -30,4 +25,4 @@ class FirTotalResolveTransformer { } } } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt index d695b9ea87b..6bc3f6a1877 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt @@ -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 = 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 { - 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 { 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 { 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 { return withScopeCleanup { property.addTypeParametersScope() @@ -117,112 +76,6 @@ open class FirTypeResolveTransformer( } override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult { - 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 { - val typeResolver = FirTypeResolver.getInstance(functionTypeRef.session) - functionTypeRef.transformChildren(this, data) - return FirResolvedFunctionTypeRefImpl( - functionTypeRef.psi, - functionTypeRef.session, - functionTypeRef.isMarkedNullable, - functionTypeRef.annotations as MutableList, - functionTypeRef.receiverTypeRef, - functionTypeRef.valueParameters as MutableList, - functionTypeRef.returnTypeRef, - typeResolver.resolveType(functionTypeRef, towerScope, FirPosition.OTHER) - ).compose() - } - - private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType): CompositeTransformResult { - return FirResolvedTypeRefImpl( - typeRef.session, - typeRef.psi, - resolvedType, - false, - typeRef.annotations - ).compose() - } - - override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): CompositeTransformResult { - return resolvedTypeRef.compose() - } - - override fun transformValueParameter(valueParameter: FirValueParameter, data: Nothing?): CompositeTransformResult { - return valueParameter.also { it.transformChildren(this, data) }.compose() - } - - - override fun transformTypeProjectionWithVariance( - typeProjectionWithVariance: FirTypeProjectionWithVariance, - data: Nothing? - ): CompositeTransformResult { - typeProjectionWithVariance.transformChildren(this, data) - return typeProjectionWithVariance.compose() - } - - private class SuperTypeResolveTransformer( - val elementIterator: Iterator, - traversedClassifiers: Set - ) : FirTypeResolveTransformer(traversedClassifiers) { - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - if (elementIterator.hasNext()) elementIterator.next().transformSingle(this, data) - return element.compose() - } - } - - private inner class SuperTypeResolver(val traversedClassifiers: Set) : FirTransformer() { - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - 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() - 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 { - 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) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt new file mode 100644 index 00000000000..833925d6adf --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt @@ -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) + ) +} diff --git a/compiler/fir/resolve/testData/resolve/fakeRecursiveSupertype.txt b/compiler/fir/resolve/testData/resolve/fakeRecursiveSupertype.txt index 147c65dd506..90e5925da58 100644 --- a/compiler/fir/resolve/testData/resolve/fakeRecursiveSupertype.txt +++ b/compiler/fir/resolve/testData/resolve/fakeRecursiveSupertype.txt @@ -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() } @@ -7,7 +7,7 @@ FILE: fakeRecursiveSupertype.kt public constructor(): super() } - public final class His : R|error: Recursion detected: Your| { + public final class His : R|error: Recursion detected: R|Your|| { public constructor(): super() } diff --git a/compiler/fir/resolve/testData/resolve/fakeRecursiveTypealias.txt b/compiler/fir/resolve/testData/resolve/fakeRecursiveTypealias.txt index 020bb475403..d02b3ac0436 100644 --- a/compiler/fir/resolve/testData/resolve/fakeRecursiveTypealias.txt +++ b/compiler/fir/resolve/testData/resolve/fakeRecursiveTypealias.txt @@ -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|| diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirElement.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirElement.kt index 555bd887d1e..cc2f73c4d2f 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirElement.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirElement.kt @@ -28,8 +28,9 @@ interface FirElement { fun acceptChildren(visitor: FirVisitorVoid) = acceptChildren(visitor, null) + @Suppress("UNCHECKED_CAST") fun transform(visitor: FirTransformer, data: D): CompositeTransformResult = - CompositeTransformResult(accept(visitor, data)) + accept(visitor, data) as CompositeTransformResult fun transformChildren(transformer: FirTransformer, data: D): FirElement = this -} \ No newline at end of file +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClassLikeDeclaration.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClassLikeDeclaration.kt index b25a1a19a84..143bbb53bf3 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClassLikeDeclaration.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirClassLikeDeclaration.kt @@ -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 + } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt index f5049864cb4..c7e21479465 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirRegularClass.kt @@ -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.acceptChildren(visitor, data) super.acceptChildren(visitor, data) } + + fun replaceSupertypes(newSupertypes: List): FirRegularClass } + +val FirRegularClass.classId get() = symbol.classId diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirTypeAlias.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirTypeAlias.kt index f6b0e2713cc..8262b50393c 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirTypeAlias.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirTypeAlias.kt @@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.visitors.FirVisitor interface FirTypeAlias : FirClassLikeDeclaration, FirSymbolOwner { + fun replaceExpandTypeRef(typeRef: FirTypeRef): FirTypeAlias + val expandedTypeRef: FirTypeRef override val symbol: FirTypeAliasSymbol diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt index 1c027a3d960..680245d5739 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirClassImpl.kt @@ -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() + override fun replaceSupertypes(newSupertypes: List): FirRegularClass { + superTypeRefs.clear() + superTypeRefs.addAll(newSupertypes) + return this + } override fun transformChildren(transformer: FirTransformer, data: D): FirRegularClass { superTypeRefs.transformInplace(transformer, data) @@ -55,4 +60,4 @@ open class FirClassImpl( declarations.transformInplace(transformer, data) return result } -} \ No newline at end of file +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt index 231eb96c272..3f53ac55751 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirTypeAliasImpl.kt @@ -32,9 +32,14 @@ class FirTypeAliasImpl( symbol.bind(this) } + override fun replaceExpandTypeRef(typeRef: FirTypeRef): FirTypeAlias { + expandedTypeRef = typeRef + return this + } + override fun transformChildren(transformer: FirTransformer, data: D): FirElement { expandedTypeRef = expandedTypeRef.transformSingle(transformer, data) return super.transformChildren(transformer, data) } -} \ No newline at end of file +} diff --git a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/CompositeTransformResult.kt b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/CompositeTransformResult.kt index e4a9ffcfae2..b4e72b71b42 100644 --- a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/CompositeTransformResult.kt +++ b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/CompositeTransformResult.kt @@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.visitors import org.jetbrains.kotlin.fir.FirElement -@Suppress("UNSUPPORTED_FEATURE") -inline class CompositeTransformResult(val a: Any) { +class CompositeTransformResult(val a: Any) { companion object { fun empty() = CompositeTransformResult(emptyList()) @@ -33,4 +32,4 @@ inline class CompositeTransformResult(val a: Any) { } @Suppress("NOTHING_TO_INLINE") -inline fun T.compose() = CompositeTransformResult.single(this) \ No newline at end of file +inline fun T.compose() = CompositeTransformResult.single(this) diff --git a/idea/testData/fir/multiModule/mppSuperTypes/jvm/jvm.kt b/idea/testData/fir/multiModule/mppSuperTypes/jvm/jvm.kt index c4d28b4a0e6..7f9212f9c55 100644 --- a/idea/testData/fir/multiModule/mppSuperTypes/jvm/jvm.kt +++ b/idea/testData/fir/multiModule/mppSuperTypes/jvm/jvm.kt @@ -24,4 +24,4 @@ class D : A() { bar() baz() } -} \ No newline at end of file +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt index e5f819f695b..f505b9e27f9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt @@ -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) } } -} \ No newline at end of file +}