diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt index f548f9678ef..0c1f5ce2604 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt @@ -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( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeFactory.kt index 8900f6c419e..ec1a6099dcd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeFactory.kt @@ -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() { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.kt index 7e0669dcebd..4e75be1e0e2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.kt @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java index 52eb9f56d07..b7bc93ae383 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt index 61c95d5e865..99e0a5cd6d7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt @@ -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 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 { shouldNotBeCalled() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java index f7c5b788a2f..18308e87ce9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/AbstractDeclarationProviderFactory.java @@ -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); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/DeclarationProviderFactory.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/DeclarationProviderFactory.java index 4359f0d0713..f953eb07417 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/DeclarationProviderFactory.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/declarations/DeclarationProviderFactory.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt index 28389553ef9..b38b100dcf0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LocalClassifierAnalyzer.kt @@ -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() } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt index 3987f8d51f2..fb0b5f89ccf 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt @@ -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().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().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