diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java index df4fd15e7e2..67e8e2e9604 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java +++ b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.java @@ -35,6 +35,10 @@ public class PathUtil { public static final String NOARG_PLUGIN_JAR_NAME = "noarg-compiler-plugin.jar"; public static final String JS_LIB_SRC_JAR_NAME = "kotlin-stdlib-js-sources.jar"; public static final String KOTLIN_JAVA_RUNTIME_JAR = "kotlin-runtime.jar"; + public static final String KOTLIN_JAVA_RUNTIME_JRE7_JAR = "kotlin-stdlib-jre7.jar"; + public static final String KOTLIN_JAVA_RUNTIME_JRE8_JAR = "kotlin-stdlib-jre8.jar"; + public static final String KOTLIN_JAVA_RUNTIME_JRE7_SRC_JAR = "kotlin-stdlib-jre7-sources.jar"; + public static final String KOTLIN_JAVA_RUNTIME_JRE8_SRC_JAR = "kotlin-stdlib-jre8-sources.jar"; public static final String KOTLIN_JAVA_STDLIB_JAR = "kotlin-stdlib.jar"; public static final String KOTLIN_JAVA_REFLECT_JAR = "kotlin-reflect.jar"; public static final String KOTLIN_JAVA_SCRIPT_RUNTIME_JAR = "kotlin-script-runtime.jar"; diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt index 002fac71724..168c14be3ef 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt @@ -18,13 +18,15 @@ package org.jetbrains.kotlin.idea.configuration import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.module.Module +import com.intellij.openapi.projectRoots.JavaSdk +import com.intellij.openapi.projectRoots.JavaSdkVersion +import com.intellij.openapi.projectRoots.Sdk 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.isKotlinJavaRuntime import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform -import org.jetbrains.kotlin.utils.PathUtil open class KotlinJavaModuleConfigurator internal constructor() : KotlinWithLibraryConfigurator() { @@ -53,11 +55,21 @@ open class KotlinJavaModuleConfigurator internal constructor() : KotlinWithLibra override val targetPlatform: TargetPlatform get() = JvmPlatform - override val libraryJarDescriptors: List - get() = listOf(LibraryJarDescriptor.RUNTIME_JAR, - LibraryJarDescriptor.REFLECT_JAR, - LibraryJarDescriptor.RUNTIME_SRC_JAR, - LibraryJarDescriptor.TEST_JAR) + override fun getLibraryJarDescriptors(sdk: Sdk?): List { + var result = listOf(LibraryJarDescriptor.RUNTIME_JAR, + LibraryJarDescriptor.REFLECT_JAR, + LibraryJarDescriptor.RUNTIME_SRC_JAR, + LibraryJarDescriptor.TEST_JAR) + val sdkVersion = sdk?.let { JavaSdk.getInstance().getVersion(it) } ?: return result + if (sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7)) { + result += listOf(LibraryJarDescriptor.RUNTIME_JRE7_JAR, LibraryJarDescriptor.RUNTIME_JRE7_SOURCES_JAR) + } + if (sdkVersion.isAtLeast(JavaSdkVersion.JDK_1_8)) { + result += listOf(LibraryJarDescriptor.RUNTIME_JRE8_JAR, LibraryJarDescriptor.RUNTIME_JRE8_SOURCES_JAR) + } + + return result + } override val libraryMatcher: (Library) -> Boolean get() = ::isKotlinJavaRuntime diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java index aec5c7c9048..80c79f509fb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.java @@ -17,17 +17,17 @@ package org.jetbrains.kotlin.idea.configuration; import com.intellij.openapi.module.Module; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.libraries.Library; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; 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; -import org.jetbrains.kotlin.utils.KotlinPaths; -import org.jetbrains.kotlin.utils.PathUtil; import java.util.Arrays; import java.util.List; @@ -84,7 +84,7 @@ public class KotlinJsModuleConfigurator extends KotlinWithLibraryConfigurator { @NotNull @Override - public List getLibraryJarDescriptors() { + public List getLibraryJarDescriptors(@Nullable Sdk sdk) { return Arrays.asList(LibraryJarDescriptor.JS_STDLIB_JAR, LibraryJarDescriptor.JS_STDLIB_SRC_JAR); } diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt index 2c5eae2464a..14ec0a54cfb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.* import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar @@ -112,19 +113,24 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj ?: getKotlinLibrary(project) ?: createNewLibrary(project, collector) - for (descriptor in libraryJarDescriptors) { + val sdk = ModuleRootManager.getInstance(module).sdk + val model = library.modifiableModel + + for (descriptor in getLibraryJarDescriptors(sdk)) { val dirToCopyJar = getPathToCopyFileTo(project, descriptor.orderRootType, defaultPath, pathFromDialog) val runtimeState = getJarState(project, File(dirToCopyJar, descriptor.jarName), descriptor.orderRootType, pathFromDialog == null) - configureLibraryJar(module, library, runtimeState, dirToCopyJar, descriptor, collector) + configureLibraryJar(model, runtimeState, dirToCopyJar, descriptor, collector) } + ApplicationManager.getApplication().runWriteAction { model.commit() } + + addLibraryToModuleIfNeeded(module, library, collector) } fun configureLibraryJar( - module: Module, - library: Library, + library: Library.ModifiableModel, jarState: FileState, dirToCopyJarTo: String, libraryJarDescriptor: LibraryJarDescriptor, @@ -151,14 +157,10 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj } if (jarRoot !in library.getFiles(libraryJarDescriptor.orderRootType)) { - val model = library.modifiableModel - model.addRoot(jarRoot, libraryJarDescriptor.orderRootType) + library.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? { @@ -181,7 +183,7 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj return getPathFromLibrary(getKotlinLibrary(project), type) } - private fun addLibraryToModuleIfNeeded(module: Module, library: Library, collector: NotificationMessageCollector) { + fun addLibraryToModuleIfNeeded(module: Module, library: Library, collector: NotificationMessageCollector) { val expectedDependencyScope = getDependencyScope(module) val kotlinLibrary = getKotlinLibrary(module) if (kotlinLibrary == null) { @@ -231,7 +233,8 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj protected fun needToChooseJarPath(project: Project): Boolean { val defaultPath = getDefaultPathToJarFile(project) - return !isProjectLibraryPresent(project) && !File(defaultPath, libraryJarDescriptors.first().jarName).exists() + return !isProjectLibraryPresent(project) && + !File(defaultPath, getLibraryJarDescriptors(null).first().jarName).exists() } protected open fun getDefaultPathToJarFile(project: Project): String { @@ -280,7 +283,7 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj return defaultDir } - abstract val libraryJarDescriptors: List + abstract fun getLibraryJarDescriptors(sdk: Sdk?): List companion object { val DEFAULT_LIBRARY_DIR = "lib" @@ -291,7 +294,7 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj !KotlinPluginUtil.isGradleModule(module) } - protected fun getPathFromLibrary(library: Library?, type: OrderRootType): String? { + fun getPathFromLibrary(library: Library?, type: OrderRootType): String? { if (library == null) return null val libraryFiles = library.getUrls(type) diff --git a/idea/src/org/jetbrains/kotlin/idea/framework/CustomLibraryDescriptorWithDeferredConfig.kt b/idea/src/org/jetbrains/kotlin/idea/framework/CustomLibraryDescriptorWithDeferredConfig.kt index 4ad3d24c1ed..c85edb079a2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/framework/CustomLibraryDescriptorWithDeferredConfig.kt +++ b/idea/src/org/jetbrains/kotlin/idea/framework/CustomLibraryDescriptorWithDeferredConfig.kt @@ -32,6 +32,9 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator +import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState.COPY +import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY +import org.jetbrains.kotlin.idea.configuration.NotificationMessageCollector import org.jetbrains.kotlin.idea.configuration.createConfigureKotlinNotificationCollector import org.jetbrains.kotlin.idea.configuration.getConfiguratorByName import org.jetbrains.kotlin.idea.framework.ui.CreateLibraryDialog @@ -40,7 +43,6 @@ import org.jetbrains.kotlin.idea.util.projectStructure.findLibrary import org.jetbrains.kotlin.idea.util.projectStructure.getModuleDir import org.jetbrains.kotlin.idea.util.projectStructure.replaceFileRoot import java.io.File -import java.util.* import javax.swing.JComponent /** @@ -48,7 +50,7 @@ import javax.swing.JComponent */ abstract class CustomLibraryDescriptorWithDeferredConfig ( - project: Project?, + val project: Project?, private val configuratorName: String, private val libraryName: String, private val dialogTitle: String, @@ -66,18 +68,32 @@ abstract class CustomLibraryDescriptorWithDeferredConfig } fun finishLibConfiguration(module: Module, rootModel: ModifiableRootModel) { - val deferredCopyFileRequests = copyFileRequests ?: return - val library = rootModel.orderEntries().findLibrary { library -> val libraryPresentationManager = LibraryPresentationManager.getInstance() - val classFiles = Arrays.asList(*library.getFiles(OrderRootType.CLASSES)) + val classFiles = library.getFiles(OrderRootType.CLASSES).toList() libraryPresentationManager.isLibraryOfKind(classFiles, libraryKind) } ?: return val model = library.modifiableModel + val copyToPath = KotlinWithLibraryConfigurator.getPathFromLibrary(library, OrderRootType.CLASSES) try { - deferredCopyFileRequests.performRequests(module.project, module.getModuleDir(), model) + val collector = createConfigureKotlinNotificationCollector(module.project) + copyFileRequests?.performRequests(module.getModuleDir(), model, collector) + + if (copyToPath != null) { + val jarState = if (copyFileRequests == null) DO_NOT_COPY else COPY + + // Now that we know the SDK which is going to be set for the module, we can add jre 7/8 if required + val descriptorsWithSdk = configurator.getLibraryJarDescriptors(rootModel.sdk) + for (jarDescriptor in descriptorsWithSdk) { + if (model.getFiles(jarDescriptor.orderRootType).any { it.name == jarDescriptor.jarName }) + continue + + configurator.configureLibraryJar(model, jarState, copyToPath, jarDescriptor, collector) + } + } + collector.showNotification() } finally { model.commit() @@ -87,8 +103,7 @@ abstract class CustomLibraryDescriptorWithDeferredConfig class DeferredCopyFileRequests(private val configurator: KotlinWithLibraryConfigurator) { private val copyFilesRequests = Lists.newArrayList() - fun performRequests(project: Project, relativePath: String, model: Library.ModifiableModel) { - val collector = createConfigureKotlinNotificationCollector(project) + fun performRequests(relativePath: String, model: Library.ModifiableModel, collector: NotificationMessageCollector) { for (request in copyFilesRequests) { val destinationPath = if (FileUtil.isAbsolute(request.toDir)) request.toDir @@ -101,7 +116,6 @@ abstract class CustomLibraryDescriptorWithDeferredConfig model.replaceFileRoot(request.file, resultFile) } } - collector.showNotification() } fun addCopyWithReplaceRequest(file: File, copyIntoPath: String) { @@ -121,7 +135,7 @@ abstract class CustomLibraryDescriptorWithDeferredConfig else FileUIUtils.createRelativePath(null, projectBaseDir, DEFAULT_LIB_DIR_NAME) - val jarDescriptors = configurator.libraryJarDescriptors + val jarDescriptors = configurator.getLibraryJarDescriptors(null) val stdJarInDefaultPath = File(defaultPathToJarFile, jarDescriptors.first().jarName) val libraryFiles = mutableListOf() @@ -150,7 +164,7 @@ abstract class CustomLibraryDescriptorWithDeferredConfig val copyIntoPath = dialog.copyIntoPath if (copyIntoPath != null) { - for (libraryJarDescriptor in configurator.libraryJarDescriptors) { + for (libraryJarDescriptor in configurator.getLibraryJarDescriptors(null)) { copyFileRequests!!.addCopyWithReplaceRequest(libraryJarDescriptor.getPathInPlugin(), copyIntoPath) } } @@ -184,7 +198,7 @@ abstract class CustomLibraryDescriptorWithDeferredConfig collectPathsInPlugin(OrderRootType.SOURCES)) private fun collectPathsInPlugin(rootType: OrderRootType): List { - return configurator.libraryJarDescriptors + return configurator.getLibraryJarDescriptors(null) .filter { it.orderRootType == rootType } .map { it.getPathInPlugin() } } diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt index bc1626c991f..cb0ee02dac1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinRuntimeLibraryUtil.kt @@ -24,10 +24,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.JavaSdk import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.LibraryOrderEntry -import com.intellij.openapi.roots.ModuleRootManager -import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.roots.ProjectFileIndex +import com.intellij.openapi.roots.* import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.ui.Messages import com.intellij.openapi.util.io.FileUtil @@ -96,12 +93,14 @@ fun updateLibraries(project: Project, libraries: Collection) { error("Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME) val collector = createConfigureKotlinNotificationCollector(project) + val sdk = ProjectRootManager.getInstance(project).projectSdk + // TODO use module SDK for (library in libraries) { val libraryJarDescriptors = if (isDetected(JavaRuntimePresentationProvider.getInstance(), library)) - kJvmConfigurator.libraryJarDescriptors + kJvmConfigurator.getLibraryJarDescriptors(sdk) else - kJsConfigurator.libraryJarDescriptors + kJsConfigurator.getLibraryJarDescriptors(sdk) for (libraryJarDescriptor in libraryJarDescriptors) { updateJar(project, library, libraryJarDescriptor) @@ -167,7 +166,7 @@ fun findAllUsedLibraries(project: Project): MultiMap { enum class LibraryJarDescriptor(val jarName: String, val orderRootType: OrderRootType, val shouldExist: Boolean, - val getPath: (KotlinPaths) -> File) { + val getPath: (KotlinPaths) -> File = { paths -> File(paths.libPath, jarName) }) { RUNTIME_JAR(PathUtil.KOTLIN_JAVA_STDLIB_JAR, OrderRootType.CLASSES, true, KotlinPaths::getStdlibPath) { override fun findExistingJar(library: Library): VirtualFile? { if (isExternalLibrary(library)) return null @@ -178,6 +177,10 @@ enum class LibraryJarDescriptor(val jarName: String, REFLECT_JAR(PathUtil.KOTLIN_JAVA_REFLECT_JAR, OrderRootType.CLASSES, false, KotlinPaths::getReflectPath), SCRIPT_RUNTIME_JAR(PathUtil.KOTLIN_JAVA_SCRIPT_RUNTIME_JAR, OrderRootType.CLASSES, true, KotlinPaths::getScriptRuntimePath), TEST_JAR(PathUtil.KOTLIN_TEST_JAR, OrderRootType.CLASSES, false, KotlinPaths::getKotlinTestPath), + RUNTIME_JRE7_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_JAR, OrderRootType.CLASSES, false), + RUNTIME_JRE8_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_JAR, OrderRootType.CLASSES, false), + RUNTIME_JRE7_SOURCES_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_SRC_JAR, OrderRootType.SOURCES, false), + RUNTIME_JRE8_SOURCES_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_SRC_JAR, OrderRootType.SOURCES, false), RUNTIME_SRC_JAR(PathUtil.KOTLIN_JAVA_STDLIB_SRC_JAR, OrderRootType.SOURCES, false, KotlinPaths::getStdlibSourcesPath) { override fun findExistingJar(library: Library): VirtualFile? { diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java index 1d816401db4..5fc7393025a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.java @@ -16,10 +16,13 @@ package org.jetbrains.kotlin.idea.configuration; +import com.intellij.openapi.application.ApplicationManager; 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.projectRoots.Sdk; +import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; @@ -67,9 +70,13 @@ public abstract class AbstractConfigureKotlinTest extends PlatformTestCase { library = configurator.createNewLibrary(project, collector); } String pathToJar = getPathToJar(runtimeState, jarFromDist, jarFromTemp); - for (LibraryJarDescriptor descriptor : configurator.getLibraryJarDescriptors()) { - configurator.configureLibraryJar(module, library, runtimeState, pathToJar, descriptor, collector); + Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + Library.ModifiableModel model = library.getModifiableModel(); + for (LibraryJarDescriptor descriptor : configurator.getLibraryJarDescriptors(sdk)) { + configurator.configureLibraryJar(model, runtimeState, pathToJar, descriptor, collector); } + ApplicationManager.getApplication().runWriteAction(model::commit); + configurator.addLibraryToModuleIfNeeded(module, library, collector); } collector.showNotification(); }