Implement FIR loading for Java (classes, supertypes, parameters, funs)
Properties aren't implemented yet FIR symbol provider functions return more specialized types now Related to KT-28918, KT-29636, KT-29218 #KT-28788 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
4ea3df53cc
commit
3a237416c9
@@ -6,11 +6,14 @@
|
|||||||
package org.jetbrains.kotlin.fir.symbols
|
package org.jetbrains.kotlin.fir.symbols
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
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
|
||||||
|
|
||||||
// NB: with className == null we are at top level
|
// NB: with className == null we are at top level
|
||||||
data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) {
|
data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) {
|
||||||
|
val classId: ClassId? get() = className?.let { ClassId(packageName, it, false) }
|
||||||
|
|
||||||
constructor(packageName: FqName, callableName: Name): this(packageName, null, callableName)
|
constructor(packageName: FqName, callableName: Name): this(packageName, null, callableName)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class FirJavaModuleBasedSession(
|
|||||||
FirCompositeSymbolProvider(
|
FirCompositeSymbolProvider(
|
||||||
listOf(
|
listOf(
|
||||||
service<FirProvider>(),
|
service<FirProvider>(),
|
||||||
JavaSymbolProvider(sessionProvider.project, scope),
|
JavaSymbolProvider(this, sessionProvider.project, scope),
|
||||||
FirDependenciesSymbolProviderImpl(this)
|
FirDependenciesSymbolProviderImpl(this)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -47,7 +47,7 @@ class FirLibrarySession(
|
|||||||
FirCompositeSymbolProvider(
|
FirCompositeSymbolProvider(
|
||||||
listOf(
|
listOf(
|
||||||
FirLibrarySymbolProviderImpl(this),
|
FirLibrarySymbolProviderImpl(this),
|
||||||
JavaSymbolProvider(sessionProvider.project, scope),
|
JavaSymbolProvider(this, sessionProvider.project, scope),
|
||||||
FirDependenciesSymbolProviderImpl(this)
|
FirDependenciesSymbolProviderImpl(this)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,29 +7,212 @@ package org.jetbrains.kotlin.fir.java
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.fir.java.symbols.JavaClassSymbol
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.service
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinTypeProjection
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirResolvedType
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
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.resolve.jvm.KotlinJavaPsiFacade
|
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
class JavaSymbolProvider(
|
class JavaSymbolProvider(
|
||||||
|
val session: FirSession,
|
||||||
val project: Project,
|
val project: Project,
|
||||||
private val searchScope: GlobalSearchScope
|
private val searchScope: GlobalSearchScope
|
||||||
) : AbstractFirSymbolProvider() {
|
) : AbstractFirSymbolProvider() {
|
||||||
override fun getCallableSymbols(callableId: CallableId): List<ConeSymbol> {
|
|
||||||
// TODO
|
private val facade: KotlinJavaPsiFacade get() = KotlinJavaPsiFacade.getInstance(project)
|
||||||
return emptyList()
|
|
||||||
|
private fun JavaAnnotation.toFirAnnotationCall(): FirAnnotationCall {
|
||||||
|
return FirAnnotationCallImpl(
|
||||||
|
session, psi = null, useSiteTarget = null,
|
||||||
|
annotationType = FirResolvedTypeImpl(
|
||||||
|
session = session,
|
||||||
|
psi = null,
|
||||||
|
type = ConeClassTypeImpl(FirClassSymbol(classId!!), emptyArray()),
|
||||||
|
isNullable = true,
|
||||||
|
annotations = emptyList()
|
||||||
|
)
|
||||||
|
).apply {
|
||||||
|
for (argument in this@toFirAnnotationCall.arguments) {
|
||||||
|
arguments += argument.toFirExpression()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol? {
|
private fun JavaAnnotationArgument.toFirExpression(): FirExpression {
|
||||||
return classCache.lookupCacheOrCalculate(classId) {
|
// TODO: this.name
|
||||||
val facade = KotlinJavaPsiFacade.getInstance(project)
|
return when (this) {
|
||||||
val foundClass = facade.findClass(JavaClassFinder.Request(classId), searchScope)
|
is JavaLiteralAnnotationArgument -> when (value) {
|
||||||
foundClass?.let { javaClass -> JavaClassSymbol(javaClass) }
|
null -> FirConstExpressionImpl(session, null, IrConstKind.Null, null)
|
||||||
|
else -> FirErrorExpressionImpl(session, null, "Unknown value in JavaLiteralAnnotationArgument: $value")
|
||||||
|
}
|
||||||
|
is JavaArrayAnnotationArgument -> FirArrayOfCallImpl(session, null).apply {
|
||||||
|
for (element in getElements()) {
|
||||||
|
arguments += element.toFirExpression()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
|
//is JavaEnumValueAnnotationArgument -> {}
|
||||||
|
is JavaClassObjectAnnotationArgument -> FirGetClassCallImpl(session, null).apply {
|
||||||
|
// TODO
|
||||||
|
//arguments += getReferencedType().toFirType()
|
||||||
|
}
|
||||||
|
is JavaAnnotationAsAnnotationArgument -> getAnnotation().toFirAnnotationCall()
|
||||||
|
else -> FirErrorExpressionImpl(session, null, "Unknown JavaAnnotationArgument: ${this::class.java}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JavaClassifierType.toFirResolvedType(): FirResolvedType {
|
||||||
|
val coneType = when (val classifier = classifier) {
|
||||||
|
is JavaClass -> {
|
||||||
|
val symbol = session.service<FirSymbolProvider>().getClassLikeSymbolByFqName(classifier.classId!!) as ConeClassSymbol
|
||||||
|
ConeClassTypeImpl(symbol, typeArguments = typeArguments.map { it.toConeProjection() }.toTypedArray())
|
||||||
|
}
|
||||||
|
is JavaTypeParameter -> {
|
||||||
|
// TODO: it's unclear how to identify type parameter by the symbol
|
||||||
|
// TODO: some type parameter cache (provider?)
|
||||||
|
val symbol = createTypeParameterSymbol(classifier.name)
|
||||||
|
ConeTypeParameterTypeImpl(symbol)
|
||||||
|
}
|
||||||
|
else -> ConeClassErrorType(reason = "Unexpected classifier: $classifier")
|
||||||
|
}
|
||||||
|
return FirResolvedTypeImpl(
|
||||||
|
session, psi = null, type = coneType,
|
||||||
|
isNullable = false, annotations = annotations.map { it.toFirAnnotationCall() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JavaType.toFirResolvedType(): FirResolvedType {
|
||||||
|
if (this is JavaClassifierType) return toFirResolvedType()
|
||||||
|
return FirResolvedTypeImpl(
|
||||||
|
session, psi = null, type = ConeClassErrorType("Unexpected JavaType: $this"),
|
||||||
|
isNullable = false, annotations = emptyList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JavaType.toConeProjection(): ConeKotlinTypeProjection {
|
||||||
|
if (this is JavaClassifierType) {
|
||||||
|
return toFirResolvedType().type
|
||||||
|
}
|
||||||
|
return ConeClassErrorType("Unexpected type argument: $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTypeParameterSymbol(name: Name): FirTypeParameterSymbol {
|
||||||
|
val firSymbol = FirTypeParameterSymbol()
|
||||||
|
FirTypeParameterImpl(session, null, firSymbol, name, variance = Variance.INVARIANT, isReified = false)
|
||||||
|
return firSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirAbstractAnnotatedElement.addAnnotationsFrom(javaAnnotationOwner: JavaAnnotationOwner) {
|
||||||
|
for (annotation in javaAnnotationOwner.annotations) {
|
||||||
|
annotations += annotation.toFirAnnotationCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findClass(classId: ClassId): JavaClass? = facade.findClass(JavaClassFinder.Request(classId), searchScope)
|
||||||
|
|
||||||
|
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol> {
|
||||||
|
return callableCache.lookupCacheOrCalculate(callableId) {
|
||||||
|
val classId = callableId.classId ?: return@lookupCacheOrCalculate emptyList()
|
||||||
|
val classSymbol = getClassLikeSymbolByFqName(classId) as? FirClassSymbol
|
||||||
|
?: return@lookupCacheOrCalculate emptyList()
|
||||||
|
val firClass = classSymbol.fir as FirModifiableClass
|
||||||
|
val callableSymbols = mutableListOf<ConeCallableSymbol>()
|
||||||
|
findClass(classId)?.let { javaClass ->
|
||||||
|
if (firClass.declarations.isEmpty()) {
|
||||||
|
for (javaMethod in javaClass.methods) {
|
||||||
|
val methodName = javaMethod.name
|
||||||
|
val methodId = CallableId(callableId.packageName, callableId.className, methodName)
|
||||||
|
val methodSymbol = FirFunctionSymbol(methodId)
|
||||||
|
val memberFunction = FirMemberFunctionImpl(
|
||||||
|
session, null, methodSymbol, methodName,
|
||||||
|
javaMethod.visibility, javaMethod.modality,
|
||||||
|
isExpect = false, isActual = false, isOverride = false,
|
||||||
|
isOperator = true, isInfix = false, isInline = false,
|
||||||
|
isTailRec = false, isExternal = false, isSuspend = false,
|
||||||
|
receiverType = null, returnType = javaMethod.returnType.toFirResolvedType()
|
||||||
|
).apply {
|
||||||
|
for (typeParameter in javaMethod.typeParameters) {
|
||||||
|
typeParameters += createTypeParameterSymbol(typeParameter.name).fir
|
||||||
|
}
|
||||||
|
addAnnotationsFrom(javaMethod)
|
||||||
|
for (valueParameter in javaMethod.valueParameters) {
|
||||||
|
valueParameters += FirValueParameterImpl(
|
||||||
|
session, null, valueParameter.name ?: Name.special("<anonymous Java parameter>"),
|
||||||
|
returnType = valueParameter.type.toFirResolvedType(),
|
||||||
|
defaultValue = null, isCrossinline = false, isNoinline = false,
|
||||||
|
isVararg = valueParameter.isVararg
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firClass.declarations += memberFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (declaration in firClass.declarations) {
|
||||||
|
if (declaration is FirNamedFunction) {
|
||||||
|
val methodId = CallableId(callableId.packageName, callableId.className, declaration.name)
|
||||||
|
if (methodId == callableId) {
|
||||||
|
val symbol = declaration.symbol as ConeCallableSymbol
|
||||||
|
callableSymbols += symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callableSymbols
|
||||||
|
}.orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {
|
||||||
|
return classCache.lookupCacheOrCalculateWithPostCompute(classId, {
|
||||||
|
val foundClass = findClass(classId)
|
||||||
|
if (foundClass == null) {
|
||||||
|
null to null
|
||||||
|
} else {
|
||||||
|
FirClassSymbol(classId) to foundClass
|
||||||
|
}
|
||||||
|
}) { firSymbol, foundClass ->
|
||||||
|
foundClass?.let { javaClass ->
|
||||||
|
FirClassImpl(
|
||||||
|
session, null, firSymbol as FirClassSymbol, javaClass.name,
|
||||||
|
javaClass.visibility, javaClass.modality,
|
||||||
|
isExpect = false, isActual = false,
|
||||||
|
classKind = javaClass.classKind,
|
||||||
|
isInner = !javaClass.isStatic, isCompanion = false,
|
||||||
|
isData = false, isInline = false
|
||||||
|
).apply {
|
||||||
|
for (typeParameter in javaClass.typeParameters) {
|
||||||
|
typeParameters += createTypeParameterSymbol(typeParameter.name).fir
|
||||||
|
}
|
||||||
|
addAnnotationsFrom(javaClass)
|
||||||
|
for (supertype in javaClass.supertypes) {
|
||||||
|
superTypes += supertype.toFirResolvedType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.JavaModifierListOwner
|
||||||
|
|
||||||
|
internal val JavaModifierListOwner.modality: Modality
|
||||||
|
get() = when {
|
||||||
|
isAbstract -> Modality.ABSTRACT
|
||||||
|
isFinal -> Modality.FINAL
|
||||||
|
else -> Modality.OPEN
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val JavaClass.classKind: ClassKind
|
||||||
|
get() = when {
|
||||||
|
isAnnotationType -> ClassKind.ANNOTATION_CLASS
|
||||||
|
isInterface -> ClassKind.INTERFACE
|
||||||
|
isEnum -> ClassKind.ENUM_CLASS
|
||||||
|
else -> ClassKind.CLASS
|
||||||
|
}
|
||||||
@@ -1,17 +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.java.symbols
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassSymbol
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.classId
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
|
|
||||||
class JavaClassSymbol(javaClass: JavaClass) : ConeClassSymbol {
|
|
||||||
override val classId: ClassId = javaClass.classId ?: error("!")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-11
@@ -1,11 +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.java.symbols
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
|
|
||||||
class JavaTypeParameterSymbol(override val name: Name) : ConeTypeParameterSymbol
|
|
||||||
+18
-2
@@ -5,12 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve
|
package org.jetbrains.kotlin.fir.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
abstract class AbstractFirSymbolProvider : FirSymbolProvider {
|
abstract class AbstractFirSymbolProvider : FirSymbolProvider {
|
||||||
protected val classCache = mutableMapOf<ClassId, ConeSymbol?>()
|
protected val classCache = mutableMapOf<ClassId, ConeClassLikeSymbol?>()
|
||||||
|
protected val callableCache = mutableMapOf<CallableId, List<ConeCallableSymbol>>()
|
||||||
protected val packageCache = mutableMapOf<FqName, FqName?>()
|
protected val packageCache = mutableMapOf<FqName, FqName?>()
|
||||||
|
|
||||||
protected inline fun <K, V : Any?> MutableMap<K, V>.lookupCacheOrCalculate(key: K, crossinline l: (K) -> V): V? {
|
protected inline fun <K, V : Any?> MutableMap<K, V>.lookupCacheOrCalculate(key: K, crossinline l: (K) -> V): V? {
|
||||||
@@ -22,4 +25,17 @@ abstract class AbstractFirSymbolProvider : FirSymbolProvider {
|
|||||||
calculated
|
calculated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected inline fun <K, V : Any?, T> MutableMap<K, V>.lookupCacheOrCalculateWithPostCompute(
|
||||||
|
key: K, crossinline l: (K) -> Pair<V, T>, postCompute: (V, T) -> Unit
|
||||||
|
): V? {
|
||||||
|
return if (key in this.keys) {
|
||||||
|
this[key]
|
||||||
|
} else {
|
||||||
|
val calculated = l(key)
|
||||||
|
this[key] = calculated.first
|
||||||
|
postCompute(calculated.first, calculated.second)
|
||||||
|
calculated.first
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,9 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration
|
||||||
import org.jetbrains.kotlin.fir.service
|
import org.jetbrains.kotlin.fir.service
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -17,7 +20,9 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
interface FirProvider : FirSymbolProvider {
|
interface FirProvider : FirSymbolProvider {
|
||||||
fun getFirClassifierByFqName(fqName: ClassId): FirMemberDeclaration?
|
fun getFirClassifierByFqName(fqName: ClassId): FirMemberDeclaration?
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol?
|
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol?
|
||||||
|
|
||||||
|
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol>
|
||||||
|
|
||||||
override fun getPackage(fqName: FqName): FqName? {
|
override fun getPackage(fqName: FqName): FqName? {
|
||||||
if (getFirFilesByPackage(fqName).isNotEmpty()) return fqName
|
if (getFirFilesByPackage(fqName).isNotEmpty()) return fqName
|
||||||
|
|||||||
@@ -8,15 +8,16 @@ package org.jetbrains.kotlin.fir.resolve
|
|||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.service
|
import org.jetbrains.kotlin.fir.service
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
interface FirSymbolProvider {
|
interface FirSymbolProvider {
|
||||||
|
|
||||||
fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol?
|
fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol?
|
||||||
|
|
||||||
fun getCallableSymbols(callableId: CallableId): List<ConeSymbol>
|
fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol>
|
||||||
|
|
||||||
fun getPackage(fqName: FqName): FqName? // TODO: Replace to symbol sometime
|
fun getPackage(fqName: FqName): FqName? // TODO: Replace to symbol sometime
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -7,13 +7,14 @@ package org.jetbrains.kotlin.fir.resolve.impl
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
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.utils.addToStdlib.firstNotNullResult
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
class FirCompositeSymbolProvider(val providers: List<FirSymbolProvider>) : FirSymbolProvider {
|
class FirCompositeSymbolProvider(val providers: List<FirSymbolProvider>) : FirSymbolProvider {
|
||||||
override fun getCallableSymbols(callableId: CallableId): List<ConeSymbol> {
|
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol> {
|
||||||
for (provider in providers) {
|
for (provider in providers) {
|
||||||
val symbols = provider.getCallableSymbols(callableId)
|
val symbols = provider.getCallableSymbols(callableId)
|
||||||
if (symbols.isNotEmpty()) return symbols
|
if (symbols.isNotEmpty()) return symbols
|
||||||
@@ -25,7 +26,7 @@ class FirCompositeSymbolProvider(val providers: List<FirSymbolProvider>) : FirSy
|
|||||||
return providers.firstNotNullResult { it.getPackage(fqName) }
|
return providers.firstNotNullResult { it.getPackage(fqName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol? {
|
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {
|
||||||
return providers.firstNotNullResult { it.getClassLikeSymbolByFqName(classId) }
|
return providers.firstNotNullResult { it.getClassLikeSymbolByFqName(classId) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-3
@@ -11,12 +11,13 @@ import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider
|
|||||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.service
|
import org.jetbrains.kotlin.fir.service
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProvider() {
|
class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProvider() {
|
||||||
override fun getCallableSymbols(callableId: CallableId): List<ConeSymbol> {
|
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol> {
|
||||||
// TODO
|
// TODO
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
@@ -28,7 +29,7 @@ class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSy
|
|||||||
}.toList()
|
}.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol? {
|
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {
|
||||||
return classCache.lookupCacheOrCalculate(classId) {
|
return classCache.lookupCacheOrCalculate(classId) {
|
||||||
for (provider in dependencyProviders) {
|
for (provider in dependencyProviders) {
|
||||||
provider.getClassLikeSymbolByFqName(classId)?.let {
|
provider.getClassLikeSymbolByFqName(classId)?.let {
|
||||||
|
|||||||
+7
-8
@@ -14,8 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
|
|||||||
import org.jetbrains.kotlin.fir.deserialization.FirTypeDeserializer
|
import org.jetbrains.kotlin.fir.deserialization.FirTypeDeserializer
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.getOrPut
|
import org.jetbrains.kotlin.fir.resolve.getOrPut
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FictitiousFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FictitiousFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
@@ -38,7 +37,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider {
|
class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider {
|
||||||
override fun getCallableSymbols(callableId: CallableId): List<ConeSymbol> {
|
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol> {
|
||||||
// TODO
|
// TODO
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
@@ -67,7 +66,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider
|
|||||||
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
|
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
|
||||||
|
|
||||||
|
|
||||||
val lookup = mutableMapOf<ClassId, ConeSymbol>()
|
val lookup = mutableMapOf<ClassId, ConeClassLikeSymbol>()
|
||||||
|
|
||||||
private fun createTypeParameterSymbol(name: Name): FirTypeParameterSymbol {
|
private fun createTypeParameterSymbol(name: Name): FirTypeParameterSymbol {
|
||||||
val firSymbol = FirTypeParameterSymbol()
|
val firSymbol = FirTypeParameterSymbol()
|
||||||
@@ -75,7 +74,7 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider
|
|||||||
return firSymbol
|
return firSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSymbolByFqName(classId: ClassId, provider: FirSymbolProvider): ConeSymbol? {
|
fun getClassLikeSymbolByFqName(classId: ClassId, provider: FirSymbolProvider): ConeClassLikeSymbol? {
|
||||||
|
|
||||||
if (classId !in classDataFinder.allClassIds) return null
|
if (classId !in classDataFinder.allClassIds) return null
|
||||||
return lookup.getOrPut(classId, { FirClassSymbol(classId) }) { symbol ->
|
return lookup.getOrPut(classId, { FirClassSymbol(classId) }) { symbol ->
|
||||||
@@ -142,11 +141,11 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider
|
|||||||
|
|
||||||
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
||||||
|
|
||||||
private val fictitiousFunctionSymbols = mutableMapOf<Int, ConeSymbol>()
|
private val fictitiousFunctionSymbols = mutableMapOf<Int, ConeClassSymbol>()
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol? {
|
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {
|
||||||
return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
|
return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
|
||||||
it.getSymbolByFqName(classId, this)
|
it.getClassLikeSymbolByFqName(classId, this)
|
||||||
} ?: with(classId) {
|
} ?: with(classId) {
|
||||||
val className = relativeClassName.asString()
|
val className = relativeClassName.asString()
|
||||||
val kind = FunctionClassDescriptor.Kind.byClassNamePrefix(packageFqName, className) ?: return@with null
|
val kind = FunctionClassDescriptor.Kind.byClassNamePrefix(packageFqName, className) ?: return@with null
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ class FirProviderImpl(val session: FirSession) : FirProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeSymbol? {
|
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {
|
||||||
return (getFirClassifierByFqName(classId) as? FirSymbolOwner<*>)?.symbol
|
return (getFirClassifierByFqName(classId) as? FirSymbolOwner<*>)?.symbol as? ConeClassLikeSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCallableSymbols(callableId: CallableId): List<ConeSymbol> {
|
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol> {
|
||||||
return (callableMap[callableId] ?: emptyList()).filterIsInstance<FirSymbolOwner<*>>().map { it.symbol }
|
return (callableMap[callableId] ?: emptyList())
|
||||||
|
.filterIsInstance<FirSymbolOwner<*>>()
|
||||||
|
.mapNotNull { it.symbol as? ConeCallableSymbol }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFirClassifierContainerFile(fqName: ClassId): FirFile {
|
override fun getFirClassifierContainerFile(fqName: ClassId): FirFile {
|
||||||
|
|||||||
+1
-6
@@ -66,12 +66,7 @@ open class FirTypeResolveTransformer(
|
|||||||
val firProvider = FirProvider.getInstance(regularClass.session)
|
val firProvider = FirProvider.getInstance(regularClass.session)
|
||||||
val classId = regularClass.symbol.classId
|
val classId = regularClass.symbol.classId
|
||||||
lookupSuperTypes(regularClass, lookupInterfaces = false, deep = true).asReversed().mapTo(towerScope.scopes) {
|
lookupSuperTypes(regularClass, lookupInterfaces = false, deep = true).asReversed().mapTo(towerScope.scopes) {
|
||||||
val symbol = it.symbol
|
FirNestedClassifierScope(it.symbol.classId, FirSymbolProvider.getInstance(regularClass.session))
|
||||||
if (symbol is FirBasedSymbol<*>) {
|
|
||||||
FirNestedClassifierScope(symbol.classId, FirProvider.getInstance(symbol.fir.session))
|
|
||||||
} else {
|
|
||||||
FirNestedClassifierScope(symbol.classId, FirSymbolProvider.getInstance(regularClass.session))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val companionObjects = regularClass.declarations.filterIsInstance<FirRegularClass>().filter { it.isCompanion }
|
val companionObjects = regularClass.declarations.filterIsInstance<FirRegularClass>().filter { it.isCompanion }
|
||||||
for (companionObject in companionObjects) {
|
for (companionObject in companionObjects) {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
public class Some {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class A : Some()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
FILE: jvm.kt
|
||||||
|
public final class A : R|Some| {
|
||||||
|
public constructor(): super<R|Some|>()
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
public class A {
|
||||||
|
public A foo() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public A bar() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class B : A() {
|
||||||
|
override fun foo(): B = this
|
||||||
|
fun bar(): B = this // Ambiguity, no override here
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo()
|
||||||
|
bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
FILE: B.kt
|
||||||
|
public final class B : R|A| {
|
||||||
|
public constructor(): super<R|A|>()
|
||||||
|
|
||||||
|
public final override function foo(): R|B| {
|
||||||
|
return@@@foo this#
|
||||||
|
}
|
||||||
|
|
||||||
|
public final function bar(): R|B| {
|
||||||
|
return@@@bar this#
|
||||||
|
}
|
||||||
|
|
||||||
|
public final function test(): R|kotlin/Unit| {
|
||||||
|
R|/B.foo|()
|
||||||
|
<Ambiguity: bar, [/B.bar, /A.bar]>#()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -34,6 +34,11 @@ public class FirMultiModuleResolveTestGenerated extends AbstractFirMultiModuleRe
|
|||||||
runTest("idea/testData/fir/multiModule/basic/");
|
runTest("idea/testData/fir/multiModule/basic/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("basicWithJava")
|
||||||
|
public void testBasicWithJava() throws Exception {
|
||||||
|
runTest("idea/testData/fir/multiModule/basicWithJava/");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mppFakeOverrides")
|
@TestMetadata("mppFakeOverrides")
|
||||||
public void testMppFakeOverrides() throws Exception {
|
public void testMppFakeOverrides() throws Exception {
|
||||||
runTest("idea/testData/fir/multiModule/mppFakeOverrides/");
|
runTest("idea/testData/fir/multiModule/mppFakeOverrides/");
|
||||||
@@ -53,4 +58,9 @@ public class FirMultiModuleResolveTestGenerated extends AbstractFirMultiModuleRe
|
|||||||
public void testMppSuperTypes() throws Exception {
|
public void testMppSuperTypes() throws Exception {
|
||||||
runTest("idea/testData/fir/multiModule/mppSuperTypes/");
|
runTest("idea/testData/fir/multiModule/mppSuperTypes/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideWithJava")
|
||||||
|
public void testOverrideWithJava() throws Exception {
|
||||||
|
runTest("idea/testData/fir/multiModule/overrideWithJava/");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user