Minor: reformat, and warning fixes in outdated notification subsystem

This commit is contained in:
Nikolay Krasko
2018-01-09 18:45:00 +03:00
parent 2386cfbd07
commit b701117ffb
7 changed files with 171 additions and 150 deletions
@@ -22,7 +22,7 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent import org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent
class KotlinExternalSystemSyncListener : ExternalSystemTaskNotificationListenerAdapter() { class KotlinExternalSystemSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
override fun onStart(id: ExternalSystemTaskId) { override fun onStart(id: ExternalSystemTaskId, workingDir: String) {
if (id.type == ExternalSystemTaskType.RESOLVE_PROJECT) { if (id.type == ExternalSystemTaskType.RESOLVE_PROJECT) {
id.findProject()?.let { project -> id.findProject()?.let { project ->
KotlinConfigurationCheckerComponent.getInstance(project).syncStarted() KotlinConfigurationCheckerComponent.getInstance(project).syncStarted()
@@ -23,6 +23,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion
import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.impl.libraries.LibraryEx import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
@@ -31,13 +32,13 @@ import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.idea.facet.initializeIfNeeded import org.jetbrains.kotlin.idea.facet.initializeIfNeeded
import org.jetbrains.kotlin.idea.framework.JavaRuntimeDetectionUtil
import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
import org.jetbrains.kotlin.idea.util.projectStructure.allModules import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import org.jetbrains.kotlin.idea.util.projectStructure.sdk import org.jetbrains.kotlin.idea.util.projectStructure.sdk
import org.jetbrains.kotlin.idea.util.projectStructure.version import org.jetbrains.kotlin.idea.util.projectStructure.version
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
import org.jetbrains.kotlin.idea.versions.isKotlinJavaRuntime
import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
@@ -73,12 +74,13 @@ open class KotlinJavaModuleConfigurator protected constructor() : KotlinWithLibr
override fun getLibraryJarDescriptors(sdk: Sdk?): List<LibraryJarDescriptor> { override fun getLibraryJarDescriptors(sdk: Sdk?): List<LibraryJarDescriptor> {
var result = listOf( var result = listOf(
LibraryJarDescriptor.RUNTIME_JAR, LibraryJarDescriptor.RUNTIME_JAR,
LibraryJarDescriptor.RUNTIME_SRC_JAR, LibraryJarDescriptor.RUNTIME_SRC_JAR,
LibraryJarDescriptor.REFLECT_JAR, LibraryJarDescriptor.REFLECT_JAR,
LibraryJarDescriptor.REFLECT_SRC_JAR, LibraryJarDescriptor.REFLECT_SRC_JAR,
LibraryJarDescriptor.TEST_JAR, LibraryJarDescriptor.TEST_JAR,
LibraryJarDescriptor.TEST_SRC_JAR) LibraryJarDescriptor.TEST_SRC_JAR
)
val sdkVersion = sdk?.version ?: return result val sdkVersion = sdk?.version ?: return result
if (sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) { if (sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) {
result += listOf(LibraryJarDescriptor.RUNTIME_JDK7_JAR, LibraryJarDescriptor.RUNTIME_JDK7_SOURCES_JAR) result += listOf(LibraryJarDescriptor.RUNTIME_JDK7_JAR, LibraryJarDescriptor.RUNTIME_JDK7_SOURCES_JAR)
@@ -90,8 +92,8 @@ open class KotlinJavaModuleConfigurator protected constructor() : KotlinWithLibr
return result return result
} }
override val libraryMatcher: (Library) -> Boolean override val libraryMatcher: (Library) -> Boolean =
get() = ::isKotlinJavaRuntime { library -> JavaRuntimeDetectionUtil.getRuntimeJar(library.getFiles(OrderRootType.CLASSES).asList()) != null }
override fun configureKotlinSettings(modules: List<Module>) { override fun configureKotlinSettings(modules: List<Module>) {
val project = modules.firstOrNull()?.project ?: return val project = modules.firstOrNull()?.project ?: return
@@ -102,8 +104,7 @@ open class KotlinJavaModuleConfigurator protected constructor() : KotlinWithLibr
Kotlin2JvmCompilerArgumentsHolder.getInstance(project).update { Kotlin2JvmCompilerArgumentsHolder.getInstance(project).update {
jvmTarget = "1.8" jvmTarget = "1.8"
} }
} } else {
else {
for (module in modules) { for (module in modules) {
val sdkVersion = module.sdk?.version val sdkVersion = module.sdk?.version
if (sdkVersion != null && sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_8)) { if (sdkVersion != null && sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_8)) {
@@ -118,19 +119,19 @@ open class KotlinJavaModuleConfigurator protected constructor() : KotlinWithLibr
} }
override fun configureModule( override fun configureModule(
module: Module, module: Module,
classesPath: String, classesPath: String,
sourcesPath: String, sourcesPath: String,
collector: NotificationMessageCollector, collector: NotificationMessageCollector,
forceJarState: FileState?, forceJarState: FileState?,
useBundled: Boolean useBundled: Boolean
) { ) {
super.configureModule(module, classesPath, sourcesPath, collector, forceJarState, useBundled) super.configureModule(module, classesPath, sourcesPath, collector, forceJarState, useBundled)
addStdlibToJavaModuleInfo(module, collector) addStdlibToJavaModuleInfo(module, collector)
} }
companion object { companion object {
val NAME = "java" const val NAME = "java"
val instance: KotlinJavaModuleConfigurator val instance: KotlinJavaModuleConfigurator
get() = Extensions.findExtension(KotlinProjectConfigurator.EP_NAME, KotlinJavaModuleConfigurator::class.java) get() = Extensions.findExtension(KotlinProjectConfigurator.EP_NAME, KotlinJavaModuleConfigurator::class.java)
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.idea.framework.JSLibraryType
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
import org.jetbrains.kotlin.idea.versions.isKotlinJsRuntime
import org.jetbrains.kotlin.js.JavaScript import org.jetbrains.kotlin.js.JavaScript
import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
@@ -60,10 +59,12 @@ open class KotlinJsModuleConfigurator : KotlinWithLibraryConfigurator() {
get() = JSLibraryStdDescription.JAVA_SCRIPT_LIBRARY_CREATION get() = JSLibraryStdDescription.JAVA_SCRIPT_LIBRARY_CREATION
override fun getLibraryJarDescriptors(sdk: Sdk?): List<LibraryJarDescriptor> = override fun getLibraryJarDescriptors(sdk: Sdk?): List<LibraryJarDescriptor> =
listOf(LibraryJarDescriptor.JS_STDLIB_JAR, listOf(
LibraryJarDescriptor.JS_STDLIB_SRC_JAR) LibraryJarDescriptor.JS_STDLIB_JAR,
LibraryJarDescriptor.JS_STDLIB_SRC_JAR
)
override val libraryMatcher: (Library) -> Boolean = ::isKotlinJsRuntime override val libraryMatcher: (Library) -> Boolean = { library -> JsLibraryStdDetectionUtil.hasJsStdlibJar(library) }
override val libraryType: LibraryType<DummyLibraryProperties>? override val libraryType: LibraryType<DummyLibraryProperties>?
get() = JSLibraryType.getInstance() get() = JSLibraryType.getInstance()
@@ -37,10 +37,13 @@ import java.util.concurrent.atomic.AtomicInteger
class KotlinConfigurationCheckerComponent(project: Project) : AbstractProjectComponent(project) { class KotlinConfigurationCheckerComponent(project: Project) : AbstractProjectComponent(project) {
private val syncDepth = AtomicInteger() private val syncDepth = AtomicInteger()
@Volatile private var notificationPostponed = false
@Volatile
private var notificationPostponed = false
init { init {
NotificationsConfiguration.getNotificationsConfiguration().register(CONFIGURE_NOTIFICATION_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true) NotificationsConfiguration.getNotificationsConfiguration()
.register(CONFIGURE_NOTIFICATION_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true)
val connection = project.messageBus.connect() val connection = project.messageBus.connect()
connection.subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener { connection.subscribe(ProjectTopics.PROJECT_ROOTS, object : ModuleRootListener {
@@ -50,8 +53,10 @@ class KotlinConfigurationCheckerComponent(project: Project) : AbstractProjectCom
DumbService.getInstance(myProject).waitForSmartMode() DumbService.getInstance(myProject).waitForSmartMode()
if (!isSyncing) { if (!isSyncing) {
notificationPostponed = false notificationPostponed = false
showConfigureKotlinNotificationIfNeeded(myProject, showConfigureKotlinNotificationIfNeeded(
collectModulesWithOutdatedRuntime(findOutdatedKotlinLibraries(myProject))) myProject,
collectModulesWithOutdatedRuntime(findOutdatedKotlinLibraries(myProject))
)
} }
} }
} }
@@ -81,8 +86,7 @@ class KotlinConfigurationCheckerComponent(project: Project) : AbstractProjectCom
if (!isSyncing) { if (!isSyncing) {
val excludeModules = collectModulesWithOutdatedRuntime(libraries) val excludeModules = collectModulesWithOutdatedRuntime(libraries)
showConfigureKotlinNotificationIfNeeded(myProject, excludeModules) showConfigureKotlinNotificationIfNeeded(myProject, excludeModules)
} } else {
else {
notificationPostponed = true notificationPostponed = true
} }
} }
@@ -100,9 +104,9 @@ class KotlinConfigurationCheckerComponent(project: Project) : AbstractProjectCom
} }
companion object { companion object {
val CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project" const val CONFIGURE_NOTIFICATION_GROUP_ID = "Configure Kotlin in Project"
fun getInstance(project: Project): KotlinConfigurationCheckerComponent fun getInstance(project: Project): KotlinConfigurationCheckerComponent =
= project.getComponent(KotlinConfigurationCheckerComponent::class.java) project.getComponent(KotlinConfigurationCheckerComponent::class.java)
} }
} }
@@ -27,15 +27,18 @@ fun updateLibraries(project: Project, libraries: Collection<Library>) {
"Automatic library version update for Maven and Gradle projects is currently unsupported. " + "Automatic library version update for Maven and Gradle projects is currently unsupported. " +
"Please update your build scripts manually.", "Please update your build scripts manually.",
"Update Kotlin Runtime Library", "Update Kotlin Runtime Library",
Messages.getErrorIcon()) Messages.getErrorIcon()
)
return return
} }
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator? ?: val kJvmConfigurator =
error("Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME) getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator?
?: error("Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME)
val kJsConfigurator = getConfiguratorByName(KotlinJsModuleConfigurator.NAME) as KotlinJsModuleConfigurator? ?: val kJsConfigurator =
error("Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME) getConfiguratorByName(KotlinJsModuleConfigurator.NAME) as KotlinJsModuleConfigurator?
?: error("Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME)
val collector = createConfigureKotlinNotificationCollector(project) val collector = createConfigureKotlinNotificationCollector(project)
val sdk = ProjectRootManager.getInstance(project).projectSdk val sdk = ProjectRootManager.getInstance(project).projectSdk
@@ -56,9 +59,10 @@ fun updateLibraries(project: Project, libraries: Collection<Library>) {
} }
private fun updateJar( private fun updateJar(
project: Project, project: Project,
library: Library, library: Library,
libraryJarDescriptor: LibraryJarDescriptor) { libraryJarDescriptor: LibraryJarDescriptor
) {
val fileToReplace = libraryJarDescriptor.findExistingJar(library) val fileToReplace = libraryJarDescriptor.findExistingJar(library)
if (fileToReplace == null && !libraryJarDescriptor.shouldExist) { if (fileToReplace == null && !libraryJarDescriptor.shouldExist) {
@@ -77,9 +81,11 @@ private fun updateJar(
val newVFile = try { val newVFile = try {
replaceFile(jarPath, jarFileToReplace) replaceFile(jarPath, jarFileToReplace)
} catch (e: IOException) { } catch (e: IOException) {
Messages.showErrorDialog(project, Messages.showErrorDialog(
"Failed to update $jarPath: ${e.message}", project,
"Library update failed") "Failed to update $jarPath: ${e.message}",
"Library update failed"
)
return return
} }
@@ -92,8 +98,7 @@ private fun updateJar(
} }
val newRoot = JarFileSystem.getInstance().getJarRootForLocalFile(newVFile)!! val newRoot = JarFileSystem.getInstance().getJarRootForLocalFile(newVFile)!!
model.addRoot(newRoot, libraryJarDescriptor.orderRootType) model.addRoot(newRoot, libraryJarDescriptor.orderRootType)
} } finally {
finally {
model.commit() model.commit()
} }
} }
@@ -57,7 +57,7 @@ fun findOutdatedKotlinLibraries(project: Project): List<VersionedLibrary> {
return outdatedLibraries return outdatedLibraries
} }
fun getOutdatedRuntimeLibraryVersion(library: Library): String? { private fun getOutdatedRuntimeLibraryVersion(library: Library): String? {
val libraryVersion = getKotlinLibraryVersion(library) ?: return null val libraryVersion = getKotlinLibraryVersion(library) ?: return null
val runtimeVersion = bundledRuntimeVersion() val runtimeVersion = bundledRuntimeVersion()
@@ -65,23 +65,22 @@ fun getOutdatedRuntimeLibraryVersion(library: Library): String? {
} }
private fun getKotlinLibraryVersion(library: Library): String? = private fun getKotlinLibraryVersion(library: Library): String? =
JavaRuntimeDetectionUtil.getJavaRuntimeVersion(library) ?: JavaRuntimeDetectionUtil.getJavaRuntimeVersion(library) ?: JsLibraryStdDetectionUtil.getJsLibraryStdVersion(library)
JsLibraryStdDetectionUtil.getJsLibraryStdVersion(library)
fun findKotlinRuntimeLibrary(module: Module, predicate: (Library) -> Boolean = ::isKotlinRuntime): Library? { fun findKotlinRuntimeLibrary(module: Module, predicate: (Library) -> Boolean = ::isKotlinRuntime): Library? {
val orderEntries = ModuleRootManager.getInstance(module).orderEntries.filterIsInstance<LibraryOrderEntry>() val orderEntries = ModuleRootManager.getInstance(module).orderEntries.filterIsInstance<LibraryOrderEntry>()
return orderEntries.asSequence() return orderEntries.asSequence()
.mapNotNull { it.library } .mapNotNull { it.library }
.firstOrNull(predicate) .firstOrNull(predicate)
} }
fun isKotlinRuntime(library: Library) = isKotlinJavaRuntime(library) || isKotlinJsRuntime(library) private fun isKotlinRuntime(library: Library) = isKotlinJavaRuntime(library) || isKotlinJsRuntime(library)
fun isKotlinJavaRuntime(library: Library) = private fun isKotlinJavaRuntime(library: Library) =
JavaRuntimeDetectionUtil.getRuntimeJar(library.getFiles(OrderRootType.CLASSES).asList()) != null JavaRuntimeDetectionUtil.getRuntimeJar(library.getFiles(OrderRootType.CLASSES).asList()) != null
fun isKotlinJsRuntime(library: Library) = private fun isKotlinJsRuntime(library: Library) =
JsLibraryStdDetectionUtil.hasJsStdlibJar(library) JsLibraryStdDetectionUtil.hasJsStdlibJar(library)
fun collectModulesWithOutdatedRuntime(libraries: List<VersionedLibrary>): List<Module> = fun collectModulesWithOutdatedRuntime(libraries: List<VersionedLibrary>): List<Module> =
libraries.flatMap { it.usedInModules } libraries.flatMap { it.usedInModules }
@@ -96,46 +95,50 @@ fun notifyOutdatedKotlinRuntime(project: Project, outdatedLibraries: Collection<
val libraryName = versionedLibrary.library.name val libraryName = versionedLibrary.library.name
"<p>Your version of Kotlin runtime in '$libraryName' library is $readableVersion, while plugin version is $pluginVersion.</p>" + "<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>Runtime library should be updated to avoid compatibility problems.</p>" +
"<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>" "<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>"
} } else {
else {
val libraryNames = outdatedLibraries.joinToString { it.library.name ?: "unknown library" } val libraryNames = outdatedLibraries.joinToString { it.library.name ?: "unknown library" }
"<p>Version of Kotlin runtime is outdated in several libraries ($libraryNames). Plugin version is $pluginVersion.</p>" + "<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>Runtime libraries should be updated to avoid compatibility problems.</p>" +
"<p><a href=\"update\">Update All</a> <a href=\"ignore\">Ignore</a></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, Notifications.Bus.notify(
NotificationType.WARNING, NotificationListener { notification, event -> Notification(
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) { OUTDATED_RUNTIME_GROUP_DISPLAY_ID, "Outdated Kotlin Runtime", message,
when { NotificationType.WARNING, NotificationListener { notification, event ->
"update" == event.description -> { if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
val outdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library } when {
ApplicationManager.getApplication().invokeLater { "update" == event.description -> {
updateLibraries(project, outdatedLibraries) val updatedOutdatedLibraries = findOutdatedKotlinLibraries(project).map { it.library }
ApplicationManager.getApplication().invokeLater {
updateLibraries(project, updatedOutdatedLibraries)
}
}
"ignore" == event.description -> {
if (!project.isDisposed) {
PropertiesComponent.getInstance(project).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion)
}
}
else -> {
throw AssertionError()
}
} }
} notification.expire()
"ignore" == event.description -> {
if (!project.isDisposed) {
PropertiesComponent.getInstance(project).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion)
}
}
else -> {
throw AssertionError()
} }
} }
notification.expire() ),
} project
}), project) )
} }
private val SUPPRESSED_PROPERTY_NAME = "oudtdated.runtime.suppressed.plugin.version" private const val SUPPRESSED_PROPERTY_NAME = "oudtdated.runtime.suppressed.plugin.version"
private val OUTDATED_RUNTIME_GROUP_DISPLAY_ID = "Outdated Kotlin Runtime" private const val OUTDATED_RUNTIME_GROUP_DISPLAY_ID = "Outdated Kotlin Runtime"
fun isRuntimeOutdated(libraryVersion: String?, runtimeVersion: String): Boolean { fun isRuntimeOutdated(libraryVersion: String?, runtimeVersion: String): Boolean {
return libraryVersion == null || libraryVersion.startsWith("internal-") != runtimeVersion.startsWith("internal-") || return libraryVersion == null || libraryVersion.startsWith("internal-") != runtimeVersion.startsWith("internal-") ||
VersionComparatorUtil.compare(runtimeVersion.substringBefore("-release-"), libraryVersion) > 0 VersionComparatorUtil.compare(runtimeVersion.substringBefore("-release-"), libraryVersion) > 0
} }
@@ -29,13 +29,12 @@ import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.Messages
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.JarFileSystem import com.intellij.openapi.vfs.JarFileSystem
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.JavaPsiFacade import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.PathUtil.getLocalFile
import com.intellij.util.containers.MultiMap import com.intellij.util.containers.MultiMap
import com.intellij.util.indexing.FileBasedIndex import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.ScalarIndexExtension import com.intellij.util.indexing.ScalarIndexExtension
@@ -43,12 +42,9 @@ import com.intellij.util.text.VersionComparatorUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.idea.KotlinPluginUtil
import org.jetbrains.kotlin.idea.framework.JavaRuntimeDetectionUtil import org.jetbrains.kotlin.idea.framework.JavaRuntimeDetectionUtil
import org.jetbrains.kotlin.idea.framework.isExternalLibrary import org.jetbrains.kotlin.idea.framework.isExternalLibrary
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import org.jetbrains.kotlin.idea.util.projectStructure.version import org.jetbrains.kotlin.idea.util.projectStructure.version
import org.jetbrains.kotlin.idea.util.runWithAlternativeResolveEnabled import org.jetbrains.kotlin.idea.util.runWithAlternativeResolveEnabled
import org.jetbrains.kotlin.idea.vfilefinder.KotlinJavaScriptMetaFileIndex import org.jetbrains.kotlin.idea.vfilefinder.KotlinJavaScriptMetaFileIndex
@@ -87,10 +83,12 @@ fun findAllUsedLibraries(project: Project): MultiMap<Library, Module> {
return libraries return libraries
} }
enum class LibraryJarDescriptor(val jarName: String, enum class LibraryJarDescriptor(
val orderRootType: OrderRootType, val jarName: String,
val shouldExist: Boolean, val orderRootType: OrderRootType,
val getPath: (KotlinPaths) -> File = { paths -> File(paths.libPath, jarName) }) { val shouldExist: Boolean,
val getPath: (KotlinPaths) -> File = { paths -> File(paths.libPath, jarName) }
) {
RUNTIME_JAR(PathUtil.KOTLIN_JAVA_STDLIB_JAR, OrderRootType.CLASSES, true, KotlinPaths::getStdlibPath) { RUNTIME_JAR(PathUtil.KOTLIN_JAVA_STDLIB_JAR, OrderRootType.CLASSES, true, KotlinPaths::getStdlibPath) {
override fun findExistingJar(library: Library): VirtualFile? { override fun findExistingJar(library: Library): VirtualFile? {
if (isExternalLibrary(library)) return null if (isExternalLibrary(library)) return null
@@ -120,8 +118,10 @@ enum class LibraryJarDescriptor(val jarName: String,
RUNTIME_SRC_JAR(PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR, OrderRootType.SOURCES, false, KotlinPaths::getStdlibSourcesPath) { RUNTIME_SRC_JAR(PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR, OrderRootType.SOURCES, false, KotlinPaths::getStdlibSourcesPath) {
override fun findExistingJar(library: Library): VirtualFile? { override fun findExistingJar(library: Library): VirtualFile? {
return super.findExistingJar(library) ?: return super.findExistingJar(library) ?: LibraryUtils.getJarFile(
LibraryUtils.getJarFile(library.getFiles(orderRootType).toList(), PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR_OLD) library.getFiles(orderRootType).toList(),
PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR_OLD
)
} }
}, },
REFLECT_SRC_JAR(PathUtil.KOTLIN_REFLECT_SRC_JAR, OrderRootType.SOURCES, false), REFLECT_SRC_JAR(PathUtil.KOTLIN_REFLECT_SRC_JAR, OrderRootType.SOURCES, false),
@@ -154,15 +154,16 @@ fun getLocalJar(kotlinRuntimeJar: VirtualFile?): VirtualFile? {
data class BinaryVersionedFile<out T : BinaryVersion>(val file: VirtualFile, val version: T, val supportedVersion: T) data class BinaryVersionedFile<out T : BinaryVersion>(val file: VirtualFile, val version: T, val supportedVersion: T)
private fun <T : BinaryVersion> getLibraryRootsWithAbiIncompatibleVersion( private fun <T : BinaryVersion> getLibraryRootsWithAbiIncompatibleVersion(
module: Module, module: Module,
supportedVersion: T, supportedVersion: T,
index: ScalarIndexExtension<T> index: ScalarIndexExtension<T>
): Collection<BinaryVersionedFile<T>> { ): Collection<BinaryVersionedFile<T>> {
val id = index.name val id = index.name
val moduleWithAllDependencies = setOf(module) + ModuleUtil.getAllDependentModules(module) val moduleWithAllDependencies = setOf(module) + ModuleUtil.getAllDependentModules(module)
val moduleWithAllDependentLibraries = GlobalSearchScope.union( val moduleWithAllDependentLibraries = GlobalSearchScope.union(
moduleWithAllDependencies.map { it.moduleWithLibrariesScope }.toTypedArray()) moduleWithAllDependencies.map { it.moduleWithLibrariesScope }.toTypedArray()
)
val allVersions = FileBasedIndex.getInstance().getAllKeys(id, module.project) val allVersions = FileBasedIndex.getInstance().getAllKeys(id, module.project)
val badVersions = allVersions.filterNot(BinaryVersion::isCompatible).toHashSet() val badVersions = allVersions.filterNot(BinaryVersion::isCompatible).toHashSet()
@@ -172,10 +173,11 @@ private fun <T : BinaryVersion> getLibraryRootsWithAbiIncompatibleVersion(
for (version in badVersions) { for (version in badVersions) {
val indexedFiles = FileBasedIndex.getInstance().getContainingFiles(id, version, moduleWithAllDependentLibraries) val indexedFiles = FileBasedIndex.getInstance().getContainingFiles(id, version, moduleWithAllDependentLibraries)
for (indexedFile in indexedFiles) { for (indexedFile in indexedFiles) {
val libraryRoot = fileIndex.getClassRootForFile(indexedFile) ?: val libraryRoot = fileIndex.getClassRootForFile(indexedFile) ?: error(
error("Only library roots were requested, and only class files should be indexed with the $id key. " + "Only library roots were requested, and only class files should be indexed with the $id key. " +
"File: ${indexedFile.path}") "File: ${indexedFile.path}"
badRoots.add(BinaryVersionedFile(getLocalFile(libraryRoot), version, supportedVersion)) )
badRoots.add(BinaryVersionedFile(VfsUtil.getLocalFile(libraryRoot), version, supportedVersion))
} }
} }
@@ -183,9 +185,11 @@ private fun <T : BinaryVersion> getLibraryRootsWithAbiIncompatibleVersion(
} }
fun showRuntimeJarNotFoundDialog(project: Project, jarName: String) { fun showRuntimeJarNotFoundDialog(project: Project, jarName: String) {
Messages.showErrorDialog(project, Messages.showErrorDialog(
jarName + " is not found. Make sure plugin is properly installed.", project,
"No Runtime Found") jarName + " is not found. Make sure plugin is properly installed.",
"No Runtime Found"
)
} }
fun getKotlinJvmRuntimeMarkerClass(project: Project, scope: GlobalSearchScope): PsiClass? { fun getKotlinJvmRuntimeMarkerClass(project: Project, scope: GlobalSearchScope): PsiClass? {
@@ -243,72 +247,75 @@ fun isSnapshot(version: String): Boolean {
} }
fun hasJdkLikeUpdatedRuntime(version: String): Boolean = fun hasJdkLikeUpdatedRuntime(version: String): Boolean =
VersionComparatorUtil.compare(version, "1.2.0-rc-39") >= 0 || VersionComparatorUtil.compare(version, "1.2.0-rc-39") >= 0 ||
isSnapshot(version) || isSnapshot(version) ||
version == "default_version" /* for tests */ version == "default_version" /* for tests */
fun hasJreSpecificRuntime(version: String): Boolean = fun hasJreSpecificRuntime(version: String): Boolean =
VersionComparatorUtil.compare(version, "1.1.0") >= 0 || VersionComparatorUtil.compare(version, "1.1.0") >= 0 ||
isSnapshot(version) || isSnapshot(version) ||
version == "default_version" /* for tests */ version == "default_version" /* for tests */
val MAVEN_STDLIB_ID = PathUtil.KOTLIN_JAVA_STDLIB_NAME const val MAVEN_STDLIB_ID = PathUtil.KOTLIN_JAVA_STDLIB_NAME
val MAVEN_STDLIB_ID_JRE7 = PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME const val MAVEN_STDLIB_ID_JRE7 = PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME
val MAVEN_STDLIB_ID_JDK7 = PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME const val MAVEN_STDLIB_ID_JDK7 = PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME
val MAVEN_STDLIB_ID_JRE8 = PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME const val MAVEN_STDLIB_ID_JRE8 = PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME
val MAVEN_STDLIB_ID_JDK8 = PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME const val MAVEN_STDLIB_ID_JDK8 = PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME
val MAVEN_JS_STDLIB_ID = PathUtil.JS_LIB_NAME const val MAVEN_JS_STDLIB_ID = PathUtil.JS_LIB_NAME
val MAVEN_JS_TEST_ID = PathUtil.KOTLIN_TEST_JS_NAME const val MAVEN_JS_TEST_ID = PathUtil.KOTLIN_TEST_JS_NAME
val MAVEN_OLD_JS_STDLIB_ID = "kotlin-js-library" const val MAVEN_OLD_JS_STDLIB_ID = "kotlin-js-library"
val MAVEN_COMMON_STDLIB_ID = "kotlin-stdlib-common" // TODO: KotlinCommonMavenConfigurator const val MAVEN_COMMON_STDLIB_ID = "kotlin-stdlib-common" // TODO: KotlinCommonMavenConfigurator
val MAVEN_TEST_ID = PathUtil.KOTLIN_TEST_NAME const val MAVEN_TEST_ID = PathUtil.KOTLIN_TEST_NAME
val MAVEN_TEST_JUNIT_ID = "kotlin-test-junit" const val MAVEN_TEST_JUNIT_ID = "kotlin-test-junit"
val MAVEN_COMMON_TEST_ID = "kotlin-test-common" const val MAVEN_COMMON_TEST_ID = "kotlin-test-common"
val MAVEN_COMMON_TEST_ANNOTATIONS_ID = "kotlin-test-annotations-common" const val MAVEN_COMMON_TEST_ANNOTATIONS_ID = "kotlin-test-annotations-common"
val LOG = Logger.getInstance("org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt") val LOG = Logger.getInstance("org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt")
data class LibInfo( data class LibInfo(
val groupId: String, val groupId: String,
val name: String val name: String
) )
data class DeprecatedLibInfo( data class DeprecatedLibInfo(
val old: LibInfo, val old: LibInfo,
val new: LibInfo, val new: LibInfo,
val outdatedAfterVersion: String, val outdatedAfterVersion: String,
val message: String val message: String
) )
private fun deprecatedLib( private fun deprecatedLib(
oldGroupId: String, oldGroupId: String,
oldName: String, oldName: String,
newGroupId: String = oldGroupId, newGroupId: String = oldGroupId,
newName: String = oldName, newName: String = oldName,
outdatedAfterVersion: String, outdatedAfterVersion: String,
message: String): DeprecatedLibInfo { message: String
): DeprecatedLibInfo {
return DeprecatedLibInfo( return DeprecatedLibInfo(
old = LibInfo(groupId = oldGroupId, name = oldName), old = LibInfo(groupId = oldGroupId, name = oldName),
new = LibInfo(groupId = newGroupId, name = newName), new = LibInfo(groupId = newGroupId, name = newName),
outdatedAfterVersion = outdatedAfterVersion, outdatedAfterVersion = outdatedAfterVersion,
message = message message = message
) )
} }
val DEPRECATED_LIBRARIES_INFORMATION = listOf( val DEPRECATED_LIBRARIES_INFORMATION = listOf(
deprecatedLib( deprecatedLib(
oldGroupId = "org.jetbrains.kotlin", oldGroupId = "org.jetbrains.kotlin",
oldName = PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME, newName = PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME, oldName = PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME, newName = PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME,
outdatedAfterVersion = "1.2.0-rc-39", outdatedAfterVersion = "1.2.0-rc-39",
message = "${PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME} is deprecated since 1.2.0 and should be replaced with ${PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME}"), message = "${PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME} is deprecated since 1.2.0 and should be replaced with ${PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME}"
),
deprecatedLib( deprecatedLib(
oldGroupId = "org.jetbrains.kotlin", oldGroupId = "org.jetbrains.kotlin",
oldName = PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME, newName = PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME, oldName = PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME, newName = PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME,
outdatedAfterVersion = "1.2.0-rc-39", outdatedAfterVersion = "1.2.0-rc-39",
message = "${PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME} is deprecated since 1.2.0 and should be replaced with ${PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME}") message = "${PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME} is deprecated since 1.2.0 and should be replaced with ${PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME}"
)
) )