[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.FirJavaFacadeForSource
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider 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.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -230,11 +231,12 @@ internal object LLFirSessionFactory {
register(FirKotlinScopeProvider::class, kotlinScopeProvider) register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val moduleDataProvider = createModuleDataProviderWithLibraryDependencies(sourceModule, this) val moduleDataProvider = createModuleDataProviderWithLibraryDependencies(sourceModule, this)
val packagePartProvider = project.createPackagePartProviderForLibrary(searchScope)
val classFileBasedSymbolProvider = JvmClassFileBasedSymbolProvider( val classFileBasedSymbolProvider = JvmClassFileBasedSymbolProvider(
this@session, this@session,
moduleDataProvider = moduleDataProvider, moduleDataProvider = moduleDataProvider,
kotlinScopeProvider = kotlinScopeProvider, kotlinScopeProvider = kotlinScopeProvider,
packagePartProvider = project.createPackagePartProviderForLibrary(searchScope), packagePartProvider = packagePartProvider,
kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope), kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope),
javaFacade = LLFirJavaFacadeForBinaries( javaFacade = LLFirJavaFacadeForBinaries(
this@session, this@session,
@@ -243,8 +245,17 @@ internal object LLFirSessionFactory {
moduleDataProvider moduleDataProvider
) )
) )
val optionalAnnotationClassesProvider = OptionalAnnotationClassesProvider(
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider
)
val symbolProvider = val symbolProvider =
FirCompositeSymbolProvider(this, listOf(classFileBasedSymbolProvider, builtinsAndCloneableSession.symbolProvider)) FirCompositeSymbolProvider(
this,
listOf(classFileBasedSymbolProvider, optionalAnnotationClassesProvider, builtinsAndCloneableSession.symbolProvider)
)
register(FirProvider::class, LLFirLibrariesSessionProvider(symbolProvider)) register(FirProvider::class, LLFirLibrariesSessionProvider(symbolProvider))
register(FirSymbolProvider::class, symbolProvider) register(FirSymbolProvider::class, symbolProvider)
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this)) register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
@@ -374,6 +385,7 @@ internal object LLFirSessionFactory {
val dependentProviders = buildList { val dependentProviders = buildList {
val librariesSearchScope = ProjectScope.getLibrariesScope(project) val librariesSearchScope = ProjectScope.getLibrariesScope(project)
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope> .intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope>
val packagePartProvider = project.createPackagePartProviderForLibrary(librariesSearchScope)
add(builtinsAndCloneableSession.symbolProvider) add(builtinsAndCloneableSession.symbolProvider)
val libraryDependenciesModuleDataProvider = createModuleDataProviderWithLibraryDependencies(module, this@session) val libraryDependenciesModuleDataProvider = createModuleDataProviderWithLibraryDependencies(module, this@session)
add( add(
@@ -381,7 +393,7 @@ internal object LLFirSessionFactory {
this@session, this@session,
moduleDataProvider = libraryDependenciesModuleDataProvider, moduleDataProvider = libraryDependenciesModuleDataProvider,
kotlinScopeProvider = scopeProvider, kotlinScopeProvider = scopeProvider,
packagePartProvider = project.createPackagePartProviderForLibrary(librariesSearchScope), packagePartProvider = packagePartProvider,
kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(librariesSearchScope), kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(librariesSearchScope),
javaFacade = LLFirJavaFacadeForBinaries( javaFacade = LLFirJavaFacadeForBinaries(
this@session, 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 // We need FirRegisteredPluginAnnotations during extensions' registration process
@@ -13084,6 +13084,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt"); 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 @Test
@TestMetadata("PackageLocalClassNotImported.kt") @TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception { public void testPackageLocalClassNotImported() throws Exception {
@@ -13084,6 +13084,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt"); 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 @Test
@TestMetadata("PackageLocalClassNotImported.kt") @TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception { public void testPackageLocalClassNotImported() throws Exception {
@@ -13084,6 +13084,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/imports/OperatorRenameOnImport.kt"); 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 @Test
@TestMetadata("PackageLocalClassNotImported.kt") @TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception { 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.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider 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.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -73,7 +74,7 @@ object FirSessionFactory {
// (maybe easiest way to achieve is to delete libraries // (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 // TODO: consider passing something more abstract instead of precompiler component, in order to avoid file ops here
val previousFirSessionsSymbolProviders: Collection<FirSymbolProvider>, val previousFirSessionsSymbolProviders: Collection<FirSymbolProvider>,
val precomiledBinariesPackagePartProvider: PackagePartProvider?, val precompiledBinariesPackagePartProvider: PackagePartProvider?,
val precompiledBinariesFileScope: AbstractProjectFileSearchScope? val precompiledBinariesFileScope: AbstractProjectFileSearchScope?
) )
@@ -155,19 +156,31 @@ object FirSessionFactory {
val firProvider = FirProviderImpl(this, kotlinScopeProvider) val firProvider = FirProviderImpl(this, kotlinScopeProvider)
register(FirProvider::class, firProvider) register(FirProvider::class, firProvider)
val symbolProviderForBinariesFromIncrementalCompilation = var symbolProviderForBinariesFromIncrementalCompilation: JvmClassFileBasedSymbolProvider? = null
incrementalCompilationContext?.let { (_, precompiledBinariesPackagePartProvider, precompiledBinariesFileScope) -> var optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation: OptionalAnnotationClassesProvider? = null
if (precompiledBinariesPackagePartProvider == null || precompiledBinariesFileScope == null) null incrementalCompilationContext?.let {
else JvmClassFileBasedSymbolProvider( if (it.precompiledBinariesPackagePartProvider != null && it.precompiledBinariesFileScope != null) {
this@session, val moduleDataProvider = SingleModuleDataProvider(moduleData)
SingleModuleDataProvider(moduleData), symbolProviderForBinariesFromIncrementalCompilation =
kotlinScopeProvider, JvmClassFileBasedSymbolProvider(
precompiledBinariesPackagePartProvider, this@session,
projectEnvironment.getKotlinClassFinder(precompiledBinariesFileScope), moduleDataProvider,
projectEnvironment.getFirJavaFacade(this, moduleData, precompiledBinariesFileScope), kotlinScopeProvider,
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled 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 { FirSessionConfigurator(this).apply {
registerCommonCheckers() registerCommonCheckers()
@@ -188,6 +201,7 @@ object FirSessionFactory {
firProvider.symbolProvider, firProvider.symbolProvider,
*(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()), *(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
symbolProviderForBinariesFromIncrementalCompilation, symbolProviderForBinariesFromIncrementalCompilation,
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation,
generatedSymbolsProvider, generatedSymbolsProvider,
JavaSymbolProvider(this, projectEnvironment.getFirJavaFacade(this, moduleData, javaSourcesScope)), JavaSymbolProvider(this, projectEnvironment.getFirJavaFacade(this, moduleData, javaSourcesScope)),
dependenciesSymbolProvider, dependenciesSymbolProvider,
@@ -238,6 +252,13 @@ object FirSessionFactory {
projectEnvironment.getFirJavaFacade(this, moduleDataProvider.allModuleData.last(), scope) projectEnvironment.getFirJavaFacade(this, moduleDataProvider.allModuleData.last(), scope)
) )
val optionalAnnotationClassesProvider = OptionalAnnotationClassesProvider(
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider
)
val builtinsModuleData = createModuleDataForBuiltins( val builtinsModuleData = createModuleDataForBuiltins(
mainModuleName, mainModuleName,
moduleDataProvider.platform, moduleDataProvider.platform,
@@ -248,6 +269,7 @@ object FirSessionFactory {
this, this,
listOf( listOf(
classFileBasedSymbolProvider, classFileBasedSymbolProvider,
optionalAnnotationClassesProvider,
FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider), FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider), FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirDependenciesSymbolProviderImpl(this) FirDependenciesSymbolProviderImpl(this)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.deserialization package org.jetbrains.kotlin.fir.deserialization
import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProcessCanceledException
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.FirCache import org.jetbrains.kotlin.fir.caches.FirCache
import org.jetbrains.kotlin.fir.caches.createCache import org.jetbrains.kotlin.fir.caches.createCache
@@ -107,10 +108,10 @@ abstract class AbstractFirDeserializedSymbolProvider(
data class Metadata( data class Metadata(
val nameResolver: NameResolver, val nameResolver: NameResolver,
val classProto: ProtoBuf.Class, val classProto: ProtoBuf.Class,
val annotationDeserializer: AbstractAnnotationDeserializer, val annotationDeserializer: AbstractAnnotationDeserializer?,
val containingLibraryPath: Path?, val moduleData: FirModuleData?,
val sourceElement: DeserializedContainerSource, val sourceElement: DeserializedContainerSource?,
val classPostProcessor: DeserializedClassPostProcessor val classPostProcessor: DeserializedClassPostProcessor?
) : ClassMetadataFindResult() ) : ClassMetadataFindResult()
} }
@@ -138,8 +139,8 @@ abstract class AbstractFirDeserializedSymbolProvider(
return when (val result = extractClassMetadata(classId, parentContext)) { return when (val result = extractClassMetadata(classId, parentContext)) {
is ClassMetadataFindResult.NoMetadata -> FirRegularClassSymbol(classId) to result.classPostProcessor is ClassMetadataFindResult.NoMetadata -> FirRegularClassSymbol(classId) to result.classPostProcessor
is ClassMetadataFindResult.Metadata -> { is ClassMetadataFindResult.Metadata -> {
val (nameResolver, classProto, annotationDeserializer, containingLibrary, sourceElement, postProcessor) = result val (nameResolver, classProto, annotationDeserializer, moduleData, sourceElement, postProcessor) = result
val moduleData = moduleDataProvider.getModuleData(containingLibrary) ?: return null to null moduleData ?: return null to null
val symbol = FirRegularClassSymbol(classId) val symbol = FirRegularClassSymbol(classId)
deserializeClassToSymbol( deserializeClassToSymbol(
classId, classId,
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
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.resolve.jvm.JvmClassName 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.Path
import java.nio.file.Paths import java.nio.file.Paths
@@ -132,7 +132,7 @@ class JvmClassFileBasedSymbolProvider(
nameResolver, nameResolver,
classProto, classProto,
JvmBinaryAnnotationDeserializer(session, kotlinClass, kotlinClassFinder, result.byteContent), JvmBinaryAnnotationDeserializer(session, kotlinClass, kotlinClassFinder, result.byteContent),
kotlinClass.containingLibrary.toPath(), moduleDataProvider.getModuleData(kotlinClass.containingLibrary?.toPath()),
KotlinJvmBinarySourceElement(kotlinClass), KotlinJvmBinarySourceElement(kotlinClass),
classPostProcessor = { loadAnnotationsFromClassFile(result, it) } 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"); 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 @Test
@TestMetadata("PackageLocalClassNotImported.kt") @TestMetadata("PackageLocalClassNotImported.kt")
public void testPackageLocalClassNotImported() throws Exception { public void testPackageLocalClassNotImported() throws Exception {