From 0750de73e1cf3500f92c074f08418a7ba937d015 Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Tue, 24 Jul 2018 15:02:31 +0300 Subject: [PATCH] Distinguish exceptions about unknown module info --- .../kotlin/analyzer/AnalyzerFacade.kt | 62 ++++++++++++++++++- .../caches/resolve/KotlinCacheServiceImpl.kt | 15 +++-- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt index b6f391d57a4..33d459874bd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalyzerFacade.kt @@ -64,6 +64,15 @@ abstract class ResolverForProject { abstract val builtIns: KotlinBuiltIns override fun toString() = name + + companion object { + const val resolverForSdkName = "sdk" + const val resolverForLibrariesName = "project libraries" + const val resolverForModulesName = "project source roots and libraries" + const val resolverForScriptDependenciesName = "dependencies of scripts" + + const val resolverForSpecialInfoName = "completion/highlighting in " + } } class EmptyResolverForProject : ResolverForProject() { @@ -205,8 +214,9 @@ class ResolverForProjectImpl( return doGetDescriptorForModule(moduleInfo) } - override fun diagnoseUnknownModuleInfo(infos: List) = - throw AssertionError("$name does not know how to resolve $infos") + override fun diagnoseUnknownModuleInfo(infos: List): Nothing { + DiagnoseUnknownModuleInfoReporter.report(name, infos) + } private fun checkModuleIsCorrect(moduleInfo: M) { if (!isCorrectModuleInfo(moduleInfo)) { @@ -445,3 +455,51 @@ interface ResolverForModuleComputationTracker { ServiceManager.getService(project, ResolverForModuleComputationTracker::class.java) ?: null } } + +private object DiagnoseUnknownModuleInfoReporter { + fun report(name: String, infos: List): Nothing { + val message = "$name does not know how to resolve $infos" + when { + name.contains(ResolverForProject.resolverForSdkName) -> errorInSdkResolver(message) + name.contains(ResolverForProject.resolverForLibrariesName) -> errorInLibrariesResolver(message) + name.contains(ResolverForProject.resolverForModulesName) -> { + when { + infos.isEmpty() -> errorInModulesResolverWithEmptyInfos(message) + infos.size == 1 -> { + val infoAsString = infos.single().toString() + when { + infoAsString.contains("ScriptDependencies") -> errorInModulesResolverWithScriptDependencies(message) + infoAsString.contains("Library") -> errorInModulesResolverWithLibraryInfo(message) + else -> errorInModulesResolver(message) + } + } + else -> throw errorInModulesResolver(message) + } + } + name.contains(ResolverForProject.resolverForScriptDependenciesName) -> errorInScriptDependenciesInfoResolver(message) + name.contains(ResolverForProject.resolverForSpecialInfoName) -> { + when { + name.contains("ScriptModuleInfo") -> errorInScriptModuleInfoResolver(message) + else -> errorInSpecialModuleInfoResolver(message) + } + } + else -> otherError(message) + } + } + + // Do not inline 'error*'-methods, they are needed to avoid Exception Analyzer merging those AssertionErrors + + private fun errorInSdkResolver(message: String): Nothing = throw AssertionError(message) + private fun errorInLibrariesResolver(message: String): Nothing = throw AssertionError(message) + private fun errorInModulesResolver(message: String): Nothing = throw AssertionError(message) + + private fun errorInModulesResolverWithEmptyInfos(message: String): Nothing = throw AssertionError(message) + private fun errorInModulesResolverWithScriptDependencies(message: String): Nothing = throw AssertionError(message) + private fun errorInModulesResolverWithLibraryInfo(message: String): Nothing = throw AssertionError(message) + + private fun errorInScriptDependenciesInfoResolver(message: String): Nothing = throw AssertionError(message) + private fun errorInScriptModuleInfoResolver(message: String): Nothing = throw AssertionError(message) + private fun errorInSpecialModuleInfoResolver(message: String): Nothing = throw AssertionError(message) + + private fun otherError(message: String): Nothing = throw AssertionError(message) +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index 5311c99d9d6..b4493fd067e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -29,6 +29,11 @@ import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiModificationTracker import com.intellij.util.containers.SLRUCache import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForLibrariesName +import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForModulesName +import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForScriptDependenciesName +import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForSdkName +import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForSpecialInfoName import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.config.LanguageFeature @@ -116,7 +121,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { val globalContext = globalFacade.globalContext.contextWithNewLockAndCompositeExceptionTracker() return ProjectResolutionFacade( "facadeForScriptDependencies", - "dependencies of scripts", + resolverForScriptDependenciesName, project, globalContext, settings, reuseDataFrom = globalFacade, allModules = dependenciesModuleInfo.dependencies(), @@ -132,7 +137,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private inner class GlobalFacade(settings: PlatformAnalysisSettings) { private val sdkContext = GlobalContext() val facadeForSdk = ProjectResolutionFacade( - "facadeForSdk", "sdk ${settings.sdk}", + "facadeForSdk", "$resolverForSdkName ${settings.sdk}", project, sdkContext, settings, moduleFilter = { it is SdkInfo }, dependencies = listOf( @@ -145,7 +150,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private val librariesContext = sdkContext.contextWithNewLockAndCompositeExceptionTracker() val facadeForLibraries = ProjectResolutionFacade( - "facadeForLibraries", "project libraries for platform ${settings.sdk}", + "facadeForLibraries", "$resolverForLibrariesName for platform ${settings.sdk}", project, librariesContext, settings, reuseDataFrom = facadeForSdk, moduleFilter = { it is LibraryInfo }, @@ -158,7 +163,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private val modulesContext = librariesContext.contextWithNewLockAndCompositeExceptionTracker() val facadeForModules = ProjectResolutionFacade( - "facadeForModules", "project source roots and libraries for platform ${settings.platform}", + "facadeForModules", "$resolverForModulesName for platform ${settings.platform}", project, modulesContext, settings, reuseDataFrom = facadeForLibraries, moduleFilter = { !it.isLibraryClasses() }, @@ -225,7 +230,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ) val resolverDebugName = - "completion/highlighting in $specialModuleInfo for files ${files.joinToString { it.name }} for platform $targetPlatform" + "$resolverForSpecialInfoName $specialModuleInfo for files ${files.joinToString { it.name }} for platform $targetPlatform" fun makeProjectResolutionFacade( debugName: String,