Add ultraKtLightClassForFacade multifile support

This commit is contained in:
Igor Yakovlev
2019-05-23 16:27:57 +03:00
parent 86e9018f49
commit 24253e21d0
5 changed files with 54 additions and 42 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValue
import org.jetbrains.kotlin.asJava.LightClassBuilder
@@ -45,9 +46,10 @@ import org.jetbrains.kotlin.resolve.BindingContext
class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : LightClassGenerationSupport() {
override fun createUltraLightClassForFacade(
manager: PsiManager,
facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
facadeFile: KtFile
files: Collection<KtFile>
): KtUltraLightClassForFacade? = null
override fun createUltraLightClass(element: KtClassOrObject) = null
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.asJava
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValue
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
@@ -50,9 +51,10 @@ abstract class LightClassGenerationSupport {
abstract fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass?
abstract fun createUltraLightClassForFacade(
manager: PsiManager,
facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
facadeFile: KtFile
files: Collection<KtFile>
): KtUltraLightClassForFacade?
companion object {
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.codegen.inline.getOrPut
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.KotlinLanguage
@@ -266,23 +267,14 @@ open class KtLightClassForFacade protected constructor(
val ultraLightEnabled =
!KtUltraLightSupport.forceUsingOldLightClasses && Registry.`is`("kotlin.use.ultra.light.classes", true)
if (ultraLightEnabled && files.count() == 1) {
val facadeFile = files.first()
return CachedValuesManager.getCachedValue(facadeFile) {
val lightClassDataCache = FacadeStubCache.getInstance(manager.project).get(facadeClassFqName, searchScope)
val classForFacade = LightClassGenerationSupport.getInstance(facadeFile.project)
.createUltraLightClassForFacade(facadeClassFqName, lightClassDataCache, facadeFile)
?: KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
CachedValueProvider.Result.create(classForFacade, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
}
}
val lightClassDataCache = FacadeStubCache.getInstance(manager.project).get(facadeClassFqName, searchScope)
return KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
val ultraLightClass = if (ultraLightEnabled)
LightClassGenerationSupport.getInstance(manager.project)
.createUltraLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
else null
return ultraLightClass ?: KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
}
fun createForSyntheticFile(
@@ -20,11 +20,9 @@ class KtUltraLightClassForFacade(
manager: PsiManager,
facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
private val file: KtFile,
private val support: KtUltraLightSupport
) : KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, listOf(file)) {
private val membersBuilder by lazyPub { UltraLightMembersCreator(this, false, true, support) }
files: Collection<KtFile>,
private val filesToSupports: Collection<Pair<KtFile, KtUltraLightSupport>>
) : KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files) {
private inline fun <T> forTooComplex(getter: () -> T): T {
check(tooComplex) {
@@ -39,17 +37,30 @@ class KtUltraLightClassForFacade(
override val clsDelegate: PsiClass
get() = forTooComplex { super.clsDelegate }
private val tooComplex: Boolean by lazyPub { file.declarations.any { support.isTooComplexForUltraLightGeneration(it) } }
private val tooComplex: Boolean by lazyPub {
filesToSupports.any { (file, support) ->
file.declarations.any { support.isTooComplexForUltraLightGeneration(it) }
}
}
private val filesToSupportsToMemberCreators by lazyPub {
filesToSupports.map { (file, support) ->
Triple(file, support, UltraLightMembersCreator(this, false, true, support))
}
}
private val ownMethodsForNotTooComplex: List<KtLightMethod> by lazyPub {
val result = arrayListOf<KtLightMethod>()
for (declaration in file.declarations.filterNot { it.isHiddenByDeprecation(support) }) {
if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) continue
when (declaration) {
is KtNamedFunction -> result.addAll(membersBuilder.createMethods(declaration, true))
is KtProperty -> result.addAll(membersBuilder.propertyAccessors(declaration, declaration.isVar, true, false))
for ((file, support, creator) in filesToSupportsToMemberCreators) {
for (declaration in file.declarations.filterNot { it.isHiddenByDeprecation(support) }) {
if (declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) continue
when (declaration) {
is KtNamedFunction -> result.addAll(creator.createMethods(declaration, true))
is KtProperty -> result.addAll(creator.propertyAccessors(declaration, declaration.isVar, true, false))
}
}
}
@@ -57,9 +68,11 @@ class KtUltraLightClassForFacade(
}
private val ownFieldsForNotTooComplex: List<KtLightField> by lazyPub {
hashSetOf<String>().run {
file.declarations.filterIsInstance<KtProperty>().mapNotNull {
membersBuilder.createPropertyField(it, this, forceStatic = true)
hashSetOf<String>().let { nameCache ->
filesToSupportsToMemberCreators.flatMap { (file, support, creator) ->
file.declarations.filterIsInstance<KtProperty>().mapNotNull {
creator.createPropertyField(it, nameCache, forceStatic = true)
}
}
}
}
@@ -68,8 +81,6 @@ class KtUltraLightClassForFacade(
override fun getOwnMethods() = if (!tooComplex) ownMethodsForNotTooComplex else super.getOwnMethods()
override fun toString(): String = "UltraLight class for file facade"
override fun copy(): KtLightClassForFacade = KtUltraLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, file, support)
override fun copy(): KtLightClassForFacade =
KtUltraLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files, filesToSupports)
}
@@ -60,6 +60,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.keysToMap
import java.util.concurrent.ConcurrentMap
class IDELightClassGenerationSupport(private val project: Project) : LightClassGenerationSupport() {
@@ -178,21 +179,25 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
}
override fun createUltraLightClassForFacade(
manager: PsiManager,
facadeClassFqName: FqName,
lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
facadeFile: KtFile
files: Collection<KtFile>
): KtUltraLightClassForFacade? {
if (facadeFile.isScript()) return null
if (files.any { it.isScript() }) return null
val module = ModuleUtilCore.findModuleForPsiElement(facadeFile) ?: return null
val filesToSupports: List<Pair<KtFile, KtUltraLightSupport>> = files.map {
val module = ModuleUtilCore.findModuleForPsiElement(it) ?: return null
it to KtUltraLightSupportImpl(it, module)
}
return KtUltraLightClassForFacade(
facadeFile.manager,
manager,
facadeClassFqName,
lightClassDataCache,
facadeFile,
KtUltraLightSupportImpl(facadeFile, module)
files,
filesToSupports
)
}