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
This commit is contained in:
Pavel V. Talanov
2015-12-28 20:09:20 +03:00
parent b38fc7b3c1
commit 9096a443ea
4 changed files with 39 additions and 17 deletions
@@ -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<out KtClassOrObject>? = classOrObject.stub
companion object {
private val JAVA_API_STUB = Key.create<CachedValue<OutermostKotlinClassLightClassData>>("JAVA_API_STUB")
private val JAVA_API_STUB = Key.create<CachedValue<WithFileStubAndExtraDiagnostics>>("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<OutermostKotlinClassLightClassData> {
public fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<WithFileStubAndExtraDiagnostics> {
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)
}
}
@@ -70,6 +70,13 @@ abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
abstract val isLocal: Boolean
override fun compute(): CachedValueProvider.Result<T>? {
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<T : WithFileStubAndExtraDiagnostics>(
}
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<T : WithFileStubAndExtraDiagnostics>(
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<KtFile>): PsiJavaFileStub {
@@ -167,7 +170,7 @@ abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
}
class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) :
LightClassDataProvider<OutermostKotlinClassLightClassData>(classOrObject.project) {
LightClassDataProvider<WithFileStubAndExtraDiagnostics>(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<KtClassOrObject, InnerKotlinClassLightClassData>())
extraDiagnostics: Diagnostics): WithFileStubAndExtraDiagnostics {
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassData
val fqName = predictClassFqName(bindingContext, classDescriptor)
val allInnerClasses = CodegenBinding.getAllInnerClasses(bindingContext, classDescriptor)
@@ -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
@@ -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? {