Improve diagnosticMissingPackageFragment reporting
Single execution path to report missing package fragment problems Split failures on PluginDeclarationProviderFactory site by known reasons to improve exception analysis
This commit is contained in:
@@ -153,8 +153,8 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
|
||||
return delegateFactory.getPackageMemberDeclarationProvider(packageFqName)
|
||||
}
|
||||
|
||||
override fun diagnoseMissingPackageFragment(file: KtFile) {
|
||||
delegateFactory.diagnoseMissingPackageFragment(file)
|
||||
override fun diagnoseMissingPackageFragment(fqName: FqName, file: KtFile?) {
|
||||
delegateFactory.diagnoseMissingPackageFragment(fqName, file)
|
||||
}
|
||||
|
||||
class AdaptablePackageMemberDeclarationProvider(
|
||||
|
||||
@@ -55,12 +55,7 @@ class FileScopeFactory(
|
||||
|
||||
fun createScopesForFile(file: KtFile, existingImports: ImportingScope? = null): FileScopes {
|
||||
val packageView = moduleDescriptor.getPackage(file.packageFqName)
|
||||
val packageFragment = topLevelDescriptorProvider.getPackageFragment(file.packageFqName)
|
||||
if (packageFragment == null) {
|
||||
// TODO J2K and change return type of diagnoseMissingPackageFragment() to Nothing
|
||||
(topLevelDescriptorProvider as? LazyClassContext)?.declarationProviderFactory?.diagnoseMissingPackageFragment(file)
|
||||
error("Could not find fragment ${file.packageFqName} for file ${file.name}")
|
||||
}
|
||||
val packageFragment = topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(file.packageFqName, file)
|
||||
|
||||
return FilesScopesBuilder(file, existingImports, packageFragment, packageView).result
|
||||
}
|
||||
@@ -119,7 +114,7 @@ class FileScopeFactory(
|
||||
}
|
||||
}
|
||||
|
||||
val lexicalScope = LexicalScope.Base(lazyImportingScope, topLevelDescriptorProvider.getPackageFragment(file.packageFqName)!!)
|
||||
val lexicalScope = LexicalScope.Base(lazyImportingScope, topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(file.packageFqName, file))
|
||||
|
||||
val importResolver = object : ImportResolver {
|
||||
override fun forceResolveAllImports() {
|
||||
|
||||
@@ -216,16 +216,8 @@ open class LazyDeclarationResolver @Deprecated("") constructor(
|
||||
val ktFile = declaration.containingFile as KtFile
|
||||
val fqName = ktFile.packageFqName
|
||||
topLevelDescriptorProvider.assertValid()
|
||||
val packageDescriptor = topLevelDescriptorProvider.getPackageFragment(fqName)
|
||||
if (packageDescriptor == null) {
|
||||
if (topLevelDescriptorProvider is LazyClassContext) {
|
||||
topLevelDescriptorProvider.declarationProviderFactory.diagnoseMissingPackageFragment(ktFile)
|
||||
}
|
||||
else {
|
||||
throw IllegalStateException("Cannot find package fragment for file " + ktFile.name + " with package " + fqName)
|
||||
}
|
||||
}
|
||||
return packageDescriptor!!.getMemberScope()
|
||||
val packageDescriptor = topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(fqName, ktFile)
|
||||
return packageDescriptor.getMemberScope()
|
||||
}
|
||||
else {
|
||||
return when (parentDeclaration) {
|
||||
|
||||
@@ -137,7 +137,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
|
||||
|
||||
|
||||
@Inject
|
||||
public void setDelegationFilter(@NotNull DelegationFilter delegationFilter) {
|
||||
public void setDelegationFilter(@NotNull DelegationFilter delegationFilter) {
|
||||
this.delegationFilter = delegationFilter;
|
||||
}
|
||||
|
||||
@@ -213,6 +213,18 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
|
||||
return packages.invoke(fqName);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LazyPackageDescriptor getPackageFragmentOrDiagnoseFailure(@NotNull FqName fqName, @Nullable KtFile from) {
|
||||
LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName);
|
||||
if (packageDescriptor == null) {
|
||||
declarationProviderFactory.diagnoseMissingPackageFragment(fqName, from);
|
||||
assert false : "diagnoseMissingPackageFragment should throw!";
|
||||
}
|
||||
return packageDescriptor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LazyPackageDescriptor createPackage(FqName fqName) {
|
||||
PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName);
|
||||
@@ -350,8 +362,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
|
||||
) {
|
||||
result.add(current);
|
||||
for (FqName subPackage : packageFragmentProvider.getSubPackagesOf(current.getFqName(), MemberScope.Companion.getALL_NAME_FILTER())) {
|
||||
LazyPackageDescriptor fragment = getPackageFragment(subPackage);
|
||||
assert fragment != null : "Couldn't find fragment for " + subPackage;
|
||||
LazyPackageDescriptor fragment = getPackageFragmentOrDiagnoseFailure(subPackage, null);
|
||||
collectAllPackages(result, fragment);
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -19,11 +19,14 @@ package org.jetbrains.kotlin.resolve.lazy
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor
|
||||
|
||||
interface TopLevelDescriptorProvider {
|
||||
fun getPackageFragment(fqName: FqName): LazyPackageDescriptor?
|
||||
|
||||
fun getPackageFragmentOrDiagnoseFailure(fqName: FqName, from: KtFile?): LazyPackageDescriptor
|
||||
|
||||
fun getTopLevelClassifierDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassifierDescriptor>
|
||||
|
||||
fun assertValid()
|
||||
@@ -36,6 +39,10 @@ object NoTopLevelDescriptorProvider : TopLevelDescriptorProvider {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
|
||||
override fun getPackageFragmentOrDiagnoseFailure(fqName: FqName, from: KtFile?): LazyPackageDescriptor {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
|
||||
override fun getTopLevelClassifierDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassifierDescriptor> {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
|
||||
+6
-2
@@ -40,7 +40,11 @@ public abstract class AbstractDeclarationProviderFactory implements DeclarationP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diagnoseMissingPackageFragment(KtFile file) {
|
||||
throw new IllegalStateException("Cannot find package fragment for file " + file.getName() + " with package " + file.getPackageFqName());
|
||||
public void diagnoseMissingPackageFragment(@NotNull FqName fqName, @Nullable KtFile file) {
|
||||
String message = "Cannot find package fragment " + fqName;
|
||||
if (file != null) {
|
||||
message += "\nvFile = " + file.getVirtualFilePath() + ", file package = '" + file.getPackageFqName() + "'";
|
||||
}
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,5 +34,5 @@ public interface DeclarationProviderFactory {
|
||||
@Nullable
|
||||
PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName);
|
||||
|
||||
void diagnoseMissingPackageFragment(KtFile file);
|
||||
void diagnoseMissingPackageFragment(@NotNull FqName fqName, @Nullable KtFile file);
|
||||
}
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ class LocalClassDescriptorHolder(
|
||||
throw UnsupportedOperationException("Should not be called for top-level declarations")
|
||||
}
|
||||
|
||||
override fun diagnoseMissingPackageFragment(file: KtFile?) {
|
||||
override fun diagnoseMissingPackageFragment(fqName: FqName, file: KtFile?) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
+68
-13
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.stubindex.resolve
|
||||
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stubs.StubIndex
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
@@ -69,21 +70,75 @@ class PluginDeclarationProviderFactory(
|
||||
return StubBasedPackageMemberDeclarationProvider(name, project, indexedFilesScope)
|
||||
}
|
||||
|
||||
override fun diagnoseMissingPackageFragment(file: KtFile) {
|
||||
val packageFqName = file.packageFqName
|
||||
private fun diagnoseMissingPackageFragmentExactPackageIndexCorruption(message: String): Nothing {
|
||||
throw IllegalStateException(
|
||||
"KotlinExactPackageIndex seems corrupted.\n" +
|
||||
message
|
||||
)
|
||||
}
|
||||
|
||||
private fun diagnoseMissingPackageFragmentPerModulePackageCacheMiss(message: String): Nothing {
|
||||
throw IllegalStateException(
|
||||
"PerModulePackageCache miss.\n" +
|
||||
message
|
||||
)
|
||||
}
|
||||
|
||||
private fun diagnoseMissingPackageFragmentUnknownReason(message: String): Nothing {
|
||||
throw IllegalStateException(message)
|
||||
}
|
||||
|
||||
override fun diagnoseMissingPackageFragment(fqName: FqName, file: KtFile?) {
|
||||
|
||||
val subpackagesIndex = SubpackagesIndexService.getInstance(project)
|
||||
val moduleSourceInfo = moduleInfo as? ModuleSourceInfo
|
||||
val virtualFile = file.virtualFile
|
||||
throw IllegalStateException("""
|
||||
Cannot find package fragment for file ${file.name} with package '$packageFqName':
|
||||
vFile: $virtualFile,
|
||||
nonIndexed files: $nonIndexedFiles, isNonIndexed: ${file in nonIndexedFiles},
|
||||
scope = $indexedFilesScope, isInScope = ${virtualFile in indexedFilesScope},
|
||||
packageExists = ${PackageIndexUtil.packageExists(packageFqName, indexedFilesScope, project)}, cachedPackageExists = ${moduleSourceInfo?.let { project.service<PerModulePackageCacheService>().packageExists(packageFqName, it) }},
|
||||
oldPackageExists = ${oldPackageExists(packageFqName) ?: "threw exception"},
|
||||
SPI.packageExists = ${subpackagesIndex.packageExists(packageFqName)}, SPI = $subpackagesIndex, OOCB count ${file.manager.modificationTracker.outOfCodeBlockModificationCount},
|
||||
ModuleModificationCount = ${moduleSourceInfo?.createModificationTracker()?.modificationCount},
|
||||
packageFqNameByTree = '${file.packageFqNameByTree}', packageDirectiveText = '${file.packageDirective?.text}'""")
|
||||
val packageExists = PackageIndexUtil.packageExists(fqName, indexedFilesScope, project)
|
||||
val spiPackageExists = subpackagesIndex.packageExists(fqName)
|
||||
val oldPackageExists = oldPackageExists(fqName)
|
||||
val cachedPackageExists = moduleSourceInfo?.let { project.service<PerModulePackageCacheService>().packageExists(fqName, it) }
|
||||
val moduleModificationCount = moduleSourceInfo?.createModificationTracker()?.modificationCount
|
||||
|
||||
val common = """
|
||||
packageExists = $packageExists, cachedPackageExists = $cachedPackageExists,
|
||||
oldPackageExists = $oldPackageExists,
|
||||
SPI.packageExists = $spiPackageExists, SPI = $subpackagesIndex,
|
||||
OOCB count = ${PsiManager.getInstance(project).modificationTracker.outOfCodeBlockModificationCount}
|
||||
moduleModificationCount = $moduleModificationCount
|
||||
""".trimIndent()
|
||||
|
||||
val message = if (file != null) {
|
||||
val virtualFile = file.virtualFile
|
||||
val inScope = virtualFile in indexedFilesScope
|
||||
val packageFqName = file.packageFqName
|
||||
"""
|
||||
|Cannot find package fragment '$fqName' for file ${file.name}, file package = '$packageFqName':
|
||||
|vFile: $virtualFile,
|
||||
|nonIndexedFiles = $nonIndexedFiles, isNonIndexed = ${file in nonIndexedFiles},
|
||||
|scope = $indexedFilesScope, isInScope = $inScope,
|
||||
|$common,
|
||||
|packageFqNameByTree = '${file.packageFqNameByTree}', packageDirectiveText = '${file.packageDirective?.text}'
|
||||
""".trimMargin()
|
||||
}
|
||||
else {
|
||||
"""
|
||||
|Cannot find package fragment '$fqName' for unspecified file:
|
||||
|nonIndexedFiles = $nonIndexedFiles,
|
||||
|scope = $indexedFilesScope,
|
||||
|$common
|
||||
""".trimMargin()
|
||||
}
|
||||
|
||||
val scopeNotEmptyAndContainsFile =
|
||||
indexedFilesScope != GlobalSearchScope.EMPTY_SCOPE && (file == null || file.virtualFile in indexedFilesScope)
|
||||
when {
|
||||
scopeNotEmptyAndContainsFile
|
||||
&& !packageExists && oldPackageExists == false -> diagnoseMissingPackageFragmentExactPackageIndexCorruption(message)
|
||||
|
||||
scopeNotEmptyAndContainsFile
|
||||
&& packageExists && cachedPackageExists == false -> diagnoseMissingPackageFragmentPerModulePackageCacheMiss(message)
|
||||
|
||||
else -> diagnoseMissingPackageFragmentUnknownReason(message)
|
||||
}
|
||||
}
|
||||
|
||||
// trying to diagnose org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException in completion
|
||||
|
||||
Reference in New Issue
Block a user