From 170ba98b202b7e9399e6d2ea524923e00fc3422e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 19 Jan 2016 16:50:55 +0100 Subject: [PATCH] show unsupported ABI notification only when current module or its dependencies have libraries with bad ABI --- .../idea/versions/KotlinRuntimeLibraryUtil.kt | 45 +++++------------ ...rtedAbiVersionNotificationPanelProvider.kt | 50 +++++++++---------- 2 files changed, 37 insertions(+), 58 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt index c89e6fa15b5..ae457f2d14b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt @@ -20,6 +20,7 @@ import com.google.common.collect.Sets import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.module.ModuleUtil import com.intellij.openapi.project.Project import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager @@ -31,13 +32,10 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.JarFileSystem import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.ProjectScope -import com.intellij.util.CommonProcessors import com.intellij.util.PathUtil.getLocalFile import com.intellij.util.PathUtil.getLocalPath import com.intellij.util.containers.MultiMap import com.intellij.util.indexing.FileBasedIndex -import com.intellij.util.indexing.ID import com.intellij.util.indexing.ScalarIndexExtension import org.jetbrains.kotlin.idea.KotlinPluginUtil import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator @@ -46,25 +44,21 @@ import org.jetbrains.kotlin.idea.configuration.getConfiguratorByName import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider import org.jetbrains.kotlin.idea.framework.LibraryPresentationProviderUtil -import org.jetbrains.kotlin.idea.project.ProjectStructureUtil import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils import org.jetbrains.kotlin.utils.PathUtil import java.io.File import java.io.IOException -import java.util.* -fun getLibraryRootsWithAbiIncompatibleKotlinClasses(project: Project): Collection { +fun getLibraryRootsWithAbiIncompatibleKotlinClasses(module: Module): Collection { return getLibraryRootsWithAbiIncompatibleVersion( - project, KotlinMetadataVersionIndex, - { module -> ProjectStructureUtil.isJavaKotlinModule(module) }, + module, KotlinMetadataVersionIndex, { version -> !version.isCompatible() }) } -fun getLibraryRootsWithAbiIncompatibleForKotlinJs(project: Project): Collection { +fun getLibraryRootsWithAbiIncompatibleForKotlinJs(module: Module): Collection { return getLibraryRootsWithAbiIncompatibleVersion( - project, KotlinJavaScriptAbiVersionIndex, - { module -> ProjectStructureUtil.isJsKotlinModule(module) }, + module, KotlinJavaScriptAbiVersionIndex, { version -> !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.minor) }) // TODO: support major.minor.patch version in JS metadata } @@ -217,25 +211,23 @@ internal fun replaceFile(updatedFile: File, replacedJarFile: VirtualFile) { } private fun getLibraryRootsWithAbiIncompatibleVersion( - project: Project, + module: Module, index: ScalarIndexExtension, - checkModule: (Module) -> Boolean, checkVersion: (BinaryVersion) -> Boolean): Collection { val id = index.name - val modules = ModuleManager.getInstance(project).modules + val moduleWithAllDependencies = setOf(module) + ModuleUtil.getAllDependentModules(module) + val moduleWithAllDependentLibraries = GlobalSearchScope.union( + moduleWithAllDependencies.map { it.moduleWithLibrariesScope }.toTypedArray()) - val modulesToCheck = modules.filter(checkModule) - if (modulesToCheck.isEmpty()) return emptyList() - - val versions = collectAllKeys(id, modulesToCheck) - val badVersions = versions.filter(checkVersion).toHashSet() + val allVersions = FileBasedIndex.getInstance().getAllKeys(id, module.project) + val badVersions = allVersions.filter(checkVersion).toHashSet() val badRoots = Sets.newHashSet() - val fileIndex = ProjectFileIndex.SERVICE.getInstance(project) + val fileIndex = ProjectFileIndex.SERVICE.getInstance(module.project) for (version in badVersions) { val indexedFiles = FileBasedIndex.getInstance().getContainingFiles( - id, version, ProjectScope.getLibrariesScope(project)) + id, version, moduleWithAllDependentLibraries) for (indexedFile in indexedFiles) { val libraryRoot = fileIndex.getClassRootForFile(indexedFile) @@ -247,17 +239,6 @@ private fun getLibraryRootsWithAbiIncompatibleVersion( return badRoots } -private fun collectAllKeys(id: ID, modules: List): Collection { - val allKeys = HashSet() - - for (module in modules) { - val scope = GlobalSearchScope.moduleWithLibrariesScope(module) - FileBasedIndex.getInstance().processAllKeys(id, CommonProcessors.CollectProcessor(allKeys), scope, null) - } - - return allKeys -} - fun showRuntimeJarNotFoundDialog(project: Project, jarName: String) { Messages.showErrorDialog(project, jarName + " is not found. Make sure plugin is properly installed.", diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/UnsupportedAbiVersionNotificationPanelProvider.kt b/idea/src/org/jetbrains/kotlin/idea/versions/UnsupportedAbiVersionNotificationPanelProvider.kt index 4cd8351678a..f801edadd2e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/UnsupportedAbiVersionNotificationPanelProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/UnsupportedAbiVersionNotificationPanelProvider.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.compiler.CompilerManager import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.fileEditor.FileEditor import com.intellij.openapi.fileEditor.OpenFileDescriptor +import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.DumbService @@ -41,7 +42,6 @@ import com.intellij.ui.EditorNotificationPanel import com.intellij.ui.EditorNotifications import com.intellij.ui.HyperlinkLabel import org.jetbrains.kotlin.idea.KotlinFileType -import org.jetbrains.kotlin.idea.configuration.isModuleConfigured import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider import java.text.MessageFormat @@ -66,7 +66,7 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec }) } - private fun doCreate(badRoots: Collection): EditorNotificationPanel { + private fun doCreate(module: Module, badRoots: Collection): EditorNotificationPanel { val answer = ErrorNotificationPanel() val kotlinLibraries = findAllUsedLibraries(project).keySet() @@ -89,7 +89,7 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec answer.setText(text) answer.createActionLabel(actionLabelText) { updateLibraries(project, badRuntimeLibraries) } if (otherBadRootsCount > 0) { - createShowPathsActionLabel(answer, "Show all") + createShowPathsActionLabel(module, answer, "Show all") } } else if (badRoots.size == 1) { @@ -101,16 +101,16 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec } else { answer.setText("Some Kotlin libraries attached to this project have unsupported format. Please update the libraries or the plugin") - createShowPathsActionLabel(answer, "Show paths") + createShowPathsActionLabel(module, answer, "Show paths") } return answer } - private fun createShowPathsActionLabel(answer: EditorNotificationPanel, labelText: String) { + private fun createShowPathsActionLabel(module: Module, answer: EditorNotificationPanel, labelText: String) { val label: Ref = Ref.create() val action = Runnable { DumbService.getInstance(project).tryRunReadActionInSmartMode({ - val badRoots = collectBadRoots(project) + val badRoots = collectBadRoots(module) assert(!badRoots.isEmpty()) { "This action should only be called when bad roots are present" } val listPopupModel = LibraryRootsPopupModel("Unsupported format", project, badRoots) @@ -135,9 +135,7 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec val module = ModuleUtilCore.findModuleForFile(file, project) ?: return null - if (!isModuleConfigured(module)) return null - - return checkAndCreate(project) + return checkAndCreate(module) } catch (e: ProcessCanceledException) { // Ignore @@ -149,6 +147,20 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec return null } + fun checkAndCreate(module: Module): EditorNotificationPanel? { + val state = ServiceManager.getService(project, SuppressNotificationState::class.java).state + if (state != null && state.isSuppressed) { + return null + } + + val badRoots = collectBadRoots(module) + if (!badRoots.isEmpty()) { + return doCreate(module, badRoots) + } + + return null + } + private class LibraryRootsPopupModel(title: String, private val project: Project, roots: Collection) : BaseListPopupStep(title, *roots.toTypedArray()) { @@ -191,27 +203,13 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec companion object { private val KEY = Key.create("unsupported.abi.version") - fun checkAndCreate(project: Project): EditorNotificationPanel? { - val state = ServiceManager.getService(project, SuppressNotificationState::class.java).state - if (state != null && state.isSuppressed) { - return null - } - - val badRoots = collectBadRoots(project) - if (!badRoots.isEmpty()) { - return UnsupportedAbiVersionNotificationPanelProvider(project).doCreate(badRoots) - } - - return null - } - private fun navigateToLibraryRoot(project: Project, root: VirtualFile) { OpenFileDescriptor(project, root).navigate(true) } - private fun collectBadRoots(project: Project): Collection { - val badJVMRoots = getLibraryRootsWithAbiIncompatibleKotlinClasses(project) - val badJSRoots = getLibraryRootsWithAbiIncompatibleForKotlinJs(project) + private fun collectBadRoots(module: Module): Collection { + val badJVMRoots = getLibraryRootsWithAbiIncompatibleKotlinClasses(module) + val badJSRoots = getLibraryRootsWithAbiIncompatibleForKotlinJs(module) if (badJVMRoots.isEmpty() && badJSRoots.isEmpty()) return emptyList()