FIR: Support import-references to callables

This commit is contained in:
Denis Zharkov
2019-03-25 16:14:13 +03:00
parent ccca813792
commit 7a19e269fd
24 changed files with 211 additions and 99 deletions
@@ -13,17 +13,25 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.resolve.calls.CallInfo
import org.jetbrains.kotlin.fir.resolve.calls.CallResolver
import org.jetbrains.kotlin.fir.resolve.calls.createFunctionConsumer
import org.jetbrains.kotlin.fir.resolve.calls.createVariableConsumer
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.addImportingScopes
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirComputingImplicitTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
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.ir.expressions.IrConstKind
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -42,6 +50,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult<FirFile> {
packageFqName = file.packageFqName
return withScopeCleanup(scopes) {
scopes.addImportingScopes(file, session)
scopes += FirTopLevelDeclaredMemberScope(file, session)
super.transformFile(file, data)
}
@@ -538,4 +547,4 @@ inline fun <reified T : FirElement> ConeSymbol.firUnsafe(): T {
interface ReturnTypeCalculator {
fun tryCalculateReturnType(declaration: FirTypedDeclaration): FirResolvedTypeRef
}
}
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.FirSession
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.declarations.impl.FirResolvedPackageStarImport
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose
@@ -39,31 +38,43 @@ class FirImportResolveTransformer() : FirAbstractTreeTransformer() {
}
override fun transformImport(import: FirImport, data: Nothing?): CompositeTransformResult<FirImport> {
val fqName = import.importedFqName ?: return import.compose()
val fqName = import.importedFqName?.takeUnless { it.isRoot } ?: return import.compose()
if (!fqName.isRoot) {
val lastPart = StringBuilder()
var firstPart = fqName
if (import.isAllUnder && symbolProvider.getPackage(firstPart) != null) {
return FirResolvedPackageStarImport(session, import, firstPart).compose()
}
while (!firstPart.isRoot) {
if (lastPart.isNotEmpty())
lastPart.insert(0, '.')
lastPart.insert(0, firstPart.shortName().asString())
firstPart = firstPart.parent()
val resolvedFqName = ClassId(firstPart, FqName(lastPart.toString()), false)
val foundSymbol = symbolProvider.getClassLikeSymbolByFqName(resolvedFqName)
if (foundSymbol != null) {
return FirResolvedImportImpl(session, import, resolvedFqName).compose()
}
}
if (import.isAllUnder) {
return transformImportForFqName(fqName, import)
}
return import.compose()
val parentFqName = fqName.parent()
return transformImportForFqName(parentFqName, import)
}
}
private fun transformImportForFqName(fqName: FqName, delegate: FirImport): CompositeTransformResult<FirImport> {
val (packageFqName, relativeClassFqName) = resolveToPackageOrClass(fqName) ?: return delegate.compose()
return FirResolvedImportImpl(session, delegate, packageFqName, relativeClassFqName).compose()
}
private fun resolveToPackageOrClass(fqName: FqName): PackageOrClass? {
var currentPackage = fqName
val pathSegments = fqName.pathSegments()
var prefixSize = pathSegments.size
while (!currentPackage.isRoot) {
if (symbolProvider.getPackage(currentPackage) != null) {
break
}
currentPackage = currentPackage.parent()
prefixSize--
}
if (currentPackage == fqName) return PackageOrClass(currentPackage, null)
val relativeClassFqName =
FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() })
val classId = ClassId(currentPackage, relativeClassFqName, false)
if (symbolProvider.getClassLikeSymbolByFqName(classId) == null) return null
return PackageOrClass(currentPackage, relativeClassFqName)
}
private data class PackageOrClass(val packageFqName: FqName, val relativeClassFqName: FqName?)
}
@@ -9,8 +9,8 @@ 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(
fun MutableList<FirScope>.addImportingScopes(file: FirFile, session: FirSession) {
this += listOf(
// from low priority to high priority
FirDefaultStarImportingScope(session),
FirExplicitStarImportingScope(file.imports, session),
@@ -20,3 +20,7 @@ fun FirCompositeScope.addImportingScopes(file: FirFile, session: FirSession) {
FirExplicitSimpleImportingScope(file.imports, session)
)
}
fun FirCompositeScope.addImportingScopes(file: FirFile, session: FirSession) {
scopes.addImportingScopes(file, session)
}
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.scopes.FirPosition
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
abstract class FirAbstractSimpleImportingScope(val session: FirSession) : FirScope {
@@ -26,7 +28,11 @@ abstract class FirAbstractSimpleImportingScope(val session: FirSession) : FirSco
if (imports.isEmpty()) return true
val provider = FirSymbolProvider.getInstance(session)
for (import in imports) {
val symbol = provider.getClassLikeSymbolByFqName(import.resolvedFqName) ?: continue
val importedName = import.importedName ?: continue
val classId =
import.resolvedClassId?.createNestedClassId(importedName)
?: ClassId.topLevel(import.packageFqName.child(importedName))
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: continue
if (!processor(symbol)) {
return false
}
@@ -34,4 +40,36 @@ abstract class FirAbstractSimpleImportingScope(val session: FirSession) : FirSco
return true
}
override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction {
return processCallables(name, processor)
}
override fun processPropertiesByName(name: Name, processor: (ConeVariableSymbol) -> ProcessorAction): ProcessorAction {
return processCallables(name, processor)
}
private inline fun <reified T : ConeCallableSymbol> processCallables(
name: Name,
processor: (T) -> ProcessorAction
): ProcessorAction {
val imports = simpleImports[name] ?: return ProcessorAction.NEXT
if (imports.isEmpty()) return ProcessorAction.NEXT
val provider = FirSymbolProvider.getInstance(session)
for (import in imports) {
val importedName = import.importedName ?: continue
val callableId = CallableId(
import.packageFqName,
import.relativeClassName,
importedName
)
for (symbol in provider.getCallableSymbols(callableId).filterIsInstance<T>()) {
if (!processor(symbol)) {
return ProcessorAction.NEXT
}
}
}
return ProcessorAction.NEXT
}
}
@@ -8,7 +8,8 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.scopes.FirPosition
import org.jetbrains.kotlin.fir.symbols.ConeClassifierSymbol
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -38,4 +39,29 @@ abstract class FirAbstractStarImportingScope(
return true
}
override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction {
return processCallables(name, processor)
}
override fun processPropertiesByName(name: Name, processor: (ConeVariableSymbol) -> ProcessorAction): ProcessorAction {
return processCallables(name, processor)
}
private inline fun <reified T : ConeCallableSymbol> processCallables(
name: Name,
processor: (T) -> ProcessorAction
): ProcessorAction {
for (import in starImports) {
val callableId = CallableId(import.packageFqName, import.relativeClassName, name)
val symbols = provider.getCallableSymbols(callableId).filterIsInstance<T>()
for (symbol in symbols) {
if (processor(symbol) == ProcessorAction.STOP) {
return ProcessorAction.STOP
}
}
}
return ProcessorAction.NEXT
}
}
@@ -23,6 +23,6 @@ class FirDefaultSimpleImportingScope(session: FirSession) : FirAbstractSimpleImp
?.map {
FirImportImpl(session, null, it.fqName, isAllUnder = false, aliasName = null)
.resolve(importResolveTransformer)
}?.groupBy { it.resolvedFqName.shortClassName } ?: emptyMap()
}?.groupBy { it.importedName!! } ?: emptyMap()
}
}
}
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedPackageStarImport
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
class FirDefaultStarImportingScope(session: FirSession, lookupInFir: Boolean = false) :
FirAbstractStarImportingScope(session, lookupInFir) {
@@ -17,10 +17,11 @@ class FirDefaultStarImportingScope(session: FirSession, lookupInFir: Boolean = f
override val starImports = session.moduleInfo?.platform?.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT, true)
?.filter { it.isAllUnder }
?.map {
FirResolvedPackageStarImport(
FirResolvedImportImpl(
session,
FirImportImpl(session, null, it.fqName, isAllUnder = true, aliasName = null),
it.fqName
it.fqName,
null
)
} ?: emptyList()
}
}
@@ -16,6 +16,6 @@ class FirExplicitSimpleImportingScope(
override val simpleImports =
imports.filterIsInstance<FirResolvedImportImpl>()
.filter { !it.isAllUnder }
.groupBy { it.aliasName ?: it.resolvedFqName.shortClassName }
}
.filter { !it.isAllUnder && it.importedName != null }
.groupBy { it.aliasName ?: it.importedName!! }
}
@@ -0,0 +1,6 @@
package a
object A {
fun foo() {}
}
@@ -0,0 +1,6 @@
package b
import a.A.foo
fun bar() {
foo()
}
@@ -0,0 +1,4 @@
FILE: importFromObject.kt
public final fun bar(): R|kotlin/Unit| {
R|a/A.foo|()
}
@@ -1,3 +1,8 @@
package b
abstract class MyClass
abstract class MyClass
fun foo() {}
fun I() {}
interface I {}
@@ -1,4 +1,11 @@
package a
import b.MyClass as HisClass
import b.foo as foo2
import b.I as I2
class YourClass : HisClass()
class YourClass : HisClass()
fun bar() {
foo2()
I2()
}
@@ -3,3 +3,7 @@ FILE: simpleAliasedImport.kt
public constructor(): super<R|b/MyClass|>()
}
public final fun bar(): R|kotlin/Unit| {
R|b/foo|()
R|b/I|()
}
@@ -1,3 +1,8 @@
package b
abstract class MyClass
abstract class MyClass
fun foo() {}
fun I() {}
interface I {}
@@ -1,4 +1,11 @@
package a
import b.MyClass
import b.foo
import b.I
class YourClass : MyClass()
class YourClass : MyClass()
fun bar() {
foo()
I()
}
@@ -3,3 +3,7 @@ FILE: simpleImport.kt
public constructor(): super<R|b/MyClass|>()
}
public final fun bar(): R|kotlin/Unit| {
R|b/foo|()
R|b/I|()
}
@@ -2,4 +2,6 @@ package b.d
expect interface Other
expect class Another
expect class Another
fun baz() {}
@@ -2,4 +2,8 @@ package a.d
import b.d.*
fun foo(arg: Other): Another
fun foo(arg: Other): Another
fun bar() {
baz()
}
@@ -1,2 +1,5 @@
FILE: simpleStarImport.kt
public final fun foo(arg: R|b/d/Other|): R|b/d/Another|
public final fun bar(): R|kotlin/Unit| {
R|b/d/baz|()
}
@@ -293,6 +293,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/multifile/ByteArray.kt");
}
@TestMetadata("importFromObject.kt")
public void testImportFromObject() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/multifile/importFromObject.kt");
}
@TestMetadata("NestedSuperType.kt")
public void testNestedSuperType() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/multifile/NestedSuperType.kt");
@@ -8,14 +8,16 @@ package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
interface FirResolvedImport : FirImport {
val packageFqName: FqName
val relativeClassName: FqName?
val resolvedClassId: ClassId? get() = relativeClassName?.let { ClassId(packageFqName, it, false) }
val resolvedFqName: ClassId?
val importedName: Name? get() = importedFqName?.shortName()
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitResolvedImport(this, data)
}
}
@@ -9,21 +9,15 @@ import org.jetbrains.kotlin.fir.FirAbstractElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class FirResolvedImportImpl(
session: FirSession,
val delegate: FirImport,
override val resolvedFqName: ClassId
override val packageFqName: FqName,
override val relativeClassName: FqName?
) : FirAbstractElement(session, delegate.psi), FirResolvedImport, FirImport {
override val packageFqName: FqName
get() = resolvedFqName.packageFqName
override val relativeClassName: FqName
get() = resolvedFqName.relativeClassName
override val aliasName: Name?
get() = delegate.aliasName
@@ -32,4 +26,4 @@ class FirResolvedImportImpl(
override val isAllUnder: Boolean
get() = delegate.isAllUnder
}
}
@@ -1,35 +0,0 @@
/*
* 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.FirAbstractElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class FirResolvedPackageStarImport(
session: FirSession,
val delegate: FirImport,
override val packageFqName: FqName
) : FirAbstractElement(session, delegate.psi), FirResolvedImport, FirImport {
override val relativeClassName: FqName?
get() = null
override val resolvedFqName: ClassId?
get() = null
override val aliasName: Name?
get() = delegate.aliasName
override val importedFqName: FqName?
get() = delegate.importedFqName
override val isAllUnder: Boolean
get() = delegate.isAllUnder
}