FIR: make JavaClassEnhancementScope use-site, get rid of scope providers

Related to KT-29937
This commit is contained in:
Mikhail Glukhikh
2019-03-13 14:53:43 +03:00
parent e0348b56a1
commit 6c12fabf74
14 changed files with 65 additions and 159 deletions
@@ -9,9 +9,7 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.java.scopes.JavaFirScopeProvider
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.impl.*
@@ -34,15 +32,6 @@ class FirJavaModuleBasedSession(
)
)
)
registerComponent(
FirScopeProvider::class,
FirCompositeScopeProvider(
listOf(
JavaFirScopeProvider(),
FirRegularScopeProvider()
)
)
)
}
}
@@ -63,15 +52,6 @@ class FirLibrarySession(
)
)
)
registerComponent(
FirScopeProvider::class,
FirCompositeScopeProvider(
listOf(
JavaFirScopeProvider(),
FirRegularScopeProvider()
)
)
)
}
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteScope
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
@@ -48,24 +49,27 @@ class FirJavaClass(
override val superTypeRefs = mutableListOf<FirTypeRef>()
val useSiteScope: JavaClassUseSiteScope by lazy { buildUseSiteScope() }
override fun buildClassSpecificUseSiteScope(useSiteSession: FirSession): FirScope? {
return JavaClassEnhancementScope(useSiteSession, buildJavaUseSiteScope(this, useSiteSession))
}
override val declarations = mutableListOf<FirDeclaration>()
private fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession = session): JavaClassUseSiteScope {
private fun buildJavaUseSiteScope(regularClass: FirRegularClass, useSiteSession: FirSession): JavaClassUseSiteScope {
val superTypeEnhancementScope = FirCompositeScope(mutableListOf())
val declaredScope = FirClassDeclaredMemberScope(this, useSiteSession)
lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
val declaredScope = FirClassDeclaredMemberScope(regularClass, useSiteSession)
lookupSuperTypes(regularClass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
.mapNotNullTo(superTypeEnhancementScope.scopes) { useSiteSuperType ->
if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null
val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession)
if (symbol is FirClassSymbol) {
JavaClassEnhancementScope(useSiteSession, symbol.fir.buildUseSiteScope(useSiteSession))
// We need JavaClassEnhancementScope here to have already enhanced signatures from supertypes
JavaClassEnhancementScope(useSiteSession, buildJavaUseSiteScope(symbol.fir, useSiteSession))
} else {
null
}
}
return JavaClassUseSiteScope(this, useSiteSession, superTypeEnhancementScope, declaredScope)
return JavaClassUseSiteScope(regularClass, useSiteSession, superTypeEnhancementScope, declaredScope)
}
override fun replaceSupertypes(newSupertypes: List<FirTypeRef>): FirRegularClass {
@@ -1,20 +0,0 @@
/*
* 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.java.scopes
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirScope
class JavaFirScopeProvider : FirScopeProvider {
override fun getDeclaredMemberScope(klass: FirRegularClass, session: FirSession): FirScope {
if (klass !is FirJavaClass) return FirScopeProvider.emptyScope
return JavaClassEnhancementScope(session, klass.useSiteScope)
}
}
@@ -1,18 +0,0 @@
/*
* 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
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.scopes.FirScope
interface FirScopeProvider {
fun getDeclaredMemberScope(klass: FirRegularClass, session: FirSession): FirScope
companion object {
val emptyScope = object : FirScope {}
}
}
@@ -10,12 +10,16 @@ import org.jetbrains.kotlin.fir.FirSession
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.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassUseSiteScope
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.ConeAbbreviatedType
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.*
fun lookupSuperTypes(
klass: FirRegularClass,
@@ -29,6 +33,41 @@ fun lookupSuperTypes(
}
}
fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession): FirScope {
return buildClassSpecificUseSiteScope(useSiteSession) ?: buildDefaultUseSiteScope(useSiteSession)
}
private fun FirRegularClass.buildDefaultUseSiteScope(useSiteSession: FirSession): FirScope {
val superTypeScope = FirCompositeScope(mutableListOf())
val declaredScope = FirClassDeclaredMemberScope(this, useSiteSession)
lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
.mapNotNullTo(superTypeScope.scopes) { useSiteSuperType ->
if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null
val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession)
if (symbol is FirClassSymbol) {
val useSiteScope = symbol.fir.buildUseSiteScope(useSiteSession)
useSiteSuperType.buildSubstitutionScope(useSiteScope, symbol.fir) ?: useSiteScope
} else {
null
}
}
return FirClassUseSiteScope(useSiteSession, superTypeScope, declaredScope)
}
private fun ConeClassLikeType.buildSubstitutionScope(
useSiteScope: FirScope,
regularClass: FirRegularClass
): FirClassSubstitutionScope? {
if (this.typeArguments.isEmpty()) return null
@Suppress("UNCHECKED_CAST")
val substitution = regularClass.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type
}.filter { (_, type) -> type != null }.toMap() as Map<ConeTypeParameterSymbol, ConeKotlinType>
return FirClassSubstitutionScope(useSiteScope, substitution)
}
private tailrec fun ConeClassLikeType.computePartialExpansion(useSiteSession: FirSession): ConeClassLikeType? {
return when (this) {
is ConeAbbreviatedType -> directExpansionType(useSiteSession)?.computePartialExpansion(useSiteSession)
@@ -1,18 +0,0 @@
/*
* 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.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
class FirCompositeScopeProvider(private val providers: List<FirScopeProvider>) : FirScopeProvider {
override fun getDeclaredMemberScope(klass: FirRegularClass, session: FirSession): FirScope {
return FirCompositeScope(providers.mapTo(mutableListOf()) { it.getDeclaredMemberScope(klass, session) })
}
}
@@ -1,22 +0,0 @@
/*
* 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.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
class FirRegularScopeProvider : FirScopeProvider {
override fun getDeclaredMemberScope(klass: FirRegularClass, session: FirSession): FirScope {
if (klass !is FirClassImpl) return FirScopeProvider.emptyScope
return FirClassDeclaredMemberScope(klass, session)
}
}
@@ -7,27 +7,17 @@ package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirNamedReference
import org.jetbrains.kotlin.fir.FirResolvedCallableReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypedProjection
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose
@@ -40,40 +30,9 @@ class FirAccessResolveTransformer : FirAbstractTreeTransformerWithSuperTypes(rev
}
}
private fun ConeClassLikeType.buildSubstitutionScope(
useSiteScope: FirClassUseSiteScope,
regularClass: FirRegularClass
): FirClassSubstitutionScope? {
if (this.typeArguments.isEmpty()) return null
@Suppress("UNCHECKED_CAST")
val substitution = regularClass.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type
}.filter { (_, type) -> type != null }.toMap() as Map<ConeTypeParameterSymbol, ConeKotlinType>
return FirClassSubstitutionScope(useSiteScope, substitution)
}
private fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession = session): FirClassUseSiteScope {
val superTypeScope = FirCompositeScope(mutableListOf())
val declaredScope = useSiteSession.service<FirScopeProvider>().getDeclaredMemberScope(this, useSiteSession)
lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
.mapNotNullTo(superTypeScope.scopes) { useSiteSuperType ->
if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null
val symbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession)
if (symbol is FirClassSymbol) {
val useSiteScope = symbol.fir.buildUseSiteScope(useSiteSession)
useSiteSuperType.buildSubstitutionScope(useSiteScope, symbol.fir) ?: useSiteScope
} else {
null
}
}
return FirClassUseSiteScope(useSiteSession, superTypeScope, declaredScope)
}
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
return withScopeCleanup {
towerScope.scopes += regularClass.buildUseSiteScope()
towerScope.scopes += regularClass.buildUseSiteScope(regularClass.session)
super.transformRegularClass(regularClass, data)
}
}
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.name.Name
class FirClassSubstitutionScope(
private val useSiteScope: FirClassUseSiteScope,
private val useSiteScope: FirScope,
private val substitution: Map<ConeTypeParameterSymbol, ConeKotlinType>
) : FirScope {
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
@@ -171,7 +170,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
val processedJavaClasses = mutableSetOf<FirJavaClass>()
for (javaClass in javaProvider.getJavaTopLevelClasses().sortedBy { it.name }) {
if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) continue
val enhancementScope = session.service<FirScopeProvider>().getDeclaredMemberScope(javaClass, session).let {
val enhancementScope = javaClass.buildClassSpecificUseSiteScope(session).let {
when (it) {
is FirCompositeScope -> it.scopes.filterIsInstance<JavaClassEnhancementScope>().first()
is JavaClassEnhancementScope -> it
@@ -6,8 +6,10 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.expressions.FirAnnotationContainer
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
@@ -19,6 +21,8 @@ interface FirClass : FirDeclarationContainer, FirStatement, FirAnnotationContain
val classKind: ClassKind
fun buildClassSpecificUseSiteScope(useSiteSession: FirSession): FirScope? = null
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitClass(this, data)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* 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.
*/
@@ -3,8 +3,8 @@ FILE: jvm.kt
public constructor(): super<R|AnnotatedDerived|>()
public final function test(): R|kotlin/Unit| {
val x: R|error: Not supported: FirImplicitTypeRefImpl| = <Ambiguity: foo, [/AnnotatedDerived.foo, /Annotated.foo]>#(String(123))
val y: R|error: Not supported: FirImplicitTypeRefImpl| = <Ambiguity: foo, [/AnnotatedDerived.foo, /Annotated.foo]>#(Null(null))
val x: R|error: Not supported: FirImplicitTypeRefImpl| = R|/AnnotatedDerived.foo|(String(123))
val y: R|error: Not supported: FirImplicitTypeRefImpl| = R|/AnnotatedDerived.foo|(Null(null))
}
}
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.FirScopeProvider
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
@@ -133,7 +132,7 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
val javaProvider = symbolProvider.providers.filterIsInstance<JavaSymbolProvider>().first()
for (javaClass in javaProvider.getJavaTopLevelClasses().sortedBy { it.name }) {
if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) continue
val enhancementScope = session.service<FirScopeProvider>().getDeclaredMemberScope(javaClass, session).let {
val enhancementScope = javaClass.buildClassSpecificUseSiteScope(session).let {
when (it) {
is FirCompositeScope -> it.scopes.filterIsInstance<JavaClassEnhancementScope>().first()
is JavaClassEnhancementScope -> it