[SLC] provide light classes only for platforms with jvm target

Light classes are not supposed to work on non-jvm platforms due to its
specific

^KT-60318 Fixed
This commit is contained in:
Dmitrii Gridin
2023-08-25 15:13:51 +02:00
committed by Space Team
parent 13a7bb95b3
commit 7fa7d8ea8d
2 changed files with 44 additions and 32 deletions
@@ -21,13 +21,15 @@ import org.jetbrains.kotlin.fileClasses.isJvmMultifileClassFile
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.utils.exceptions.withPsiEntry
abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project) : KotlinAsJavaSupport() { abstract class KotlinAsJavaSupportBase<TModule : Any>(protected val project: Project) : KotlinAsJavaSupport() {
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
fun createLightFacade(file: KtFile): LightClassCachedValue<KtLightClassForFacade>? { fun createLightFacade(file: KtFile): LightClassCachedValue<KtLightClassForFacade>? {
if (!file.facadeIsPossible()) return null if (!file.facadeIsPossible()) return null
val module = file.findModule().takeIf { facadeIsApplicable(it, file) } ?: return null val module = file.findModule()?.takeIf { facadeIsApplicable(it, file) } ?: return null
val facadeFqName = file.javaFileFacadeFqName val facadeFqName = file.javaFileFacadeFqName
val facadeFiles = if (file.canHaveAdditionalFilesInFacade()) { val facadeFiles = if (file.canHaveAdditionalFilesInFacade()) {
findFilesForFacade(facadeFqName, module.contentSearchScope).filter(KtFile::isJvmMultifileClassFile) findFilesForFacade(facadeFqName, module.contentSearchScope).filter(KtFile::isJvmMultifileClassFile)
@@ -61,11 +63,11 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
private fun KtFile.canHaveAdditionalFilesInFacade(): Boolean = !isCompiled && isJvmMultifileClassFile private fun KtFile.canHaveAdditionalFilesInFacade(): Boolean = !isCompiled && isJvmMultifileClassFile
protected abstract fun KtFile.findModule(): TModule protected abstract fun KtFile.findModule(): TModule?
protected abstract fun facadeIsApplicable(module: TModule, file: KtFile): Boolean protected abstract fun facadeIsApplicable(module: TModule, file: KtFile): Boolean
protected abstract val TModule.contentSearchScope: GlobalSearchScope protected abstract val TModule.contentSearchScope: GlobalSearchScope
protected abstract fun createInstanceOfLightFacade(facadeFqName: FqName, files: List<KtFile>): KtLightClassForFacade protected abstract fun createInstanceOfLightFacade(facadeFqName: FqName, files: List<KtFile>): KtLightClassForFacade?
protected abstract fun createInstanceOfDecompiledLightFacade(facadeFqName: FqName, files: List<KtFile>): KtLightClassForFacade? protected abstract fun createInstanceOfDecompiledLightFacade(facadeFqName: FqName, files: List<KtFile>): KtLightClassForFacade?
protected open fun projectWideOutOfBlockModificationTracker(): ModificationTracker { protected open fun projectWideOutOfBlockModificationTracker(): ModificationTracker {
@@ -85,7 +87,12 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
} }
override fun createFacadeForSyntheticFile(file: KtFile): KtLightClassForFacade { override fun createFacadeForSyntheticFile(file: KtFile): KtLightClassForFacade {
return createInstanceOfLightFacade(file.javaFileFacadeFqName, listOf(file)) return createInstanceOfLightFacade(file.javaFileFacadeFqName, listOf(file)) ?: errorWithAttachment(
"Unsupported ${file::class.simpleName}"
) {
withEntry("module", file.findModule().toString())
withPsiEntry("file", file)
}
} }
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<KtLightClassForFacade> { override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<KtLightClassForFacade> {
@@ -99,19 +106,21 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> { override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> {
return findFilesForFacadeByPackage(packageFqName, scope).mapNotNullTo(mutableSetOf()) { file -> return findFilesForFacadeByPackage(packageFqName, scope).mapNotNullTo(mutableSetOf()) { file ->
file.takeIf { it.facadeIsPossible() } file.takeIf { it.facadeIsPossible() }
?.takeIf { facadeIsApplicable(it.findModule(), file) } ?.takeIf { it.findModule()?.let { module -> facadeIsApplicable(module, file) } == true }
?.javaFileFacadeFqName ?.javaFileFacadeFqName
?.shortName() ?.shortName()
?.asString() ?.asString()
}.toSet() }.toSet()
} }
private fun Collection<KtFile>.toFacadeClasses(): List<KtLightClassForFacade> = filter { private fun Collection<KtFile>.toFacadeClasses(): List<KtLightClassForFacade> = mapNotNull { file ->
it.facadeIsPossible() file.takeIf { it.facadeIsPossible() }?.findModule()?.let { file to it }
}.groupBy { }.groupBy { (file, module) ->
FacadeKey(it.javaFileFacadeFqName, it.isJvmMultifileClassFile, it.findModule()) FacadeKey(file.javaFileFacadeFqName, file.isJvmMultifileClassFile, module)
}.mapNotNull { (key, files) -> }.mapNotNull { (_, pairs) ->
files.firstOrNull { facadeIsApplicable(key.module, it) }?.let(::getLightFacade) pairs.firstNotNullOfOrNull { (file, module) ->
file.takeIf { facadeIsApplicable(module, file) }
}?.let(::getLightFacade)
} }
private data class FacadeKey<TModule>(val fqName: FqName, val isMultifile: Boolean, val module: TModule) private data class FacadeKey<TModule>(val fqName: FqName, val isMultifile: Boolean, val module: TModule)
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.light.classes.symbol.classes.createSymbolLightClassN
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.parentOrNull import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.platform.has
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -37,6 +39,11 @@ import org.jetbrains.kotlin.psi.KtScript
class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtModule>(project) { class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtModule>(project) {
private val projectStructureProvider by lazy { ProjectStructureProvider.getInstance(project) } private val projectStructureProvider by lazy { ProjectStructureProvider.getInstance(project) }
private fun PsiElement.getModuleIfSupportEnabled(): KtModule? = projectStructureProvider.getModule(
element = this,
contextualModule = null,
).takeIf(KtModule::isLightClassesEnabled)
override fun findClassOrObjectDeclarationsInPackage( override fun findClassOrObjectDeclarationsInPackage(
packageFqName: FqName, packageFqName: FqName,
searchScope: GlobalSearchScope searchScope: GlobalSearchScope
@@ -93,22 +100,18 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
.getKotlinOnlySubPackagesFqNames(fqn, nameFilter = { true }) .getKotlinOnlySubPackagesFqNames(fqn, nameFilter = { true })
.map { fqn.child(it) } .map { fqn.child(it) }
override fun createInstanceOfLightScript(script: KtScript): KtLightClass { override fun createInstanceOfLightScript(script: KtScript): KtLightClass? {
val module = ProjectStructureProvider.getModule(project, script, contextualModule = null) val module = script.getModuleIfSupportEnabled() ?: return null
return SymbolLightClassForScript(script, module) return SymbolLightClassForScript(script, module)
} }
override fun KtFile.findModule(): KtModule { override fun KtFile.findModule(): KtModule? = getModuleIfSupportEnabled()
return projectStructureProvider.getModule(this, contextualModule = null)
}
override fun declarationLocation(file: KtFile): DeclarationLocation? { override fun declarationLocation(file: KtFile): DeclarationLocation? = when (file.getModuleIfSupportEnabled()) {
return when (projectStructureProvider.getModule(file, contextualModule = null)) { is KtSourceModule -> DeclarationLocation.ProjectSources
is KtSourceModule -> DeclarationLocation.ProjectSources is KtLibraryModule -> DeclarationLocation.LibraryClasses
is KtLibraryModule -> DeclarationLocation.LibraryClasses is KtLibrarySourceModule -> DeclarationLocation.LibrarySources
is KtLibrarySourceModule -> DeclarationLocation.LibrarySources else -> null
else -> null
}
} }
override fun createInstanceOfDecompiledLightClass(classOrObject: KtClassOrObject): KtLightClass? { override fun createInstanceOfDecompiledLightClass(classOrObject: KtClassOrObject): KtLightClass? {
@@ -116,7 +119,7 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
} }
override fun createInstanceOfLightClass(classOrObject: KtClassOrObject): KtLightClass? { override fun createInstanceOfLightClass(classOrObject: KtClassOrObject): KtLightClass? {
val module = projectStructureProvider.getModule(classOrObject, contextualModule = null) val module = classOrObject.getModuleIfSupportEnabled() ?: return null
return createSymbolLightClassNoCache(classOrObject, module) return createSymbolLightClassNoCache(classOrObject, module)
} }
@@ -136,14 +139,15 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
return project.createAllLibrariesModificationTracker() return project.createAllLibrariesModificationTracker()
} }
override fun createInstanceOfLightFacade(facadeFqName: FqName, files: List<KtFile>): KtLightClassForFacade { override fun createInstanceOfLightFacade(facadeFqName: FqName, files: List<KtFile>): KtLightClassForFacade? {
val module = projectStructureProvider.getModule(files.first(), contextualModule = null) val module = files.first().getModuleIfSupportEnabled() ?: return null
return SymbolLightClassForFacade(facadeFqName, files, module) return SymbolLightClassForFacade(facadeFqName, files, module)
} }
override val KtModule.contentSearchScope: GlobalSearchScope get() = this.contentScope override val KtModule.contentSearchScope: GlobalSearchScope get() = this.contentScope
override fun facadeIsApplicable(module: KtModule, file: KtFile): Boolean = module.isFromSourceOrLibraryBinary() override fun facadeIsApplicable(module: KtModule, file: KtFile): Boolean =
module.isFromSourceOrLibraryBinary() && module.isLightClassesEnabled()
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> { override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
val facadeKtFiles = project.createDeclarationProvider(scope, null).findInternalFilesForFacade(fqName) val facadeKtFiles = project.createDeclarationProvider(scope, null).findInternalFilesForFacade(fqName)
@@ -176,10 +180,7 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
override fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass = SymbolBasedFakeLightClass(classOrObject) override fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass = SymbolBasedFakeLightClass(classOrObject)
private fun KtElement.isFromSourceOrLibraryBinary(): Boolean { private fun KtElement.isFromSourceOrLibraryBinary(): Boolean = getModuleIfSupportEnabled()?.isFromSourceOrLibraryBinary() == true
val module = projectStructureProvider.getModule(this, contextualModule = null)
return module.isFromSourceOrLibraryBinary()
}
private fun KtModule.isFromSourceOrLibraryBinary() = when (this) { private fun KtModule.isFromSourceOrLibraryBinary() = when (this) {
is KtSourceModule -> true is KtSourceModule -> true
@@ -187,3 +188,5 @@ class SymbolKotlinAsJavaSupport(project: Project) : KotlinAsJavaSupportBase<KtMo
else -> false else -> false
} }
} }
private fun KtModule.isLightClassesEnabled(): Boolean = platform.has<JvmPlatform>()