From 9096a443eae22ad901faf0e456562cc26607dd79 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 28 Dec 2015 20:09:20 +0300 Subject: [PATCH] Do not build light classes for local classes when the there is no class descriptor These cases should be dealt with and this is only a way to degrade gracefully --- .../KtLightClassForExplicitDeclaration.kt | 18 +++++++++++----- .../kotlin/asJava/LightClassDataProvider.kt | 21 ++++++++++--------- .../kotlin/asJava/LightClassStubWithData.kt | 15 ++++++++++++- .../asJava/duplicateJvmSignatureUtil.kt | 2 +- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt index 07f962d5144..423d95d2f52 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.asJava +import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.Comparing import com.intellij.openapi.util.Key import com.intellij.psi.* @@ -41,6 +42,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -172,7 +174,11 @@ public open class KtLightClassForExplicitDeclaration( } private fun getLightClassData(): OutermostKotlinClassLightClassData { - return getLightClassData(classOrObject) + val lightClassData = getLightClassData(classOrObject) + if (lightClassData !is OutermostKotlinClassLightClassData) { + LOG.error("Invalid light class data for existing light class:\n$lightClassData\n${classOrObject.getElementTextWithContext()}") + } + return lightClassData as OutermostKotlinClassLightClassData } private val _containingFile: PsiFile by lazy { @@ -380,7 +386,7 @@ public open class KtLightClassForExplicitDeclaration( override fun getStub(): KotlinClassOrObjectStub? = classOrObject.stub 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, @@ -408,11 +414,11 @@ public open class KtLightClassForExplicitDeclaration( return if (internalName == null) null else JvmClassName.byInternalName(internalName).fqNameForClassNameWithoutDollars } - public fun getLightClassData(classOrObject: KtClassOrObject): OutermostKotlinClassLightClassData { + public fun getLightClassData(classOrObject: KtClassOrObject): LightClassData { return getLightClassCachedValue(classOrObject).value } - public fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue { + public fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue { val outermostClassOrObject = getOutermostClassOrObject(classOrObject) var value = outermostClassOrObject.getUserData(JAVA_API_STUB) if (value == null) { @@ -424,7 +430,7 @@ public open class KtLightClassForExplicitDeclaration( } private fun getLightClassDataExactly(classOrObject: KtClassOrObject): LightClassDataForKotlinClass? { - val data = getLightClassData(classOrObject) + val data = getLightClassData(classOrObject) as? OutermostKotlinClassLightClassData ?: return null return data.dataForClass(classOrObject) } @@ -462,5 +468,7 @@ public open class KtLightClassForExplicitDeclaration( return false } + + private val LOG = Logger.getInstance(KtLightClassForExplicitDeclaration::class.java) } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt index 792031b7a73..9bc233140db 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt @@ -70,6 +70,13 @@ abstract class LightClassDataProvider( abstract val isLocal: Boolean override fun compute(): CachedValueProvider.Result? { + return CachedValueProvider.Result.create( + computeLightClassData(), + if (isLocal) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT + ) + } + + private fun computeLightClassData(): T { val packageFqName = packageFqName val files = files @@ -110,6 +117,7 @@ abstract class LightClassDataProvider( } ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub) + return createLightClassData(javaFileStub, bindingContext, state.collectedExtraJvmDiagnostics) } catch (e: ProcessCanceledException) { throw e @@ -118,11 +126,6 @@ abstract class LightClassDataProvider( logErrorWithOSInfo(e, packageFqName, null) throw e } - - return CachedValueProvider.Result.create( - createLightClassData(javaFileStub, bindingContext, state.collectedExtraJvmDiagnostics), - if (isLocal) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT - ) } private fun createJavaFileStub(packageFqName: FqName, files: Collection): PsiJavaFileStub { @@ -167,7 +170,7 @@ abstract class LightClassDataProvider( } class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) : - LightClassDataProvider(classOrObject.project) { + LightClassDataProvider(classOrObject.project) { private val file: KtFile get() = classOrObject.getContainingKtFile() @@ -181,10 +184,8 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO override fun createLightClassData( javaFileStub: PsiJavaFileStub, bindingContext: BindingContext, - extraDiagnostics: Diagnostics): OutermostKotlinClassLightClassData { - val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject) ?: return OutermostKotlinClassLightClassData( - javaFileStub, extraDiagnostics, FqName.ROOT, classOrObject, - emptyMap()) + extraDiagnostics: Diagnostics): WithFileStubAndExtraDiagnostics { + val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassData val fqName = predictClassFqName(bindingContext, classDescriptor) val allInnerClasses = CodegenBinding.getAllInnerClasses(bindingContext, classDescriptor) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassStubWithData.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassStubWithData.kt index 39dbf047181..be5d46cd2c5 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassStubWithData.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassStubWithData.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics interface LightClassData -interface WithFileStubAndExtraDiagnostics { +interface WithFileStubAndExtraDiagnostics: LightClassData { val javaFileStub: PsiJavaFileStub val extraDiagnostics: Diagnostics } @@ -33,6 +33,19 @@ interface LightClassDataForKotlinClass: LightClassData { val jvmQualifiedName: FqName } +object InvalidLightClassData: WithFileStubAndExtraDiagnostics, LightClassDataForKotlinClass { + override val javaFileStub: PsiJavaFileStub + get() = shouldNotBeCalled() + override val extraDiagnostics: Diagnostics + get() = shouldNotBeCalled() + override val classOrObject: KtClassOrObject + get() = shouldNotBeCalled() + override val jvmQualifiedName: FqName + get() = shouldNotBeCalled() + + private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called") +} + data class KotlinFacadeLightClassData( override val javaFileStub: PsiJavaFileStub, override val extraDiagnostics: Diagnostics diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt index 26d341fa279..ddc31d1be6a 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/duplicateJvmSignatureUtil.kt @@ -39,7 +39,7 @@ public fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Dia } fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics { - return KtLightClassForExplicitDeclaration.getLightClassData(ktClassOrObject).extraDiagnostics + return (KtLightClassForExplicitDeclaration.getLightClassData(ktClassOrObject) as? OutermostKotlinClassLightClassData)?.extraDiagnostics ?: Diagnostics.EMPTY } fun doGetDiagnostics(): Diagnostics? {