code review

This commit is contained in:
Dmitry Jemerov
2016-01-21 12:39:20 +01:00
parent 4910b06f2c
commit 84d507b770
10 changed files with 66 additions and 59 deletions
+2 -2
View File
@@ -23,7 +23,7 @@
<implementation-class>org.jetbrains.kotlin.idea.compiler.KotlinCompilerManager</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.NonConfiguredKotlinProjectComponent</implementation-class>
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.highlighter.KotlinBeforeResolveHighlightingPass$Factory</implementation-class>
@@ -576,7 +576,7 @@
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanelProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.highlighter.ErrorDuringFileAnalyzeNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.configuration.KotlinSetupSDKNotificationProvider"/>
<editorNotificationProvider implementation="org.jetbrains.kotlin.idea.configuration.KotlinSetupEnvironmentNotificationProvider"/>
<psi.treeChangePreprocessor implementation="org.jetbrains.kotlin.asJava.KotlinCodeBlockModificationListener"/>
@@ -25,14 +25,15 @@ import org.jetbrains.kotlin.idea.configuration.KotlinModuleTypeManager;
public class KotlinModuleTypeManagerImpl extends KotlinModuleTypeManager {
@Override
public boolean isAndroidGradleModule(@NotNull Module module) {
// We don't want to depend on the Android-Gradle plugin
// See com.android.tools.idea.gradle.util.Projects.isGradleProject()
boolean hasAndroidFacet = false;
return hasAndroidFacet(module) && isGradleModule(module);
}
private static boolean hasAndroidFacet(@NotNull Module module) {
for (Facet facet : FacetManager.getInstance(module).getAllFacets()) {
if (facet.getName().equals("Android")) {
hasAndroidFacet = true;
return true;
}
}
return hasAndroidFacet && isGradleModule(module);
return false;
}
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.utils.ifEmpty
@@ -21,11 +21,11 @@ import com.intellij.notification.NotificationType
import com.intellij.notification.Notifications
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.psi.search.FileTypeIndex
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import org.jetbrains.kotlin.utils.ifEmpty
fun isProjectConfigured(project: Project): Boolean {
@@ -33,8 +33,6 @@ fun isProjectConfigured(project: Project): Boolean {
return modules.all { isModuleConfigured(it) }
}
fun Project.allModules() = ModuleManager.getInstance(this).modules.toList()
fun isModuleConfigured(module: Module): Boolean {
val configurators = getApplicableConfigurators(module)
return configurators.any { it.isConfigured(module) }
@@ -94,8 +92,9 @@ fun getNonConfiguredModulesWithKotlinFiles(project: Project, configurator: Kotli
fun getNonConfiguredModules(project: Project, excludeModules: Collection<Module> = emptyList()): Collection<Module> {
val modulesWithKotlinFiles = getModulesWithKotlinFiles(project) - excludeModules
val ableToRunConfigurators = getAbleToRunConfigurators(project)
return modulesWithKotlinFiles.filter { module ->
getAbleToRunConfigurators(project).any { !it.isConfigured(module) }
ableToRunConfigurators.any { !it.isConfigured(module) }
}
}
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanel
import org.jetbrains.kotlin.idea.versions.createComponentActionLabel
// Code is partially copied from com.intellij.codeInsight.daemon.impl.SetupSDKNotificationProvider
class KotlinSetupSDKNotificationProvider(
class KotlinSetupEnvironmentNotificationProvider(
private val myProject: Project,
notifications: EditorNotifications) : EditorNotifications.Provider<EditorNotificationPanel>(), DumbAware {
@@ -19,19 +19,19 @@ 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 org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeCheckerKt;
import org.jetbrains.kotlin.idea.versions.VersionedLibrary;
import java.util.List;
public class NonConfiguredKotlinProjectComponent extends AbstractProjectComponent {
public class KotlinConfigurationCheckerComponent extends AbstractProjectComponent {
public static final String CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project";
protected NonConfiguredKotlinProjectComponent(Project project) {
protected KotlinConfigurationCheckerComponent(Project project) {
super(project);
NotificationsConfiguration.getNotificationsConfiguration().
@@ -48,8 +48,13 @@ public class NonConfiguredKotlinProjectComponent extends AbstractProjectComponen
DumbService.getInstance(myProject).smartInvokeLater(new Runnable() {
@Override
public void run() {
List<Module> modulesWithOutdatedRuntime = OutdatedKotlinRuntimeNotificationKt.checkOutdatedKotlinRuntime(myProject);
ConfigureKotlinInProjectUtilsKt.showConfigureKotlinNotificationIfNeeded(myProject, modulesWithOutdatedRuntime);
List<VersionedLibrary> libraries = OutdatedKotlinRuntimeCheckerKt.findOutdatedKotlinLibraries(myProject);
if (!libraries.isEmpty()) {
OutdatedKotlinRuntimeCheckerKt.notifyOutdatedKotlinRuntime(myProject, libraries);
}
ConfigureKotlinInProjectUtilsKt.showConfigureKotlinNotificationIfNeeded(myProject,
OutdatedKotlinRuntimeCheckerKt
.collectModulesWithOutdatedRuntime(libraries));
}
});
}
@@ -26,7 +26,7 @@ import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt;
import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator;
import org.jetbrains.kotlin.idea.configuration.ui.NonConfiguredKotlinProjectComponent;
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent;
import javax.swing.event.HyperlinkEvent;
import java.util.Collection;
@@ -41,7 +41,7 @@ public class ConfigureKotlinNotification extends Notification {
@NotNull final Project project,
@NotNull final List<Module> excludeModules
) {
super(NonConfiguredKotlinProjectComponent.CONFIGURE_NOTIFICATION_GROUP_ID, TITLE, getNotificationString(project,excludeModules),
super(KotlinConfigurationCheckerComponent.CONFIGURE_NOTIFICATION_GROUP_ID, TITLE, getNotificationString(project, excludeModules),
NotificationType.WARNING, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
@@ -16,12 +16,16 @@
package org.jetbrains.kotlin.idea.util.projectStructure
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.OrderEnumerator
import java.io.File
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vfs.VfsUtil
import java.io.File
fun Project.allModules() = ModuleManager.getInstance(this).modules.toList()
fun Module.findLibrary(predicate: (Library) -> Boolean): Library? = OrderEnumerator.orderEntries(this).findLibrary(predicate)
@@ -59,7 +59,7 @@ fun getLibraryRootsWithAbiIncompatibleKotlinClasses(module: Module): Collection<
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(module: Module): Collection<VirtualFile> {
return getLibraryRootsWithAbiIncompatibleVersion(
module, KotlinJavaScriptAbiVersionIndex,
{ version -> !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.minor) }) // TODO: support major.minor.patch version in JS metadata
{ version -> !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.minor) }) // TODO: support major.minor.patch version in JS metadata
}
@@ -35,9 +35,9 @@ import org.jetbrains.kotlin.idea.util.application.runWriteAction
import java.io.IOException
import javax.swing.event.HyperlinkEvent
private data class VersionedLibrary(val library: Library, val version: String?)
data class VersionedLibrary(val library: Library, val version: String?, val usedInModules: Collection<Module>)
fun checkOutdatedKotlinRuntime(project: Project): List<Module> {
fun findOutdatedKotlinLibraries(project: Project): List<VersionedLibrary> {
val pluginVersion = KotlinPluginUtil.getPluginVersion()
if ("@snapshot@" == pluginVersion) return emptyList() // plugin is run from sources, can't compare versions
@@ -46,13 +46,35 @@ fun checkOutdatedKotlinRuntime(project: Project): List<Module> {
return emptyList()
}
val versionedOutdatedLibraries = findOutdatedKotlinLibraries(project)
if (versionedOutdatedLibraries.isEmpty()) {
return emptyList()
val outdatedLibraries = arrayListOf<VersionedLibrary>()
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.add(VersionedLibrary(library, libraryVersion, modules))
}
}
val message: String = if (versionedOutdatedLibraries.size == 1) {
val versionedLibrary = versionedOutdatedLibraries.keys.first()
return outdatedLibraries
}
fun collectModulesWithOutdatedRuntime(libraries: List<VersionedLibrary>): List<Module> =
libraries.flatMap { it.usedInModules }
fun notifyOutdatedKotlinRuntime(project: Project, outdatedLibraries: Collection<VersionedLibrary>) {
val pluginVersion = KotlinPluginUtil.getPluginVersion()
val message: String = if (outdatedLibraries.size == 1) {
val versionedLibrary = outdatedLibraries.first()
val version = versionedLibrary.version
val readableVersion = version ?: "unknown"
@@ -63,7 +85,7 @@ fun checkOutdatedKotlinRuntime(project: Project): List<Module> {
"<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>"
}
else {
val libraryNames = versionedOutdatedLibraries.keys.joinToString { it.library.name!! }
val libraryNames = outdatedLibraries.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>" +
@@ -75,7 +97,7 @@ fun checkOutdatedKotlinRuntime(project: Project): List<Module> {
NotificationType.WARNING, NotificationListener { notification, event ->
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
if ("update" == event.description) {
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.key.library }
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library }
updateLibraries(project, outdatedLibraries)
suggestDeleteKotlinJsIfNeeded(project, outdatedLibraries)
}
@@ -88,11 +110,9 @@ fun checkOutdatedKotlinRuntime(project: Project): List<Module> {
notification.expire()
}
}), project)
return versionedOutdatedLibraries.flatMap { it.value }
}
private fun deleteKotlinJs(project: Project) {
fun deleteKotlinJs(project: Project) {
ApplicationManager.getApplication().invokeLater {
runWriteAction {
val kotlinJsFile = project.baseDir.findFileByRelativePath("script/kotlin.js") ?: return@runWriteAction
@@ -152,29 +172,6 @@ private fun suggestDeleteKotlinJsIfNeeded(project: Project, outdatedLibraries: C
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