don't show "kotlin not configured" notification for modules where the runtime is outdated
This commit is contained in:
@@ -22,9 +22,6 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.compiler.KotlinCompilerManager</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.NonConfiguredKotlinProjectComponent</implementation-class>
|
||||
</component>
|
||||
|
||||
@@ -41,7 +41,7 @@ abstract class ConfigureKotlinInProjectAction : AnAction() {
|
||||
val configurators = getApplicableConfigurators(project)
|
||||
|
||||
when {
|
||||
configurators.size == 1 -> configurators.first().configure(project)
|
||||
configurators.size == 1 -> configurators.first().configure(project, emptyList())
|
||||
configurators.isEmpty() -> Messages.showErrorDialog("There aren't configurators available", e.presentation.text!!)
|
||||
else -> {
|
||||
Messages.showErrorDialog("More than one configurator is available", e.presentation.text!!)
|
||||
|
||||
@@ -57,17 +57,14 @@ fun getModulesWithKotlinFiles(project: Project): Collection<Module> {
|
||||
fun showConfigureKotlinNotificationIfNeeded(module: Module) {
|
||||
if (isModuleConfigured(module)) return
|
||||
|
||||
showConfigureKotlinNotification(module.project)
|
||||
ConfigureKotlinNotificationManager.notify(module.project)
|
||||
}
|
||||
|
||||
fun showConfigureKotlinNotificationIfNeeded(project: Project) {
|
||||
if (isProjectConfigured(project)) return
|
||||
fun showConfigureKotlinNotificationIfNeeded(project: Project, excludeModules: List<Module> = emptyList()) {
|
||||
val modules = getModulesWithKotlinFiles(project) - excludeModules
|
||||
if (modules.all { isModuleConfigured(it) }) return
|
||||
|
||||
showConfigureKotlinNotification(project)
|
||||
}
|
||||
|
||||
private fun showConfigureKotlinNotification(project: Project) {
|
||||
ConfigureKotlinNotificationManager.notify(project)
|
||||
ConfigureKotlinNotificationManager.notify(project, excludeModules)
|
||||
}
|
||||
|
||||
fun getAbleToRunConfigurators(project: Project): Collection<KotlinProjectConfigurator> {
|
||||
@@ -95,8 +92,8 @@ fun getNonConfiguredModulesWithKotlinFiles(project: Project, configurator: Kotli
|
||||
return modules.filter { module -> configurator.isApplicable(module) && !configurator.isConfigured(module) }
|
||||
}
|
||||
|
||||
fun getNonConfiguredModules(project: Project): Collection<Module> {
|
||||
val modulesWithKotlinFiles = getModulesWithKotlinFiles(project)
|
||||
fun getNonConfiguredModules(project: Project, excludeModules: Collection<Module> = emptyList()): Collection<Module> {
|
||||
val modulesWithKotlinFiles = getModulesWithKotlinFiles(project) - excludeModules
|
||||
return modulesWithKotlinFiles.filter { module ->
|
||||
getAbleToRunConfigurators(project).any { !it.isConfigured(module) }
|
||||
}
|
||||
|
||||
+3
-2
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.idea.configuration
|
||||
|
||||
import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationsManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.idea.configuration.ui.notifications.ConfigureKotlinNotification
|
||||
|
||||
object ConfigureKotlinNotificationManager: KotlinSingleNotificationManager<ConfigureKotlinNotification> {
|
||||
fun notify(project: Project) {
|
||||
notify(project, ConfigureKotlinNotification(project, ConfigureKotlinNotification.getNotificationString(project)))
|
||||
fun notify(project: Project, excludeModules: List<Module> = emptyList()) {
|
||||
notify(project, ConfigureKotlinNotification(project, excludeModules))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.cli.common.KotlinVersion;
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil;
|
||||
import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class KotlinMavenConfigurator implements KotlinProjectConfigurator {
|
||||
@@ -109,9 +110,9 @@ public abstract class KotlinMavenConfigurator implements KotlinProjectConfigurat
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(@NotNull Project project) {
|
||||
public void configure(@NotNull Project project, Collection<Module> excludeModules) {
|
||||
ConfigureDialogWithModulesAndVersion dialog =
|
||||
new ConfigureDialogWithModulesAndVersion(project, this, KOTLIN_VERSIONS);
|
||||
new ConfigureDialogWithModulesAndVersion(project, this, KOTLIN_VERSIONS, excludeModules);
|
||||
|
||||
dialog.show();
|
||||
if (!dialog.isOK()) return;
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface KotlinProjectConfigurator {
|
||||
ExtensionPointName<KotlinProjectConfigurator> EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.projectConfigurator");
|
||||
|
||||
@@ -29,7 +31,7 @@ public interface KotlinProjectConfigurator {
|
||||
|
||||
boolean isApplicable(@NotNull Module module);
|
||||
|
||||
void configure(@NotNull Project project);
|
||||
void configure(@NotNull Project project, Collection<Module> excludeModules);
|
||||
|
||||
@NotNull String getPresentableText();
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrM
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt.showInfoNotification;
|
||||
|
||||
@@ -84,9 +85,9 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(@NotNull Project project) {
|
||||
public void configure(@NotNull Project project, Collection<Module> excludeModules) {
|
||||
ConfigureDialogWithModulesAndVersion dialog =
|
||||
new ConfigureDialogWithModulesAndVersion(project, this, KOTLIN_VERSIONS);
|
||||
new ConfigureDialogWithModulesAndVersion(project, this, KOTLIN_VERSIONS, excludeModules);
|
||||
|
||||
dialog.show();
|
||||
if (!dialog.isOK()) return;
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.idea.project.ProjectStructureUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt.showInfoNotification;
|
||||
@@ -75,7 +76,7 @@ public abstract class KotlinWithLibraryConfigurator implements KotlinProjectConf
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(@NotNull Project project) {
|
||||
public void configure(@NotNull Project project, Collection<Module> excludeModules) {
|
||||
String defaultPathToJar = getDefaultPathToJarFile(project);
|
||||
boolean showPathToJarPanel = needToChooseJarPath(project);
|
||||
|
||||
@@ -83,6 +84,7 @@ public abstract class KotlinWithLibraryConfigurator implements KotlinProjectConf
|
||||
!ApplicationManager.getApplication().isUnitTestMode() ?
|
||||
ConfigureKotlinInProjectUtilsKt.getNonConfiguredModules(project, this) :
|
||||
Arrays.asList(ModuleManager.getInstance(project).getModules());
|
||||
nonConfiguredModules.removeAll(excludeModules);
|
||||
|
||||
List<Module> modulesToConfigure = nonConfiguredModules;
|
||||
String copyLibraryIntoPath = null;
|
||||
@@ -91,7 +93,8 @@ public abstract class KotlinWithLibraryConfigurator implements KotlinProjectConf
|
||||
CreateLibraryDialogWithModules dialog = new CreateLibraryDialogWithModules(
|
||||
project, this, defaultPathToJar, showPathToJarPanel,
|
||||
getDialogTitle(),
|
||||
getLibraryCaption());
|
||||
getLibraryCaption(),
|
||||
excludeModules);
|
||||
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
dialog.show();
|
||||
|
||||
+6
-1
@@ -19,10 +19,14 @@ package org.jetbrains.kotlin.idea.configuration.ui;
|
||||
import com.intellij.notification.NotificationDisplayType;
|
||||
import com.intellij.notification.NotificationsConfiguration;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotificationKt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NonConfiguredKotlinProjectComponent extends AbstractProjectComponent {
|
||||
public static final String CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project";
|
||||
@@ -44,7 +48,8 @@ public class NonConfiguredKotlinProjectComponent extends AbstractProjectComponen
|
||||
DumbService.getInstance(myProject).smartInvokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConfigureKotlinInProjectUtilsKt.showConfigureKotlinNotificationIfNeeded(myProject);
|
||||
List<Module> modulesWithOutdatedRuntime = OutdatedKotlinRuntimeNotificationKt.checkOutdatedKotlinRuntime(myProject);
|
||||
ConfigureKotlinInProjectUtilsKt.showConfigureKotlinNotificationIfNeeded(myProject, modulesWithOutdatedRuntime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+9
-11
@@ -30,19 +30,19 @@ import org.jetbrains.kotlin.idea.configuration.ui.NonConfiguredKotlinProjectComp
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static kotlin.collections.CollectionsKt.first;
|
||||
|
||||
public class ConfigureKotlinNotification extends Notification {
|
||||
private static final String TITLE = "Configure Kotlin";
|
||||
|
||||
@NotNull private final String notificationText;
|
||||
|
||||
public ConfigureKotlinNotification(
|
||||
@NotNull final Project project,
|
||||
@NotNull String notificationText
|
||||
@NotNull final List<Module> excludeModules
|
||||
) {
|
||||
super(NonConfiguredKotlinProjectComponent.CONFIGURE_NOTIFICATION_GROUP_ID, TITLE, notificationText, NotificationType.WARNING, new NotificationListener() {
|
||||
super(NonConfiguredKotlinProjectComponent.CONFIGURE_NOTIFICATION_GROUP_ID, TITLE, getNotificationString(project,excludeModules),
|
||||
NotificationType.WARNING, new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
@@ -52,17 +52,15 @@ public class ConfigureKotlinNotification extends Notification {
|
||||
}
|
||||
notification.expire();
|
||||
|
||||
configurator.configure(project);
|
||||
configurator.configure(project, excludeModules);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.notificationText = notificationText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getNotificationString(Project project) {
|
||||
Collection<Module> modules = ConfigureKotlinInProjectUtilsKt.getNonConfiguredModules(project);
|
||||
public static String getNotificationString(Project project, Collection<Module> excludeModules) {
|
||||
Collection<Module> modules = ConfigureKotlinInProjectUtilsKt.getNonConfiguredModules(project, excludeModules);
|
||||
|
||||
final boolean isOnlyOneModule = modules.size() == 1;
|
||||
|
||||
@@ -92,13 +90,13 @@ public class ConfigureKotlinNotification extends Notification {
|
||||
|
||||
ConfigureKotlinNotification that = (ConfigureKotlinNotification) o;
|
||||
|
||||
if (!notificationText.equals(that.notificationText)) return false;
|
||||
if (!getContent().equals(that.getContent())) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return notificationText.hashCode();
|
||||
return getContent().hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -43,7 +44,7 @@ public class ChooseModulePanel {
|
||||
@NotNull private final List<Module> modules;
|
||||
@NotNull private final List<Module> modulesWithKtFiles;
|
||||
|
||||
public ChooseModulePanel(@NotNull Project project, @NotNull KotlinProjectConfigurator configurator) {
|
||||
public ChooseModulePanel(@NotNull Project project, @NotNull KotlinProjectConfigurator configurator, Collection<Module> excludeModules) {
|
||||
this.project = project;
|
||||
this.modules = ConfigureKotlinInProjectUtilsKt.getNonConfiguredModules(project, configurator);
|
||||
this.modulesWithKtFiles = ConfigureKotlinInProjectUtilsKt.getNonConfiguredModulesWithKotlinFiles(project, configurator);
|
||||
|
||||
+3
-2
@@ -62,7 +62,8 @@ public class ConfigureDialogWithModulesAndVersion extends DialogWrapper {
|
||||
public ConfigureDialogWithModulesAndVersion(
|
||||
@NotNull Project project,
|
||||
@NotNull KotlinProjectConfigurator configurator,
|
||||
@NotNull final String[] kotlinVersions
|
||||
@NotNull final String[] kotlinVersions,
|
||||
@NotNull Collection<Module> excludeModules
|
||||
) {
|
||||
super(project);
|
||||
|
||||
@@ -90,7 +91,7 @@ public class ConfigureDialogWithModulesAndVersion extends DialogWrapper {
|
||||
processIcon.resume();
|
||||
infoPanel.add(processIcon, BorderLayout.CENTER);
|
||||
|
||||
chooseModulePanel = new ChooseModulePanel(project, configurator);
|
||||
chooseModulePanel = new ChooseModulePanel(project, configurator, excludeModules);
|
||||
chooseModulesPanelPlace.add(chooseModulePanel.getContentPane(), BorderLayout.CENTER);
|
||||
|
||||
updateComponents();
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class CreateLibraryDialogWithModules extends CreateLibraryDialogBase {
|
||||
@@ -34,11 +35,12 @@ public class CreateLibraryDialogWithModules extends CreateLibraryDialogBase {
|
||||
@NotNull String defaultPath,
|
||||
boolean showPathPanel,
|
||||
@NotNull String title,
|
||||
@NotNull String libraryCaption
|
||||
@NotNull String libraryCaption,
|
||||
@NotNull Collection<Module> excludeModules
|
||||
) {
|
||||
super(project, defaultPath, title, libraryCaption);
|
||||
|
||||
chooseModulePanel = new ChooseModulePanel(project, configurator);
|
||||
chooseModulePanel = new ChooseModulePanel(project, configurator, excludeModules);
|
||||
chooseModulesPanelPlace.add(chooseModulePanel.getContentPane(), BorderLayout.CENTER);
|
||||
|
||||
chooseLibraryPathPlace.setVisible(showPathPanel);
|
||||
|
||||
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType
|
||||
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||
import org.jetbrains.kotlin.idea.versions.findKotlinLibraries
|
||||
import org.jetbrains.kotlin.idea.versions.findAllUsedLibraries
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -156,7 +156,7 @@ abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixAction<K
|
||||
val configurator = Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)
|
||||
.firstIsInstanceOrNull<KotlinJavaModuleConfigurator>() ?: return
|
||||
|
||||
for (library in findKotlinLibraries(project)) {
|
||||
for (library in findAllUsedLibraries(project).keySet()) {
|
||||
val runtimeJar = JavaRuntimePresentationProvider.getRuntimeJar(library) ?: continue
|
||||
if (hasLibJarInLibrary(library)) continue
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ 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
|
||||
@@ -132,20 +133,18 @@ private fun updateJar(
|
||||
replaceFile(jarPath, localJar!!)
|
||||
}
|
||||
|
||||
fun findKotlinLibraries(project: Project): Collection<Library> {
|
||||
val libraries = Sets.newHashSet<Library>()
|
||||
fun findAllUsedLibraries(project: Project): MultiMap<Library, Module> {
|
||||
val libraries = MultiMap<Library, Module>()
|
||||
|
||||
for (module in ModuleManager.getInstance(project).modules) {
|
||||
val moduleRootManager = ModuleRootManager.getInstance(module)
|
||||
|
||||
for (entry in moduleRootManager.orderEntries) {
|
||||
if (entry is LibraryOrderEntry) {
|
||||
val library = entry.library ?: continue
|
||||
for (entry in moduleRootManager.orderEntries.filterIsInstance<LibraryOrderEntry>()) {
|
||||
val library = entry.library ?: continue
|
||||
|
||||
libraries.add(library)
|
||||
libraries.putValue(library, module)
|
||||
|
||||
// TODO: search js libraries as well
|
||||
}
|
||||
// TODO: search js libraries as well
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+130
-138
@@ -16,17 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.versions
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationListener
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.notification.Notifications
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.AbstractProjectComponent
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.startup.StartupManager
|
||||
import com.intellij.util.PathUtil.getLocalFile
|
||||
import com.intellij.util.text.VersionComparatorUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||
@@ -37,153 +35,147 @@ import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import java.io.IOException
|
||||
import javax.swing.event.HyperlinkEvent
|
||||
|
||||
class OutdatedKotlinRuntimeNotification(project: Project) : AbstractProjectComponent(project) {
|
||||
private data class VersionedLibrary(val library: Library, val version: String?)
|
||||
|
||||
private data class VersionedLibrary(val library: Library, val version: String?)
|
||||
fun checkOutdatedKotlinRuntime(project: Project): List<Module> {
|
||||
val pluginVersion = KotlinPluginUtil.getPluginVersion()
|
||||
if ("@snapshot@" == pluginVersion) return emptyList() // plugin is run from sources, can't compare versions
|
||||
|
||||
override fun projectOpened() {
|
||||
StartupManager.getInstance(myProject).registerPostStartupActivity(Runnable {
|
||||
val pluginVersion = KotlinPluginUtil.getPluginVersion()
|
||||
if ("@snapshot@" == pluginVersion) return@Runnable // plugin is run from sources, can't compare versions
|
||||
// user already clicked suppress
|
||||
if (pluginVersion == PropertiesComponent.getInstance(project).getValue(SUPPRESSED_PROPERTY_NAME)) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
// user already clicked suppress
|
||||
if (pluginVersion == PropertiesComponent.getInstance(myProject).getValue(SUPPRESSED_PROPERTY_NAME)) return@Runnable
|
||||
val versionedOutdatedLibraries = findOutdatedKotlinLibraries(project)
|
||||
if (versionedOutdatedLibraries.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val versionedOutdatedLibraries = findOutdatedKotlinLibraries(myProject)
|
||||
if (versionedOutdatedLibraries.isEmpty()) {
|
||||
return@Runnable
|
||||
val message: String = if (versionedOutdatedLibraries.size == 1) {
|
||||
val versionedLibrary = versionedOutdatedLibraries.keys.first()
|
||||
|
||||
val version = versionedLibrary.version
|
||||
val readableVersion = version ?: "unknown"
|
||||
val libraryName = versionedLibrary.library.name
|
||||
|
||||
"<p>Your version of Kotlin runtime in '$libraryName' library is $readableVersion, while plugin version is $pluginVersion.</p>" +
|
||||
"<p>Runtime library should be updated to avoid compatibility problems.</p>" +
|
||||
"<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>"
|
||||
}
|
||||
else {
|
||||
val libraryNames = versionedOutdatedLibraries.keys.joinToString { it.library.name!! }
|
||||
|
||||
"<p>Version of Kotlin runtime is outdated in several libraries ($libraryNames). Plugin version is $pluginVersion.</p>" +
|
||||
"<p>Runtime libraries should be updated to avoid compatibility problems.</p>" +
|
||||
"<p><a href=\"update\">Update All</a> <a href=\"ignore\">Ignore</a></p>"
|
||||
}
|
||||
|
||||
|
||||
Notifications.Bus.notify(Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
|
||||
NotificationType.WARNING, NotificationListener { notification, event ->
|
||||
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if ("update" == event.description) {
|
||||
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.key.library }
|
||||
updateLibraries(project, outdatedLibraries)
|
||||
suggestDeleteKotlinJsIfNeeded(project, outdatedLibraries)
|
||||
}
|
||||
|
||||
val message: String = if (versionedOutdatedLibraries.size == 1) {
|
||||
val versionedLibrary = versionedOutdatedLibraries.first()
|
||||
|
||||
val version = versionedLibrary.version
|
||||
val readableVersion = version ?: "unknown"
|
||||
val libraryName = versionedLibrary.library.name
|
||||
|
||||
"<p>Your version of Kotlin runtime in '$libraryName' library is $readableVersion, while plugin version is $pluginVersion.</p>" +
|
||||
"<p>Runtime library should be updated to avoid compatibility problems.</p>" +
|
||||
"<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>"
|
||||
else if ("ignore" == event.description) {
|
||||
PropertiesComponent.getInstance(project).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion)
|
||||
}
|
||||
else {
|
||||
val libraryNames = versionedOutdatedLibraries.joinToString { it.library.name!! }
|
||||
|
||||
"<p>Version of Kotlin runtime is outdated in several libraries ($libraryNames). Plugin version is $pluginVersion.</p>" +
|
||||
"<p>Runtime libraries should be updated to avoid compatibility problems.</p>" +
|
||||
"<p><a href=\"update\">Update All</a> <a href=\"ignore\">Ignore</a></p>"
|
||||
throw AssertionError()
|
||||
}
|
||||
notification.expire()
|
||||
}
|
||||
}), project)
|
||||
|
||||
return versionedOutdatedLibraries.flatMap { it.value }
|
||||
}
|
||||
|
||||
Notifications.Bus.notify(Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
|
||||
NotificationType.WARNING, NotificationListener { notification, event ->
|
||||
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if ("update" == event.description) {
|
||||
val outdatedLibraries = findOutdatedKotlinLibraries(myProject).map { it.library }
|
||||
updateLibraries(myProject, outdatedLibraries)
|
||||
suggestDeleteKotlinJsIfNeeded(outdatedLibraries)
|
||||
}
|
||||
else if ("ignore" == event.description) {
|
||||
PropertiesComponent.getInstance(myProject).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion)
|
||||
}
|
||||
else {
|
||||
throw AssertionError()
|
||||
}
|
||||
notification.expire()
|
||||
}
|
||||
}), myProject)
|
||||
})
|
||||
}
|
||||
private fun deleteKotlinJs(project: Project) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
runWriteAction {
|
||||
val kotlinJsFile = project.baseDir.findFileByRelativePath("script/kotlin.js") ?: return@runWriteAction
|
||||
|
||||
private fun deleteKotlinJs() {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
runWriteAction {
|
||||
val kotlinJsFile = myProject.baseDir.findFileByRelativePath("script/kotlin.js") ?: return@runWriteAction
|
||||
|
||||
val fileToDelete = getLocalFile(kotlinJsFile)
|
||||
try {
|
||||
val parent = fileToDelete.parent
|
||||
fileToDelete.delete(this)
|
||||
parent.refresh(false, true)
|
||||
}
|
||||
catch (ex: IOException) {
|
||||
Notifications.Bus.notify(
|
||||
Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Error", "Could not delete 'script/kotlin.js': " + ex.message, NotificationType.ERROR))
|
||||
}
|
||||
val fileToDelete = getLocalFile(kotlinJsFile)
|
||||
try {
|
||||
val parent = fileToDelete.parent
|
||||
fileToDelete.delete(null)
|
||||
parent.refresh(false, true)
|
||||
}
|
||||
catch (ex: IOException) {
|
||||
Notifications.Bus.notify(
|
||||
Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Error", "Could not delete 'script/kotlin.js': " + ex.message, NotificationType.ERROR))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun suggestDeleteKotlinJsIfNeeded(outdatedLibraries: Collection<Library>) {
|
||||
myProject.baseDir.findFileByRelativePath("script/kotlin.js") ?: return
|
||||
|
||||
var addNotification = false
|
||||
for (library in outdatedLibraries) {
|
||||
if (LibraryPresentationProviderUtil.isDetected(JSLibraryStdPresentationProvider.getInstance(), library)) {
|
||||
val jsStdlibJar = JSLibraryStdPresentationProvider.getJsStdLibJar(library)
|
||||
assert(jsStdlibJar != null) { "jslibFile should not be null" }
|
||||
|
||||
if (jsStdlibJar!!.findFileByRelativePath("kotlin.js") == null) {
|
||||
addNotification = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!addNotification) return
|
||||
|
||||
val message = "<p>File 'script/kotlin.js' was probably created by an older version of the Kotlin plugin.</p>" +
|
||||
"<p>The new Kotlin plugin copies an up-to-date version of this file to the output directory automatically, so the old version of it can be deleted.</p>" +
|
||||
"<p><a href=\"delete\">Delete this file</a> <a href=\"ignore\">Ignore</a></p>"
|
||||
|
||||
Notifications.Bus.notify(Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
|
||||
NotificationType.WARNING, NotificationListener { notification, event ->
|
||||
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if ("delete" == event.description) {
|
||||
deleteKotlinJs()
|
||||
}
|
||||
else if ("ignore" == event.description) {
|
||||
// pass
|
||||
}
|
||||
else {
|
||||
throw AssertionError()
|
||||
}
|
||||
notification.expire()
|
||||
}
|
||||
}), myProject)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SUPPRESSED_PROPERTY_NAME = "oudtdated.runtime.suppressed.plugin.version"
|
||||
private val OUTDATED_RUNTIME_GROUP_DISPLAY_ID = "Outdated Kotlin Runtime"
|
||||
|
||||
private fun findOutdatedKotlinLibraries(project: Project): Collection<VersionedLibrary> {
|
||||
val outdatedLibraries = Lists.newArrayList<VersionedLibrary>()
|
||||
|
||||
for (library in findKotlinLibraries(project)) {
|
||||
var libraryVersionProperties = LibraryPresentationProviderUtil.getLibraryProperties(JavaRuntimePresentationProvider.getInstance(), library)
|
||||
if (libraryVersionProperties == null) {
|
||||
libraryVersionProperties = LibraryPresentationProviderUtil.getLibraryProperties(JSLibraryStdPresentationProvider.getInstance(), library)
|
||||
}
|
||||
if (libraryVersionProperties == null) {
|
||||
continue
|
||||
}
|
||||
val libraryVersion = libraryVersionProperties.versionString
|
||||
|
||||
val runtimeVersion = bundledRuntimeVersion()
|
||||
|
||||
val isOutdated = isRuntimeOutdated(libraryVersion, runtimeVersion)
|
||||
|
||||
if (isOutdated) {
|
||||
outdatedLibraries.add(VersionedLibrary(library, libraryVersion))
|
||||
}
|
||||
}
|
||||
|
||||
return outdatedLibraries
|
||||
}
|
||||
|
||||
fun isRuntimeOutdated(libraryVersion: String?, runtimeVersion: String): Boolean {
|
||||
return libraryVersion == null || libraryVersion.startsWith("internal-") != runtimeVersion.startsWith("internal-") ||
|
||||
VersionComparatorUtil.compare(runtimeVersion, libraryVersion) > 0
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun suggestDeleteKotlinJsIfNeeded(project: Project, outdatedLibraries: Collection<Library>) {
|
||||
project.baseDir.findFileByRelativePath("script/kotlin.js") ?: return
|
||||
|
||||
var addNotification = false
|
||||
for (library in outdatedLibraries) {
|
||||
if (LibraryPresentationProviderUtil.isDetected(JSLibraryStdPresentationProvider.getInstance(), library)) {
|
||||
val jsStdlibJar = JSLibraryStdPresentationProvider.getJsStdLibJar(library)
|
||||
assert(jsStdlibJar != null) { "jslibFile should not be null" }
|
||||
|
||||
if (jsStdlibJar!!.findFileByRelativePath("kotlin.js") == null) {
|
||||
addNotification = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!addNotification) return
|
||||
|
||||
val message = "<p>File 'script/kotlin.js' was probably created by an older version of the Kotlin plugin.</p>" +
|
||||
"<p>The new Kotlin plugin copies an up-to-date version of this file to the output directory automatically, so the old version of it can be deleted.</p>" +
|
||||
"<p><a href=\"delete\">Delete this file</a> <a href=\"ignore\">Ignore</a></p>"
|
||||
|
||||
Notifications.Bus.notify(Notification(OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
|
||||
NotificationType.WARNING, NotificationListener { notification, event ->
|
||||
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if ("delete" == event.description) {
|
||||
deleteKotlinJs(project)
|
||||
}
|
||||
else if ("ignore" == event.description) {
|
||||
// pass
|
||||
}
|
||||
else {
|
||||
throw AssertionError()
|
||||
}
|
||||
notification.expire()
|
||||
}
|
||||
}), project)
|
||||
}
|
||||
|
||||
private val SUPPRESSED_PROPERTY_NAME = "oudtdated.runtime.suppressed.plugin.version"
|
||||
private val OUTDATED_RUNTIME_GROUP_DISPLAY_ID = "Outdated Kotlin Runtime"
|
||||
|
||||
private fun findOutdatedKotlinLibraries(project: Project): Map<VersionedLibrary, Collection<Module>> {
|
||||
val outdatedLibraries = hashMapOf<VersionedLibrary, Collection<Module>>()
|
||||
|
||||
for ((library, modules) in findAllUsedLibraries(project).entrySet()) {
|
||||
val libraryVersionProperties =
|
||||
LibraryPresentationProviderUtil.getLibraryProperties(JavaRuntimePresentationProvider.getInstance(), library) ?:
|
||||
LibraryPresentationProviderUtil.getLibraryProperties(JSLibraryStdPresentationProvider.getInstance(), library) ?:
|
||||
continue
|
||||
|
||||
val libraryVersion = libraryVersionProperties.versionString
|
||||
|
||||
val runtimeVersion = bundledRuntimeVersion()
|
||||
|
||||
val isOutdated = isRuntimeOutdated(libraryVersion, runtimeVersion)
|
||||
|
||||
if (isOutdated) {
|
||||
outdatedLibraries[VersionedLibrary(library, libraryVersion)] = modules
|
||||
}
|
||||
}
|
||||
|
||||
return outdatedLibraries
|
||||
}
|
||||
|
||||
fun isRuntimeOutdated(libraryVersion: String?, runtimeVersion: String): Boolean {
|
||||
return libraryVersion == null || libraryVersion.startsWith("internal-") != runtimeVersion.startsWith("internal-") ||
|
||||
VersionComparatorUtil.compare(runtimeVersion, libraryVersion) > 0
|
||||
}
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
||||
private EditorNotificationPanel doCreate(final Collection<VirtualFile> badRoots) {
|
||||
EditorNotificationPanel answer = new ErrorNotificationPanel();
|
||||
|
||||
Collection<Library> kotlinLibraries = KotlinRuntimeLibraryUtilKt.findKotlinLibraries(project);
|
||||
Collection<Library> kotlinLibraries = KotlinRuntimeLibraryUtilKt.findAllUsedLibraries(project).keySet();
|
||||
final Collection<Library> badRuntimeLibraries = Collections2.filter(kotlinLibraries, new Predicate<Library>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable Library library) {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification
|
||||
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||
import org.jetbrains.kotlin.idea.versions.isRuntimeOutdated
|
||||
import org.junit.Assert
|
||||
|
||||
|
||||
@@ -87,12 +87,12 @@ class KotlinRuntimeLibraryUtilTest : TestCase() {
|
||||
|
||||
private fun outdated(plugin: String, library: String) {
|
||||
Assert.assertTrue("Should be outdated: plugin=$plugin, library=$library",
|
||||
OutdatedKotlinRuntimeNotification.isRuntimeOutdated(library, bundledRuntimeVersion(plugin)))
|
||||
isRuntimeOutdated(library, bundledRuntimeVersion(plugin)))
|
||||
}
|
||||
|
||||
private fun notOutdated(plugin: String, library: String) {
|
||||
Assert.assertFalse("Should NOT be outdated: plugin=$plugin, library=$library",
|
||||
OutdatedKotlinRuntimeNotification.isRuntimeOutdated(library, bundledRuntimeVersion(plugin)))
|
||||
isRuntimeOutdated(library, bundledRuntimeVersion(plugin)))
|
||||
}
|
||||
|
||||
private fun test(version: String, expected: String) {
|
||||
|
||||
@@ -127,7 +127,7 @@ public class ConfigureKotlinTest extends PlatformTestCase {
|
||||
new File(JAVA_CONFIGURATOR.getDefaultPathToJarFile(getProject()) + "/kotlin-runtime.jar"));
|
||||
|
||||
assertNotConfigured(module, JAVA_CONFIGURATOR);
|
||||
JAVA_CONFIGURATOR.configure(myProject);
|
||||
JAVA_CONFIGURATOR.configure(myProject, Collections.<Module>emptyList());
|
||||
assertProperlyConfigured(module, JAVA_CONFIGURATOR);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ public class ConfigureKotlinTest extends PlatformTestCase {
|
||||
assertNotConfigured(module, configurator);
|
||||
}
|
||||
|
||||
configurator.configure(myProject);
|
||||
configurator.configure(myProject, Collections.<Module>emptyList());
|
||||
|
||||
assertNoFilesInDefaultPaths();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user