diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt index 10e06529fdb..3a26e53a32d 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/PathUtil.kt @@ -48,6 +48,7 @@ object PathUtil { @JvmField val KOTLIN_RUNTIME_JAR_PATTERN: Pattern = Pattern.compile("kotlin-(stdlib|runtime)(-\\d[\\d.]+(-.+)?)?\\.jar") val KOTLIN_STDLIB_JS_JAR_PATTERN: Pattern = Pattern.compile("kotlin-stdlib-js.*\\.jar") + val KOTLIN_STDLIB_COMMON_JAR_PATTERN: Pattern = Pattern.compile("kotlin-stdlib-common.*\\.jar") val KOTLIN_JS_LIBRARY_JAR_PATTERN: Pattern = Pattern.compile("kotlin-js-library.*\\.jar") const val HOME_FOLDER_NAME = "kotlinc" diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/LibraryKinds.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/LibraryKinds.kt index 60e0d81a30b..9c98f9b85d8 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/LibraryKinds.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/LibraryKinds.kt @@ -14,36 +14,22 @@ * limitations under the License. */ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package org.jetbrains.kotlin.idea.framework +import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.impl.libraries.LibraryEx import com.intellij.openapi.roots.libraries.DummyLibraryProperties import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.PersistentLibraryKind -import com.intellij.openapi.vfs.JarFileSystem -import com.intellij.openapi.vfs.VfsUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.VirtualFileVisitor +import com.intellij.openapi.util.io.JarUtil +import com.intellij.openapi.vfs.* import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment +import org.jetbrains.kotlin.utils.PathUtil +import java.util.jar.Attributes +import java.util.regex.Pattern object JSLibraryKind : PersistentLibraryKind("kotlin.js") { override fun createDefaultProperties() = DummyLibraryProperties.INSTANCE!! @@ -99,3 +85,15 @@ private fun detectLibraryKindFromJarContents(jarRoot: VirtualFile): PersistentLi }) return result } + +fun getLibraryJarVersion(library: Library, jarPattern: Pattern): String? { + for (file in library.getFiles(OrderRootType.CLASSES)) { + if (jarPattern.matcher(file.name).matches()) { + return JarUtil.getJarAttribute(VfsUtilCore.virtualToIoFile(file), Attributes.Name.IMPLEMENTATION_VERSION) + } + } + return null +} + +fun getCommonRuntimeLibraryVersion(library: Library) = + getLibraryJarVersion(library, PathUtil.KOTLIN_STDLIB_COMMON_JAR_PATTERN) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformGradleProjectTaskRunner.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformGradleProjectTaskRunner.kt index 66a52b79265..3b8d823dfb4 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformGradleProjectTaskRunner.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/run/MultiplatformGradleProjectTaskRunner.kt @@ -30,9 +30,8 @@ import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.task.* import com.intellij.task.impl.ModuleBuildTaskImpl -import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider import org.jetbrains.kotlin.config.TargetPlatformKind -import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.targetPlatform import org.jetbrains.kotlin.idea.util.rootManager import org.jetbrains.plugins.gradle.execution.build.GradleProjectTaskRunner @@ -116,7 +115,6 @@ class MultiplatformGradleOrderEnumeratorHandler : OrderEnumerationHandler() { File(gradleProjectPath)) ?: return false val externalSourceSets = externalProjectDataCache.findExternalProject(externalRootProject, rootModel.module) - if (externalSourceSets.isEmpty()) return false for (sourceSet in externalSourceSets.values) { if (includeTests) { @@ -147,7 +145,6 @@ class MultiplatformGradleOrderEnumeratorHandler : OrderEnumerationHandler() { class FactoryImpl : Factory() { override fun isApplicable(module: Module): Boolean { return ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module) && - !GradleSystemRunningSettings.getInstance().isUseGradleAwareMake && module.isMultiplatformModule() } @@ -156,5 +153,7 @@ class MultiplatformGradleOrderEnumeratorHandler : OrderEnumerationHandler() { } } -private fun Module.isMultiplatformModule(): Boolean = - languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) +private fun Module.isMultiplatformModule(): Boolean { + val settings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this) + return settings.targetPlatformKind is TargetPlatformKind.Common || settings.implementedModuleName != null +} diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMultiplatformRunTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMultiplatformRunTest.kt new file mode 100644 index 00000000000..ff0277f5237 --- /dev/null +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleMultiplatformRunTest.kt @@ -0,0 +1,160 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.codeInsight.gradle + +import com.intellij.compiler.options.CompileStepBeforeRun +import com.intellij.execution.Location +import com.intellij.execution.PsiLocation +import com.intellij.execution.actions.ConfigurationContext +import com.intellij.execution.actions.RunConfigurationProducer +import com.intellij.execution.configurations.JavaCommandLineState +import com.intellij.execution.executors.DefaultRunExecutor +import com.intellij.execution.runners.ExecutionEnvironmentBuilder +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.LangDataKeys +import com.intellij.openapi.application.invokeAndWaitIfNeed +import com.intellij.psi.PsiManager +import com.intellij.testFramework.MapDataContext +import org.jetbrains.kotlin.idea.run.KotlinRunConfigurationProducer +import org.jetbrains.kotlin.idea.util.module +import org.jetbrains.kotlin.psi.KtFile +import org.junit.Test + +class GradleMultiplatformRunTest : GradleImportingTestCase() { + @Test + fun testMultiplatformClasspath() { + createProjectSubFile( + "build.gradle", + """ + buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.4") + } + } + + apply plugin: 'kotlin-platform-common' + + repositories { + jcenter() + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib-common:1.1.4" + } + + """.trimIndent() + ) + createProjectSubFile( + "settings.gradle", + """ + rootProject.name = 'MultiTest' + include 'MultiTest-jvm', 'MultiTest-js' + """.trimIndent() + ) + createProjectSubFile( + "MultiTest-js/build.gradle", + """ + buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.4") + } + } + + apply plugin: 'kotlin-platform-js' + + repositories { + jcenter() + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.4" + implement project(":") + } + + """.trimIndent() + ) + createProjectSubFile( + "MultiTest-jvm/build.gradle", + """ + buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.4") + } + } + + apply plugin: 'kotlin-platform-jvm' + + repositories { + jcenter() + mavenCentral() + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.4" + implement project(":") + } + + """.trimIndent() + ) + val virtualFile = createProjectSubFile("src/main/kotlin/foo.kt", "fun main(args: Array) { println(\"Foo!\") }") + + importProject() + + val javaParameters = invokeAndWaitIfNeed { + val psiFile = PsiManager.getInstance(myProject).findFile(virtualFile) as KtFile + val function = psiFile.declarations.single() + val dataContext = MapDataContext().apply { + put(CommonDataKeys.PROJECT, myProject) + put(LangDataKeys.MODULE, function.module) + put(Location.DATA_KEY, PsiLocation.fromPsiElement(function)) + } + val configurationContext = ConfigurationContext.getFromContext(dataContext) + val producer = RunConfigurationProducer.getInstance(KotlinRunConfigurationProducer::class.java) + val configuration = producer.createConfigurationFromContext(configurationContext)!! + + val executionEnvironment = ExecutionEnvironmentBuilder.create(myProject, + DefaultRunExecutor.getRunExecutorInstance(), + configuration.configuration) + .build() + + val compileStepBeforeRun = CompileStepBeforeRun(myProject) + compileStepBeforeRun.executeTask(dataContext, configuration.configuration, executionEnvironment, + CompileStepBeforeRun.MakeBeforeRunTask()) + + val state = configuration.configuration.getState(DefaultRunExecutor.getRunExecutorInstance(), executionEnvironment) as JavaCommandLineState + state.javaParameters + + } + + val p = javaParameters.classPath + assertTrue(p.virtualFiles.any { it.findChild("FooKt.class") != null }) + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProviderByModuleDependencies.kt b/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProviderByModuleDependencies.kt index 438af7f3102..df8d16c6b5d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProviderByModuleDependencies.kt +++ b/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProviderByModuleDependencies.kt @@ -24,6 +24,7 @@ import com.intellij.openapi.roots.libraries.Library import org.jetbrains.kotlin.config.TargetPlatformKind import org.jetbrains.kotlin.idea.framework.JavaRuntimeDetectionUtil import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil +import org.jetbrains.kotlin.idea.framework.getCommonRuntimeLibraryVersion import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion class KotlinVersionInfoProviderByModuleDependencies : KotlinVersionInfoProvider { @@ -33,7 +34,7 @@ class KotlinVersionInfoProviderByModuleDependencies : KotlinVersionInfoProvider val versionProvider: (Library) -> String? = when (targetPlatform) { is TargetPlatformKind.JavaScript -> JsLibraryStdDetectionUtil::getJsLibraryStdVersion is TargetPlatformKind.Jvm -> JavaRuntimeDetectionUtil::getJavaRuntimeVersion - is TargetPlatformKind.Common -> return emptyList() + is TargetPlatformKind.Common -> ::getCommonRuntimeLibraryVersion } return (rootModel ?: ModuleRootManager.getInstance(module)) .orderEntries