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.incremental.components.LookupTracker
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
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.*
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.LocalClassDescriptorHolder
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
@@ -90,6 +86,7 @@ fun createContainerForLazyBodyResolve(
useInstance(kotlinCodeAnalyzer.getFileScopeProvider())
useInstance(bodyResolveCache)
useImpl<LazyTopDownAnalyzerForTopLevel>()
useImpl<BasicAbsentDescriptorHandler>()
}
fun createContainerForLazyLocalClassifierAnalyzer(
@@ -20,10 +20,12 @@ import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.resolve.lazy.CompilerLocalDescriptorResolver
import org.jetbrains.kotlin.resolve.lazy.BasicAbsentDescriptorHandler
object CompilerEnvironment : TargetEnvironment("Compiler") {
override fun configure(container: StorageComponentContainer) {
container.useInstance(BodyResolveCache.ThrowException)
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");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,18 @@
package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
class NoDescriptorForDeclarationException(declaration: KtDeclaration) :
IllegalStateException("Descriptor wasn't found for declaration $declaration\n${declaration.getElementTextWithContext()}")
interface AbsentDescriptorHandler {
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 {
@NotNull private final TopLevelDescriptorProvider topLevelDescriptorProvider;
@NotNull private final AbsentDescriptorHandler absentDescriptorHandler;
@NotNull private final BindingTrace trace;
protected DeclarationScopeProvider scopeProvider;
@@ -55,9 +56,11 @@ public class LazyDeclarationResolver {
public LazyDeclarationResolver(
@NotNull GlobalContext globalContext,
@NotNull BindingTrace delegationTrace,
@NotNull TopLevelDescriptorProvider topLevelDescriptorProvider
@NotNull TopLevelDescriptorProvider topLevelDescriptorProvider,
@NotNull AbsentDescriptorHandler absentDescriptorHandler
) {
this.topLevelDescriptorProvider = topLevelDescriptorProvider;
this.absentDescriptorHandler = absentDescriptorHandler;
LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager =
new LockBasedLazyResolveStorageManager(globalContext.getStorageManager());
@@ -233,7 +236,7 @@ public class LazyDeclarationResolver {
}
}, null);
if (result == null) {
throw new NoDescriptorForDeclarationException(declaration);
return absentDescriptorHandler.diagnoseDescriptorNotFound(declaration);
}
return result;
}
@@ -166,8 +166,9 @@ class LocalLazyDeclarationResolver(
globalContext: GlobalContext,
trace: BindingTrace,
private val localClassDescriptorManager: LocalClassDescriptorHolder,
topLevelDescriptorProvider : TopLevelDescriptorProvider
) : LazyDeclarationResolver(globalContext, trace, topLevelDescriptorProvider) {
topLevelDescriptorProvider : TopLevelDescriptorProvider,
absentDescriptorHandler: AbsentDescriptorHandler
) : LazyDeclarationResolver(globalContext, trace, topLevelDescriptorProvider, absentDescriptorHandler) {
override fun getClassDescriptor(classOrObject: KtClassOrObject, location: LookupLocation): ClassDescriptor {
if (localClassDescriptorManager.isMyClass(classOrObject)) {
@@ -24,5 +24,6 @@ object IdeaEnvironment : TargetEnvironment("Idea") {
override fun configure(container: StorageComponentContainer) {
container.useImpl<ResolveElementCache>()
container.useImpl<IdeaLocalDescriptorResolver>()
container.useImpl<IdeaAbsentDescriptorHandler>()
}
}
@@ -17,18 +17,33 @@
package org.jetbrains.kotlin.idea.project
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.stubindex.resolve.PluginDeclarationProviderFactory
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
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.declarations.DeclarationProviderFactory
class IdeaLocalDescriptorResolver(
private val resolveElementCache: ResolveElementCache
): LocalDescriptorResolver {
private val resolveElementCache: ResolveElementCache,
private val absentDescriptorHandler: AbsentDescriptorHandler
) : LocalDescriptorResolver {
override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor {
val context = resolveElementCache.resolveToElement(declaration, BodyResolveMode.FULL)
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}, " +
"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()
}
}
}
}