Show the hint how to resolve incompatible ABI library problem (KT-11024)
This commit is contained in:
@@ -29,24 +29,24 @@ import java.io.DataOutput
|
||||
/**
|
||||
* Important! This is not a stub-based index. And it has its own version
|
||||
*/
|
||||
abstract class KotlinAbiVersionIndexBase<T>(
|
||||
abstract class KotlinAbiVersionIndexBase<T, V : BinaryVersion>(
|
||||
private val classOfIndex: Class<T>,
|
||||
private val createBinaryVersion: (IntArray) -> BinaryVersion
|
||||
) : ScalarIndexExtension<BinaryVersion>() {
|
||||
protected val createBinaryVersion: (IntArray) -> V
|
||||
) : ScalarIndexExtension<V>() {
|
||||
|
||||
override fun getName() = ID.create<BinaryVersion, Void>(classOfIndex.canonicalName)
|
||||
override fun getName() = ID.create<V, Void>(classOfIndex.canonicalName)
|
||||
|
||||
override fun getKeyDescriptor(): KeyDescriptor<BinaryVersion> = object : KeyDescriptor<BinaryVersion> {
|
||||
override fun isEqual(val1: BinaryVersion, val2: BinaryVersion): Boolean = val1 == val2
|
||||
override fun getKeyDescriptor(): KeyDescriptor<V> = object : KeyDescriptor<V> {
|
||||
override fun isEqual(val1: V, val2: V): Boolean = val1 == val2
|
||||
|
||||
override fun getHashCode(value: BinaryVersion): Int = value.hashCode()
|
||||
override fun getHashCode(value: V): Int = value.hashCode()
|
||||
|
||||
override fun read(input: DataInput): BinaryVersion {
|
||||
override fun read(input: DataInput): V {
|
||||
val size = DataInputOutputUtil.readINT(input)
|
||||
return createBinaryVersion((0..size - 1).map { DataInputOutputUtil.readINT(input) }.toIntArray())
|
||||
}
|
||||
|
||||
override fun save(output: DataOutput, value: BinaryVersion) {
|
||||
override fun save(output: DataOutput, value: V) {
|
||||
val array = value.toArray()
|
||||
DataInputOutputUtil.writeINT(output, array.size)
|
||||
for (number in array) {
|
||||
|
||||
@@ -21,13 +21,12 @@ import com.intellij.util.indexing.DataIndexer
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import com.intellij.util.indexing.FileContent
|
||||
import org.jetbrains.kotlin.js.JavaScript
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.utils.JsBinaryVersion
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import java.util.*
|
||||
|
||||
object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinJavaScriptAbiVersionIndex>(
|
||||
object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinJavaScriptAbiVersionIndex, JsBinaryVersion>(
|
||||
KotlinJavaScriptAbiVersionIndex::class.java, { JsBinaryVersion(*it) }
|
||||
) {
|
||||
override fun getIndexer() = INDEXER
|
||||
@@ -39,7 +38,7 @@ object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinJavaScr
|
||||
private val VERSION = 2
|
||||
|
||||
private val INDEXER = DataIndexer { inputData: FileContent ->
|
||||
val result = HashMap<BinaryVersion, Void?>()
|
||||
val result = HashMap<JsBinaryVersion, Void?>()
|
||||
|
||||
tryBlock(inputData) {
|
||||
val text = VfsUtilCore.loadText(inputData.file)
|
||||
|
||||
@@ -23,13 +23,12 @@ import com.intellij.util.indexing.FileContent
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.*
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
object KotlinMetadataVersionIndex : KotlinAbiVersionIndexBase<KotlinMetadataVersionIndex>(
|
||||
object KotlinMetadataVersionIndex : KotlinAbiVersionIndexBase<KotlinMetadataVersionIndex, JvmMetadataVersion>(
|
||||
KotlinMetadataVersionIndex::class.java, { JvmMetadataVersion(*it) }
|
||||
) {
|
||||
override fun getIndexer() = INDEXER
|
||||
@@ -46,8 +45,8 @@ object KotlinMetadataVersionIndex : KotlinAbiVersionIndexBase<KotlinMetadataVers
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS
|
||||
)
|
||||
|
||||
private val INDEXER = DataIndexer<BinaryVersion, Void, FileContent>() { inputData: FileContent ->
|
||||
var version: BinaryVersion? = null
|
||||
private val INDEXER = DataIndexer<JvmMetadataVersion, Void, FileContent>() { inputData: FileContent ->
|
||||
var version: JvmMetadataVersion? = null
|
||||
var annotationPresent = false
|
||||
var kind: KotlinClassHeader.Kind? = null
|
||||
|
||||
@@ -62,7 +61,7 @@ object KotlinMetadataVersionIndex : KotlinAbiVersionIndexBase<KotlinMetadataVers
|
||||
override fun visit(name: String, value: Any) {
|
||||
when (name) {
|
||||
METADATA_VERSION_FIELD_NAME -> if (value is IntArray) {
|
||||
version = JvmMetadataVersion(*value)
|
||||
version = createBinaryVersion(value)
|
||||
}
|
||||
KIND_FIELD_NAME -> if (value is Int) {
|
||||
kind = KotlinClassHeader.Kind.getById(value)
|
||||
|
||||
@@ -47,25 +47,30 @@ import org.jetbrains.kotlin.idea.configuration.getConfiguratorByName
|
||||
import org.jetbrains.kotlin.idea.framework.*
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.runWithAlternativeResolveEnabled
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.utils.JsBinaryVersion
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
fun getLibraryRootsWithAbiIncompatibleKotlinClasses(module: Module): Collection<VirtualFile> {
|
||||
fun getLibraryRootsWithAbiIncompatibleKotlinClasses(module: Module): Collection<BinaryVersionedFile<JvmMetadataVersion>> {
|
||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||
module, KotlinMetadataVersionIndex,
|
||||
module,
|
||||
JvmMetadataVersion.INSTANCE,
|
||||
KotlinMetadataVersionIndex,
|
||||
{ version -> !version.isCompatible() })
|
||||
}
|
||||
|
||||
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(module: Module): Collection<VirtualFile> {
|
||||
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(module: Module): Collection<BinaryVersionedFile<JsBinaryVersion>> {
|
||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||
module, KotlinJavaScriptAbiVersionIndex,
|
||||
module,
|
||||
JsBinaryVersion.INSTANCE,
|
||||
KotlinJavaScriptAbiVersionIndex,
|
||||
{ version -> !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.minor) }) // TODO: support major.minor.patch version in JS metadata
|
||||
}
|
||||
|
||||
|
||||
fun updateLibraries(project: Project, libraries: Collection<Library>) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator? ?:
|
||||
@@ -215,10 +220,13 @@ internal fun replaceFile(updatedFile: File, replacedJarFile: VirtualFile) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLibraryRootsWithAbiIncompatibleVersion(
|
||||
data class BinaryVersionedFile<out T : BinaryVersion>(val file: VirtualFile, val version: T, val supportedVersion: T)
|
||||
|
||||
private fun <T : BinaryVersion> getLibraryRootsWithAbiIncompatibleVersion(
|
||||
module: Module,
|
||||
index: ScalarIndexExtension<BinaryVersion>,
|
||||
checkVersion: (BinaryVersion) -> Boolean): Collection<VirtualFile> {
|
||||
supportedVersion: T,
|
||||
index: ScalarIndexExtension<T>,
|
||||
checkVersion: (T) -> Boolean): Collection<BinaryVersionedFile<T>> {
|
||||
val id = index.name
|
||||
|
||||
val moduleWithAllDependencies = setOf(module) + ModuleUtil.getAllDependentModules(module)
|
||||
@@ -227,7 +235,7 @@ private fun getLibraryRootsWithAbiIncompatibleVersion(
|
||||
|
||||
val allVersions = FileBasedIndex.getInstance().getAllKeys(id, module.project)
|
||||
val badVersions = allVersions.filter(checkVersion).toHashSet()
|
||||
val badRoots = Sets.newHashSet<VirtualFile>()
|
||||
val badRoots = Sets.newHashSet<BinaryVersionedFile<T>>()
|
||||
val fileIndex = ProjectFileIndex.SERVICE.getInstance(module.project)
|
||||
|
||||
for (version in badVersions) {
|
||||
@@ -236,7 +244,7 @@ private fun getLibraryRootsWithAbiIncompatibleVersion(
|
||||
val libraryRoot = fileIndex.getClassRootForFile(indexedFile) ?:
|
||||
error("Only library roots were requested, and only class files should be indexed with KotlinAbiVersionIndex key. " +
|
||||
"File: ${indexedFile.path}")
|
||||
badRoots.add(getLocalFile(libraryRoot))
|
||||
badRoots.add(BinaryVersionedFile(getLocalFile(libraryRoot), version, supportedVersion))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+160
-31
@@ -31,6 +31,7 @@ import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleRootAdapter
|
||||
import com.intellij.openapi.roots.ModuleRootEvent
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
@@ -40,12 +41,22 @@ import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import com.intellij.ui.HyperlinkAdapter
|
||||
import com.intellij.ui.HyperlinkLabel
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUpdater
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||
import org.jetbrains.kotlin.idea.PluginUpdateStatus
|
||||
import org.jetbrains.kotlin.idea.framework.getJsStdLibJar
|
||||
import org.jetbrains.kotlin.idea.framework.getReflectJar
|
||||
import org.jetbrains.kotlin.idea.framework.getRuntimeJar
|
||||
import org.jetbrains.kotlin.idea.framework.getTestJar
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import java.text.MessageFormat
|
||||
import java.util.*
|
||||
import javax.swing.Icon
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.event.HyperlinkEvent
|
||||
|
||||
class UnsupportedAbiVersionNotificationPanelProvider(private val project: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
|
||||
|
||||
@@ -66,43 +77,87 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
})
|
||||
}
|
||||
|
||||
private fun doCreate(module: Module, badRoots: Collection<VirtualFile>): EditorNotificationPanel {
|
||||
private fun doCreate(module: Module, badVersionedRoots: Collection<BinaryVersionedFile<BinaryVersion>>): EditorNotificationPanel {
|
||||
val answer = ErrorNotificationPanel()
|
||||
val badRootFiles = badVersionedRoots.map { it.file }
|
||||
|
||||
val kotlinLibraries = findAllUsedLibraries(project).keySet()
|
||||
val badRuntimeLibraries = kotlinLibraries.filter { library ->
|
||||
val runtimeJar = getLocalJar(getRuntimeJar(library))
|
||||
val jsLibJar = getLocalJar(getJsStdLibJar(library))
|
||||
badRoots.contains(runtimeJar) || badRoots.contains(jsLibJar)
|
||||
badRootFiles.contains(runtimeJar) || badRootFiles.contains(jsLibJar)
|
||||
}
|
||||
|
||||
if (!badRuntimeLibraries.isEmpty()) {
|
||||
val otherBadRootsCount = badRoots.size - badRuntimeLibraries.size
|
||||
val isPluginOldForAllRoots = badVersionedRoots.all { it.supportedVersion < it.version }
|
||||
val isPluginNewForAllRoots = badVersionedRoots.all { it.supportedVersion > it.version }
|
||||
|
||||
val text = MessageFormat.format("<html><b>{0,choice,0#|1#|1<Some }Kotlin runtime librar{0,choice,0#|1#y|1<ies}</b>" + "{1,choice,0#|1# and one other jar|1< and {1} other jars} " + "{1,choice,0#has|0<have} an unsupported format</html>",
|
||||
if (!badRuntimeLibraries.isEmpty()) {
|
||||
val badRootsInRuntimeLibraries = findBadRootsInRuntimeLibraries(badRuntimeLibraries, badVersionedRoots)
|
||||
val otherBadRootsCount = badVersionedRoots.size - badRootsInRuntimeLibraries.size
|
||||
|
||||
val text = MessageFormat.format("<html><b>{0,choice,0#|1#|1<Some }Kotlin runtime librar{0,choice,0#|1#y|1<ies}</b>" +
|
||||
"{1,choice,0#|1# and one other jar|1< and {1} other jars} " +
|
||||
"{1,choice,0#has|0<have} an unsupported binary format.</html>",
|
||||
badRuntimeLibraries.size,
|
||||
otherBadRootsCount)
|
||||
|
||||
val actionLabelText = MessageFormat.format("Update {0,choice,0#|1#|1<all }Kotlin runtime librar{0,choice,0#|1#y|1<ies} ",
|
||||
badRuntimeLibraries.size)
|
||||
|
||||
answer.setText(text)
|
||||
answer.createActionLabel(actionLabelText) { updateLibraries(project, badRuntimeLibraries) }
|
||||
if (otherBadRootsCount > 0) {
|
||||
createShowPathsActionLabel(module, answer, "Show all")
|
||||
}
|
||||
}
|
||||
else if (badRoots.size == 1) {
|
||||
val root = badRoots.iterator().next()
|
||||
val presentableName = root.presentableName
|
||||
answer.setText("<html>Kotlin library <b>'$presentableName'</b> has an unsupported format. Please update the library or the plugin</html>")
|
||||
|
||||
answer.createActionLabel("Go to " + presentableName) { navigateToLibraryRoot(project, root) }
|
||||
if (isPluginOldForAllRoots) {
|
||||
createUpdatePluginLink(answer)
|
||||
}
|
||||
|
||||
val isPluginOldForAllRuntimeLibraries = badRootsInRuntimeLibraries.all { it.supportedVersion < it.version }
|
||||
val isPluginNewForAllRuntimeLibraries = badRootsInRuntimeLibraries.all { it.supportedVersion > it.version }
|
||||
|
||||
val updateAction = when {
|
||||
isPluginNewForAllRuntimeLibraries -> "Update"
|
||||
isPluginOldForAllRuntimeLibraries -> "Downgrade"
|
||||
else -> "Replace"
|
||||
}
|
||||
|
||||
val actionLabelText = MessageFormat.format("$updateAction {0,choice,0#|1#|1<all }Kotlin runtime librar{0,choice,0#|1#y|1<ies} ", badRuntimeLibraries.size)
|
||||
answer.createActionLabel(actionLabelText) { updateLibraries(project, badRuntimeLibraries) }
|
||||
}
|
||||
else if (badVersionedRoots.size == 1) {
|
||||
val badVersionedRoot = badVersionedRoots.first()
|
||||
val presentableName = badVersionedRoot.file.presentableName
|
||||
|
||||
when {
|
||||
isPluginOldForAllRoots -> {
|
||||
answer.setText("<html>Kotlin library <b>'$presentableName'</b> was compiled with a newer Kotlin compiler and can't be read. Please update Kotlin plugin.</html>")
|
||||
createUpdatePluginLink(answer)
|
||||
}
|
||||
|
||||
isPluginNewForAllRoots ->
|
||||
answer.setText("<html>Kotlin library <b>'$presentableName'</b> has outdated binary format and can't be read by current plugin. Please update the library.</html>")
|
||||
|
||||
else -> {
|
||||
throw IllegalStateException("Bad root with compatible version found: $badVersionedRoot")
|
||||
}
|
||||
}
|
||||
|
||||
answer.createActionLabel("Go to " + presentableName) { navigateToLibraryRoot(project, badVersionedRoot.file) }
|
||||
}
|
||||
else {
|
||||
answer.setText("Some Kotlin libraries attached to this project have unsupported format. Please update the libraries or the plugin")
|
||||
createShowPathsActionLabel(module, answer, "Show paths")
|
||||
when {
|
||||
isPluginOldForAllRoots -> {
|
||||
answer.setText("Some Kotlin libraries attached to this project were compiled with a newer Kotlin compiler and can't be read. " +
|
||||
"Please update Kotlin plugin.")
|
||||
createUpdatePluginLink(answer)
|
||||
}
|
||||
|
||||
isPluginNewForAllRoots ->
|
||||
answer.setText("Some Kotlin libraries attached to this project have outdated binary format and can't be read by current plugin. " +
|
||||
"Please update found libraries.")
|
||||
|
||||
else ->
|
||||
answer.setText("Some Kotlin libraries attached to this project have unsupported binary format. Please update the libraries or the plugin.")
|
||||
}
|
||||
}
|
||||
|
||||
createShowPathsActionLabel(module, answer, "Details")
|
||||
|
||||
return answer
|
||||
}
|
||||
|
||||
@@ -112,7 +167,7 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
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)
|
||||
val listPopupModel = LibraryRootsPopupModel("Unsupported format, plugin version: " + KotlinPluginUtil.getPluginVersion(), project, badRoots)
|
||||
val popup = JBPopupFactory.getInstance().createListPopup(listPopupModel)
|
||||
popup.showUnderneathOf(label)
|
||||
|
||||
@@ -121,6 +176,30 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUpdatePluginLink(answer: ErrorNotificationPanel) {
|
||||
answer.createProgressAction(" Check...", "Update plugin") { link, updateLink ->
|
||||
KotlinPluginUpdater.getInstance().runUpdateCheck { pluginUpdateStatus ->
|
||||
when (pluginUpdateStatus) {
|
||||
is PluginUpdateStatus.Update -> {
|
||||
link.isVisible = false
|
||||
updateLink.isVisible = true
|
||||
|
||||
updateLink.addHyperlinkListener(object : HyperlinkAdapter() {
|
||||
override fun hyperlinkActivated(e: HyperlinkEvent) {
|
||||
KotlinPluginUpdater.getInstance().installPluginUpdate(pluginUpdateStatus)
|
||||
}
|
||||
})
|
||||
}
|
||||
is PluginUpdateStatus.LatestVersionInstalled -> {
|
||||
link.text = "No updates found"
|
||||
}
|
||||
}
|
||||
|
||||
false // do not auto-retry update check
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getKey(): Key<EditorNotificationPanel> = KEY
|
||||
|
||||
override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor): EditorNotificationPanel? {
|
||||
@@ -159,23 +238,50 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
return null
|
||||
}
|
||||
|
||||
private class LibraryRootsPopupModel(title: String, private val project: Project, roots: Collection<VirtualFile>)
|
||||
: BaseListPopupStep<VirtualFile>(title, *roots.toTypedArray()) {
|
||||
private fun findBadRootsInRuntimeLibraries(
|
||||
badRuntimeLibraries: List<Library>,
|
||||
badVersionedRoots: Collection<BinaryVersionedFile<BinaryVersion>>): ArrayList<BinaryVersionedFile<BinaryVersion>> {
|
||||
val badRootsInLibraries = ArrayList<BinaryVersionedFile<BinaryVersion>>()
|
||||
|
||||
override fun getTextFor(root: VirtualFile): String {
|
||||
val relativePath = VfsUtilCore.getRelativePath(root, project.baseDir, '/')
|
||||
return relativePath ?: root.path
|
||||
fun addToBadRoots(file: VirtualFile?) {
|
||||
if (file != null) {
|
||||
val runtimeJarBadRoot = badVersionedRoots.firstOrNull { it.file == file }
|
||||
if (runtimeJarBadRoot != null) {
|
||||
badRootsInLibraries.add(runtimeJarBadRoot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIconFor(aValue: VirtualFile): Icon? {
|
||||
if (aValue.isDirectory) {
|
||||
badRuntimeLibraries.forEach { library ->
|
||||
addToBadRoots(getLocalJar(getRuntimeJar(library)))
|
||||
addToBadRoots(getLocalJar(getJsStdLibJar(library)))
|
||||
addToBadRoots(getLocalJar(getReflectJar(library)))
|
||||
addToBadRoots(getLocalJar(getTestJar(library)))
|
||||
}
|
||||
|
||||
return badRootsInLibraries
|
||||
}
|
||||
|
||||
private class LibraryRootsPopupModel(
|
||||
title: String,
|
||||
private val project: Project,
|
||||
roots: Collection<BinaryVersionedFile<BinaryVersion>>
|
||||
) : BaseListPopupStep<BinaryVersionedFile<BinaryVersion>>(title, *roots.toTypedArray()) {
|
||||
|
||||
override fun getTextFor(root: BinaryVersionedFile<BinaryVersion>): String {
|
||||
val relativePath = VfsUtilCore.getRelativePath(root.file, project.baseDir, '/')
|
||||
return "${relativePath ?: root.file.path} (${root.version}) - expected: ${root.supportedVersion}"
|
||||
}
|
||||
|
||||
override fun getIconFor(aValue: BinaryVersionedFile<BinaryVersion>): Icon? {
|
||||
if (aValue.file.isDirectory) {
|
||||
return AllIcons.Nodes.Folder
|
||||
}
|
||||
return AllIcons.FileTypes.Archive
|
||||
}
|
||||
|
||||
override fun onChosen(selectedValue: VirtualFile, finalChoice: Boolean): PopupStep<Any>? {
|
||||
navigateToLibraryRoot(project, selectedValue)
|
||||
override fun onChosen(selectedValue: BinaryVersionedFile<BinaryVersion>, finalChoice: Boolean): PopupStep<Any>? {
|
||||
navigateToLibraryRoot(project, selectedValue.file)
|
||||
return PopupStep.FINAL_CHOICE
|
||||
}
|
||||
|
||||
@@ -186,6 +292,16 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
init {
|
||||
myLabel.icon = AllIcons.General.Error
|
||||
}
|
||||
|
||||
fun createProgressAction(text: String, successLinkText: String, updater: (JLabel, HyperlinkLabel) -> Unit) {
|
||||
val label = JLabel(text)
|
||||
myLinksPanel.add(label)
|
||||
|
||||
val successLink = createActionLabel(successLinkText, { })
|
||||
successLink.isVisible = false
|
||||
|
||||
updater(label, successLink)
|
||||
}
|
||||
}
|
||||
|
||||
private val updateNotifications = Runnable { updateNotifications() }
|
||||
@@ -205,7 +321,7 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
|
||||
OpenFileDescriptor(project, root).navigate(true)
|
||||
}
|
||||
|
||||
fun collectBadRoots(module: Module): Collection<VirtualFile> {
|
||||
fun collectBadRoots(module: Module): Collection<BinaryVersionedFile<BinaryVersion>> {
|
||||
val badJVMRoots = getLibraryRootsWithAbiIncompatibleKotlinClasses(module)
|
||||
val badJSRoots = getLibraryRootsWithAbiIncompatibleForKotlinJs(module)
|
||||
|
||||
@@ -223,3 +339,16 @@ fun EditorNotificationPanel.createComponentActionLabel(labelText: String, callba
|
||||
}
|
||||
label.set(createActionLabel(labelText, action))
|
||||
}
|
||||
|
||||
private operator fun BinaryVersion.compareTo(other: BinaryVersion): Int {
|
||||
for (i in 0..Math.max(numbers.size, other.numbers.size) - 1) {
|
||||
val thisPart = numbers.getOrNull(i) ?: -1
|
||||
val otherPart = other.numbers.getOrNull(i) ?: -1
|
||||
|
||||
if (thisPart != otherPart) {
|
||||
return thisPart - otherPart
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user