FIR: Support import-references to callables
This commit is contained in:
+16
-7
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+37
-26
@@ -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)
|
||||
}
|
||||
|
||||
+40
-2
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+27
-1
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -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|()
|
||||
}
|
||||
|
||||
+5
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-9
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
-35
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user