FIR: introduce classifier scopes #KT-24022 Fixed

This commit is contained in:
Mikhail Glukhikh
2018-03-20 17:27:54 +03:00
parent 1ba498b021
commit d5463193fd
10 changed files with 120 additions and 20 deletions
@@ -6,40 +6,65 @@
package org.jetbrains.kotlin.descriptors package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirNestedClassifierScope
import org.jetbrains.kotlin.fir.scopes.impl.FirSelfImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirSelfImportingScope
import org.jetbrains.kotlin.fir.transformInplace
import org.jetbrains.kotlin.fir.types.ConeClassType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirResolvedType import org.jetbrains.kotlin.fir.types.FirResolvedType
import org.jetbrains.kotlin.fir.types.FirType import org.jetbrains.kotlin.fir.types.FirType
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl
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.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
class FirTypeResolveTransformer : FirTransformer<Nothing?>() { class FirTypeResolveTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> { override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return (element.transformChildren(this, data) as E).compose() return (element.transformChildren(this, data) as E).compose()
} }
lateinit var importingScope: FirImportingScope lateinit var scope: FirCompositeScope
lateinit var packageFqName: FqName
var className: FqName = FqName.ROOT
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> { override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
importingScope = FirCompositeImportingScope( scope = FirCompositeScope(
FirExplicitImportingScope(file.imports), mutableListOf(
FirSelfImportingScope(file.packageFqName, file.session) FirExplicitImportingScope(file.imports),
FirSelfImportingScope(file.packageFqName, file.session)
)
) )
packageFqName = file.packageFqName
return file.also { it.transformChildren(this, null) }.compose() return file.also { it.transformChildren(this, null) }.compose()
} }
override fun transformClass(klass: FirClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
klass.transformChildren(SuperTypeResolver(), null)
className = className.child(klass.name)
scope.scopes += FirNestedClassifierScope(ClassId(packageFqName, className, false), klass.session)
val result = super.transformClass(klass, data)
scope.scopes.also { it.removeAt(it.lastIndex) }
className = className.parent()
return result
}
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> { override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
val typeResolver = FirTypeResolver.getInstance(type.session) val typeResolver = FirTypeResolver.getInstance(type.session)
return FirResolvedTypeImpl( return FirResolvedTypeImpl(
type.session, type.session,
type.psi, type.psi,
typeResolver.resolveType(type, importingScope), typeResolver.resolveType(type, scope),
false, false,
type.annotations type.annotations
).compose() ).compose()
@@ -48,4 +73,22 @@ class FirTypeResolveTransformer : FirTransformer<Nothing?>() {
override fun transformResolvedType(resolvedType: FirResolvedType, data: Nothing?): CompositeTransformResult<FirType> { override fun transformResolvedType(resolvedType: FirResolvedType, data: Nothing?): CompositeTransformResult<FirType> {
return resolvedType.compose() return resolvedType.compose()
} }
private inner class SuperTypeResolver : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
}
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
val transformedType = this@FirTypeResolveTransformer.transformType(type, data).single as FirResolvedType
val classId = (transformedType.type as? ConeClassType)?.fqName ?: return transformedType.compose()
val firProvider = FirProvider.getInstance(transformedType.session)
// ???
firProvider.getFirClassifierByFqName(classId)!!.transformChildren(this, data)
return transformedType.compose()
}
}
} }
@@ -6,14 +6,14 @@
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.scopes.FirImportingScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.types.FirType import org.jetbrains.kotlin.fir.types.FirType
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
interface FirTypeResolver { interface FirTypeResolver {
fun resolveType(type: FirType, importingScope: FirImportingScope): ConeKotlinType fun resolveType(type: FirType, scope: FirScope): ConeKotlinType
companion object { companion object {
fun getInstance(session: FirSession): FirTypeResolver = session.service() fun getInstance(session: FirSession): FirTypeResolver = session.service()
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.fir.resolve.impl
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeKotlinErrorType import org.jetbrains.kotlin.fir.types.impl.ConeKotlinErrorType
class FirTypeResolverImpl : FirTypeResolver { class FirTypeResolverImpl : FirTypeResolver {
override fun resolveType(type: FirType, importingScope: FirImportingScope): ConeKotlinType { override fun resolveType(type: FirType, scope: FirScope): ConeKotlinType {
return when (type) { return when (type) {
is FirResolvedType -> type.type is FirResolvedType -> type.type
is FirUserType -> { is FirUserType -> {
@@ -20,7 +20,7 @@ class FirTypeResolverImpl : FirTypeResolver {
val qualifierResolver = FirQualifierResolver.getInstance(type.session) val qualifierResolver = FirQualifierResolver.getInstance(type.session)
var resolvedType: ConeKotlinType? = null var resolvedType: ConeKotlinType? = null
importingScope.processClassifiersByName(type.qualifier.first().name) { fqName -> scope.processClassifiersByName(type.qualifier.first().name) { fqName ->
resolvedType = qualifierResolver.resolveTypeWithPrefix(type.qualifier.drop(1), fqName) resolvedType = qualifierResolver.resolveTypeWithPrefix(type.qualifier.drop(1), fqName)
resolvedType == null resolvedType == null
} }
@@ -8,6 +8,6 @@ package org.jetbrains.kotlin.fir.scopes
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
interface FirImportingScope { interface FirScope {
fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean
} }
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.fir.scopes.impl package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class FirCompositeImportingScope(vararg val scopes: FirImportingScope) : FirImportingScope { class FirCompositeScope(val scopes: MutableList<FirScope>) : FirScope {
override fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean { override fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean {
for (scope in scopes) { for (scope in scopes) {
if (!scope.processClassifiersByName(name, processor)) { if (!scope.processClassifiersByName(name, processor)) {
@@ -7,11 +7,11 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.declarations.FirImport import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class FirExplicitImportingScope(imports: List<FirImport>) : FirImportingScope { class FirExplicitImportingScope(imports: List<FirImport>) : FirScope {
// TODO: Resolve imports! Instead of computing it resolution results here // TODO: Resolve imports! Instead of computing it resolution results here
private val simpleImports = private val simpleImports =
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2018 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.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.types.ConeClassType
import org.jetbrains.kotlin.fir.types.FirResolvedType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
class FirNestedClassifierScope(val classId: ClassId, val session: FirSession) : FirScope {
private val firProvider = FirProvider.getInstance(session)
fun ClassId.getFir(): FirMemberDeclaration? {
return firProvider.getFirClassifierByFqName(this)
}
private val superScopes by lazy {
val self = classId.getFir()
when (self) {
is FirClass -> {
val superTypes = self.superTypes as List<FirResolvedType>
FirCompositeScope(superTypes.mapTo(ArrayList(superTypes.size)) {
FirNestedClassifierScope((it.type as ConeClassType).fqName, session)
})
}
else -> error("!")
}
}
override fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean {
val child = ClassId(classId.packageFqName, classId.relativeClassName.child(name), false)
if (child.getFir() != null && !processor(child)) return false
return superScopes.processClassifiersByName(name, processor)
}
}
@@ -7,13 +7,13 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.FirProvider import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.scopes.FirImportingScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class FirSelfImportingScope(val fqName: FqName, val session: FirSession) : FirImportingScope { class FirSelfImportingScope(val fqName: FqName, val session: FirSession) : FirScope {
override fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean { override fun processClassifiersByName(name: Name, processor: (ClassId) -> Boolean): Boolean {
+4
View File
@@ -6,4 +6,8 @@ abstract class My {
} }
} }
}
class Your : My() {
class NestedThree : NestedOne()
} }
+6 -1
View File
@@ -1,9 +1,14 @@
FILE: NestedSuperType.kt FILE: NestedSuperType.kt
unknown abstract class My() { unknown abstract class My() {
unknown abstract class NestedOne() : R/p.My/ { unknown abstract class NestedOne() : R/p.My/ {
unknown abstract class NestedTwo() : R/error: Failed to resolve qualified type/ { unknown abstract class NestedTwo() : R/p.My.NestedOne/ {
} }
} }
} }
unknown final class Your() : R/p.My/ {
unknown final class NestedThree() : R/p.My.NestedOne/ {
}
}