[FIR] Split creating fir for java declarations to separate methods
This commit is contained in:
@@ -7,12 +7,10 @@ package org.jetbrains.kotlin.fir.java
|
|||||||
|
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||||
@@ -26,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.SymbolProviderCache
|
|||||||
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||||
@@ -57,7 +56,8 @@ class JavaSymbolProvider(
|
|||||||
private val scopeProvider = JavaScopeProvider(::wrapScopeWithJvmMapped, this)
|
private val scopeProvider = JavaScopeProvider(::wrapScopeWithJvmMapped, this)
|
||||||
|
|
||||||
private val facade: KotlinJavaPsiFacade get() = KotlinJavaPsiFacade.getInstance(project)
|
private val facade: KotlinJavaPsiFacade get() = KotlinJavaPsiFacade.getInstance(project)
|
||||||
private val parentClassTypeParameterStackCache: SymbolProviderCache<FirRegularClassSymbol, JavaTypeParameterStack> = SymbolProviderCache()
|
private val parentClassTypeParameterStackCache: SymbolProviderCache<FirRegularClassSymbol, JavaTypeParameterStack> =
|
||||||
|
SymbolProviderCache()
|
||||||
|
|
||||||
private fun findClass(
|
private fun findClass(
|
||||||
classId: ClassId,
|
classId: ClassId,
|
||||||
@@ -65,7 +65,8 @@ class JavaSymbolProvider(
|
|||||||
): JavaClass? = facade.findClass(JavaClassFinder.Request(classId, previouslyFoundClassFileContent = content?.content), searchScope)
|
): JavaClass? = facade.findClass(JavaClassFinder.Request(classId, previouslyFoundClassFileContent = content?.content), searchScope)
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {}
|
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||||
|
}
|
||||||
|
|
||||||
private fun JavaTypeParameter.toFirTypeParameterSymbol(
|
private fun JavaTypeParameter.toFirTypeParameterSymbol(
|
||||||
javaTypeParameterStack: JavaTypeParameterStack
|
javaTypeParameterStack: JavaTypeParameterStack
|
||||||
@@ -140,7 +141,18 @@ class JavaSymbolProvider(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
) { firSymbol, foundClass ->
|
) { firSymbol, foundClass ->
|
||||||
foundClass?.let { javaClass ->
|
convertJavaClassToFir(firSymbol, foundClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ValueParametersForAnnotationConstructor {
|
||||||
|
val valueParameters: MutableList<FirJavaValueParameter> = mutableListOf()
|
||||||
|
var valueParameterForValue: FirJavaValueParameter? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertJavaClassToFir(classSymbol: FirRegularClassSymbol, javaClass: JavaClass?): FirJavaClass? {
|
||||||
|
if (javaClass == null) return null
|
||||||
|
val classId = classSymbol.classId
|
||||||
val javaTypeParameterStack = JavaTypeParameterStack()
|
val javaTypeParameterStack = JavaTypeParameterStack()
|
||||||
val outerClassId = classId.outerClassId
|
val outerClassId = classId.outerClassId
|
||||||
val parentClassSymbol = if (outerClassId != null) {
|
val parentClassSymbol = if (outerClassId != null) {
|
||||||
@@ -156,7 +168,7 @@ class JavaSymbolProvider(
|
|||||||
val firJavaClass = buildJavaClass {
|
val firJavaClass = buildJavaClass {
|
||||||
source = (javaClass as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement()
|
source = (javaClass as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement()
|
||||||
session = this@JavaSymbolProvider.session
|
session = this@JavaSymbolProvider.session
|
||||||
symbol = firSymbol
|
symbol = classSymbol
|
||||||
name = javaClass.name
|
name = javaClass.name
|
||||||
visibility = javaClass.visibility
|
visibility = javaClass.visibility
|
||||||
modality = javaClass.modality
|
modality = javaClass.modality
|
||||||
@@ -164,10 +176,10 @@ class JavaSymbolProvider(
|
|||||||
this.isTopLevel = outerClassId == null
|
this.isTopLevel = outerClassId == null
|
||||||
isStatic = javaClass.isStatic
|
isStatic = javaClass.isStatic
|
||||||
this.javaTypeParameterStack = javaTypeParameterStack
|
this.javaTypeParameterStack = javaTypeParameterStack
|
||||||
parentClassTypeParameterStackCache[firSymbol] = javaTypeParameterStack
|
parentClassTypeParameterStackCache[classSymbol] = javaTypeParameterStack
|
||||||
existingNestedClassifierNames += javaClass.innerClassNames
|
existingNestedClassifierNames += javaClass.innerClassNames
|
||||||
scopeProvider = this@JavaSymbolProvider.scopeProvider
|
scopeProvider = this@JavaSymbolProvider.scopeProvider
|
||||||
val classTypeParameters = foundClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
|
val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
|
||||||
typeParameters += classTypeParameters
|
typeParameters += classTypeParameters
|
||||||
if (!isStatic && parentClassSymbol != null) {
|
if (!isStatic && parentClassSymbol != null) {
|
||||||
typeParameters += parentClassSymbol.fir.typeParameters.map {
|
typeParameters += parentClassSymbol.fir.typeParameters.map {
|
||||||
@@ -188,10 +200,75 @@ class JavaSymbolProvider(
|
|||||||
// TODO: may be we can process fields & methods later.
|
// TODO: may be we can process fields & methods later.
|
||||||
// However, they should be built up to override resolve stage
|
// However, they should be built up to override resolve stage
|
||||||
for (javaField in javaClass.fields) {
|
for (javaField in javaClass.fields) {
|
||||||
|
declarations += convertJavaFieldToFir(javaField, classId, javaTypeParameterStack)
|
||||||
|
}
|
||||||
|
val valueParametersForAnnotationConstructor = ValueParametersForAnnotationConstructor()
|
||||||
|
val classIsAnnotation = classKind == ClassKind.ANNOTATION_CLASS
|
||||||
|
|
||||||
|
for (javaMethod in javaClass.methods) {
|
||||||
|
declarations += convertJavaMethodToFir(
|
||||||
|
javaMethod,
|
||||||
|
classId,
|
||||||
|
javaTypeParameterStack,
|
||||||
|
classIsAnnotation,
|
||||||
|
valueParametersForAnnotationConstructor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val javaClassDeclaredConstructors = javaClass.constructors
|
||||||
|
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
|
||||||
|
|
||||||
|
if (javaClassDeclaredConstructors.isEmpty()
|
||||||
|
&& javaClass.classKind == ClassKind.CLASS
|
||||||
|
&& javaClass.hasDefaultConstructor()
|
||||||
|
) {
|
||||||
|
declarations += convertJavaConstructorToFir(
|
||||||
|
javaConstructor = null,
|
||||||
|
constructorId,
|
||||||
|
javaClass,
|
||||||
|
ownerClassBuilder = this,
|
||||||
|
classTypeParameters,
|
||||||
|
javaTypeParameterStack
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for (javaConstructor in javaClassDeclaredConstructors) {
|
||||||
|
declarations += convertJavaConstructorToFir(
|
||||||
|
javaConstructor,
|
||||||
|
constructorId,
|
||||||
|
javaClass,
|
||||||
|
ownerClassBuilder = this,
|
||||||
|
classTypeParameters,
|
||||||
|
javaTypeParameterStack,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classKind == ClassKind.ENUM_CLASS) {
|
||||||
|
generateValuesFunction(session, classId.packageFqName, classId.relativeClassName)
|
||||||
|
generateValueOfFunction(session, classId.packageFqName, classId.relativeClassName)
|
||||||
|
}
|
||||||
|
if (classIsAnnotation) {
|
||||||
|
declarations += buildConstructorForAnnotationClass(constructorId, this, valueParametersForAnnotationConstructor)
|
||||||
|
}
|
||||||
|
parentClassTypeParameterStackCache.remove(classSymbol)
|
||||||
|
}
|
||||||
|
firJavaClass.replaceSuperTypeRefs(
|
||||||
|
javaClass.supertypes.map { supertype ->
|
||||||
|
supertype.toFirResolvedTypeRef(
|
||||||
|
this@JavaSymbolProvider.session, javaTypeParameterStack, isForSupertypes = true, forTypeParameterBounds = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return firJavaClass
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertJavaFieldToFir(
|
||||||
|
javaField: JavaField,
|
||||||
|
classId: ClassId,
|
||||||
|
javaTypeParameterStack: JavaTypeParameterStack
|
||||||
|
): FirDeclaration {
|
||||||
val fieldName = javaField.name
|
val fieldName = javaField.name
|
||||||
val fieldId = CallableId(classId.packageFqName, classId.relativeClassName, fieldName)
|
val fieldId = CallableId(classId.packageFqName, classId.relativeClassName, fieldName)
|
||||||
val returnType = javaField.type
|
val returnType = javaField.type
|
||||||
val firJavaDeclaration = when {
|
return when {
|
||||||
javaField.isEnumEntry -> buildEnumEntry {
|
javaField.isEnumEntry -> buildEnumEntry {
|
||||||
source = (javaField as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement()
|
source = (javaField as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement()
|
||||||
session = this@JavaSymbolProvider.session
|
session = this@JavaSymbolProvider.session
|
||||||
@@ -233,13 +310,15 @@ class JavaSymbolProvider(
|
|||||||
addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack)
|
addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declarations += firJavaDeclaration
|
|
||||||
}
|
}
|
||||||
val valueParametersForAnnotationConstructor = mutableListOf<FirJavaValueParameter>()
|
|
||||||
var valueParameterForValueInAnnotationConstructor: FirJavaValueParameter? = null
|
|
||||||
val classIsAnnotation = classKind == ClassKind.ANNOTATION_CLASS
|
|
||||||
|
|
||||||
for (javaMethod in javaClass.methods) {
|
private fun convertJavaMethodToFir(
|
||||||
|
javaMethod: JavaMethod,
|
||||||
|
classId: ClassId,
|
||||||
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
|
classIsAnnotation: Boolean,
|
||||||
|
valueParametersForAnnotationConstructor: ValueParametersForAnnotationConstructor
|
||||||
|
): FirJavaMethod {
|
||||||
val methodName = javaMethod.name
|
val methodName = javaMethod.name
|
||||||
val methodId = CallableId(classId.packageFqName, classId.relativeClassName, methodName)
|
val methodId = CallableId(classId.packageFqName, classId.relativeClassName, methodName)
|
||||||
val methodSymbol = FirNamedFunctionSymbol(methodId)
|
val methodSymbol = FirNamedFunctionSymbol(methodId)
|
||||||
@@ -289,35 +368,30 @@ class JavaSymbolProvider(
|
|||||||
isVararg = javaMethod.returnType is JavaArrayType
|
isVararg = javaMethod.returnType is JavaArrayType
|
||||||
}
|
}
|
||||||
if (firJavaMethod.name == VALUE_METHOD_NAME) {
|
if (firJavaMethod.name == VALUE_METHOD_NAME) {
|
||||||
valueParameterForValueInAnnotationConstructor = parameterForAnnotationConstructor
|
valueParametersForAnnotationConstructor.valueParameterForValue = parameterForAnnotationConstructor
|
||||||
} else {
|
} else {
|
||||||
valueParametersForAnnotationConstructor += parameterForAnnotationConstructor
|
valueParametersForAnnotationConstructor.valueParameters += parameterForAnnotationConstructor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declarations += firJavaMethod
|
return firJavaMethod
|
||||||
}
|
}
|
||||||
val javaClassDeclaredConstructors = javaClass.constructors
|
|
||||||
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
|
|
||||||
|
|
||||||
fun buildSelfTypeRef() = firSymbol.constructType(
|
private fun convertJavaConstructorToFir(
|
||||||
this@buildJavaClass.typeParameters.map {
|
javaConstructor: JavaConstructor?,
|
||||||
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
constructorId: CallableId,
|
||||||
}.toTypedArray(),
|
javaClass: JavaClass,
|
||||||
false,
|
ownerClassBuilder: FirJavaClassBuilder,
|
||||||
)
|
classTypeParameters: List<FirTypeParameter>,
|
||||||
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
fun prepareJavaConstructor(
|
): FirJavaConstructor {
|
||||||
visibility: Visibility = this.visibility,
|
|
||||||
psi: PsiElement? = null,
|
|
||||||
isPrimary: Boolean = false,
|
|
||||||
): FirJavaConstructorBuilder {
|
|
||||||
val constructorSymbol = FirConstructorSymbol(constructorId)
|
val constructorSymbol = FirConstructorSymbol(constructorId)
|
||||||
return FirJavaConstructorBuilder().apply {
|
return buildJavaConstructor {
|
||||||
source = psi?.toFirPsiSourceElement()
|
source = (javaConstructor as? JavaElementImpl<*>)?.psi?.toFirPsiSourceElement()
|
||||||
session = this@JavaSymbolProvider.session
|
session = this@JavaSymbolProvider.session
|
||||||
symbol = constructorSymbol
|
symbol = constructorSymbol
|
||||||
isInner = javaClass.outerClass != null && !javaClass.isStatic
|
isInner = javaClass.outerClass != null && !javaClass.isStatic
|
||||||
val isThisInner = this.isInner
|
val isThisInner = this.isInner
|
||||||
|
val visibility = javaConstructor?.visibility ?: ownerClassBuilder.visibility
|
||||||
status = FirResolvedDeclarationStatusImpl(
|
status = FirResolvedDeclarationStatusImpl(
|
||||||
visibility,
|
visibility,
|
||||||
Modality.FINAL
|
Modality.FINAL
|
||||||
@@ -328,24 +402,13 @@ class JavaSymbolProvider(
|
|||||||
isInner = isThisInner
|
isInner = isThisInner
|
||||||
}
|
}
|
||||||
this.visibility = visibility
|
this.visibility = visibility
|
||||||
this.isPrimary = isPrimary
|
isPrimary = javaConstructor == null
|
||||||
returnTypeRef = buildResolvedTypeRef {
|
returnTypeRef = buildResolvedTypeRef {
|
||||||
type = buildSelfTypeRef()
|
type = ownerClassBuilder.buildSelfTypeRef()
|
||||||
}
|
}
|
||||||
typeParameters += classTypeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
|
typeParameters += classTypeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (javaClassDeclaredConstructors.isEmpty()
|
if (javaConstructor != null) {
|
||||||
&& javaClass.classKind == ClassKind.CLASS
|
|
||||||
&& javaClass.hasDefaultConstructor()) {
|
|
||||||
declarations += prepareJavaConstructor(isPrimary = true).build()
|
|
||||||
}
|
|
||||||
for (javaConstructor in javaClassDeclaredConstructors) {
|
|
||||||
declarations += prepareJavaConstructor(
|
|
||||||
visibility = javaConstructor.visibility,
|
|
||||||
psi = (javaConstructor as? JavaElementImpl<*>)?.psi,
|
|
||||||
).apply {
|
|
||||||
this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
|
this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
|
||||||
addAnnotationsFrom(this@JavaSymbolProvider.session, javaConstructor, javaTypeParameterStack)
|
addAnnotationsFrom(this@JavaSymbolProvider.session, javaConstructor, javaTypeParameterStack)
|
||||||
for ((index, valueParameter) in javaConstructor.valueParameters.withIndex()) {
|
for ((index, valueParameter) in javaConstructor.valueParameters.withIndex()) {
|
||||||
@@ -353,40 +416,36 @@ class JavaSymbolProvider(
|
|||||||
this@JavaSymbolProvider.session, index, javaTypeParameterStack,
|
this@JavaSymbolProvider.session, index, javaTypeParameterStack,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.build()
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classKind == ClassKind.ENUM_CLASS) {
|
private fun buildConstructorForAnnotationClass(
|
||||||
generateValuesFunction(session, classId.packageFqName, classId.relativeClassName)
|
constructorId: CallableId,
|
||||||
generateValueOfFunction(session, classId.packageFqName, classId.relativeClassName)
|
ownerClassBuilder: FirJavaClassBuilder,
|
||||||
}
|
valueParametersForAnnotationConstructor: ValueParametersForAnnotationConstructor
|
||||||
if (classIsAnnotation) {
|
): FirJavaConstructor {
|
||||||
declarations += buildJavaConstructor {
|
return buildJavaConstructor {
|
||||||
session = this@JavaSymbolProvider.session
|
session = this@JavaSymbolProvider.session
|
||||||
symbol = FirConstructorSymbol(constructorId)
|
symbol = FirConstructorSymbol(constructorId)
|
||||||
status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.FINAL)
|
status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.FINAL)
|
||||||
returnTypeRef = buildResolvedTypeRef {
|
returnTypeRef = buildResolvedTypeRef {
|
||||||
type = buildSelfTypeRef()
|
type = ownerClassBuilder.buildSelfTypeRef()
|
||||||
}
|
}
|
||||||
valueParameters.addIfNotNull(valueParameterForValueInAnnotationConstructor)
|
valueParameters.addIfNotNull(valueParametersForAnnotationConstructor.valueParameterForValue)
|
||||||
valueParameters += valueParametersForAnnotationConstructor
|
valueParameters += valueParametersForAnnotationConstructor.valueParameters
|
||||||
visibility = Visibilities.Public
|
visibility = Visibilities.Public
|
||||||
isInner = false
|
isInner = false
|
||||||
isPrimary = true
|
isPrimary = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentClassTypeParameterStackCache.remove(firSymbol)
|
|
||||||
}
|
private fun FirJavaClassBuilder.buildSelfTypeRef(): ConeKotlinType = symbol.constructType(
|
||||||
firJavaClass.replaceSuperTypeRefs(
|
typeParameters.map {
|
||||||
javaClass.supertypes.map { supertype ->
|
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false)
|
||||||
supertype.toFirResolvedTypeRef(
|
}.toTypedArray(),
|
||||||
this@JavaSymbolProvider.session, javaTypeParameterStack, isForSupertypes = true, forTypeParameterBounds = false
|
isNullable = false,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPackage(fqName: FqName): FqName? {
|
override fun getPackage(fqName: FqName): FqName? {
|
||||||
return packageCache.lookupCacheOrCalculate(fqName) {
|
return packageCache.lookupCacheOrCalculate(fqName) {
|
||||||
|
|||||||
Reference in New Issue
Block a user