From 6664b7759bbd50f20d1ed89ba9fc12ecdeaf53bd Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 3 Oct 2017 16:08:37 +0300 Subject: [PATCH] Configure kotlin.stdlib for gradle projects (KT-19207) #KT-19207 Fixed --- .../KotlinGradleModuleConfigurator.kt | 19 ++++++ .../KotlinWithGradleConfigurator.kt | 27 ++++++--- ...radleConfigureProjectByChangingFileTest.kt | 60 +++++++++++++------ ...ureProjectByChangingFileTestGenerated.java | 6 ++ .../idea/configuration/ModuleSourceRootMap.kt | 17 ++++++ .../withJava9ModuleInfo/build_after.gradle | 33 ++++++++++ .../withJava9ModuleInfo/build_before.gradle | 12 ++++ .../withJava9ModuleInfo/module-info.java | 3 + .../module-info_after.java | 4 ++ 9 files changed, 154 insertions(+), 27 deletions(-) create mode 100644 idea/testData/configuration/gradle/withJava9ModuleInfo/build_after.gradle create mode 100644 idea/testData/configuration/gradle/withJava9ModuleInfo/build_before.gradle create mode 100644 idea/testData/configuration/gradle/withJava9ModuleInfo/module-info.java create mode 100644 idea/testData/configuration/gradle/withJava9ModuleInfo/module-info_after.java diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.kt index cc4e24409c9..da5ca7cd7ab 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.kt @@ -16,7 +16,9 @@ package org.jetbrains.kotlin.idea.configuration +import com.intellij.openapi.module.Module import com.intellij.openapi.projectRoots.Sdk +import com.intellij.psi.PsiFile import org.jetbrains.kotlin.idea.versions.getDefaultJvmTarget import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform @@ -37,6 +39,23 @@ class KotlinGradleModuleConfigurator : KotlinWithGradleConfigurator() { override fun getJvmTarget(sdk: Sdk?, version: String) = getDefaultJvmTarget(sdk, version)?.description + override fun configureModule( + module: Module, + file: PsiFile, + isTopLevelProjectFile: Boolean, + version: String, collector: NotificationMessageCollector, + filesToOpen: MutableCollection + ) { + super.configureModule(module, file, isTopLevelProjectFile, version, collector, filesToOpen) + + val moduleGroup = module.getWholeModuleGroup() + for (sourceModule in moduleGroup.allModules()) { + if (addStdlibToJavaModuleInfo(sourceModule, collector)) { + break + } + } + } + companion object { val NAME = "gradle" val KOTLIN = "kotlin" diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt index 3671e6e48ac..ccf77965ecb 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.kt @@ -118,28 +118,39 @@ abstract class KotlinWithGradleConfigurator : KotlinProjectConfigurator { modulesToConfigure: List, kotlinVersion: String, collector: NotificationMessageCollector): HashSet { - val changedFiles = HashSet() + val filesToOpen = HashSet() val buildScript = project.getTopLevelBuildScriptPsiFile() if (buildScript != null && canConfigureFile(buildScript)) { val isModified = configureBuildScript(buildScript, true, kotlinVersion, collector) if (isModified) { - changedFiles.add(buildScript) + filesToOpen.add(buildScript) } } for (module in modulesToConfigure) { val file = module.getBuildScriptPsiFile() if (file != null && canConfigureFile(file)) { - val isModified = configureBuildScript(file, false, kotlinVersion, collector) - if (isModified) { - changedFiles.add(file) - } + configureModule(module, file, false, kotlinVersion, collector, filesToOpen) } else { showErrorMessage(project, "Cannot find build.gradle file for module " + module.name) } } - return changedFiles + return filesToOpen + } + + open fun configureModule( + module: Module, + file: PsiFile, + isTopLevelProjectFile: Boolean, + version: String, + collector: NotificationMessageCollector, + filesToOpen: MutableCollection + ) { + val isModified = configureBuildScript(file, isTopLevelProjectFile, version, collector) + if (isModified) { + filesToOpen.add(file) + } } protected fun configureModuleBuildScript(file: PsiFile, version: String): Boolean { @@ -171,7 +182,7 @@ abstract class KotlinWithGradleConfigurator : KotlinProjectConfigurator { return false } - fun configureBuildScript( + private fun configureBuildScript( file: PsiFile, isTopLevelProjectFile: Boolean, version: String, diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/AbstractGradleConfigureProjectByChangingFileTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/AbstractGradleConfigureProjectByChangingFileTest.kt index 24eab43a124..dac8b351463 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/AbstractGradleConfigureProjectByChangingFileTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/AbstractGradleConfigureProjectByChangingFileTest.kt @@ -17,40 +17,62 @@ package org.jetbrains.kotlin.idea.configuration import com.intellij.openapi.module.Module +import com.intellij.openapi.projectRoots.Sdk import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.KotlinTestUtils.isAllFilesPresentTest import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import java.io.File abstract class AbstractGradleConfigureProjectByChangingFileTest : AbstractConfigureProjectByChangingFileTest() { - fun doTestGradle(path: String) { - val testPathFile = File(testDataPath + path) - val (before, after) = if (testPathFile.isFile) { - path to path.replace("before", "after") - } - else { - when { - File(testPathFile, "build_before.gradle").exists() -> - "$path/build_before.gradle" to "$path/build_after.gradle" - - File(testPathFile, "build_before.gradle.kts").exists() -> - "$path/build_before.gradle.kts" to "$path/build_after.gradle.kts" - - else -> error("Can't find test data files") - } - } - + val (before, after) = beforeAfterFiles() doTest(before, after, if ("js" in path) KotlinJsGradleModuleConfigurator() else KotlinGradleModuleConfigurator()) } + private fun beforeAfterFiles(): Pair { + val root = KotlinTestUtils.getTestsRoot(this::class.java) + val test = KotlinTestUtils.getTestDataFileName(this::class.java, name) + val path = "$root/$test" + val testFile = File(path) + + if (testFile.isFile) { + return path to path.replace("before", "after") + } + + return when { + File(path, "build_before.gradle").exists() -> + "$path/build_before.gradle" to "$path/build_after.gradle" + + File(path, "build_before.gradle.kts").exists() -> + "$path/build_before.gradle.kts" to "$path/build_after.gradle.kts" + + else -> error("Can't find test data files") + } + } + override fun runConfigurator(module: Module, file: PsiFile, configurator: KotlinWithGradleConfigurator, version: String, collector: NotificationMessageCollector) { if (file !is GroovyFile && file !is KtFile) { fail("file $file is not a GroovyFile or KtFile") return } - configurator.configureBuildScript(file, true, version, collector) - configurator.configureBuildScript(file, false, version, collector) + configurator.configureModule(module, file, true, version, collector, ArrayList()) + configurator.configureModule(module, file, false, version, collector, ArrayList()) + } + + override fun getProjectJDK(): Sdk { + if (!isAllFilesPresentTest(getTestName(false))) { + val beforeAfterFiles = beforeAfterFiles() + val (before, _) = beforeAfterFiles + val gradleFile = File(before) + if (gradleFile.readText().contains("1.9")) { + return PluginTestCaseBase.mockJdk9() + } + } + + return super.getProjectJDK() } } diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/GradleConfigureProjectByChangingFileTestGenerated.java b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/GradleConfigureProjectByChangingFileTestGenerated.java index 1fd2dcf205a..d9db3671e0d 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/GradleConfigureProjectByChangingFileTestGenerated.java +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/configuration/GradleConfigureProjectByChangingFileTestGenerated.java @@ -79,6 +79,12 @@ public class GradleConfigureProjectByChangingFileTestGenerated extends AbstractG String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/rcVersion/"); doTestGradle(fileName); } + + @TestMetadata("withJava9ModuleInfo") + public void testWithJava9ModuleInfo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/withJava9ModuleInfo/"); + doTestGradle(fileName); + } } @TestMetadata("idea/testData/configuration/gsk") diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt index 8ed0f7fc432..3f4a4337be4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/ModuleSourceRootMap.kt @@ -56,9 +56,19 @@ class ModuleSourceRootMap(val modules: Collection) { } fun toModuleGroup(module: Module): ModuleSourceRootGroup = groupByBaseModules(listOf(module)).single() + + fun getWholeModuleGroup(module: Module): ModuleSourceRootGroup { + val externalPath = module.externalProjectPath + val baseModule = (if (externalPath != null) baseModuleByExternalPath[externalPath] else null) ?: + return ModuleSourceRootGroup(module, listOf(module)) + + val externalPathModules = allModulesByExternalPath[externalPath] ?: listOf() + return ModuleSourceRootGroup(baseModule, if (externalPathModules.size > 1) externalPathModules - module else externalPathModules) + } } fun Module.toModuleGroup() = ModuleSourceRootMap(project).toModuleGroup(this) +fun Module.getWholeModuleGroup() = ModuleSourceRootMap(project).getWholeModuleGroup(this) private fun isSourceRootPrefix(externalId: String, previousModuleExternalId: String) = externalId.length < previousModuleExternalId.length && previousModuleExternalId.startsWith(externalId) @@ -69,6 +79,13 @@ val Module.externalProjectId: String? val Module.externalProjectPath: String? get() = ExternalSystemApiUtil.getExternalProjectPath(this) +fun ModuleSourceRootGroup.allModules(): Set { + val result = LinkedHashSet() + result.add(baseModule) + result.addAll(sourceRootModules) + return result +} + fun List.exclude(excludeModules: Collection): List { return mapNotNull { if (it.baseModule in excludeModules) diff --git a/idea/testData/configuration/gradle/withJava9ModuleInfo/build_after.gradle b/idea/testData/configuration/gradle/withJava9ModuleInfo/build_after.gradle new file mode 100644 index 00000000000..799bf7b1964 --- /dev/null +++ b/idea/testData/configuration/gradle/withJava9ModuleInfo/build_after.gradle @@ -0,0 +1,33 @@ +apply plugin: 'java' +apply plugin: 'kotlin' + +sourceCompatibility = 1.9 +version = '1.0' + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.11' + compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" +} +buildscript { + ext.kotlin_version = '$VERSION$' + repositories { + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +compileKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} +compileTestKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} \ No newline at end of file diff --git a/idea/testData/configuration/gradle/withJava9ModuleInfo/build_before.gradle b/idea/testData/configuration/gradle/withJava9ModuleInfo/build_before.gradle new file mode 100644 index 00000000000..f49708d6dc2 --- /dev/null +++ b/idea/testData/configuration/gradle/withJava9ModuleInfo/build_before.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' + +sourceCompatibility = 1.9 +version = '1.0' + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.11' +} \ No newline at end of file diff --git a/idea/testData/configuration/gradle/withJava9ModuleInfo/module-info.java b/idea/testData/configuration/gradle/withJava9ModuleInfo/module-info.java new file mode 100644 index 00000000000..696515864d9 --- /dev/null +++ b/idea/testData/configuration/gradle/withJava9ModuleInfo/module-info.java @@ -0,0 +1,3 @@ +module TestModule { + +} \ No newline at end of file diff --git a/idea/testData/configuration/gradle/withJava9ModuleInfo/module-info_after.java b/idea/testData/configuration/gradle/withJava9ModuleInfo/module-info_after.java new file mode 100644 index 00000000000..6484cb66f3d --- /dev/null +++ b/idea/testData/configuration/gradle/withJava9ModuleInfo/module-info_after.java @@ -0,0 +1,4 @@ +module TestModule { + requires kotlin.stdlib; + +} \ No newline at end of file