From 04591bb938efd5c23373bf6802988b9456b22789 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 15 Mar 2017 14:36:16 +0300 Subject: [PATCH] LightClassDataHolder: refactor, extract subinterfaces --- .../CliLightClassGenerationSupport.kt | 6 ++++-- .../asJava/LightClassGenerationSupport.kt | 8 +++----- .../asJava/builder/LightClassDataHolder.kt | 19 ++++++++++++------- .../asJava/builder/LightClassDataProvider.kt | 16 +++++++++------- .../asJava/classes/KtLightClassForFacade.kt | 13 ++++++------- .../KtLightClassForSourceDeclaration.kt | 9 ++++----- .../resolve/IDELightClassGenerationSupport.kt | 10 +++++----- .../lightClasses/LazyLightClassDataHolder.kt | 18 +++++++++++++----- 8 files changed, 56 insertions(+), 43 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt index 51627e655c4..14b7cf9708f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt @@ -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, builder: LightClassBuilder): LightClassDataHolder { + override fun createDataHolderForFacade(files: Collection, builder: LightClassBuilder): LightClassDataHolder.ForFacade { val (stub, _, diagnostics) = builder(getContext()) return LightClassDataHolderImpl(stub, diagnostics) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt index 207467c489e..9808b591f14 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt @@ -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, builder: LightClassBuilder): LightClassDataHolder + abstract fun createDataHolderForFacade(files: Collection, builder: LightClassBuilder): LightClassDataHolder.ForFacade abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt index 486fc5e3e60..ffef15dbdf0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataHolder.kt @@ -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) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataProvider.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataProvider.kt index 3dae9966d2f..8ff3af30e02 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataProvider.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassDataProvider.kt @@ -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 { +class LightClassDataProviderForClassOrObject( + private val classOrObject: KtClassOrObject +) : CachedValueProvider { - 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? { + override fun compute(): CachedValueProvider.Result? { 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 { +) : CachedValueProvider { abstract fun findFiles(): Collection - private fun computeLightClassData(files: Collection): LightClassDataHolder { + private fun computeLightClassData(files: Collection): 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? { + override fun compute(): CachedValueProvider.Result? { val files = findFiles() if (files.isEmpty()) return null diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt index 58e1b54aea6..9684f618fe0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt @@ -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, + private val lightClassDataCache: CachedValue, files: Collection ) : 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>(20, 30) { - override fun createValue(key: StubCacheKey): CachedValue { + val cache = object : SLRUCache>(20, 30) { + override fun createValue(key: StubCacheKey): CachedValue { val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, key.fqName, key.searchScope) - return CachedValuesManager.getManager(project).createCachedValue(stubProvider, /*trackValue = */false) + return CachedValuesManager.getManager(project).createCachedValue(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 { + operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue { 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( + createCachedValue( LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), /*trackValue = */false ) return KtLightClassForFacade(manager, facadeClassFqName, cachedValue, listOf(file)) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index e8f86fac882..97aeb7272d3 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -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>("JAVA_API_STUB") + private val JAVA_API_STUB = Key.create>("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 { + fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue { var value = getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB) // stub computed for outer class can be used for inner/nested ?: classOrObject.getUserData(JAVA_API_STUB) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt index 924070e3d5c..a20de69d60a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt @@ -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, builder: LightClassBuilder): LightClassDataHolder { + override fun createDataHolderForFacade(files: Collection, 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) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LazyLightClassDataHolder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LazyLightClassDataHolder.kt index 0c60af0f5c7..3c9cfe7e59f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LazyLightClassDataHolder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/LazyLightClassDataHolder.kt @@ -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,