diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJavaFacadeForBinaries.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJavaFacadeForBinaries.kt new file mode 100644 index 00000000000..422bf8dbfcd --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJavaFacadeForBinaries.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.analysis.low.level.api.fir.sessions + +import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance +import org.jetbrains.kotlin.fir.BuiltinTypes +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider +import org.jetbrains.kotlin.fir.java.FirJavaFacade +import org.jetbrains.kotlin.load.java.JavaClassFinder +import org.jetbrains.kotlin.load.java.structure.JavaClass +import org.jetbrains.kotlin.load.java.structure.classId +import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass +import java.nio.file.Path +import java.nio.file.Paths + +internal class LLFirJavaFacadeForBinaries( + session: FirSession, + builtinTypes: BuiltinTypes, + classFinder: JavaClassFinder, + private val binaryDependenciesModuleDataProvider: ModuleDataProvider, +) : FirJavaFacade(session, builtinTypes, classFinder) { + override fun getModuleDataForClass(javaClass: JavaClass): FirModuleData { + requireIsInstance(javaClass) + val path = getBinaryPath(javaClass) + return binaryDependenciesModuleDataProvider.getModuleData(path) + ?: error("No module data found for ${javaClass.classId} with path $path") + } + + private fun getBinaryPath(javaClass: VirtualFileBoundJavaClass): Path { + val virtualFile = javaClass.virtualFile + ?: error("no virtual file for ${javaClass.classId}") + val path = virtualFile.path + return Paths.get(path) + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt index 6eb5c7f4f8d..7410ae7ddea 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt @@ -41,7 +41,7 @@ import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations import org.jetbrains.kotlin.fir.extensions.FirSwitchableExtensionDeclarationsSymbolProvider import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate -import org.jetbrains.kotlin.fir.java.FirJavaFacade +import org.jetbrains.kotlin.fir.java.FirJavaFacadeForSource import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider @@ -188,7 +188,7 @@ internal object LLFirSessionFactory { switchableExtensionDeclarationsSymbolProvider, JavaSymbolProvider( this, - FirJavaFacade( + FirJavaFacadeForSource( this, moduleData, project.createJavaClassFinder(contentScope) ) ), @@ -226,8 +226,6 @@ internal object LLFirSessionFactory { val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) register(FirKotlinScopeProvider::class, kotlinScopeProvider) - val mainModuleData = KtModuleBasedModuleData(sourceModule).apply { bindSession(this@session) } - val moduleDataProvider = createModuleDataProviderWithLibraryDependencies(sourceModule, this) val classFileBasedSymbolProvider = JvmClassFileBasedSymbolProvider( this@session, @@ -235,8 +233,11 @@ internal object LLFirSessionFactory { kotlinScopeProvider = kotlinScopeProvider, packagePartProvider = project.createPackagePartProviderForLibrary(searchScope), kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope), - javaFacade = FirJavaFacade( - this@session, mainModuleData, project.createJavaClassFinder(searchScope) + javaFacade = LLFirJavaFacadeForBinaries( + this@session, + builtinTypes, + project.createJavaClassFinder(searchScope), + moduleDataProvider ) ) val symbolProvider = @@ -281,18 +282,12 @@ internal object LLFirSessionFactory { fun createBuiltinsAndCloneableSession( project: Project, builtinTypes: BuiltinTypes, + stdlibModule: KtModule, languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, configureSession: (LLFirSession.() -> Unit)? = null, ): LLFirBuiltinsAndCloneableSession { return LLFirBuiltinsAndCloneableSession(project, builtinTypes).apply session@{ - val moduleData = FirModuleDataImpl( - Name.special(""), - emptyList(), - emptyList(), - emptyList(), - JvmPlatforms.unspecifiedJvmPlatform, - JvmPlatformAnalyzerServices - ).apply { + val moduleData = KtModuleBasedModuleData(stdlibModule).apply { bindSession(this@session) } registerIdeComponents(project) @@ -376,15 +371,19 @@ internal object LLFirSessionFactory { val librariesSearchScope = ProjectScope.getLibrariesScope(project) .intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // - add(builtinsAndCloneableSession.symbolProvider) + val libraryDependenciesModuleDataProvider = createModuleDataProviderWithLibraryDependencies(module, this@session) add( JvmClassFileBasedSymbolProvider( this@session, - moduleDataProvider = createModuleDataProviderWithLibraryDependencies(module, this@session), + moduleDataProvider = libraryDependenciesModuleDataProvider, kotlinScopeProvider = scopeProvider, packagePartProvider = project.createPackagePartProviderForLibrary(librariesSearchScope), kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(librariesSearchScope), - javaFacade = FirJavaFacade( - this@session, moduleData, project.createJavaClassFinder(librariesSearchScope) + javaFacade = LLFirJavaFacadeForBinaries( + this@session, + builtinTypes, + project.createJavaClassFinder(librariesSearchScope), + libraryDependenciesModuleDataProvider ) ) ) @@ -422,7 +421,7 @@ internal object LLFirSessionFactory { provider.symbolProvider, JavaSymbolProvider( this, - FirJavaFacade( + FirJavaFacadeForSource( this, moduleData, project.createJavaClassFinder(contentScope) ) ), diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/VfsBasedProjectEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/VfsBasedProjectEnvironment.kt index 0afedde160e..17aba27d702 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/VfsBasedProjectEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/VfsBasedProjectEnvironment.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.java.FirJavaElementFinder -import org.jetbrains.kotlin.fir.java.FirJavaFacade +import org.jetbrains.kotlin.fir.java.FirJavaFacadeForSource import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.load.java.createJavaClassFinder @@ -128,7 +128,7 @@ open class VfsBasedProjectEnvironment( firSession: FirSession, baseModuleData: FirModuleData, fileSearchScope: AbstractProjectFileSearchScope - ) = FirJavaFacade(firSession, baseModuleData, project.createJavaClassFinder(fileSearchScope.asPsiSearchScope())) + ) = FirJavaFacadeForSource(firSession, baseModuleData, project.createJavaClassFinder(fileSearchScope.asPsiSearchScope())) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt index 16695f91509..852a42c1ac0 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameter import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility import org.jetbrains.kotlin.fir.declarations.utils.modality +import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.classId @@ -46,15 +47,26 @@ import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl +import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.toKtPsiSourceElement import org.jetbrains.kotlin.types.Variance.INVARIANT import org.jetbrains.kotlin.util.OperatorNameConventions +class FirJavaFacadeForSource( + session: FirSession, + private val sourceModuleData: FirModuleData, + classFinder: JavaClassFinder +) : FirJavaFacade(session, sourceModuleData.session.builtinTypes, classFinder) { + override fun getModuleDataForClass(javaClass: JavaClass): FirModuleData { + return sourceModuleData + } +} + @ThreadSafeMutableState -class FirJavaFacade( +abstract class FirJavaFacade( private val session: FirSession, - private val baseModuleData: FirModuleData, + private val builtinTypes: BuiltinTypes, private val classFinder: JavaClassFinder ) { companion object { @@ -90,12 +102,15 @@ class FirJavaFacade( return classId.relativeClassName.topLevelName() in knownNames } + abstract fun getModuleDataForClass(javaClass: JavaClass): FirModuleData + private fun JavaTypeParameter.toFirTypeParameter( javaTypeParameterStack: JavaTypeParameterStack, - containingDeclarationSymbol: FirBasedSymbol<*> + containingDeclarationSymbol: FirBasedSymbol<*>, + moduleData: FirModuleData, ): FirTypeParameter { return buildTypeParameter { - moduleData = baseModuleData + this.moduleData = moduleData origin = FirDeclarationOrigin.Java resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES name = this@toFirTypeParameter.name @@ -110,7 +125,6 @@ class FirJavaFacade( bounds += upperBound.toFirJavaTypeRef(session, javaTypeParameterStack) } if (bounds.isEmpty()) { - val builtinTypes = baseModuleData.session.builtinTypes bounds += buildResolvedTypeRef { type = ConeFlexibleType(builtinTypes.anyType.type, builtinTypes.nullableAnyType.type) } @@ -120,9 +134,10 @@ class FirJavaFacade( private fun List.convertTypeParameters( stack: JavaTypeParameterStack, - containingDeclarationSymbol: FirBasedSymbol<*> + containingDeclarationSymbol: FirBasedSymbol<*>, + moduleData: FirModuleData, ): List { - return map { it.toFirTypeParameter(stack, containingDeclarationSymbol) } + return map { it.toFirTypeParameter(stack, containingDeclarationSymbol, moduleData) } } private fun JavaClass.hasMetadataAnnotation(): Boolean = @@ -221,9 +236,10 @@ class FirJavaFacade( ): FirJavaClass { val valueParametersForAnnotationConstructor = ValueParametersForAnnotationConstructor() val classIsAnnotation = javaClass.classKind == ClassKind.ANNOTATION_CLASS + val moduleData = getModuleDataForClass(javaClass) return buildJavaClass { source = (javaClass as? JavaElementImpl<*>)?.psi?.toKtPsiSourceElement() - moduleData = baseModuleData + this.moduleData = moduleData symbol = classSymbol name = javaClass.name val visibility = javaClass.visibility @@ -244,7 +260,7 @@ class FirJavaFacade( val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext) parentClassEffectiveVisibilityCache[classSymbol] = effectiveVisibility - val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack, classSymbol) + val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack, classSymbol, moduleData) typeParameters += classTypeParameters if (!isStatic && parentClassSymbol != null) { typeParameters += parentClassSymbol.fir.typeParameters.map { @@ -276,7 +292,7 @@ class FirJavaFacade( // TODO: may be we can process fields & methods later. // However, they should be built up to override resolve stage for (javaField in javaClass.fields) { - declarations += convertJavaFieldToFir(javaField, classId, javaTypeParameterStack, dispatchReceiver) + declarations += convertJavaFieldToFir(javaField, classId, javaTypeParameterStack, dispatchReceiver, moduleData) } for (javaMethod in javaClass.methods) { @@ -285,12 +301,14 @@ class FirJavaFacade( javaMethod, classId, javaTypeParameterStack, - dispatchReceiver + dispatchReceiver, + moduleData, ) declarations += firJavaMethod if (classIsAnnotation) { - val parameterForAnnotationConstructor = convertJavaAnnotationMethodToValueParameter(javaMethod, firJavaMethod) + val parameterForAnnotationConstructor = + convertJavaAnnotationMethodToValueParameter(javaMethod, firJavaMethod, moduleData) if (javaMethod.name == VALUE_METHOD_NAME) { valueParametersForAnnotationConstructor.valueParameterForValue = javaMethod to parameterForAnnotationConstructor } else { @@ -313,6 +331,7 @@ class FirJavaFacade( classTypeParameters, javaTypeParameterStack, parentClassSymbol, + moduleData, ) } for (javaConstructor in javaClassDeclaredConstructors) { @@ -324,16 +343,17 @@ class FirJavaFacade( classTypeParameters, javaTypeParameterStack, parentClassSymbol, + moduleData, ) } if (classKind == ClassKind.ENUM_CLASS) { generateValuesFunction( - baseModuleData, + moduleData, classId.packageFqName, classId.relativeClassName ) - generateValueOfFunction(baseModuleData, classId.packageFqName, classId.relativeClassName) + generateValueOfFunction(moduleData, classId.packageFqName, classId.relativeClassName) } if (classIsAnnotation) { declarations += @@ -341,7 +361,8 @@ class FirJavaFacade( classSource = (javaClass as? JavaElementImpl<*>)?.psi?.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor) as? KtFakeSourceElement, constructorId = constructorId, ownerClassBuilder = this, - valueParametersForAnnotationConstructor = valueParametersForAnnotationConstructor + valueParametersForAnnotationConstructor = valueParametersForAnnotationConstructor, + moduleData = moduleData, ) } }.apply { @@ -369,7 +390,8 @@ class FirJavaFacade( javaField: JavaField, classId: ClassId, javaTypeParameterStack: JavaTypeParameterStack, - dispatchReceiver: ConeClassLikeType + dispatchReceiver: ConeClassLikeType, + moduleData: FirModuleData, ): FirDeclaration { val fieldName = javaField.name val fieldId = CallableId(classId.packageFqName, classId.relativeClassName, fieldName) @@ -377,7 +399,7 @@ class FirJavaFacade( return when { javaField.isEnumEntry -> buildEnumEntry { source = (javaField as? JavaElementImpl<*>)?.psi?.toKtPsiSourceElement() - moduleData = baseModuleData + this.moduleData = moduleData symbol = FirEnumEntrySymbol(fieldId) name = fieldName status = FirResolvedDeclarationStatusImpl( @@ -400,7 +422,7 @@ class FirJavaFacade( } else -> buildJavaField { source = (javaField as? JavaElementImpl<*>)?.psi?.toKtPsiSourceElement() - moduleData = baseModuleData + this.moduleData = moduleData symbol = FirFieldSymbol(fieldId) name = fieldName status = FirResolvedDeclarationStatusImpl( @@ -441,20 +463,21 @@ class FirJavaFacade( javaMethod: JavaMethod, classId: ClassId, javaTypeParameterStack: JavaTypeParameterStack, - dispatchReceiver: ConeClassLikeType + dispatchReceiver: ConeClassLikeType, + moduleData: FirModuleData, ): FirJavaMethod { val methodName = javaMethod.name val methodId = CallableId(classId.packageFqName, classId.relativeClassName, methodName) val methodSymbol = FirNamedFunctionSymbol(methodId) val returnType = javaMethod.returnType return buildJavaMethod { - moduleData = baseModuleData + this.moduleData = moduleData source = (javaMethod as? JavaElementImpl<*>)?.psi?.toKtPsiSourceElement() symbol = methodSymbol name = methodName returnTypeRef = returnType.toFirJavaTypeRef(session, javaTypeParameterStack) isStatic = javaMethod.isStatic - typeParameters += javaMethod.typeParameters.convertTypeParameters(javaTypeParameterStack, methodSymbol) + typeParameters += javaMethod.typeParameters.convertTypeParameters(javaTypeParameterStack, methodSymbol, moduleData) for ((index, valueParameter) in javaMethod.valueParameters.withIndex()) { valueParameters += valueParameter.toFirValueParameter(session, moduleData, index, javaTypeParameterStack) } @@ -488,11 +511,15 @@ class FirJavaFacade( } } - private fun convertJavaAnnotationMethodToValueParameter(javaMethod: JavaMethod, firJavaMethod: FirJavaMethod): FirJavaValueParameter = + private fun convertJavaAnnotationMethodToValueParameter( + javaMethod: JavaMethod, + firJavaMethod: FirJavaMethod, + moduleData: FirModuleData, + ): FirJavaValueParameter = buildJavaValueParameter { source = (javaMethod as? JavaElementImpl<*>)?.psi ?.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitJavaAnnotationConstructor) - moduleData = baseModuleData + this.moduleData = moduleData returnTypeRef = firJavaMethod.returnTypeRef name = javaMethod.name isVararg = javaMethod.returnType is JavaArrayType && javaMethod.name == VALUE_METHOD_NAME @@ -507,11 +534,12 @@ class FirJavaFacade( classTypeParameters: List, javaTypeParameterStack: JavaTypeParameterStack, outerClassSymbol: FirRegularClassSymbol?, + moduleData: FirModuleData, ): FirJavaConstructor { val constructorSymbol = FirConstructorSymbol(constructorId) return buildJavaConstructor { source = (javaConstructor as? JavaElementImpl<*>)?.psi?.toKtPsiSourceElement() - moduleData = baseModuleData + this.moduleData = moduleData symbol = constructorSymbol isInner = javaClass.outerClass != null && !javaClass.isStatic val isThisInner = this.isInner @@ -535,7 +563,7 @@ class FirJavaFacade( typeParameters += classTypeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } } if (javaConstructor != null) { - this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack, constructorSymbol) + this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack, constructorSymbol, moduleData) annotationBuilder = { javaConstructor.convertAnnotationsToFir(session, javaTypeParameterStack) } for ((index, valueParameter) in javaConstructor.valueParameters.withIndex()) { valueParameters += valueParameter.toFirValueParameter(session, moduleData, index, javaTypeParameterStack) @@ -552,11 +580,12 @@ class FirJavaFacade( classSource: KtFakeSourceElement?, constructorId: CallableId, ownerClassBuilder: FirJavaClassBuilder, - valueParametersForAnnotationConstructor: ValueParametersForAnnotationConstructor + valueParametersForAnnotationConstructor: ValueParametersForAnnotationConstructor, + moduleData: FirModuleData, ): FirJavaConstructor { return buildJavaConstructor { source = classSource - moduleData = baseModuleData + this.moduleData = moduleData symbol = FirConstructorSymbol(constructorId) status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.FINAL, EffectiveVisibility.Public) returnTypeRef = buildResolvedTypeRef {