[lc] introduce KotlinAsJavaSupportBase with new common facade logic
^KT-53543
This commit is contained in:
@@ -11,6 +11,7 @@ import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -21,12 +22,13 @@ abstract class KotlinAsJavaSupport {
|
||||
|
||||
abstract fun getLightClassForScript(script: KtScript): KtLightClass?
|
||||
|
||||
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass
|
||||
|
||||
abstract fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass
|
||||
abstract fun getLightFacade(file: KtFile): KtLightClassForFacade?
|
||||
|
||||
abstract fun createFacadeForSyntheticFile(file: KtFile): KtLightClassForFacade
|
||||
|
||||
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtLightClassForFacade>
|
||||
|
||||
// Returns only immediately declared classes/objects, package classes are not included (they have no declarations)
|
||||
abstract fun findClassOrObjectDeclarationsInPackage(packageFqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
||||
@@ -38,7 +40,11 @@ abstract class KotlinAsJavaSupport {
|
||||
*
|
||||
* If the resulting collection is empty, it means that this package has not other declarations than sub-packages
|
||||
*/
|
||||
abstract fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile>
|
||||
abstract fun findFilesForPackage(packageFqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
abstract fun findFilesForFacade(facadeFqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
abstract fun findFilesForFacadeByPackage(packageFqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
||||
|
||||
@@ -50,12 +56,10 @@ abstract class KotlinAsJavaSupport {
|
||||
|
||||
abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<KtLightClassForFacade>
|
||||
|
||||
abstract fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String>
|
||||
|
||||
abstract fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile>
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project): KotlinAsJavaSupport {
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.asJava
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.fileClasses.isJvmMultifileClassFile
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project) : KotlinAsJavaSupport() {
|
||||
fun createLightFacade(file: KtFile): KtLightClassForFacade? {
|
||||
if (file.isScript()) return null
|
||||
|
||||
val module = file.findModule().takeIf { facadeIsApplicable(it, file) } ?: return null
|
||||
val facadeFqName = file.javaFileFacadeFqName
|
||||
val facadeFiles = if (file.isJvmMultifileClassFile) {
|
||||
findFilesForFacade(facadeFqName, module.contentSearchScope).filter(KtFile::isJvmMultifileClassFile)
|
||||
} else {
|
||||
listOf(file)
|
||||
}
|
||||
|
||||
if (facadeFiles.none(KtFile::hasTopLevelCallables)) return null
|
||||
return when {
|
||||
facadeFiles.none(KtFile::isCompiled) -> createInstanceOfLightFacade(facadeFqName, facadeFiles, module)
|
||||
facadeFiles.all(KtFile::isCompiled) -> createInstanceOfDecompiledLightFacade(facadeFqName, facadeFiles, module)
|
||||
else -> error("Source and compiled files are mixed: $facadeFiles")
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun KtFile.findModule(): TModule
|
||||
abstract fun facadeIsApplicable(module: TModule, file: KtFile): Boolean
|
||||
abstract val TModule.contentSearchScope: GlobalSearchScope
|
||||
|
||||
abstract fun createInstanceOfLightFacade(facadeFqName: FqName, files: List<KtFile>, module: TModule): KtLightClassForFacade
|
||||
abstract fun createInstanceOfDecompiledLightFacade(facadeFqName: FqName, files: List<KtFile>, module: TModule): KtLightClassForFacade?
|
||||
|
||||
override fun createFacadeForSyntheticFile(file: KtFile): KtLightClassForFacade {
|
||||
return createInstanceOfLightFacade(file.javaFileFacadeFqName, listOf(file), file.findModule())
|
||||
}
|
||||
|
||||
override fun getLightFacade(file: KtFile): KtLightClassForFacade? = CachedValuesManager.getCachedValue(file) {
|
||||
CachedValueProvider.Result.create(
|
||||
createLightFacade(file),
|
||||
tracker(file),
|
||||
)
|
||||
}
|
||||
|
||||
open fun tracker(file: KtFile): ModificationTracker {
|
||||
return KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
|
||||
}
|
||||
|
||||
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<KtLightClassForFacade> {
|
||||
return findFilesForFacadeByPackage(packageFqName, scope).toFacadeClasses()
|
||||
}
|
||||
|
||||
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtLightClassForFacade> {
|
||||
return findFilesForFacade(facadeFqName, scope).toFacadeClasses()
|
||||
}
|
||||
|
||||
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> {
|
||||
return findFilesForFacadeByPackage(packageFqName, scope).mapNotNullTo(mutableSetOf()) { file ->
|
||||
file.takeIf { facadeIsApplicable(it.findModule(), file) }?.javaFileFacadeFqName?.shortName()?.asString()
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
private fun Collection<KtFile>.toFacadeClasses(): List<KtLightClassForFacade> = groupBy {
|
||||
FacadeKey(it.javaFileFacadeFqName, it.isJvmMultifileClassFile, it.findModule())
|
||||
}.mapNotNull { (key, files) ->
|
||||
files.firstOrNull { facadeIsApplicable(key.module, it) }?.let(::getLightFacade)
|
||||
}
|
||||
|
||||
private data class FacadeKey<TModule>(val fqName: FqName, val isMultifile: Boolean, val module: TModule)
|
||||
}
|
||||
|
||||
-14
@@ -8,17 +8,11 @@
|
||||
package org.jetbrains.kotlin.asJava.classes
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
|
||||
interface KotlinLightClassFactory {
|
||||
fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration?
|
||||
fun createFacade(project: Project, facadeClassFqName: FqName, searchScope: GlobalSearchScope): KtLightClassForFacade?
|
||||
fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): KtLightClassForFacade
|
||||
fun createScript(script: KtScript): KtLightClassForScript?
|
||||
|
||||
companion object {
|
||||
@@ -29,14 +23,6 @@ interface KotlinLightClassFactory {
|
||||
return instance.createClass(classOrObject)
|
||||
}
|
||||
|
||||
fun createFacade(project: Project, facadeClassFqName: FqName, searchScope: GlobalSearchScope): KtLightClassForFacade? {
|
||||
return instance.createFacade(project, facadeClassFqName, searchScope)
|
||||
}
|
||||
|
||||
fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): KtLightClassForFacade {
|
||||
return instance.createFacadeForSyntheticFile(facadeClassFqName, file)
|
||||
}
|
||||
|
||||
fun createScript(script: KtScript): KtLightClassForScript? {
|
||||
return instance.createScript(script)
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.isJvmMultifileClassFile
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.JvmNames
|
||||
import org.jetbrains.kotlin.name.JvmNames.JVM_NAME_SHORT
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -36,7 +36,7 @@ abstract class KtLightClassForFacadeBase constructor(
|
||||
private val firstFileInFacade by lazyPub { files.first() }
|
||||
|
||||
val isMultiFileClass: Boolean by lazyPub {
|
||||
files.size > 1 || JvmFileClassUtil.findAnnotationEntryOnFileNoResolve(firstFileInFacade, JvmNames.JVM_MULTIFILE_CLASS_SHORT) != null
|
||||
files.size > 1 || firstFileInFacade.isJvmMultifileClassFile
|
||||
}
|
||||
|
||||
private val _modifierList: PsiModifierList by lazyPub {
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -40,9 +39,7 @@ fun KtClassOrObject.toLightClassWithBuiltinMapping(): PsiClass? {
|
||||
|
||||
fun KtClassOrObject.toFakeLightClass(): KtFakeLightClass = KotlinAsJavaSupport.getInstance(project).getFakeLightClass(this)
|
||||
|
||||
fun KtFile.findFacadeClass(): KtLightClass? = KotlinAsJavaSupport.getInstance(project)
|
||||
.getFacadeClassesInPackage(packageFqName, this.useScope as? GlobalSearchScope ?: GlobalSearchScope.projectScope(project))
|
||||
.firstOrNull { it is KtLightClassForFacade && this in it.files } as? KtLightClass
|
||||
fun KtFile.findFacadeClass(): KtLightClass? = KotlinAsJavaSupport.getInstance(project).getLightFacade(this)
|
||||
|
||||
fun KtScript.toLightClass(): KtLightClass? = KotlinAsJavaSupport.getInstance(project).getLightClassForScript(this)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user