From f9aff3be13813ab07734621447aeb6bee0559068 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 3 Apr 2017 11:47:28 +0200 Subject: [PATCH] Rewrite configureModuleWithLibrary() based on LibraryJarDescriptor Also remove duplicated logic for identifying Kotlin libraries. --- .../framework/JsLibraryStdDetectionUtil.kt | 2 +- .../KotlinJavaModuleConfigurator.kt | 14 +- .../KotlinJsModuleConfigurator.java | 9 + .../KotlinWithLibraryConfigurator.kt | 268 ++++-------------- .../idea/inspections/AddKotlinLibQuickFix.kt | 3 +- .../quickfix/EnableUnsupportedFeatureFix.kt | 2 +- .../idea/versions/KotlinRuntimeLibraryUtil.kt | 5 +- .../versions/OutdatedKotlinRuntimeChecker.kt | 18 +- .../AbstractConfigureKotlinTest.java | 32 ++- .../configuration/ConfigureKotlinTest.java | 48 +--- 10 files changed, 120 insertions(+), 281 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/JsLibraryStdDetectionUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/JsLibraryStdDetectionUtil.kt index fe9fcd3e373..063c6881418 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/JsLibraryStdDetectionUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/JsLibraryStdDetectionUtil.kt @@ -53,7 +53,7 @@ object JsLibraryStdDetectionUtil { return JarUtil.getJarAttribute(VfsUtilCore.virtualToIoFile(jar), Attributes.Name.IMPLEMENTATION_VERSION) } - private fun getJsStdLibJar(classesRoots: List): VirtualFile? { + fun getJsStdLibJar(classesRoots: List): VirtualFile? { for (root in classesRoots) { if (root.fileSystem.protocol !== StandardFileSystems.JAR_PROTOCOL) continue diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt index e63bf4411ac..cbd71cad098 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt @@ -18,12 +18,10 @@ package org.jetbrains.kotlin.idea.configuration import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.module.Module -import com.intellij.openapi.module.impl.scopes.LibraryScope -import com.intellij.openapi.project.Project import com.intellij.openapi.roots.libraries.Library import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor -import org.jetbrains.kotlin.idea.versions.getKotlinJvmRuntimeMarkerClass +import org.jetbrains.kotlin.idea.versions.isKotlinJavaRuntime import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.utils.PathUtil @@ -71,14 +69,8 @@ open class KotlinJavaModuleConfigurator internal constructor() : KotlinWithLibra LibraryJarDescriptor.RUNTIME_SRC_JAR, LibraryJarDescriptor.TEST_JAR) - override fun isKotlinLibrary(project: Project, library: Library): Boolean { - if (super.isKotlinLibrary(project, library)) { - return true - } - - val scope = LibraryScope(project, library) - return getKotlinJvmRuntimeMarkerClass(project, scope) != null - } + override val libraryMatcher: (Library) -> Boolean + get() = ::isKotlinJavaRuntime companion object { val NAME = "java" diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java index e2838ab8af0..4e9f4123e2e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java @@ -17,9 +17,12 @@ package org.jetbrains.kotlin.idea.configuration; import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.libraries.Library; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.framework.JSLibraryStdDescription; import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor; +import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeCheckerKt; import org.jetbrains.kotlin.js.JavaScript; import org.jetbrains.kotlin.js.resolve.JsPlatform; import org.jetbrains.kotlin.resolve.TargetPlatform; @@ -97,6 +100,12 @@ public class KotlinJsModuleConfigurator extends KotlinWithLibraryConfigurator { LibraryJarDescriptor.JS_STDLIB_SRC_JAR); } + @NotNull + @Override + protected Function1 getLibraryMatcher() { + return OutdatedKotlinRuntimeCheckerKt::isKotlinJsRuntime; + } + KotlinJsModuleConfigurator() { } } diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt index 794de13bc83..12873d31198 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt @@ -23,18 +23,18 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.roots.* import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar -import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer -import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory import com.intellij.openapi.ui.Messages -import com.intellij.openapi.util.Ref +import com.intellij.openapi.vfs.JarFileSystem +import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.util.Processor import org.jetbrains.annotations.Contract import org.jetbrains.kotlin.idea.KotlinPluginUtil import org.jetbrains.kotlin.idea.framework.ui.CreateLibraryDialogWithModules import org.jetbrains.kotlin.idea.framework.ui.FileUIUtils +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor +import org.jetbrains.kotlin.idea.versions.findKotlinRuntimeLibrary import java.io.File import java.util.* @@ -114,122 +114,60 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj ) { val project = module.project - val files = existingJarFiles - val libraryState = getLibraryState(project) - val dirToCopyJar = getPathToCopyFileTo(project, OrderRootType.CLASSES, defaultPath, pathFromDialog) - val runtimeState = getJarState(project, files.getRuntimeDestination(dirToCopyJar), OrderRootType.CLASSES, pathFromDialog == null) + val library = getKotlinLibrary(module) ?: createNewLibrary(project, collector) - configureModuleWithLibraryClasses(module, libraryState, runtimeState, dirToCopyJar, collector) + for (descriptor in libraryJarDescriptors) { + val dirToCopyJar = getPathToCopyFileTo(project, descriptor.orderRootType, defaultPath, pathFromDialog) + val runtimeState = getJarState(project, + File(dirToCopyJar, descriptor.jarName), + descriptor.orderRootType, pathFromDialog == null) - val library = getKotlinLibrary(project) ?: return - - val dirToCopySourcesJar = getPathToCopyFileTo(project, OrderRootType.SOURCES, defaultPath, pathFromDialog) - val sourcesState = getJarState(project, files.getRuntimeSourcesDestination(dirToCopySourcesJar), OrderRootType.SOURCES, - pathFromDialog == null) - - configureModuleWithLibrarySources(library, sourcesState, dirToCopySourcesJar, collector) - } - - fun configureModuleWithLibraryClasses( - module: Module, - libraryState: LibraryState, - jarState: FileState, - dirToCopyJarTo: String, - collector: NotificationMessageCollector - ) { - val project = module.project - val files = existingJarFiles - val runtimeJar = files.runtimeJar - val reflectJar = files.reflectJar - - when (libraryState) { - KotlinWithLibraryConfigurator.LibraryState.LIBRARY -> when (jarState) { - KotlinWithLibraryConfigurator.FileState.EXISTS -> { - } - KotlinWithLibraryConfigurator.FileState.COPY -> { - copyFileToDir(runtimeJar, dirToCopyJarTo, collector) - if (reflectJar != null) { - copyFileToDir(reflectJar, dirToCopyJarTo, collector) - } - } - KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> { - throw IllegalStateException( - "Kotlin library exists, so path to copy should be hidden in configuration dialog and jar should be copied using path in library table") - } - } - KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY -> when (jarState) { - KotlinWithLibraryConfigurator.FileState.EXISTS -> { - addJarsToExistingLibrary( - project, files.getRuntimeDestination(dirToCopyJarTo), files.getReflectDestination(dirToCopyJarTo), collector - ) - } - KotlinWithLibraryConfigurator.FileState.COPY -> { - val copiedRuntimeJar = copyFileToDir(runtimeJar, dirToCopyJarTo, collector) - val copiedReflectJar = copyFileToDir(reflectJar, dirToCopyJarTo, collector) - addJarsToExistingLibrary(project, copiedRuntimeJar!!, copiedReflectJar, collector) - } - KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> { - addJarsToExistingLibrary(project, runtimeJar, reflectJar, collector) - } - } - KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY -> when (jarState) { - KotlinWithLibraryConfigurator.FileState.EXISTS -> { - addJarsToNewLibrary( - project, files.getRuntimeDestination(dirToCopyJarTo), files.getReflectDestination(dirToCopyJarTo), collector - ) - } - KotlinWithLibraryConfigurator.FileState.COPY -> { - val copiedRuntimeJar = copyFileToDir(runtimeJar, dirToCopyJarTo, collector) - val copiedReflectJar = copyFileToDir(reflectJar, dirToCopyJarTo, collector) - addJarsToNewLibrary(project, copiedRuntimeJar!!, copiedReflectJar, collector) - } - KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> { - addJarsToNewLibrary(project, runtimeJar, reflectJar, collector) - } - } + configureLibraryJar(module, library, runtimeState, dirToCopyJar, descriptor, collector) } - - addLibraryToModuleIfNeeded(module, collector) } - protected fun configureModuleWithLibrarySources( + fun configureLibraryJar( + module: Module, library: Library, jarState: FileState, - dirToCopyJarTo: String?, + dirToCopyJarTo: String, + libraryJarDescriptor: LibraryJarDescriptor, collector: NotificationMessageCollector ) { - val files = existingJarFiles - val runtimeSourcesJar = files.runtimeSourcesJar - when (jarState) { - KotlinWithLibraryConfigurator.FileState.EXISTS -> { - if (dirToCopyJarTo != null) { - addSourcesToLibraryIfNeeded(library, files.getRuntimeSourcesDestination(dirToCopyJarTo), collector) - } - } - KotlinWithLibraryConfigurator.FileState.COPY -> { - assert(dirToCopyJarTo != null) { "Path to copy should be non-null" } - val file = copyFileToDir(runtimeSourcesJar, dirToCopyJarTo!!, collector) - addSourcesToLibraryIfNeeded(library, file!!, collector) - } - KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> { - addSourcesToLibraryIfNeeded(library, runtimeSourcesJar, collector) - } + val jarFile = if (jarState == KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY) + libraryJarDescriptor.getPathInPlugin() + else + File(dirToCopyJarTo, libraryJarDescriptor.jarName) + + if (jarState == KotlinWithLibraryConfigurator.FileState.COPY) { + copyFileToDir(libraryJarDescriptor.getPathInPlugin(), dirToCopyJarTo, collector) } + + val jarVFile = LocalFileSystem.getInstance().findFileByIoFile(jarFile) + if (jarVFile == null) { + collector.addMessage("Can't find library JAR file " + jarFile) + return + } + val jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(jarVFile) + if (jarRoot == null) { + collector.addMessage("Couldn't configure library; JAR file $jarVFile may be corrupted") + return + } + + if (jarRoot !in library.getFiles(libraryJarDescriptor.orderRootType)) { + val model = library.modifiableModel + model.addRoot(jarRoot, libraryJarDescriptor.orderRootType) + + ApplicationManager.getApplication().runWriteAction { model.commit() } + collector.addMessage("Added $jarFile to library configuration") + } + + addLibraryToModuleIfNeeded(module, library, collector) } fun getKotlinLibrary(project: Project): Library? { - val librariesContainer = LibrariesContainerFactory.createContainer(project) - for (library in librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.PROJECT)) { - if (isKotlinLibrary(project, library)) { - return library - } - } - for (library in librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.GLOBAL)) { - if (isKotlinLibrary(project, library)) { - return library - } - } - return null + return LibraryTablesRegistrar.getInstance().getLibraryTable(project).libraries.firstOrNull(this::isKotlinLibrary) ?: + LibraryTablesRegistrar.getInstance().libraryTable.libraries.firstOrNull(this::isKotlinLibrary) } @Contract("!null, _, _ -> !null") @@ -247,12 +185,10 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj return getPathFromLibrary(getKotlinLibrary(project), type) } - private fun addLibraryToModuleIfNeeded(module: Module, collector: NotificationMessageCollector) { + private fun addLibraryToModuleIfNeeded(module: Module, library: Library, collector: NotificationMessageCollector) { val expectedDependencyScope = getDependencyScope(module) val kotlinLibrary = getKotlinLibrary(module) if (kotlinLibrary == null) { - val library = getKotlinLibrary(module.project) ?: error("Kotlin project library should exists") - ModuleRootModificationUtil.addDependency(module, library, expectedDependencyScope, false) collector.addMessage(library.name + " library was added to module " + module.name) } @@ -271,44 +207,17 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj } } - private fun addJarsToExistingLibrary(project: Project, runtimeJar: File, reflectJar: File?, collector: NotificationMessageCollector) { - val library = getKotlinLibrary(project) ?: error("Kotlin library should present, instead createNewLibrary should be invoked") - - val model = library.modifiableModel - model.addRoot(VfsUtil.getUrlForLibraryRoot(runtimeJar), OrderRootType.CLASSES) - if (reflectJar != null) { - model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectJar), OrderRootType.CLASSES) - } - - ApplicationManager.getApplication().runWriteAction { model.commit() } - - collector.addMessage(library.name!! + " library was configured") - } - - private fun addJarsToNewLibrary( + fun createNewLibrary( project: Project, - runtimeJar: File, - reflectJar: File?, collector: NotificationMessageCollector - ) { + ): Library { val table = LibraryTablesRegistrar.getInstance().getLibraryTable(project) - val library = Ref() - ApplicationManager.getApplication().runWriteAction { - library.set(table.createLibrary(libraryName)) - val model = library.get().modifiableModel - model.addRoot(VfsUtil.getUrlForLibraryRoot(runtimeJar), OrderRootType.CLASSES) - if (reflectJar != null) { - model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectJar), OrderRootType.CLASSES) - } - model.commit() + val library = runWriteAction { + table.createLibrary(libraryName) } - collector.addMessage(library.get().name!! + " library was created") - } - - private fun isProjectLibraryWithoutPathsPresent(project: Project): Boolean { - val library = getKotlinLibrary(project) - return library != null && library.getUrls(OrderRootType.CLASSES).size == 0 + collector.addMessage(library.name!! + " library was created") + return library!! } private fun isProjectLibraryPresent(project: Project): Boolean { @@ -316,33 +225,13 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj return library != null && library.getUrls(OrderRootType.CLASSES).size > 0 } - private fun getKotlinLibrary(module: Module): Library? { - val result = Ref.create(null) - OrderEnumerator.orderEntries(module).forEachLibrary(Processor { library -> - if (isKotlinLibrary(module.project, library)) { - result.set(library) - return@Processor false - } - true - }) - return result.get() + protected abstract val libraryMatcher: (Library) -> Boolean + + fun getKotlinLibrary(module: Module): Library? { + return findKotlinRuntimeLibrary(module, this::isKotlinLibrary) } - protected open fun isKotlinLibrary(project: Project, library: Library): Boolean { - if (libraryName == library.name) { - return true - } - - val fileName = existingJarFiles.runtimeJar.name - - for (root in library.getFiles(OrderRootType.CLASSES)) { - if (root.name == fileName) { - return true - } - } - - return false - } + private fun isKotlinLibrary(library: Library) = library.name == libraryName || libraryMatcher(library) protected fun needToChooseJarPath(project: Project): Boolean { val defaultPath = getDefaultPathToJarFile(project) @@ -363,22 +252,6 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj DO_NOT_COPY } - enum class LibraryState { - LIBRARY, - NON_CONFIGURED_LIBRARY, - NEW_LIBRARY - } - - fun getLibraryState(project: Project): LibraryState { - if (isProjectLibraryPresent(project)) { - return LibraryState.LIBRARY - } - else if (isProjectLibraryWithoutPathsPresent(project)) { - return LibraryState.NON_CONFIGURED_LIBRARY - } - return LibraryState.NEW_LIBRARY - } - protected fun getJarState( project: Project, targetFile: File, @@ -415,13 +288,6 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj return defaultDir } - protected fun assertFileExists(file: File): File { - if (!file.exists()) { - showError("Couldn't find file: " + file.path) - } - return file - } - abstract val libraryJarDescriptors: List companion object { @@ -449,26 +315,6 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj return parentDir } - protected fun addSourcesToLibraryIfNeeded( - library: Library, - file: File, - collector: NotificationMessageCollector - ): Boolean { - val librarySourceRoots = library.getUrls(OrderRootType.SOURCES) - val librarySourceRoot = VfsUtil.getUrlForLibraryRoot(file) - for (sourceRoot in librarySourceRoots) { - if (sourceRoot == librarySourceRoot) return false - } - - val model = library.modifiableModel - model.addRoot(librarySourceRoot, OrderRootType.SOURCES) - - ApplicationManager.getApplication().runWriteAction { model.commit() } - - collector.addMessage("Source root '" + librarySourceRoot + "' was added to " + library.name + " library") - return true - } - private fun findLibraryOrderEntry(orderEntries: Array, library: Library): LibraryOrderEntry? { for (orderEntry in orderEntries) { if (orderEntry is LibraryOrderEntry && library == orderEntry.library) { diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt index b9017a325d2..3d3cb9bf000 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt @@ -49,7 +49,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.io.File @@ -119,7 +118,7 @@ abstract class AddKotlinLibQuickFix(element: KtElement, val libraryJarDescriptor protected abstract fun getLibraryDescriptor(module: Module): MavenExternalLibraryDescriptor fun libraryPath(): String = libraryJarDescriptor.jarName - fun getLibFile(): File = libraryJarDescriptor.getPath(PathUtil.getKotlinPathsForIdeaPlugin()) + fun getLibFile(): File = libraryJarDescriptor.getPathInPlugin() fun hasLibJarInLibrary(library: Library): Boolean = libraryJarDescriptor.findExistingJar(library) != null class MavenExternalLibraryDescriptor(groupId: String, artifactId: String, version: String) : diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt index 9ec19129702..4d518ef28e1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt @@ -171,7 +171,7 @@ fun checkUpdateRuntime(project: Project, requiredVersion: ApiVersion): Boolean { } if (modulesWithOutdatedRuntime.isNotEmpty()) { if (!askUpdateRuntime(project, requiredVersion, - modulesWithOutdatedRuntime.mapNotNull(::findKotlinRuntimeLibrary))) return false + modulesWithOutdatedRuntime.mapNotNull { findKotlinRuntimeLibrary(it) })) return false } return true } diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt index 0eb2aa2f8fc..4a6e404de41 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt @@ -120,8 +120,7 @@ private fun updateJar( } val oldUrl = fileToReplace?.url - val paths = PathUtil.getKotlinPathsForIdeaPlugin() - val jarPath: File = libraryJarDescriptor.getPath(paths) + val jarPath: File = libraryJarDescriptor.getPathInPlugin() if (!jarPath.exists()) { showRuntimeJarNotFoundDialog(project, libraryJarDescriptor.jarName) @@ -185,6 +184,8 @@ enum class LibraryJarDescriptor(val jarName: String, if (isExternalLibrary(library)) return null return LibraryUtils.getJarFile(Arrays.asList(*library.getFiles(orderRootType)), jarName) } + + fun getPathInPlugin() = getPath(PathUtil.getKotlinPathsForIdeaPlugin()) } fun bundledRuntimeVersion(): String { diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/OutdatedKotlinRuntimeChecker.kt b/idea/src/org/jetbrains/kotlin/idea/versions/OutdatedKotlinRuntimeChecker.kt index ea558018aa0..a074944b3af 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/OutdatedKotlinRuntimeChecker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/OutdatedKotlinRuntimeChecker.kt @@ -26,14 +26,12 @@ import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.libraries.Library import com.intellij.util.PathUtil.getLocalFile import com.intellij.util.text.VersionComparatorUtil import org.jetbrains.kotlin.idea.KotlinPluginUtil -import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider -import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider -import org.jetbrains.kotlin.idea.framework.getLibraryProperties -import org.jetbrains.kotlin.idea.framework.isDetected +import org.jetbrains.kotlin.idea.framework.* import org.jetbrains.kotlin.idea.util.application.runWriteAction import java.io.IOException import javax.swing.event.HyperlinkEvent @@ -74,13 +72,21 @@ private fun getKotlinLibraryVersionProperties(library: Library) = getLibraryProperties(JavaRuntimePresentationProvider.getInstance(), library) ?: getLibraryProperties(JSLibraryStdPresentationProvider.getInstance(), library) -fun findKotlinRuntimeLibrary(module: Module): Library? { +fun findKotlinRuntimeLibrary(module: Module, predicate: (Library) -> Boolean = ::isKotlinRuntime): Library? { val orderEntries = ModuleRootManager.getInstance(module).orderEntries.filterIsInstance() return orderEntries.asSequence() .mapNotNull { it.library } - .firstOrNull { getKotlinLibraryVersionProperties(it) != null } + .firstOrNull(predicate) } +fun isKotlinRuntime(library: Library) = isKotlinJavaRuntime(library) || isKotlinJsRuntime(library) + +fun isKotlinJavaRuntime(library: Library) = + JavaRuntimeDetectionUtil.getRuntimeJar(library.getFiles(OrderRootType.CLASSES).asList()) != null + +fun isKotlinJsRuntime(library: Library) = + JsLibraryStdDetectionUtil.getJsStdLibJar(library.getFiles(OrderRootType.CLASSES).asList()) != null + fun collectModulesWithOutdatedRuntime(libraries: List): List = libraries.flatMap { it.usedInModules } diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java index 57e7eb61d69..1d816401db4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java @@ -20,10 +20,12 @@ import com.intellij.openapi.application.PathMacros; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.testFramework.PlatformTestCase; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor; import org.jetbrains.kotlin.utils.PathUtil; import java.io.File; @@ -32,7 +34,6 @@ import java.util.Collections; import java.util.List; import static org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState; -import static org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.LibraryState; public abstract class AbstractConfigureKotlinTest extends PlatformTestCase { private static final String BASE_PATH = "idea/testData/configuration/"; @@ -53,16 +54,22 @@ public abstract class AbstractConfigureKotlinTest extends PlatformTestCase { private static void configure( @NotNull List modules, @NotNull FileState runtimeState, - @NotNull LibraryState libraryState, @NotNull KotlinWithLibraryConfigurator configurator, @NotNull String jarFromDist, @NotNull String jarFromTemp ) { Project project = modules.iterator().next().getProject(); NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(project); + for (Module module : modules) { + Library library = configurator.getKotlinLibrary(module); + if (library == null) { + library = configurator.createNewLibrary(project, collector); + } String pathToJar = getPathToJar(runtimeState, jarFromDist, jarFromTemp); - configurator.configureModuleWithLibraryClasses(module, libraryState, runtimeState, pathToJar, collector); + for (LibraryJarDescriptor descriptor : configurator.getLibraryJarDescriptors()) { + configurator.configureLibraryJar(module, library, runtimeState, pathToJar, descriptor, collector); + } } collector.showNotification(); } @@ -80,14 +87,14 @@ public abstract class AbstractConfigureKotlinTest extends PlatformTestCase { return jarFromDist; } - protected static void configure(@NotNull Module module, @NotNull FileState jarState, @NotNull LibraryState libraryState, @NotNull KotlinProjectConfigurator configurator) { + protected static void configure(@NotNull Module module, @NotNull FileState jarState, @NotNull KotlinProjectConfigurator configurator) { if (configurator instanceof KotlinJavaModuleConfigurator) { - configure(Collections.singletonList(module), jarState, libraryState, + configure(Collections.singletonList(module), jarState, (KotlinWithLibraryConfigurator) configurator, getPathToExistentRuntimeJar(), getPathToNonexistentRuntimeJar()); } if (configurator instanceof KotlinJsModuleConfigurator) { - configure(Collections.singletonList(module), jarState, libraryState, + configure(Collections.singletonList(module), jarState, (KotlinWithLibraryConfigurator) configurator, getPathToExistentJsJar(), getPathToNonexistentJsJar()); } @@ -174,20 +181,19 @@ public abstract class AbstractConfigureKotlinTest extends PlatformTestCase { } } - protected void doTestOneJavaModule(@NotNull FileState jarState, @NotNull LibraryState libraryState) { - doTestOneModule(jarState, libraryState, JAVA_CONFIGURATOR); + protected void doTestOneJavaModule(@NotNull FileState jarState) { + doTestOneModule(jarState, JAVA_CONFIGURATOR); } - protected void doTestOneJsModule(@NotNull FileState jarState, @NotNull LibraryState libraryState) { - doTestOneModule(jarState, libraryState, JS_CONFIGURATOR); + protected void doTestOneJsModule(@NotNull FileState jarState) { + doTestOneModule(jarState, JS_CONFIGURATOR); } - private void doTestOneModule(@NotNull FileState jarState, @NotNull LibraryState libraryState, @NotNull KotlinWithLibraryConfigurator configurator) { + private void doTestOneModule(@NotNull FileState jarState, @NotNull KotlinWithLibraryConfigurator configurator) { Module module = getModule(); - assertEquals("Library state loaded from project files should be " + libraryState, libraryState, configurator.getLibraryState(module.getProject())); assertNotConfigured(module, configurator); - configure(module, jarState, libraryState, configurator); + configure(module, jarState, configurator); assertProperlyConfigured(module, configurator); } diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinTest.java b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinTest.java index c16d37c75cd..7e2ffa216e0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinTest.java @@ -34,37 +34,27 @@ import java.util.Collections; public class ConfigureKotlinTest extends AbstractConfigureKotlinTest { public void testNewLibrary_copyJar() { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY); + doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY); } public void testNewLibrary_doNotCopyJar() { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY); - } - - public void testLibrary_doNotCopyJar() { - try { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.LIBRARY); - } - catch (IllegalStateException e) { - return; - } - fail("Test should throw IllegalStateException"); + doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY); } public void testLibraryWithoutPaths_jarExists() { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS, KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY); + doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS); } public void testNewLibrary_jarExists() { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY); + doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.EXISTS); } public void testLibraryWithoutPaths_copyJar() { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY, KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY); + doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.COPY); } public void testLibraryWithoutPaths_doNotCopyJar() { - doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY); + doTestOneJavaModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY); } @SuppressWarnings("ConstantConditions") @@ -72,12 +62,12 @@ public class ConfigureKotlinTest extends AbstractConfigureKotlinTest { Module[] modules = getModules(); for (Module module : modules) { if (module.getName().equals("module1")) { - configure(module, KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY, JAVA_CONFIGURATOR); + configure(module, KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, JAVA_CONFIGURATOR); assertConfigured(module, JAVA_CONFIGURATOR); } else if (module.getName().equals("module2")) { assertNotConfigured(module, JAVA_CONFIGURATOR); - configure(module, KotlinWithLibraryConfigurator.FileState.EXISTS, KotlinWithLibraryConfigurator.LibraryState.LIBRARY, JAVA_CONFIGURATOR); + configure(module, KotlinWithLibraryConfigurator.FileState.EXISTS, JAVA_CONFIGURATOR); assertConfigured(module, JAVA_CONFIGURATOR); } } @@ -107,37 +97,27 @@ public class ConfigureKotlinTest extends AbstractConfigureKotlinTest { } public void testNewLibrary_jarExists_js() { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY); + doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS); } public void testNewLibrary_copyJar_js() { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY); + doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY); } public void testNewLibrary_doNotCopyJar_js() { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY); - } - - public void testJsLibrary_doNotCopyJar() { - try { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.LIBRARY); - } - catch (IllegalStateException e) { - return; - } - fail("Test should throw IllegalStateException"); + doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY); } public void testJsLibraryWithoutPaths_jarExists() { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS, KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY); + doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.EXISTS); } public void testJsLibraryWithoutPaths_copyJar() { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY, KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY); + doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.COPY); } public void testJsLibraryWithoutPaths_doNotCopyJar() { - doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY); + doTestOneJsModule(KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY); } public void testProjectWithoutFacetWithRuntime106WithoutLanguageLevel() {