[light classes] introduce KotlinLightClassFactory

^KT-53097
This commit is contained in:
Dmitry Gridin
2022-07-08 18:48:17 +02:00
committed by Space
parent 52e0e744af
commit 9510c4876c
7 changed files with 49 additions and 36 deletions
@@ -108,7 +108,7 @@ class CliKotlinAsJavaSupport(
).mapNotNull { member -> (member as? PackageViewDescriptor)?.fqName }
}
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = KtLightClassImpl.create(classOrObject)
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = KotlinLightClassFactory.createClass(classOrObject)
override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = KtLightClassForScript.create(script)
@@ -0,0 +1,41 @@
/*
* 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.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtCodeFragment
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)
}
}
}
@@ -85,7 +85,7 @@ abstract class KtLightClassForScript(val script: KtScript) : KtLightClassBase(sc
// inner classes with null names can't be searched for and can't be used from java anyway
// we can't prohibit creating light classes with null names either since they can contain members
.filter { it.name != null }
.mapNotNull { KtLightClassImpl.create(it) }
.mapNotNull { KotlinLightClassFactory.createClass(it) }
}
override fun getInitializers(): Array<PsiClassInitializer> = PsiClassInitializer.EMPTY_ARRAY
@@ -8,9 +8,6 @@ package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.scope.PsiScopeProcessor
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
@@ -22,7 +19,6 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.resolve.DescriptorUtils
private class KtLightClassModifierList(containingClass: KtLightClassForSourceDeclaration, computeModifiers: () -> Set<String>) :
@@ -138,7 +134,7 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
private val _containingFile: PsiFile by lazyPub {
object : FakeFileForLightClass(
classOrObject.containingKtFile,
{ if (classOrObject.isTopLevel()) this else create(getOutermostClassOrObject(classOrObject))!! },
{ if (classOrObject.isTopLevel()) this else KotlinLightClassFactory.createClass(getOutermostClassOrObject(classOrObject))!! },
) {
override fun findReferenceAt(offset: Int) = ktFile.findReferenceAt(offset)
@@ -173,7 +169,7 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
// we can't prohibit creating light classes with null names either since they can contain members
.filter { it.name != null }
.mapNotNullTo(result) {
create(it)
KotlinLightClassFactory.createClass(it)
}
if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) {
@@ -190,7 +186,7 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
val containingClassOrObject = (classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject
if (containingClassOrObject != null) {
return create(containingClassOrObject)
return KotlinLightClassFactory.createClass(containingClassOrObject)
}
// TODO: should return null
@@ -234,29 +230,5 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
KtTokens.PROTECTED_KEYWORD to PsiModifier.PROTECTED,
KtTokens.FINAL_KEYWORD to PsiModifier.FINAL,
)
fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? =
CachedValuesManager.getCachedValue(classOrObject) {
CachedValueProvider.Result.create(
createNoCache(classOrObject),
KotlinModificationTrackerService.getInstance(classOrObject.project).outOfBlockModificationTracker,
)
}
private fun createNoCache(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)
}
}
}
}
@@ -59,7 +59,7 @@ class KtUltraLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject,
override fun setName(name: String): PsiElement =
throw IncorrectOperationException("Impossible to rename ${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}")
override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject)
override fun getContainingClass(): KtLightClassForSourceDeclaration? = KotlinLightClassFactory.createClass(classOrObject)
override fun getOwnInnerClasses() = emptyList<PsiClass>()
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value
@@ -22,7 +22,7 @@ class KtUltraLightClassForRepeatableAnnotationContainer(classOrObject: KtClassOr
override fun getParent() = containingClass
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject)
override fun getContainingClass(): KtLightClassForSourceDeclaration? = KotlinLightClassFactory.createClass(classOrObject)
override fun getScope(): PsiElement? = containingClass
override fun getOwnInnerClasses() = emptyList<PsiClass>()
override fun getOwnFields(): List<KtLightField> = emptyList()
@@ -485,7 +485,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
val containingBody = classOrObject.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject
containingClass?.let { return create(it) }
containingClass?.let { return KotlinLightClassFactory.createClass(it) }
val containingBlock = classOrObject.parent as? KtBlockExpression
val containingScript = containingBlock?.parent as? KtScript