[light classes] extract KotlinLightClassFactory to service
^KT-53097
This commit is contained in:
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.cli.jvm.compiler
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.PsiSearchScopeUtil
|
import com.intellij.psi.search.PsiSearchScopeUtil
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
@@ -27,16 +26,14 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
|
||||||
class CliKotlinAsJavaSupport(
|
class CliKotlinAsJavaSupport(
|
||||||
project: Project,
|
private val project: Project,
|
||||||
private val traceHolder: CliTraceHolder
|
private val traceHolder: CliTraceHolder
|
||||||
) : KotlinAsJavaSupport() {
|
) : KotlinAsJavaSupport() {
|
||||||
private val psiManager = PsiManager.getInstance(project)
|
|
||||||
|
|
||||||
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||||
return findFacadeFilesInPackage(packageFqName, scope)
|
return findFacadeFilesInPackage(packageFqName, scope)
|
||||||
.groupBy { it.javaFileFacadeFqName }
|
.groupBy { it.javaFileFacadeFqName }
|
||||||
.mapNotNull { (facadeClassFqName, _) ->
|
.mapNotNull { (facadeClassFqName, _) ->
|
||||||
KotlinLightClassFactory.createFacade(psiManager, facadeClassFqName, scope)
|
KotlinLightClassFactory.createFacade(project, facadeClassFqName, scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +50,7 @@ class CliKotlinAsJavaSupport(
|
|||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
||||||
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||||
return listOfNotNull(KotlinLightClassFactory.createFacade(psiManager, facadeFqName, scope))
|
return listOfNotNull(KotlinLightClassFactory.createFacade(project, facadeFqName, scope))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ import org.jetbrains.annotations.TestOnly
|
|||||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.FacadeCache
|
import org.jetbrains.kotlin.asJava.classes.FacadeCache
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KotlinK1LightClassFactory
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KotlinLightClassFactory
|
||||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
import org.jetbrains.kotlin.cli.common.*
|
import org.jetbrains.kotlin.cli.common.*
|
||||||
@@ -63,8 +65,8 @@ import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver
|
|||||||
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtension
|
import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtension
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
|
||||||
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
|
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||||
import org.jetbrains.kotlin.compiler.plugin.registerInProject
|
import org.jetbrains.kotlin.compiler.plugin.registerInProject
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.extensions.*
|
import org.jetbrains.kotlin.extensions.*
|
||||||
@@ -673,6 +675,7 @@ class KotlinCoreEnvironment private constructor(
|
|||||||
// ability to get text from annotations xml files
|
// ability to get text from annotations xml files
|
||||||
applicationEnvironment.registerFileType(PlainTextFileType.INSTANCE, "xml")
|
applicationEnvironment.registerFileType(PlainTextFileType.INSTANCE, "xml")
|
||||||
applicationEnvironment.registerParserDefinition(JavaParserDefinition())
|
applicationEnvironment.registerParserDefinition(JavaParserDefinition())
|
||||||
|
applicationEnvironment.registerApplicationService(KotlinLightClassFactory::class.java, KotlinK1LightClassFactory())
|
||||||
}
|
}
|
||||||
|
|
||||||
// made public for Upsource
|
// made public for Upsource
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
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 {
|
||||||
|
private val instance: KotlinLightClassFactory
|
||||||
|
get() = ServiceManager.getService(KotlinLightClassFactory::class.java)
|
||||||
|
|
||||||
|
fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ class FacadeCache(private val project: Project) {
|
|||||||
private inner class FacadeCacheData {
|
private inner class FacadeCacheData {
|
||||||
val cache = object : SLRUCache<FacadeCacheKey, ValueWrapper>(20, 30) {
|
val cache = object : SLRUCache<FacadeCacheKey, ValueWrapper>(20, 30) {
|
||||||
override fun createValue(key: FacadeCacheKey): ValueWrapper =
|
override fun createValue(key: FacadeCacheKey): ValueWrapper =
|
||||||
KotlinLightClassFactory.createFacadeNoCache(key.fqName, key.searchScope, project)
|
KotlinK1LightClassFactory.createFacadeNoCache(key.fqName, key.searchScope, project)
|
||||||
?.let { ValueWrapper(it) }
|
?.let { ValueWrapper(it) }
|
||||||
?: ValueWrapper.Null
|
?: ValueWrapper.Null
|
||||||
}
|
}
|
||||||
|
|||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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.classes
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiManager
|
||||||
|
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.KotlinAsJavaSupport
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
|
|
||||||
|
class KotlinK1LightClassFactory : KotlinLightClassFactory {
|
||||||
|
override fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? =
|
||||||
|
CachedValuesManager.getCachedValue(classOrObject) {
|
||||||
|
CachedValueProvider.Result.create(
|
||||||
|
createClassNoCache(classOrObject),
|
||||||
|
KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createFacade(
|
||||||
|
project: Project,
|
||||||
|
facadeClassFqName: FqName,
|
||||||
|
searchScope: GlobalSearchScope,
|
||||||
|
): KtLightClassForFacade? = FacadeCache.getInstance(project)[facadeClassFqName, searchScope]
|
||||||
|
|
||||||
|
override fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): KtLightClassForFacade {
|
||||||
|
val project = file.project
|
||||||
|
val manager = PsiManager.getInstance(project)
|
||||||
|
return LightClassGenerationSupport.getInstance(project).run {
|
||||||
|
createUltraLightClassForFacade(manager, facadeClassFqName, listOf(file)) ?: error { "Unable to create UL class for facade" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createScript(script: KtScript): KtLightClassForScript? = CachedValuesManager.getCachedValue(script) {
|
||||||
|
CachedValueProvider.Result.create(
|
||||||
|
createScriptNoCache(script),
|
||||||
|
KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun createScriptNoCache(script: KtScript): KtLightClassForScript? {
|
||||||
|
val containingFile = script.containingFile
|
||||||
|
if (containingFile is KtCodeFragment) {
|
||||||
|
// Avoid building light classes for code fragments
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return LightClassGenerationSupport.getInstance(script.project).run {
|
||||||
|
createUltraLightClassForScript(script)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createClassNoCache(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? {
|
||||||
|
val containingFile = classOrObject.containingFile
|
||||||
|
if (containingFile is KtCodeFragment) {
|
||||||
|
// Avoid building light classes for code fragments
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classOrObject.shouldNotBeVisibleAsLightClass()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return LightClassGenerationSupport.getInstance(classOrObject.project).run {
|
||||||
|
createUltraLightClass(classOrObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createFacadeNoCache(fqName: FqName, searchScope: GlobalSearchScope, project: Project): KtLightClassForFacade? {
|
||||||
|
val sources = KotlinAsJavaSupport.getInstance(project)
|
||||||
|
.findFilesForFacade(fqName, searchScope)
|
||||||
|
.filterNot { it.isCompiled || it.isScript() }
|
||||||
|
|
||||||
|
if (sources.isEmpty()) return null
|
||||||
|
val manager = PsiManager.getInstance(project)
|
||||||
|
return LightClassGenerationSupport.getInstance(project).run {
|
||||||
|
if (!canCreateUltraLightClassForFacade(sources)) return null
|
||||||
|
createUltraLightClassForFacade(manager, fqName, sources)
|
||||||
|
?: error("Unable to create UL class for facade: $fqName for ${sources.joinToString { it.virtualFilePath }}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-101
@@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.asJava.classes
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
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.KotlinAsJavaSupport
|
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
|
||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
import org.jetbrains.kotlin.psi.KtScript
|
|
||||||
|
|
||||||
object KotlinLightClassFactory {
|
|
||||||
fun createClass(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? =
|
|
||||||
CachedValuesManager.getCachedValue(classOrObject) {
|
|
||||||
CachedValueProvider.Result.create(
|
|
||||||
createClassNoCache(classOrObject),
|
|
||||||
KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createClassNoCache(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? {
|
|
||||||
val containingFile = classOrObject.containingFile
|
|
||||||
if (containingFile is KtCodeFragment) {
|
|
||||||
// Avoid building light classes for code fragments
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (classOrObject.shouldNotBeVisibleAsLightClass()) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return LightClassGenerationSupport.getInstance(classOrObject.project).run {
|
|
||||||
createUltraLightClass(classOrObject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createFacadeNoCache(fqName: FqName, searchScope: GlobalSearchScope, project: Project): KtLightClassForFacade? {
|
|
||||||
val sources = KotlinAsJavaSupport.getInstance(project)
|
|
||||||
.findFilesForFacade(fqName, searchScope)
|
|
||||||
.filterNot { it.isCompiled || it.isScript() }
|
|
||||||
|
|
||||||
if (sources.isEmpty()) return null
|
|
||||||
val manager = PsiManager.getInstance(project)
|
|
||||||
return LightClassGenerationSupport.getInstance(project).run {
|
|
||||||
if (!canCreateUltraLightClassForFacade(sources)) return null
|
|
||||||
createUltraLightClassForFacade(manager, fqName, sources)
|
|
||||||
?: error("Unable to create UL class for facade: $fqName for ${sources.joinToString { it.virtualFilePath }}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createFacade(
|
|
||||||
manager: PsiManager,
|
|
||||||
facadeClassFqName: FqName,
|
|
||||||
searchScope: GlobalSearchScope
|
|
||||||
): KtLightClassForFacade? {
|
|
||||||
return FacadeCache.getInstance(manager.project)[facadeClassFqName, searchScope]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createFacadeForSyntheticFile(
|
|
||||||
facadeClassFqName: FqName,
|
|
||||||
file: KtFile
|
|
||||||
): KtLightClassForFacade {
|
|
||||||
val project = file.project
|
|
||||||
val manager = PsiManager.getInstance(project)
|
|
||||||
return LightClassGenerationSupport.getInstance(project).run {
|
|
||||||
createUltraLightClassForFacade(manager, facadeClassFqName, listOf(file)) ?: error { "Unable to create UL class for facade" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createScript(script: KtScript): KtLightClassForScript? =
|
|
||||||
CachedValuesManager.getCachedValue(script) {
|
|
||||||
CachedValueProvider.Result.create(
|
|
||||||
createScriptNoCache(script),
|
|
||||||
KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createScriptNoCache(script: KtScript): KtLightClassForScript? {
|
|
||||||
val containingFile = script.containingFile
|
|
||||||
if (containingFile is KtCodeFragment) {
|
|
||||||
// Avoid building light classes for code fragments
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return LightClassGenerationSupport.getInstance(script.project).run {
|
|
||||||
createUltraLightClassForScript(script)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user