don't show "kotlin not configured" notification for modules where the runtime is outdated

This commit is contained in:
Dmitry Jemerov
2015-11-23 14:10:58 +01:00
parent 85ea295e92
commit 2379fd80fc
19 changed files with 194 additions and 194 deletions
-3
View File
@@ -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) }
}
@@ -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();
@@ -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);
}
});
}
@@ -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);
@@ -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
}
}
@@ -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
}
@@ -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();