LightClassDataHolder: refactor, extract subinterfaces
This commit is contained in:
+4
-2
@@ -76,7 +76,9 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup
|
||||
trace.setKotlinCodeAnalyzer(codeAnalyzer)
|
||||
}
|
||||
|
||||
override fun createDataHolderForClassOrObject(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder {
|
||||
override fun createDataHolderForClass(
|
||||
classOrObject: KtClassOrObject, builder: LightClassBuilder
|
||||
): LightClassDataHolder.ForClass {
|
||||
//force resolve companion for light class generation
|
||||
bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
|
||||
|
||||
@@ -172,7 +174,7 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup
|
||||
}
|
||||
}
|
||||
|
||||
override fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder {
|
||||
override fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade {
|
||||
val (stub, _, diagnostics) = builder(getContext())
|
||||
return LightClassDataHolderImpl(stub, diagnostics)
|
||||
}
|
||||
|
||||
+3
-5
@@ -20,9 +20,7 @@ import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.builder.*
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -36,9 +34,9 @@ typealias LightClassBuilder = (LightClassConstructionContext) -> LightClassBuild
|
||||
|
||||
abstract class LightClassGenerationSupport {
|
||||
|
||||
abstract fun createDataHolderForClassOrObject(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder
|
||||
abstract fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass
|
||||
|
||||
abstract fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder
|
||||
abstract fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade
|
||||
|
||||
abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
||||
|
||||
|
||||
+12
-7
@@ -42,13 +42,18 @@ interface LightClassDataHolder {
|
||||
|
||||
fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass): LightClassData
|
||||
|
||||
fun findDataForDefaultImpls(classOrObject: KtClassOrObject) = findData {
|
||||
it.findDelegate(classOrObject).findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false)
|
||||
?: throw IllegalStateException("Couldn't get delegate for $this\n in ${DebugUtil.stubTreeToString(it)}")
|
||||
interface ForClass : LightClassDataHolder {
|
||||
fun findDataForDefaultImpls(classOrObject: KtClassOrObject) = findData {
|
||||
it.findDelegate(classOrObject).findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false)
|
||||
?: throw IllegalStateException("Couldn't get delegate for $this\n in ${DebugUtil.stubTreeToString(it)}")
|
||||
}
|
||||
|
||||
fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData = findData { it.findDelegate(classOrObject) }
|
||||
}
|
||||
|
||||
fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData = findData { it.findDelegate(classOrObject) }
|
||||
fun findDataForFacade(classFqName: FqName): LightClassData = findData { it.findDelegate(classFqName) }
|
||||
interface ForFacade : LightClassDataHolder {
|
||||
fun findDataForFacade(classFqName: FqName): LightClassData = findData { it.findDelegate(classFqName) }
|
||||
}
|
||||
}
|
||||
|
||||
interface LightClassData {
|
||||
@@ -70,7 +75,7 @@ class LightClassDataImpl(override val clsDelegate: PsiClass) : LightClassData {
|
||||
}
|
||||
}
|
||||
|
||||
object InvalidLightClassDataHolder : LightClassDataHolder {
|
||||
object InvalidLightClassDataHolder : LightClassDataHolder.ForClass {
|
||||
override val javaFileStub: PsiJavaFileStub
|
||||
get() = shouldNotBeCalled()
|
||||
|
||||
@@ -85,7 +90,7 @@ object InvalidLightClassDataHolder : LightClassDataHolder {
|
||||
class LightClassDataHolderImpl(
|
||||
override val javaFileStub: PsiJavaFileStub,
|
||||
override val extraDiagnostics: Diagnostics
|
||||
) : LightClassDataHolder {
|
||||
) : LightClassDataHolder.ForClass, LightClassDataHolder.ForFacade {
|
||||
override fun findData(findDelegate: (PsiJavaFileStub) -> PsiClass) = findDelegate(javaFileStub).let(::LightClassDataImpl)
|
||||
}
|
||||
|
||||
|
||||
+9
-7
@@ -36,12 +36,14 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
|
||||
class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) : CachedValueProvider<LightClassDataHolder> {
|
||||
class LightClassDataProviderForClassOrObject(
|
||||
private val classOrObject: KtClassOrObject
|
||||
) : CachedValueProvider<LightClassDataHolder.ForClass> {
|
||||
|
||||
private fun computeLightClassData(): LightClassDataHolder {
|
||||
private fun computeLightClassData(): LightClassDataHolder.ForClass {
|
||||
val file = classOrObject.containingKtFile
|
||||
val packageFqName = file.packageFqName
|
||||
return LightClassGenerationSupport.getInstance(classOrObject.project).createDataHolderForClassOrObject(classOrObject) {
|
||||
return LightClassGenerationSupport.getInstance(classOrObject.project).createDataHolderForClass(classOrObject) {
|
||||
constructionContext ->
|
||||
buildLightClass(packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) {
|
||||
state, files ->
|
||||
@@ -54,7 +56,7 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
||||
}
|
||||
}
|
||||
|
||||
override fun compute(): CachedValueProvider.Result<LightClassDataHolder>? {
|
||||
override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForClass>? {
|
||||
return CachedValueProvider.Result.create(
|
||||
computeLightClassData(),
|
||||
if (classOrObject.isLocal()) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
@@ -68,10 +70,10 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
|
||||
|
||||
sealed class LightClassDataProviderForFileFacade constructor(
|
||||
protected val project: Project, protected val facadeFqName: FqName
|
||||
) : CachedValueProvider<LightClassDataHolder> {
|
||||
) : CachedValueProvider<LightClassDataHolder.ForFacade> {
|
||||
abstract fun findFiles(): Collection<KtFile>
|
||||
|
||||
private fun computeLightClassData(files: Collection<KtFile>): LightClassDataHolder {
|
||||
private fun computeLightClassData(files: Collection<KtFile>): LightClassDataHolder.ForFacade {
|
||||
return LightClassGenerationSupport.getInstance(project).createDataHolderForFacade(files) {
|
||||
constructionContext ->
|
||||
buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
|
||||
@@ -92,7 +94,7 @@ sealed class LightClassDataProviderForFileFacade constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun compute(): CachedValueProvider.Result<LightClassDataHolder>? {
|
||||
override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForFacade>? {
|
||||
val files = findFiles()
|
||||
if (files.isEmpty()) return null
|
||||
|
||||
|
||||
+6
-7
@@ -32,7 +32,6 @@ import org.jetbrains.annotations.NonNls
|
||||
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.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
@@ -50,17 +49,17 @@ import javax.swing.Icon
|
||||
class KtLightClassForFacade private constructor(
|
||||
manager: PsiManager,
|
||||
private val facadeClassFqName: FqName,
|
||||
private val lightClassDataCache: CachedValue<LightClassDataHolder>,
|
||||
private val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
|
||||
files: Collection<KtFile>
|
||||
) : KtLazyLightClass(manager) {
|
||||
private data class StubCacheKey(val fqName: FqName, val searchScope: GlobalSearchScope)
|
||||
|
||||
class FacadeStubCache(private val project: Project) {
|
||||
private inner class FacadeCacheData {
|
||||
val cache = object : SLRUCache<StubCacheKey, CachedValue<LightClassDataHolder>>(20, 30) {
|
||||
override fun createValue(key: StubCacheKey): CachedValue<LightClassDataHolder> {
|
||||
val cache = object : SLRUCache<StubCacheKey, CachedValue<LightClassDataHolder.ForFacade>>(20, 30) {
|
||||
override fun createValue(key: StubCacheKey): CachedValue<LightClassDataHolder.ForFacade> {
|
||||
val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, key.fqName, key.searchScope)
|
||||
return CachedValuesManager.getManager(project).createCachedValue<LightClassDataHolder>(stubProvider, /*trackValue = */false)
|
||||
return CachedValuesManager.getManager(project).createCachedValue<LightClassDataHolder.ForFacade>(stubProvider, /*trackValue = */false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +68,7 @@ class KtLightClassForFacade private constructor(
|
||||
{ CachedValueProvider.Result.create(FacadeCacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) },
|
||||
/*trackValue = */ false)
|
||||
|
||||
operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<LightClassDataHolder> {
|
||||
operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<LightClassDataHolder.ForFacade> {
|
||||
synchronized (cachedValue) {
|
||||
return cachedValue.value.cache.get(StubCacheKey(qualifiedName, searchScope))
|
||||
}
|
||||
@@ -273,7 +272,7 @@ class KtLightClassForFacade private constructor(
|
||||
): KtLightClassForFacade {
|
||||
// TODO: refactor, using cached value doesn't make sense for this case
|
||||
val cachedValue = CachedValuesManager.getManager(manager.project).
|
||||
createCachedValue<LightClassDataHolder>(
|
||||
createCachedValue<LightClassDataHolder.ForFacade>(
|
||||
LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), /*trackValue = */false
|
||||
)
|
||||
return KtLightClassForFacade(manager, facadeClassFqName, cachedValue, listOf(file))
|
||||
|
||||
+4
-5
@@ -42,7 +42,6 @@ import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightModifierListWithExplicitModifiers
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
|
||||
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -91,7 +90,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
return LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
|
||||
}
|
||||
|
||||
protected fun getLightClassDataHolder(): LightClassDataHolder {
|
||||
protected fun getLightClassDataHolder(): LightClassDataHolder.ForClass {
|
||||
val lightClassData = getLightClassDataHolder(classOrObject)
|
||||
if (lightClassData is InvalidLightClassDataHolder) {
|
||||
LOG.error("Invalid light class data for existing light class:\n$lightClassData\n${classOrObject.getElementTextWithContext()}")
|
||||
@@ -324,7 +323,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
override fun getImplementsList() = _implementsList
|
||||
|
||||
companion object {
|
||||
private val JAVA_API_STUB = Key.create<CachedValue<LightClassDataHolder>>("JAVA_API_STUB")
|
||||
private val JAVA_API_STUB = Key.create<CachedValue<LightClassDataHolder.ForClass>>("JAVA_API_STUB")
|
||||
|
||||
private val jetTokenToPsiModifier = listOf(
|
||||
PUBLIC_KEYWORD to PsiModifier.PUBLIC,
|
||||
@@ -365,11 +364,11 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
|
||||
return classOrObject.getBody()?.declarations?.isEmpty() ?: true
|
||||
}
|
||||
|
||||
fun getLightClassDataHolder(classOrObject: KtClassOrObject): LightClassDataHolder {
|
||||
fun getLightClassDataHolder(classOrObject: KtClassOrObject): LightClassDataHolder.ForClass {
|
||||
return getLightClassCachedValue(classOrObject).value
|
||||
}
|
||||
|
||||
fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder> {
|
||||
fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder.ForClass> {
|
||||
var value =
|
||||
getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB) // stub computed for outer class can be used for inner/nested
|
||||
?: classOrObject.getUserData(JAVA_API_STUB)
|
||||
|
||||
+5
-5
@@ -60,16 +60,16 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
||||
private val psiManager: PsiManager = PsiManager.getInstance(project)
|
||||
|
||||
override fun createDataHolderForClassOrObject(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder {
|
||||
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
||||
return if (classOrObject.isLocal) {
|
||||
LazyLightClassDataHolder(
|
||||
LazyLightClassDataHolder.ForClass(
|
||||
builder,
|
||||
exactContextProvider = { IDELightClassContexts.contextForLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = null
|
||||
)
|
||||
}
|
||||
else {
|
||||
LazyLightClassDataHolder(
|
||||
LazyLightClassDataHolder.ForClass(
|
||||
builder,
|
||||
exactContextProvider = { IDELightClassContexts.contextForNonLocalClassOrObject(classOrObject) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForClassOrObject(classOrObject) }
|
||||
@@ -78,12 +78,12 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
|
||||
|
||||
override fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder {
|
||||
override fun createDataHolderForFacade(files: Collection<KtFile>, builder: LightClassBuilder): LightClassDataHolder.ForFacade {
|
||||
assert(!files.isEmpty()) { "No files in facade" }
|
||||
|
||||
val sortedFiles = files.sortedWith(scopeFileComparator)
|
||||
|
||||
return LazyLightClassDataHolder(
|
||||
return LazyLightClassDataHolder.ForFacade(
|
||||
builder,
|
||||
exactContextProvider = { IDELightClassContexts.contextForFacade(sortedFiles) },
|
||||
dummyContextProvider = { IDELightClassContexts.lightContextForFacade(sortedFiles) }
|
||||
|
||||
+13
-5
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
typealias LightClassContextProvider = () -> LightClassConstructionContext
|
||||
|
||||
class LazyLightClassDataHolder(
|
||||
sealed class LazyLightClassDataHolder(
|
||||
builder: LightClassBuilder,
|
||||
exactContextProvider: LightClassContextProvider,
|
||||
dummyContextProvider: LightClassContextProvider?
|
||||
@@ -57,10 +57,18 @@ class LazyLightClassDataHolder(
|
||||
findDelegate(lightClassBuilderResult.stub)
|
||||
}
|
||||
|
||||
override fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData =
|
||||
LazyLightClassData(relyOnDummySupertypes = classOrObject.getSuperTypeList() == null) { lightClassBuilderResult ->
|
||||
lightClassBuilderResult.stub.findDelegate(classOrObject)
|
||||
}
|
||||
class ForClass(
|
||||
builder: LightClassBuilder, exactContextProvider: LightClassContextProvider, dummyContextProvider: LightClassContextProvider?
|
||||
) : LazyLightClassDataHolder(builder, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForClass {
|
||||
override fun findDataForClassOrObject(classOrObject: KtClassOrObject): LightClassData =
|
||||
LazyLightClassData(relyOnDummySupertypes = classOrObject.getSuperTypeList() == null) { lightClassBuilderResult ->
|
||||
lightClassBuilderResult.stub.findDelegate(classOrObject)
|
||||
}
|
||||
}
|
||||
|
||||
class ForFacade(
|
||||
builder: LightClassBuilder, exactContextProvider: LightClassContextProvider, dummyContextProvider: LightClassContextProvider?
|
||||
) : LazyLightClassDataHolder(builder, exactContextProvider, dummyContextProvider), LightClassDataHolder.ForFacade
|
||||
|
||||
private inner class LazyLightClassData(
|
||||
private val relyOnDummySupertypes: Boolean,
|
||||
|
||||
Reference in New Issue
Block a user