Try to diagnose NoDescriptorForDeclarationException in completion

This commit is contained in:
Pavel V. Talanov
2016-01-20 17:21:08 +03:00
parent 55b7e4bbf0
commit 16ab4bec34
8 changed files with 64 additions and 15 deletions
@@ -22,12 +22,8 @@ import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.lazy.NoTopLevelDescriptorProvider
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
@@ -90,6 +86,7 @@ fun createContainerForLazyBodyResolve(
useInstance(kotlinCodeAnalyzer.getFileScopeProvider()) useInstance(kotlinCodeAnalyzer.getFileScopeProvider())
useInstance(bodyResolveCache) useInstance(bodyResolveCache)
useImpl<LazyTopDownAnalyzerForTopLevel>() useImpl<LazyTopDownAnalyzerForTopLevel>()
useImpl<BasicAbsentDescriptorHandler>()
} }
fun createContainerForLazyLocalClassifierAnalyzer( fun createContainerForLazyLocalClassifierAnalyzer(
@@ -20,10 +20,12 @@ import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.resolve.lazy.CompilerLocalDescriptorResolver import org.jetbrains.kotlin.resolve.lazy.CompilerLocalDescriptorResolver
import org.jetbrains.kotlin.resolve.lazy.BasicAbsentDescriptorHandler
object CompilerEnvironment : TargetEnvironment("Compiler") { object CompilerEnvironment : TargetEnvironment("Compiler") {
override fun configure(container: StorageComponentContainer) { override fun configure(container: StorageComponentContainer) {
container.useInstance(BodyResolveCache.ThrowException) container.useInstance(BodyResolveCache.ThrowException)
container.useImpl<CompilerLocalDescriptorResolver>() container.useImpl<CompilerLocalDescriptorResolver>()
container.useImpl<BasicAbsentDescriptorHandler>()
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * Copyright 2010-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,8 +16,18 @@
package org.jetbrains.kotlin.resolve.lazy package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
class NoDescriptorForDeclarationException(declaration: KtDeclaration) : interface AbsentDescriptorHandler {
IllegalStateException("Descriptor wasn't found for declaration $declaration\n${declaration.getElementTextWithContext()}") fun diagnoseDescriptorNotFound(declaration: KtDeclaration): DeclarationDescriptor
}
class BasicAbsentDescriptorHandler : AbsentDescriptorHandler {
override fun diagnoseDescriptorNotFound(declaration: KtDeclaration) = throw NoDescriptorForDeclarationException(declaration)
}
class NoDescriptorForDeclarationException @JvmOverloads constructor(declaration: KtDeclaration, additionalDetails: String? = null) :
IllegalStateException("Descriptor wasn't found for declaration $declaration\n${declaration.getElementTextWithContext()}"
+ (additionalDetails?.let { "\n---------------------------------------------------\n$it" } ?: ""))
@@ -41,6 +41,7 @@ import java.util.List;
public class LazyDeclarationResolver { public class LazyDeclarationResolver {
@NotNull private final TopLevelDescriptorProvider topLevelDescriptorProvider; @NotNull private final TopLevelDescriptorProvider topLevelDescriptorProvider;
@NotNull private final AbsentDescriptorHandler absentDescriptorHandler;
@NotNull private final BindingTrace trace; @NotNull private final BindingTrace trace;
protected DeclarationScopeProvider scopeProvider; protected DeclarationScopeProvider scopeProvider;
@@ -55,9 +56,11 @@ public class LazyDeclarationResolver {
public LazyDeclarationResolver( public LazyDeclarationResolver(
@NotNull GlobalContext globalContext, @NotNull GlobalContext globalContext,
@NotNull BindingTrace delegationTrace, @NotNull BindingTrace delegationTrace,
@NotNull TopLevelDescriptorProvider topLevelDescriptorProvider @NotNull TopLevelDescriptorProvider topLevelDescriptorProvider,
@NotNull AbsentDescriptorHandler absentDescriptorHandler
) { ) {
this.topLevelDescriptorProvider = topLevelDescriptorProvider; this.topLevelDescriptorProvider = topLevelDescriptorProvider;
this.absentDescriptorHandler = absentDescriptorHandler;
LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager = LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager =
new LockBasedLazyResolveStorageManager(globalContext.getStorageManager()); new LockBasedLazyResolveStorageManager(globalContext.getStorageManager());
@@ -233,7 +236,7 @@ public class LazyDeclarationResolver {
} }
}, null); }, null);
if (result == null) { if (result == null) {
throw new NoDescriptorForDeclarationException(declaration); return absentDescriptorHandler.diagnoseDescriptorNotFound(declaration);
} }
return result; return result;
} }
@@ -166,8 +166,9 @@ class LocalLazyDeclarationResolver(
globalContext: GlobalContext, globalContext: GlobalContext,
trace: BindingTrace, trace: BindingTrace,
private val localClassDescriptorManager: LocalClassDescriptorHolder, private val localClassDescriptorManager: LocalClassDescriptorHolder,
topLevelDescriptorProvider : TopLevelDescriptorProvider topLevelDescriptorProvider : TopLevelDescriptorProvider,
) : LazyDeclarationResolver(globalContext, trace, topLevelDescriptorProvider) { absentDescriptorHandler: AbsentDescriptorHandler
) : LazyDeclarationResolver(globalContext, trace, topLevelDescriptorProvider, absentDescriptorHandler) {
override fun getClassDescriptor(classOrObject: KtClassOrObject, location: LookupLocation): ClassDescriptor { override fun getClassDescriptor(classOrObject: KtClassOrObject, location: LookupLocation): ClassDescriptor {
if (localClassDescriptorManager.isMyClass(classOrObject)) { if (localClassDescriptorManager.isMyClass(classOrObject)) {
@@ -24,5 +24,6 @@ object IdeaEnvironment : TargetEnvironment("Idea") {
override fun configure(container: StorageComponentContainer) { override fun configure(container: StorageComponentContainer) {
container.useImpl<ResolveElementCache>() container.useImpl<ResolveElementCache>()
container.useImpl<IdeaLocalDescriptorResolver>() container.useImpl<IdeaLocalDescriptorResolver>()
container.useImpl<IdeaAbsentDescriptorHandler>()
} }
} }
@@ -17,18 +17,33 @@
package org.jetbrains.kotlin.idea.project package org.jetbrains.kotlin.idea.project
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.stubindex.resolve.PluginDeclarationProviderFactory
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.LocalDescriptorResolver import org.jetbrains.kotlin.resolve.lazy.LocalDescriptorResolver
import org.jetbrains.kotlin.resolve.lazy.AbsentDescriptorHandler
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
class IdeaLocalDescriptorResolver( class IdeaLocalDescriptorResolver(
private val resolveElementCache: ResolveElementCache private val resolveElementCache: ResolveElementCache,
): LocalDescriptorResolver { private val absentDescriptorHandler: AbsentDescriptorHandler
) : LocalDescriptorResolver {
override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor { override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor {
val context = resolveElementCache.resolveToElement(declaration, BodyResolveMode.FULL) val context = resolveElementCache.resolveToElement(declaration, BodyResolveMode.FULL)
return context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) return context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
?: throw NoDescriptorForDeclarationException(declaration) ?: absentDescriptorHandler.diagnoseDescriptorNotFound(declaration)
}
}
class IdeaAbsentDescriptorHandler(
private val declarationProviderFactory: DeclarationProviderFactory
) : AbsentDescriptorHandler {
override fun diagnoseDescriptorNotFound(declaration: KtDeclaration): DeclarationDescriptor {
throw NoDescriptorForDeclarationException(
declaration,
(declarationProviderFactory as? PluginDeclarationProviderFactory)?.debugToString()
)
} }
} }
@@ -58,4 +58,24 @@ class PluginDeclarationProviderFactory(
throw IllegalStateException("Cannot find package fragment for file ${file.name} with package ${file.packageFqName}, " + throw IllegalStateException("Cannot find package fragment for file ${file.name} with package ${file.packageFqName}, " +
"vFile ${file.virtualFile}, nonIndexed ${file in nonIndexedFiles}") "vFile ${file.virtualFile}, nonIndexed ${file in nonIndexedFiles}")
} }
// trying to diagnose org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException in completion
private val onCreationDebugInfo = debugInfo()
fun debugToString(): String {
return "PluginDeclarationProviderFactory\nOn failure:\n${debugInfo()}On creation:\n$onCreationDebugInfo"
}
private fun debugInfo(): String {
if (nonIndexedFiles.isEmpty()) return "-no synthetic files-\n"
return buildString {
nonIndexedFiles.forEach {
append(it.name)
append(" isPhysical=${it.isPhysical}")
append(" modStamp=${it.modificationStamp}")
appendln()
}
}
}
} }