show unsupported ABI notification only when current module or its dependencies have libraries with bad ABI
This commit is contained in:
@@ -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<VirtualFile> {
|
||||
fun getLibraryRootsWithAbiIncompatibleKotlinClasses(module: Module): Collection<VirtualFile> {
|
||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||
project, KotlinMetadataVersionIndex,
|
||||
{ module -> ProjectStructureUtil.isJavaKotlinModule(module) },
|
||||
module, KotlinMetadataVersionIndex,
|
||||
{ version -> !version.isCompatible() })
|
||||
}
|
||||
|
||||
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(project: Project): Collection<VirtualFile> {
|
||||
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(module: Module): Collection<VirtualFile> {
|
||||
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<BinaryVersion>,
|
||||
checkModule: (Module) -> Boolean,
|
||||
checkVersion: (BinaryVersion) -> Boolean): Collection<VirtualFile> {
|
||||
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<VirtualFile>()
|
||||
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 <T> collectAllKeys(id: ID<T, Void>, modules: List<Module>): Collection<T> {
|
||||
val allKeys = HashSet<T>()
|
||||
|
||||
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.",
|
||||
|
||||
+24
-26
@@ -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<VirtualFile>): EditorNotificationPanel {
|
||||
private fun doCreate(module: Module, badRoots: Collection<VirtualFile>): 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<HyperlinkLabel> = 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<VirtualFile>)
|
||||
: BaseListPopupStep<VirtualFile>(title, *roots.toTypedArray()) {
|
||||
|
||||
@@ -191,27 +203,13 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
companion object {
|
||||
private val KEY = Key.create<EditorNotificationPanel>("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<VirtualFile> {
|
||||
val badJVMRoots = getLibraryRootsWithAbiIncompatibleKotlinClasses(project)
|
||||
val badJSRoots = getLibraryRootsWithAbiIncompatibleForKotlinJs(project)
|
||||
private fun collectBadRoots(module: Module): Collection<VirtualFile> {
|
||||
val badJVMRoots = getLibraryRootsWithAbiIncompatibleKotlinClasses(module)
|
||||
val badJSRoots = getLibraryRootsWithAbiIncompatibleForKotlinJs(module)
|
||||
|
||||
if (badJVMRoots.isEmpty() && badJSRoots.isEmpty()) return emptyList()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user