FIR: split transformer into three (imports / types / descriptors)

This commit is contained in:
Mikhail Glukhikh
2018-03-20 15:25:16 +03:00
parent 8933c9035b
commit 6c8a326e15
22 changed files with 243 additions and 81 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.types.FirType
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.modalityModifierType
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
@@ -206,7 +207,7 @@ class RawFirBuilder(val session: FirSession) {
importDirective,
importDirective.importedFqName,
importDirective.isAllUnder,
importDirective.aliasName
importDirective.aliasName?.let { Name.identifier(it) }
)
}
for (declaration in file.declarations) {
@@ -33,31 +33,9 @@ class FirClassifierResolveTransformer : FirTransformer<Nothing?>() {
lateinit var packageFqName: FqNameUnsafe
lateinit var importingScope: FirImportingScope
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
packageFqName = file.packageFqName.toUnsafe()
importingScope = FirCompositeImportingScope(
FirExplicitImportingScope(file.imports),
FirSelfImportingScope(file.packageFqName.toUnsafe(), file.session)
)
return file.also { it.acceptChildren(this, null) }.compose()
}
// TODO: Extract to separate transformer?
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
val typeResolver = FirTypeResolver.getInstance(type.session)
return FirResolvedTypeImpl(
type.session,
type.psi,
typeResolver.resolveType(type, importingScope),
false,
type.annotations
).compose()
}
override fun transformResolvedType(resolvedType: FirResolvedType, data: Nothing?): CompositeTransformResult<FirType> {
return resolvedType.compose()
return file.also { it.transformChildren(this, null) }.compose()
}
var className: FqName = FqName.ROOT
@@ -0,0 +1,52 @@
/*
* 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.descriptors
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.UnambiguousFqName
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.name.FqName
class FirImportResolveTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose()
}
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
return file.also { it.transformChildren(this, null) }.compose()
}
override fun transformImport(import: FirImport, data: Nothing?): CompositeTransformResult<FirImport> {
val fqName = import.importedFqName ?: return import.compose()
val firProvider = FirProvider.getInstance(import.session)
if (!fqName.isRoot) {
val lastPart = mutableListOf<String>()
var firstPart = fqName
while (!firstPart.isRoot) {
lastPart.add(0, firstPart.shortName().asString())
firstPart = firstPart.parent()
val resolvedFqName = UnambiguousFqName(firstPart.toUnsafe(), FqName.fromSegments(lastPart))
val foundClassifier = firProvider.getFirClassifierByFqName(resolvedFqName)
if (foundClassifier != null) {
return FirResolvedImportImpl(import, resolvedFqName).compose()
}
}
return import.compose()
} else {
return import.compose()
}
}
}
@@ -0,0 +1,32 @@
/*
* 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.descriptors
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.visitors.FirTransformer
class FirTotalResolveTransformer {
private val transformers: List<FirTransformer<Nothing?>> = listOf(
FirImportResolveTransformer(),
FirTypeResolveTransformer(),
FirClassifierResolveTransformer()
)
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) {
firFile.transform<FirFile, Nothing?>(transformer, null)
}
}
}
}
@@ -0,0 +1,51 @@
/*
* 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.descriptors
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
import org.jetbrains.kotlin.fir.scopes.FirImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitImportingScope
import org.jetbrains.kotlin.fir.scopes.impl.FirSelfImportingScope
import org.jetbrains.kotlin.fir.types.FirResolvedType
import org.jetbrains.kotlin.fir.types.FirType
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
class FirTypeResolveTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return (element.transformChildren(this, data) as E).compose()
}
lateinit var importingScope: FirImportingScope
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
importingScope = FirCompositeImportingScope(
FirExplicitImportingScope(file.imports),
FirSelfImportingScope(file.packageFqName.toUnsafe(), file.session)
)
return file.also { it.transformChildren(this, null) }.compose()
}
override fun transformType(type: FirType, data: Nothing?): CompositeTransformResult<FirType> {
val typeResolver = FirTypeResolver.getInstance(type.session)
return FirResolvedTypeImpl(
type.session,
type.psi,
typeResolver.resolveType(type, importingScope),
false,
type.annotations
).compose()
}
override fun transformResolvedType(resolvedType: FirResolvedType, data: Nothing?): CompositeTransformResult<FirType> {
return resolvedType.compose()
}
}
@@ -17,8 +17,6 @@ interface FirQualifierResolver {
fun resolveType(parts: List<FirQualifierPart>): ConeKotlinType?
fun resolveImport(fqName: FqName): UnambiguousFqName?
companion object {
fun getInstance(session: FirSession): FirQualifierResolver = session.service()
}
@@ -71,33 +71,6 @@ class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
}
}
// TODO: extract common part from resolveType/Import
override fun resolveImport(fqName: FqName): UnambiguousFqName? {
val firProvider = FirProvider.getInstance(session)
if (!fqName.isRoot) {
val lastPart = mutableListOf<String>()
var firstPart = fqName
while (!firstPart.isRoot) {
lastPart.add(0, firstPart.shortName().asString())
firstPart = firstPart.parent()
val fqName = UnambiguousFqName(firstPart.toUnsafe(), FqName.fromSegments(lastPart))
val foundClassifier = firProvider.getFirClassifierByFqName(fqName)
if (foundClassifier != null) {
return fqName
}
}
return null
} else {
return null
}
}
private fun List<FirQualifierPart>.toFqNameUnsafe() = toFqName().toUnsafe()
private fun List<FirQualifierPart>.toFqName() = fold(FqName.ROOT) { a, b -> a.child(b.name) }
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.UnambiguousFqName
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
import org.jetbrains.kotlin.fir.scopes.FirImportingScope
import org.jetbrains.kotlin.name.Name
@@ -15,20 +16,14 @@ class FirExplicitImportingScope(imports: List<FirImport>) : FirImportingScope {
// TODO: Resolve imports! Instead of computing it resolution results here
private val simpleImports =
imports.filter { !it.isAllUnder && it.aliasName == null && it.importedFqName != null }
.mapNotNull { it.resolve() }
.groupBy { it.classFqName.shortName() }
private fun FirImport.resolve(): UnambiguousFqName? {
val session = session
val qualifierResolver = FirQualifierResolver.getInstance(session)
return qualifierResolver.resolveImport(importedFqName!!)
}
imports.filterIsInstance<FirResolvedImport>()
.filter { !it.isAllUnder }
.groupBy { it.aliasName ?: it.resolvedFqName.classFqName.shortName() }
override fun processClassifiersByName(name: Name, processor: (UnambiguousFqName) -> Boolean): Boolean {
val imports = simpleImports[name] ?: return true
for (import in imports) {
if (!processor(import)) {
if (!processor(import.resolvedFqName)) {
return false
}
}
@@ -6,8 +6,10 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.BaseTransformedType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.VisitedSupertype
import org.jetbrains.kotlin.fir.expressions.FirAnnotationContainer
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.FqName
@@ -5,16 +5,19 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.BaseTransformedType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@BaseTransformedType
interface FirImport : FirElement {
val importedFqName: FqName?
val isAllUnder: Boolean
val aliasName: String?
val aliasName: Name?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitImport(this, data)
@@ -6,5 +6,9 @@
package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.FirDescriptorOwner
import org.jetbrains.kotlin.fir.visitors.FirVisitor
interface FirResolvedClass : FirClass, FirDescriptorOwner<FirResolvedClass>
interface FirResolvedClass : FirClass, FirDescriptorOwner<FirResolvedClass> {
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitResolvedClass(this, data)
}
@@ -0,0 +1,16 @@
/*
* 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.declarations
import org.jetbrains.kotlin.fir.UnambiguousFqName
import org.jetbrains.kotlin.fir.visitors.FirVisitor
interface FirResolvedImport : FirImport {
val resolvedFqName: UnambiguousFqName
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitResolvedImport(this, data)
}
@@ -9,11 +9,12 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class FirImportImpl(
override val session: FirSession,
override val psi: PsiElement?,
override val importedFqName: FqName?,
override val isAllUnder: Boolean,
override val aliasName: String?
override val aliasName: Name?
) : FirImport
@@ -0,0 +1,19 @@
/*
* 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.declarations.impl
import org.jetbrains.kotlin.fir.UnambiguousFqName
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.visitors.FirVisitor
class FirResolvedImportImpl(
val delegate: FirImport,
override val resolvedFqName: UnambiguousFqName
) : FirResolvedImport, FirImport by delegate {
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitResolvedImport(this, data)
}
@@ -94,10 +94,14 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformDeclaration(variable, data)
}
open fun <E : FirElement> transformImport(import: E, data: D): CompositeTransformResult<E> {
open fun transformImport(import: FirImport, data: D): CompositeTransformResult<FirImport> {
return transformElement(import, data)
}
open fun transformResolvedImport(resolvedImport: FirResolvedImport, data: D): CompositeTransformResult<FirImport> {
return transformImport(resolvedImport, data)
}
open fun <E : FirElement> transformPackageFragment(packageFragment: E, data: D): CompositeTransformResult<E> {
return transformElement(packageFragment, data)
}
@@ -210,6 +214,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformFunction(function, data)
}
final override fun visitImport(import: FirImport, data: D): CompositeTransformResult<FirElement> {
return transformImport(import, data)
}
final override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration, data: D): CompositeTransformResult<FirElement> {
return transformMemberDeclaration(memberDeclaration, data)
}
@@ -282,10 +290,6 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformAnonymousInitializer(anonymousInitializer, data)
}
final override fun visitImport(import: FirImport, data: D): CompositeTransformResult<FirElement> {
return transformImport(import, data)
}
final override fun visitBody(body: FirBody, data: D): CompositeTransformResult<FirElement> {
return transformBody(body, data)
}
@@ -306,6 +310,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformPropertyAccessor(propertyAccessor, data)
}
final override fun visitResolvedImport(resolvedImport: FirResolvedImport, data: D): CompositeTransformResult<FirElement> {
return transformResolvedImport(resolvedImport, data)
}
final override fun visitTypeAlias(typeAlias: FirTypeAlias, data: D): CompositeTransformResult<FirElement> {
return transformTypeAlias(typeAlias, data)
}
@@ -98,6 +98,10 @@ abstract class FirVisitor<out R, in D> {
return visitElement(import, data)
}
open fun visitResolvedImport(resolvedImport: FirResolvedImport, data: D): R {
return visitImport(resolvedImport, data)
}
open fun visitPackageFragment(packageFragment: FirPackageFragment, data: D): R {
return visitElement(packageFragment, data)
}
@@ -98,6 +98,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(import, null)
}
open fun visitResolvedImport(resolvedImport: FirResolvedImport) {
visitImport(resolvedImport, null)
}
open fun visitPackageFragment(packageFragment: FirPackageFragment) {
visitElement(packageFragment, null)
}
@@ -210,6 +214,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitFunction(function)
}
final override fun visitImport(import: FirImport, data: Nothing?) {
visitImport(import)
}
final override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration, data: Nothing?) {
visitMemberDeclaration(memberDeclaration)
}
@@ -282,10 +290,6 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitAnonymousInitializer(anonymousInitializer)
}
final override fun visitImport(import: FirImport, data: Nothing?) {
visitImport(import)
}
final override fun visitBody(body: FirBody, data: Nothing?) {
visitBody(body)
}
@@ -306,6 +310,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitPropertyAccessor(propertyAccessor)
}
final override fun visitResolvedImport(resolvedImport: FirResolvedImport, data: Nothing?) {
visitResolvedImport(resolvedImport)
}
final override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Nothing?) {
visitTypeAlias(typeAlias)
}
@@ -0,0 +1,3 @@
package b
abstract class MyClass
@@ -0,0 +1,4 @@
package a
import b.MyClass as HisClass
class YourClass : HisClass
@@ -0,0 +1,3 @@
FILE: simpleAliasedImport.kt
unknown final class YourClass() : R/b.MyClass/ {
}
@@ -6,10 +6,11 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.descriptors.FirClassifierResolveTransformer
import org.jetbrains.kotlin.descriptors.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.FirQualifierResolver
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.impl.FirQualifierResolverImpl
import org.jetbrains.kotlin.fir.resolve.impl.FirTypeResolverImpl
@@ -47,13 +48,13 @@ abstract class AbstractFirResolveTestCase : KotlinTestWithEnvironment() {
val builder = RawFirBuilder(session)
val transformer = FirClassifierResolveTransformer()
val transformer = FirTotalResolveTransformer()
val firFiles = ktFiles.map {
val firFile = builder.buildFirFile(it)
(session.service<FirProvider>() as FirProviderImpl).recordFile(firFile)
firFile
}.onEach {
it.transform<FirFile, Nothing?>(transformer, null)
}.also {
transformer.processFiles(it)
}
val firFileDump = StringBuilder().also { firFiles.first().accept(FirRenderer(it), null) }.toString()
@@ -51,6 +51,12 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/fir/resolve/multifile"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("simpleAliasedImport.kt")
public void testSimpleAliasedImport() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/simpleAliasedImport.kt");
doTest(fileName);
}
@TestMetadata("simpleImport.kt")
public void testSimpleImport() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/fir/resolve/multifile/simpleImport.kt");