[FIR] Support of importing optional annotation classes (JS/Native), ^KT-51757 Fixed

This commit is contained in:
Ivan Kochurkin
2022-04-16 15:03:29 +03:00
committed by teamcity
parent 73e7b99e05
commit 3b8183a736
11 changed files with 181 additions and 24 deletions
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
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.java.deserialization.OptionalAnnotationClassesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -230,11 +231,12 @@ internal object LLFirSessionFactory {
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val moduleDataProvider = createModuleDataProviderWithLibraryDependencies(sourceModule, this)
val packagePartProvider = project.createPackagePartProviderForLibrary(searchScope)
val classFileBasedSymbolProvider = JvmClassFileBasedSymbolProvider(
this@session,
moduleDataProvider = moduleDataProvider,
kotlinScopeProvider = kotlinScopeProvider,
packagePartProvider = project.createPackagePartProviderForLibrary(searchScope),
packagePartProvider = packagePartProvider,
kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope),
javaFacade = LLFirJavaFacadeForBinaries(
this@session,
@@ -243,8 +245,17 @@ internal object LLFirSessionFactory {
moduleDataProvider
)
)
val optionalAnnotationClassesProvider = OptionalAnnotationClassesProvider(
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider
)
val symbolProvider =
FirCompositeSymbolProvider(this, listOf(classFileBasedSymbolProvider, builtinsAndCloneableSession.symbolProvider))
FirCompositeSymbolProvider(
this,
listOf(classFileBasedSymbolProvider, optionalAnnotationClassesProvider, builtinsAndCloneableSession.symbolProvider)
)
register(FirProvider::class, LLFirLibrariesSessionProvider(symbolProvider))
register(FirSymbolProvider::class, symbolProvider)
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
@@ -374,6 +385,7 @@ internal object LLFirSessionFactory {
val dependentProviders = buildList {
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope>
val packagePartProvider = project.createPackagePartProviderForLibrary(librariesSearchScope)
add(builtinsAndCloneableSession.symbolProvider)
val libraryDependenciesModuleDataProvider = createModuleDataProviderWithLibraryDependencies(module, this@session)
add(
@@ -381,7 +393,7 @@ internal object LLFirSessionFactory {
this@session,
moduleDataProvider = libraryDependenciesModuleDataProvider,
kotlinScopeProvider = scopeProvider,
packagePartProvider = project.createPackagePartProviderForLibrary(librariesSearchScope),
packagePartProvider = packagePartProvider,
kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(librariesSearchScope),
javaFacade = LLFirJavaFacadeForBinaries(
this@session,
@@ -391,6 +403,14 @@ internal object LLFirSessionFactory {
)
)
)
add(
OptionalAnnotationClassesProvider(
this@session,
moduleDataProvider = libraryDependenciesModuleDataProvider,
kotlinScopeProvider = scopeProvider,
packagePartProvider = packagePartProvider,
)
)
}
// We need FirRegisteredPluginAnnotations during extensions' registration process
@@ -13084,6 +13084,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt");
}
@Test
@TestMetadata("OptionalAnnotationClasses.kt")
public void testOptionalAnnotationClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/imports/OptionalAnnotationClasses.kt");
}
@Test
@TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception {
@@ -13084,6 +13084,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt");
}
@Test
@TestMetadata("OptionalAnnotationClasses.kt")
public void testOptionalAnnotationClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/imports/OptionalAnnotationClasses.kt");
}
@Test
@TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception {
@@ -13084,6 +13084,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt");
}
@Test
@TestMetadata("OptionalAnnotationClasses.kt")
public void testOptionalAnnotationClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/imports/OptionalAnnotationClasses.kt");
}
@Test
@TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception {
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.java.FirCliSession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.OptionalAnnotationClassesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -73,7 +74,7 @@ object FirSessionFactory {
// (maybe easiest way to achieve is to delete libraries
// TODO: consider passing something more abstract instead of precompiler component, in order to avoid file ops here
val previousFirSessionsSymbolProviders: Collection<FirSymbolProvider>,
val precomiledBinariesPackagePartProvider: PackagePartProvider?,
val precompiledBinariesPackagePartProvider: PackagePartProvider?,
val precompiledBinariesFileScope: AbstractProjectFileSearchScope?
)
@@ -155,19 +156,31 @@ object FirSessionFactory {
val firProvider = FirProviderImpl(this, kotlinScopeProvider)
register(FirProvider::class, firProvider)
val symbolProviderForBinariesFromIncrementalCompilation =
incrementalCompilationContext?.let { (_, precompiledBinariesPackagePartProvider, precompiledBinariesFileScope) ->
if (precompiledBinariesPackagePartProvider == null || precompiledBinariesFileScope == null) null
else JvmClassFileBasedSymbolProvider(
this@session,
SingleModuleDataProvider(moduleData),
kotlinScopeProvider,
precompiledBinariesPackagePartProvider,
projectEnvironment.getKotlinClassFinder(precompiledBinariesFileScope),
projectEnvironment.getFirJavaFacade(this, moduleData, precompiledBinariesFileScope),
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
var symbolProviderForBinariesFromIncrementalCompilation: JvmClassFileBasedSymbolProvider? = null
var optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation: OptionalAnnotationClassesProvider? = null
incrementalCompilationContext?.let {
if (it.precompiledBinariesPackagePartProvider != null && it.precompiledBinariesFileScope != null) {
val moduleDataProvider = SingleModuleDataProvider(moduleData)
symbolProviderForBinariesFromIncrementalCompilation =
JvmClassFileBasedSymbolProvider(
this@session,
moduleDataProvider,
kotlinScopeProvider,
it.precompiledBinariesPackagePartProvider,
projectEnvironment.getKotlinClassFinder(it.precompiledBinariesFileScope),
projectEnvironment.getFirJavaFacade(this, moduleData, it.precompiledBinariesFileScope),
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation =
OptionalAnnotationClassesProvider(
this@session,
moduleDataProvider,
kotlinScopeProvider,
it.precompiledBinariesPackagePartProvider,
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
}
}
FirSessionConfigurator(this).apply {
registerCommonCheckers()
@@ -188,6 +201,7 @@ object FirSessionFactory {
firProvider.symbolProvider,
*(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
symbolProviderForBinariesFromIncrementalCompilation,
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation,
generatedSymbolsProvider,
JavaSymbolProvider(this, projectEnvironment.getFirJavaFacade(this, moduleData, javaSourcesScope)),
dependenciesSymbolProvider,
@@ -238,6 +252,13 @@ object FirSessionFactory {
projectEnvironment.getFirJavaFacade(this, moduleDataProvider.allModuleData.last(), scope)
)
val optionalAnnotationClassesProvider = OptionalAnnotationClassesProvider(
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider
)
val builtinsModuleData = createModuleDataForBuiltins(
mainModuleName,
moduleDataProvider.platform,
@@ -248,6 +269,7 @@ object FirSessionFactory {
this,
listOf(
classFileBasedSymbolProvider,
optionalAnnotationClassesProvider,
FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirDependenciesSymbolProviderImpl(this)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.deserialization
import com.intellij.openapi.progress.ProcessCanceledException
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.createCache
@@ -107,10 +108,10 @@ abstract class AbstractFirDeserializedSymbolProvider(
data class Metadata(
val nameResolver: NameResolver,
val classProto: ProtoBuf.Class,
val annotationDeserializer: AbstractAnnotationDeserializer,
val containingLibraryPath: Path?,
val sourceElement: DeserializedContainerSource,
val classPostProcessor: DeserializedClassPostProcessor
val annotationDeserializer: AbstractAnnotationDeserializer?,
val moduleData: FirModuleData?,
val sourceElement: DeserializedContainerSource?,
val classPostProcessor: DeserializedClassPostProcessor?
) : ClassMetadataFindResult()
}
@@ -138,8 +139,8 @@ abstract class AbstractFirDeserializedSymbolProvider(
return when (val result = extractClassMetadata(classId, parentContext)) {
is ClassMetadataFindResult.NoMetadata -> FirRegularClassSymbol(classId) to result.classPostProcessor
is ClassMetadataFindResult.Metadata -> {
val (nameResolver, classProto, annotationDeserializer, containingLibrary, sourceElement, postProcessor) = result
val moduleData = moduleDataProvider.getModuleData(containingLibrary) ?: return null to null
val (nameResolver, classProto, annotationDeserializer, moduleData, sourceElement, postProcessor) = result
moduleData ?: return null to null
val symbol = FirRegularClassSymbol(classId)
deserializeClassToSymbol(
classId,
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.*
import java.nio.file.Path
import java.nio.file.Paths
@@ -132,7 +132,7 @@ class JvmClassFileBasedSymbolProvider(
nameResolver,
classProto,
JvmBinaryAnnotationDeserializer(session, kotlinClass, kotlinClassFinder, result.byteContent),
kotlinClass.containingLibrary.toPath(),
moduleDataProvider.getModuleData(kotlinClass.containingLibrary?.toPath()),
KotlinJvmBinarySourceElement(kotlinClass),
classPostProcessor = { loadAnnotationsFromClassFile(result, it) }
)
@@ -0,0 +1,73 @@
/*
* 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.fir.java.deserialization
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolProvider
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.PackagePartsCacheData
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmFlags
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.deserialization.ClassData
import org.jetbrains.kotlin.serialization.deserialization.getClassId
class OptionalAnnotationClassesProvider(
session: FirSession,
moduleDataProvider: ModuleDataProvider,
kotlinScopeProvider: FirKotlinScopeProvider,
packagePartProvider: PackagePartProvider,
defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
) : AbstractFirDeserializedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, defaultDeserializationOrigin) {
private val optionalAnnotationClasses: Map<ClassId, ClassData>
private val optionalAnnotationPackages: Set<FqName>
init {
val optionalAnnotationClasses = mutableMapOf<ClassId, ClassData>()
val optionalAnnotationPackages = mutableSetOf<FqName>()
for (klass in packagePartProvider.getAllOptionalAnnotationClasses()) {
val classId = klass.nameResolver.getClassId(klass.classProto.fqName)
optionalAnnotationClasses[classId] = klass
optionalAnnotationPackages.add(classId.packageFqName)
}
this.optionalAnnotationClasses = optionalAnnotationClasses
this.optionalAnnotationPackages = optionalAnnotationPackages
}
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
return emptyList()
}
override fun extractClassMetadata(
classId: ClassId,
parentContext: FirDeserializationContext?
): ClassMetadataFindResult? {
val optionalAnnotationClass = optionalAnnotationClasses[classId] ?: return null
return ClassMetadataFindResult.Metadata(
optionalAnnotationClass.nameResolver,
optionalAnnotationClass.classProto,
null,
moduleDataProvider.allModuleData.last(),
null,
classPostProcessor = null
)
}
override fun isNewPlaceForBodyGeneration(classProto: ProtoBuf.Class): Boolean {
return JvmFlags.IS_COMPILED_IN_JVM_DEFAULT_MODE.get(classProto.getExtension(JvmProtoBuf.jvmClassFlags))
}
override fun getPackage(fqName: FqName): FqName? = if (optionalAnnotationPackages.contains(fqName)) fqName else null
}
@@ -0,0 +1,13 @@
// FIR_IDENTICAL
// WITH_STDLIB
@file:Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE")
import kotlin.js.*
import kotlin.native.concurrent.*
@JsName("")
public fun test() {}
@SharedImmutable
private val EmptyArray: Array<Int> = arrayOf()
@@ -0,0 +1,4 @@
package
@kotlin.native.concurrent.SharedImmutable private val EmptyArray: kotlin.Array<kotlin.Int>
@kotlin.js.JsName(name = "") public fun test(): kotlin.Unit
@@ -13090,6 +13090,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt");
}
@Test
@TestMetadata("OptionalAnnotationClasses.kt")
public void testOptionalAnnotationClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/imports/OptionalAnnotationClasses.kt");
}
@Test
@TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception {