From b9161c5293dd7a9377fbd3ab524292ca5589c63a Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 23 Oct 2018 16:06:10 +0300 Subject: [PATCH] Gradle configurator: handle kotlin options correctly with new-mpp plugin #KT-27052 Fixed --- .../GroovyBuildScriptManipulator.kt | 70 +++++++++++++++++-- .../gradle/GradleConfiguratorTest.kt | 64 +++++++++++++++++ .../build.gradle | 31 ++++++++ .../build.gradle.after | 36 ++++++++++ .../build.gradle | 31 ++++++++ .../build.gradle.after | 36 ++++++++++ .../build.gradle | 36 ++++++++++ .../build.gradle.after | 36 ++++++++++ .../build.gradle | 29 ++++++++ .../build.gradle.after | 36 ++++++++++ 10 files changed, 398 insertions(+), 7 deletions(-) create mode 100644 idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle create mode 100644 idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle.after create mode 100644 idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle create mode 100644 idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle.after create mode 100644 idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle create mode 100644 idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle.after create mode 100644 idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle create mode 100644 idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle.after diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GroovyBuildScriptManipulator.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GroovyBuildScriptManipulator.kt index 2ae609d28a8..b7f0a9b3dc2 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GroovyBuildScriptManipulator.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GroovyBuildScriptManipulator.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator.Comp import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement @@ -246,6 +247,34 @@ class GroovyBuildScriptManipulator( ) } + private fun usesNewMultiplatform(): Boolean { + val fileText = runReadAction { scriptFile.text } + return fileText.contains("kotlin-multiplatform") + } + + private fun GrClosableBlock.addParameterAssignment( + parameterName: String, + defaultValue: String, + replaceIt: GrStatement.(Boolean) -> GrStatement + ) { + statements.firstOrNull { stmt -> + (stmt as? GrAssignmentExpression)?.lValue?.text == parameterName + }?.let { stmt -> + stmt.replaceIt(false) + } ?: addLastExpressionInBlockIfNeeded("$parameterName = $defaultValue") + } + + private fun String.extractTextFromQuotes(quoteCharacter: Char): String? { + val quoteIndex = indexOf(quoteCharacter) + if (quoteIndex != -1) { + val lastQuoteIndex = lastIndexOf(quoteCharacter) + return if (lastQuoteIndex > quoteIndex) substring(quoteIndex + 1, lastQuoteIndex) else null + } + return null + } + + private fun String.extractTextFromQuotes(): String = extractTextFromQuotes('\'') ?: extractTextFromQuotes('"') ?: this + private fun addOrReplaceKotlinTaskParameter( gradleFile: GroovyFile, parameterName: String, @@ -253,6 +282,39 @@ class GroovyBuildScriptManipulator( forTests: Boolean, replaceIt: GrStatement.(Boolean) -> GrStatement ): PsiElement? { + if (usesNewMultiplatform()) { + val kotlinBlock = gradleFile.getBlockOrCreate("kotlin") + val kotlinTargets = kotlinBlock.getBlockOrCreate("targets") + val targetNames = mutableListOf() + + fun GrStatement.handleTarget(targetExpectedText: String) { + if (this is GrMethodCallExpression && invokedExpression.text == targetExpectedText) { + val targetNameArgument = argumentList.expressionArguments.getOrNull(1)?.text + if (targetNameArgument != null) { + targetNames += targetNameArgument.extractTextFromQuotes() + } + } + } + + for (target in kotlinTargets.statements) { + target.handleTarget("fromPreset") + } + for (target in kotlinBlock.statements) { + target.handleTarget("targets.fromPreset") + } + + val configureBlock = kotlinTargets.getBlockOrCreate("configure") + val factory = GroovyPsiElementFactory.getInstance(kotlinTargets.project) + val argumentList = factory.createArgumentListFromText( + targetNames.joinToString(prefix = "([", postfix = "])", separator = ", ") + ) + configureBlock.getStrictParentOfType()!!.argumentList.replaceWithArgumentList(argumentList) + + val kotlinOptions = configureBlock.getBlockOrCreate("tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions") + kotlinOptions.addParameterAssignment(parameterName, defaultValue, replaceIt) + return kotlinOptions.parent.parent + } + val kotlinBlock = gradleFile.getBlockOrCreate(if (forTests) "compileTestKotlin" else "compileKotlin") for (stmt in kotlinBlock.statements) { @@ -261,13 +323,7 @@ class GroovyBuildScriptManipulator( } } - kotlinBlock.getBlockOrCreate("kotlinOptions").apply { - statements.firstOrNull { stmt -> - (stmt as? GrAssignmentExpression)?.lValue?.text == parameterName - }?.let { stmt -> - stmt.replaceIt(false) - } ?: addLastExpressionInBlockIfNeeded("$parameterName = $defaultValue") - } + kotlinBlock.getBlockOrCreate("kotlinOptions").addParameterAssignment(parameterName, defaultValue, replaceIt) return kotlinBlock.parent } diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt index e964b6cb918..edab338556b 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorTest.kt @@ -581,6 +581,22 @@ class GradleConfiguratorTest : GradleImportingTestCase() { } } + @TargetVersions("4.7+") + @Test + fun testDisableFeatureSupportMultiplatform() { + val files = importProjectFromTestData() + + runInEdtAndWait { + myTestFixture.project.executeWriteCommand("") { + KotlinWithGradleConfigurator.changeFeatureConfiguration( + myTestFixture.module, LanguageFeature.InlineClasses, LanguageFeature.State.DISABLED, false + ) + } + + checkFiles(files) + } + } + @Test fun testEnableFeatureSupport() { val files = importProjectFromTestData() @@ -596,6 +612,54 @@ class GradleConfiguratorTest : GradleImportingTestCase() { } } + @TargetVersions("4.7+") + @Test + fun testEnableFeatureSupportMultiplatform() { + val files = importProjectFromTestData() + + runInEdtAndWait { + myTestFixture.project.executeWriteCommand("") { + KotlinWithGradleConfigurator.changeFeatureConfiguration( + myTestFixture.module, LanguageFeature.InlineClasses, LanguageFeature.State.ENABLED, false + ) + } + + checkFiles(files) + } + } + + @TargetVersions("4.7+") + @Test + fun testEnableFeatureSupportMultiplatformWithDots() { + val files = importProjectFromTestData() + + runInEdtAndWait { + myTestFixture.project.executeWriteCommand("") { + KotlinWithGradleConfigurator.changeFeatureConfiguration( + myTestFixture.module, LanguageFeature.InlineClasses, LanguageFeature.State.ENABLED, false + ) + } + + checkFiles(files) + } + } + + @TargetVersions("4.7+") + @Test + fun testEnableFeatureSupportMultiplatformToExistentArguments() { + val files = importProjectFromTestData() + + runInEdtAndWait { + myTestFixture.project.executeWriteCommand("") { + KotlinWithGradleConfigurator.changeFeatureConfiguration( + myTestFixture.module, LanguageFeature.InlineClasses, LanguageFeature.State.ENABLED, false + ) + } + + checkFiles(files) + } + } + @Test fun testEnableFeatureSupportToExistentArguments() { val files = importProjectFromTestData() diff --git a/idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle b/idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle new file mode 100644 index 00000000000..84b1b320c04 --- /dev/null +++ b/idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle @@ -0,0 +1,31 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle.after b/idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle.after new file mode 100644 index 00000000000..7ef39f1c443 --- /dev/null +++ b/idea/testData/gradle/configurator/disableFeatureSupportMultiplatform/build.gradle.after @@ -0,0 +1,36 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + configure([jvm]) { + tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions { + freeCompilerArgs = ["-XXLanguage:-InlineClasses"] + } + } + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle new file mode 100644 index 00000000000..84b1b320c04 --- /dev/null +++ b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle @@ -0,0 +1,31 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle.after b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle.after new file mode 100644 index 00000000000..4350b62943a --- /dev/null +++ b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatform/build.gradle.after @@ -0,0 +1,36 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + configure([jvm]) { + tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions { + freeCompilerArgs = ["-XXLanguage:+InlineClasses"] + } + } + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle new file mode 100644 index 00000000000..c06e5a5f4bd --- /dev/null +++ b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle @@ -0,0 +1,36 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + configure([jvm]) { + tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions { + freeCompilerArgs = ["-XXLanguage:+SamConversionForKotlinFunctions"] + } + } + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle.after b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle.after new file mode 100644 index 00000000000..0599bc2c7f3 --- /dev/null +++ b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformToExistentArguments/build.gradle.after @@ -0,0 +1,36 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets { + fromPreset(presets.jvm, 'jvm') + configure([jvm]) { + tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions { + freeCompilerArgs = ["-XXLanguage:+SamConversionForKotlinFunctions", "-XXLanguage:+InlineClasses"] + } + } + } + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle new file mode 100644 index 00000000000..3c60ed007dc --- /dev/null +++ b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets.fromPreset(presets.jvm, 'jvm') + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } +} diff --git a/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle.after b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle.after new file mode 100644 index 00000000000..647c6ac247c --- /dev/null +++ b/idea/testData/gradle/configurator/enableFeatureSupportMultiplatformWithDots/build.gradle.after @@ -0,0 +1,36 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.0-rc-190" + } +} +apply plugin: "kotlin-multiplatform" +repositories { + jcenter() + mavenCentral() +} +kotlin { + targets.fromPreset(presets.jvm, 'jvm') + sourceSets { + commonMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + jvmMain { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-stdlib' + } + } + } + targets { + configure([jvm]) { + tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions { + freeCompilerArgs = ["-XXLanguage:+InlineClasses"] + } + } + } +}