From 6b48eae03e6f5cd0b82a934c5704da6f0f38abc5 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Thu, 3 Mar 2016 13:24:31 +0300 Subject: [PATCH] Configure Kotlin for Android: add kotlin plugin to project build.gradle file. Do not add mavenCentral dependency if jcenter is present --- generators/generators.iml | 1 + .../kotlin/generators/tests/GenerateTests.kt | 8 +- idea/idea.iml | 1 - .../kotlin-android-plugin.iml | 4 + ...KotlinAndroidGradleModuleConfigurator.java | 16 +- .../AbstractConfigureProjectTest.java | 26 +++ .../ConfigureProjectTestGenerated.java | 166 ++++++++++++++++++ idea/src/META-INF/android.xml | 2 + idea/src/META-INF/gradle.xml | 1 - .../KotlinGradleModuleConfigurator.java | 10 ++ .../KotlinWithGradleConfigurator.java | 82 +++++++-- ...actConfigureProjectByChangingFileTest.java | 9 +- ...ureProjectByChangingFileTestGenerated.java | 138 --------------- 13 files changed, 296 insertions(+), 168 deletions(-) rename idea/{src/org/jetbrains/kotlin/idea/configuration => kotlin-android-plugin/src/org/jetbrains/kotlin/android/configure}/KotlinAndroidGradleModuleConfigurator.java (80%) create mode 100644 idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/AbstractConfigureProjectTest.java create mode 100644 idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/ConfigureProjectTestGenerated.java diff --git a/generators/generators.iml b/generators/generators.iml index 0fe94e730fd..36ad805cfc5 100644 --- a/generators/generators.iml +++ b/generators/generators.iml @@ -33,5 +33,6 @@ + \ No newline at end of file diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index ab3b03f28c3..3d07e19d498 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.android.AbstractAndroidCompletionTest import org.jetbrains.kotlin.android.AbstractAndroidFindUsagesTest import org.jetbrains.kotlin.android.AbstractAndroidGotoTest import org.jetbrains.kotlin.android.AbstractAndroidRenameTest +import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest import org.jetbrains.kotlin.asJava.AbstractCompilerLightClassTest import org.jetbrains.kotlin.cfg.AbstractControlFlowTest @@ -568,7 +569,6 @@ fun main(args: Array) { } testClass() { - model("configuration/android-gradle", pattern = """(\w+)_before\.gradle$""", testMethod = "doTestAndroidGradle") model("configuration/gradle", pattern = """(\w+)_before\.gradle$""", testMethod = "doTestGradle") model("configuration/maven", extension = null, recursive = false, testMethod = "doTestWithMaven") model("configuration/js-maven", extension = null, recursive = false, testMethod = "doTestWithJSMaven") @@ -974,6 +974,12 @@ fun main(args: Array) { } } + testGroup("idea/kotlin-android-plugin/tests", "idea/testData") { + testClass() { + model("configuration/android-gradle", pattern = """(\w+)_before\.gradle$""", testMethod = "doTestAndroidGradle") + } + } + testGroup("plugins/android-jps-plugin/tests", "plugins/android-jps-plugin/testData") { testClass() { model("android", recursive = false, extension = null) diff --git a/idea/idea.iml b/idea/idea.iml index 8c98b4e91d6..29a43318a37 100644 --- a/idea/idea.iml +++ b/idea/idea.iml @@ -38,7 +38,6 @@ - diff --git a/idea/kotlin-android-plugin/kotlin-android-plugin.iml b/idea/kotlin-android-plugin/kotlin-android-plugin.iml index 212437c1f39..b2c079fe125 100644 --- a/idea/kotlin-android-plugin/kotlin-android-plugin.iml +++ b/idea/kotlin-android-plugin/kotlin-android-plugin.iml @@ -4,6 +4,7 @@ + @@ -13,5 +14,8 @@ + + + \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinAndroidGradleModuleConfigurator.java b/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleModuleConfigurator.java similarity index 80% rename from idea/src/org/jetbrains/kotlin/idea/configuration/KotlinAndroidGradleModuleConfigurator.java rename to idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleModuleConfigurator.java index e718aecffe6..cf98cd79157 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinAndroidGradleModuleConfigurator.java +++ b/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleModuleConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.configuration; +package org.jetbrains.kotlin.android.configure; import com.intellij.openapi.module.Module; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.KotlinPluginUtil; +import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator; import org.jetbrains.kotlin.resolve.TargetPlatform; import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; @@ -63,6 +64,17 @@ public class KotlinAndroidGradleModuleConfigurator extends KotlinWithGradleConfi addLastExpressionInBlockIfNeeded(SOURCE_SET, getSourceSetsBlock(androidBlock)); } + @Override + protected boolean addElementsToFile(@NotNull GroovyFile groovyFile, boolean isTopLevelProjectFile, @NotNull String version) { + if (isTopLevelProjectFile) { + addElementsToProjectFile(groovyFile, version); + } + else { + addElementsToModuleFile(groovyFile, version); + } + return true; + } + @NotNull private static GrClosableBlock getAndroidBlock(@NotNull GroovyFile file) { return getBlockOrCreate(file, "android"); diff --git a/idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/AbstractConfigureProjectTest.java b/idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/AbstractConfigureProjectTest.java new file mode 100644 index 00000000000..2b157c36a1e --- /dev/null +++ b/idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/AbstractConfigureProjectTest.java @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2016 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.android.configure; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.idea.configuration.AbstractConfigureProjectByChangingFileTest; + +public abstract class AbstractConfigureProjectTest extends AbstractConfigureProjectByChangingFileTest { + public void doTestAndroidGradle(@NotNull String path) throws Exception { + doTest(path, path.replace("before", "after"), new KotlinAndroidGradleModuleConfigurator()); + } +} diff --git a/idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/ConfigureProjectTestGenerated.java b/idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/ConfigureProjectTestGenerated.java new file mode 100644 index 00000000000..c3d4c434dcd --- /dev/null +++ b/idea/kotlin-android-plugin/tests/org/jetbrains/kotlin/android/configure/ConfigureProjectTestGenerated.java @@ -0,0 +1,166 @@ +/* + * Copyright 2010-2016 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.android.configure; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/configuration/android-gradle") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class ConfigureProjectTestGenerated extends AbstractConfigureProjectTest { + public void testAllFilesPresentInAndroid_gradle() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/android-gradle"), Pattern.compile("(\\w+)_before\\.gradle$"), true); + } + + @TestMetadata("androidStudioDefault_before.gradle") + public void testAndroidStudioDefault() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/androidStudioDefault_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("androidStudioDefaultShapshot_before.gradle") + public void testAndroidStudioDefaultShapshot() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/androidStudioDefaultShapshot_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("buildConfigs_before.gradle") + public void testBuildConfigs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/buildConfigs_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("emptyDependencyList_before.gradle") + public void testEmptyDependencyList() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/emptyDependencyList_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("emptyFile_before.gradle") + public void testEmptyFile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/emptyFile_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("helloWorld_before.gradle") + public void testHelloWorld() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/helloWorld_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("libraryFile_before.gradle") + public void testLibraryFile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/libraryFile_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("missedApplyAndroidStatement_before.gradle") + public void testMissedApplyAndroidStatement() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/missedApplyAndroidStatement_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("missedBuildscriptBlock_before.gradle") + public void testMissedBuildscriptBlock() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/missedBuildscriptBlock_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("missedRepositoriesInBuildscriptBlock_before.gradle") + public void testMissedRepositoriesInBuildscriptBlock() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/missedRepositoriesInBuildscriptBlock_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("productFlavor_before.gradle") + public void testProductFlavor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/productFlavor_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("idea/testData/configuration/android-gradle/gradleExamples") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GradleExamples extends AbstractConfigureProjectTest { + public void testAllFilesPresentInGradleExamples() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/android-gradle/gradleExamples"), Pattern.compile("(\\w+)_before\\.gradle$"), true); + } + + @TestMetadata("gradleExample0_before.gradle") + public void testGradleExample0() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample0_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample18_before.gradle") + public void testGradleExample18() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample18_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample22_before.gradle") + public void testGradleExample22() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample22_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample44_before.gradle") + public void testGradleExample44() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample44_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample5_before.gradle") + public void testGradleExample5() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample5_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample50_before.gradle") + public void testGradleExample50() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample50_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample58_before.gradle") + public void testGradleExample58() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample58_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample65_before.gradle") + public void testGradleExample65() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample65_before.gradle"); + doTestAndroidGradle(fileName); + } + + @TestMetadata("gradleExample8_before.gradle") + public void testGradleExample8() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample8_before.gradle"); + doTestAndroidGradle(fileName); + } + } +} diff --git a/idea/src/META-INF/android.xml b/idea/src/META-INF/android.xml index abfb9468828..1a6150e70bb 100644 --- a/idea/src/META-INF/android.xml +++ b/idea/src/META-INF/android.xml @@ -25,6 +25,8 @@ + + diff --git a/idea/src/META-INF/gradle.xml b/idea/src/META-INF/gradle.xml index 2fe9a36e85f..53b2348a075 100644 --- a/idea/src/META-INF/gradle.xml +++ b/idea/src/META-INF/gradle.xml @@ -1,6 +1,5 @@ - diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.java b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.java index 86d31f0a1ea..719524bdedc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.java +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleModuleConfigurator.java @@ -64,6 +64,16 @@ public class KotlinGradleModuleConfigurator extends KotlinWithGradleConfigurator addLastExpressionInBlockIfNeeded(SOURCE_SET, sourceSetBlock); } + @Override + protected boolean addElementsToFile(@NotNull GroovyFile groovyFile, boolean isTopLevelProjectFile, @NotNull String version) { + if (!isTopLevelProjectFile) { + addElementsToProjectFile(groovyFile, version); + addElementsToModuleFile(groovyFile, version); + return true; + } + return false; + } + KotlinGradleModuleConfigurator() { } } diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java index 62df722838c..7cc413cbb8c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java @@ -49,13 +49,16 @@ import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import java.io.File; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfigurator { protected static final String VERSION_TEMPLATE = "$VERSION$"; protected static final String CLASSPATH = "classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\""; protected static final String SNAPSHOT_REPOSITORY = "maven {\nurl 'http://oss.sonatype.org/content/repositories/snapshots'\n}"; - public static final String REPOSITORY = "mavenCentral()\n"; + public static final String MAVEN_CENTRAL = "mavenCentral()\n"; + public static final String JCENTER = "jcenter()\n"; public static final String LIBRARY = "compile \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\""; protected static final String SOURCE_SET = "main.java.srcDirs += 'src/main/kotlin'\n"; protected static final String VERSION = String.format("ext.kotlin_version = '%s'", VERSION_TEMPLATE); @@ -66,11 +69,11 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi return true; } - GroovyFile moduleGradleFile = getBuildGradleFile(module.getProject(), getDefaultPathToBuildGradleFile(module)); + GroovyFile moduleGradleFile = getBuildGradleFile(module.getProject(), getModuleFilePath(module)); if (moduleGradleFile != null && isFileConfigured(moduleGradleFile)) { return true; } - GroovyFile projectGradleFile = getBuildGradleFile(module.getProject(), getDefaultPathToBuildGradleFile(module.getProject())); + GroovyFile projectGradleFile = getBuildGradleFile(module.getProject(), getTopLevelProjectFilePath(module.getProject())); return projectGradleFile != null && isFileConfigured(projectGradleFile); } @@ -88,22 +91,36 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi if (!dialog.isOK()) return; NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(project); + Set changedFiles = new HashSet(); + GroovyFile projectGradleFile = getBuildGradleFile(project, getTopLevelProjectFilePath(project)); + if (projectGradleFile != null && canConfigureFile(projectGradleFile)) { + boolean isModified = changeGradleFile(projectGradleFile, true, dialog.getKotlinVersion(), collector); + if (isModified) { + changedFiles.add(projectGradleFile); + } + } + for (Module module : dialog.getModulesToConfigure()) { - String gradleFilePath = getDefaultPathToBuildGradleFile(module); - GroovyFile file = getBuildGradleFile(project, gradleFilePath); + GroovyFile file = getBuildGradleFile(project, getModuleFilePath(module)); if (file != null && canConfigureFile(file)) { - changeGradleFile(file, dialog.getKotlinVersion(), collector); - OpenFileAction.openFile(gradleFilePath, project); + boolean isModified = changeGradleFile(file, false, dialog.getKotlinVersion(), collector); + if (isModified) { + changedFiles.add(file); + } } else { showErrorMessage(project, "Cannot find build.gradle file for module " + module.getName()); } } + + for (GroovyFile file : changedFiles) { + OpenFileAction.openFile(file.getVirtualFile(), project); + } collector.showNotification(); } public static void addKotlinLibraryToModule(final Module module, final DependencyScope scope, final ExternalLibraryDescriptor libraryDescriptor) { - String gradleFilePath = getDefaultPathToBuildGradleFile(module); + String gradleFilePath = getModuleFilePath(module); final GroovyFile gradleFile = getBuildGradleFile(module.getProject(), gradleFilePath); if (gradleFile != null && canConfigureFile(gradleFile)) { @@ -156,7 +173,7 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi @Nullable public static String getKotlinStdlibVersion(@NotNull Module module) { - String gradleFilePath = getDefaultPathToBuildGradleFile(module); + String gradleFilePath = getModuleFilePath(module); GroovyFile gradleFile = getBuildGradleFile(module.getProject(), gradleFilePath); if (gradleFile == null) return null; @@ -181,7 +198,7 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi return null; } - private void addElements(@NotNull GroovyFile file, @NotNull String version) { + protected void addElementsToProjectFile(@NotNull GroovyFile file, @NotNull String version) { GrClosableBlock buildScriptBlock = getBuildScriptBlock(file); addFirstExpressionInBlockIfNeeded(VERSION.replace(VERSION_TEMPLATE, version), buildScriptBlock); @@ -189,13 +206,15 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi if (isSnapshot(version)) { addLastExpressionInBlockIfNeeded(SNAPSHOT_REPOSITORY, buildScriptRepositoriesBlock); } - else if (!buildScriptRepositoriesBlock.getText().contains(REPOSITORY)) { - addLastExpressionInBlockIfNeeded(REPOSITORY, buildScriptRepositoriesBlock); + else if (!isRepositoryConfigured(buildScriptRepositoriesBlock)) { + addLastExpressionInBlockIfNeeded(MAVEN_CENTRAL, buildScriptRepositoriesBlock); } GrClosableBlock buildScriptDependenciesBlock = getBuildScriptDependenciesBlock(file); addLastExpressionInBlockIfNeeded(CLASSPATH, buildScriptDependenciesBlock); + } + protected void addElementsToModuleFile(@NotNull GroovyFile file, @NotNull String version) { if (!file.getText().contains(getApplyPluginDirective())) { GrExpression apply = GroovyPsiElementFactory.getInstance(file.getProject()).createExpressionFromText(getApplyPluginDirective()); GrApplicationStatement applyStatement = getApplyStatement(file); @@ -203,7 +222,19 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi file.addAfter(apply, applyStatement); } else { - file.addAfter(apply, buildScriptBlock.getParent()); + GrClosableBlock buildScript = getBlockByName(file, "buildscript"); + if (buildScript != null) { + file.addAfter(apply, buildScript.getParent()); + } + else { + GrStatement[] statements = file.getStatements(); + if (statements.length > 0) { + file.addAfter(apply, statements[statements.length - 1]); + } + else { + file.addAfter(apply, file.getFirstChild()); + } + } } } @@ -211,8 +242,8 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi if (isSnapshot(version)) { addLastExpressionInBlockIfNeeded(SNAPSHOT_REPOSITORY, repositoriesBlock); } - else if (!repositoriesBlock.getText().contains(REPOSITORY)) { - addLastExpressionInBlockIfNeeded(REPOSITORY, repositoriesBlock); + else if (!isRepositoryConfigured(repositoriesBlock)) { + addLastExpressionInBlockIfNeeded(MAVEN_CENTRAL, repositoriesBlock); } GrClosableBlock dependenciesBlock = getDependenciesBlock(file); @@ -221,10 +252,20 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi addSourceSetsBlock(file); } + private boolean isRepositoryConfigured(GrClosableBlock repositoriesBlock) { + return repositoriesBlock.getText().contains(MAVEN_CENTRAL) || repositoriesBlock.getText().contains(JCENTER); + } + protected abstract String getApplyPluginDirective(); protected abstract void addSourceSetsBlock(@NotNull GroovyFile file); + protected abstract boolean addElementsToFile( + @NotNull GroovyFile groovyFile, + boolean isTopLevelProjectFile, + @NotNull String version + ); + protected static boolean canConfigureFile(@NotNull GroovyFile file) { return WritingAccessProvider.isPotentiallyWritable(file.getVirtualFile(), null); } @@ -241,12 +282,12 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi } @NotNull - protected static String getDefaultPathToBuildGradleFile(@NotNull Project project) { + protected static String getTopLevelProjectFilePath(@NotNull Project project) { return project.getBasePath() + "/" + GradleConstants.DEFAULT_SCRIPT_NAME; } @NotNull - protected static String getDefaultPathToBuildGradleFile(@NotNull Module module) { + protected static String getModuleFilePath(@NotNull Module module) { return new File(module.getModuleFilePath()).getParent() + "/" + GradleConstants.DEFAULT_SCRIPT_NAME; } @@ -254,15 +295,17 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi return version.contains("SNAPSHOT"); } - protected void changeGradleFile( + protected boolean changeGradleFile( @NotNull final GroovyFile groovyFile, + final boolean isTopLevelProjectFile, @NotNull final String version, @NotNull NotificationMessageCollector collector ) { + final boolean[] isModified = {false}; new WriteCommandAction(groovyFile.getProject()) { @Override protected void run(@NotNull Result result) { - addElements(groovyFile, version); + isModified[0] = addElementsToFile(groovyFile, isTopLevelProjectFile, version); CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(groovyFile); } @@ -272,6 +315,7 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi if (virtualFile != null) { collector.addMessage(virtualFile.getPath() + " was modified"); } + return isModified[0]; } @NotNull diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureProjectByChangingFileTest.java b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureProjectByChangingFileTest.java index 6fc6f65976a..b864e1107de 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureProjectByChangingFileTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureProjectByChangingFileTest.java @@ -38,15 +38,11 @@ public abstract class AbstractConfigureProjectByChangingFileTest extends LightCo doTest(pathWithFile, pathWithFile.replace("pom", "pom_after"), new KotlinJavascriptMavenConfigurator()); } - public void doTestAndroidGradle(@NotNull String path) throws Exception { - doTest(path, path.replace("before", "after"), new KotlinAndroidGradleModuleConfigurator()); - } - public void doTestGradle(@NotNull String path) throws Exception { doTest(path, path.replace("before", "after"), new KotlinGradleModuleConfigurator()); } - private void doTest(@NotNull String beforeFile, @NotNull String afterFile, @NotNull KotlinProjectConfigurator configurator) throws Exception { + protected void doTest(@NotNull String beforeFile, @NotNull String afterFile, @NotNull KotlinProjectConfigurator configurator) throws Exception { configureByFile(beforeFile); String versionFromFile = InTextDirectivesUtils.findStringWithPrefixes(getFile().getText(), "// VERSION:"); @@ -54,7 +50,8 @@ public abstract class AbstractConfigureProjectByChangingFileTest extends LightCo NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(getProject()); if (configurator instanceof KotlinWithGradleConfigurator) { - ((KotlinWithGradleConfigurator) configurator).changeGradleFile((GroovyFile) getFile(), version, collector); + ((KotlinWithGradleConfigurator) configurator).changeGradleFile((GroovyFile) getFile(), true, version, collector); + ((KotlinWithGradleConfigurator) configurator).changeGradleFile((GroovyFile) getFile(), false, version, collector); } else if (configurator instanceof KotlinMavenConfigurator) { ((KotlinMavenConfigurator) configurator).changePomFile(getModule(), getFile(), version, collector); diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureProjectByChangingFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureProjectByChangingFileTestGenerated.java index feec0917073..ed35fd5ad5f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureProjectByChangingFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureProjectByChangingFileTestGenerated.java @@ -29,144 +29,6 @@ import java.util.regex.Pattern; @SuppressWarnings("all") @RunWith(JUnit3RunnerWithInners.class) public class ConfigureProjectByChangingFileTestGenerated extends AbstractConfigureProjectByChangingFileTest { - @TestMetadata("idea/testData/configuration/android-gradle") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Android_gradle extends AbstractConfigureProjectByChangingFileTest { - public void testAllFilesPresentInAndroid_gradle() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/android-gradle"), Pattern.compile("(\\w+)_before\\.gradle$"), true); - } - - @TestMetadata("androidStudioDefault_before.gradle") - public void testAndroidStudioDefault() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/androidStudioDefault_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("androidStudioDefaultShapshot_before.gradle") - public void testAndroidStudioDefaultShapshot() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/androidStudioDefaultShapshot_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("buildConfigs_before.gradle") - public void testBuildConfigs() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/buildConfigs_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("emptyDependencyList_before.gradle") - public void testEmptyDependencyList() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/emptyDependencyList_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("emptyFile_before.gradle") - public void testEmptyFile() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/emptyFile_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("helloWorld_before.gradle") - public void testHelloWorld() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/helloWorld_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("libraryFile_before.gradle") - public void testLibraryFile() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/libraryFile_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("missedApplyAndroidStatement_before.gradle") - public void testMissedApplyAndroidStatement() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/missedApplyAndroidStatement_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("missedBuildscriptBlock_before.gradle") - public void testMissedBuildscriptBlock() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/missedBuildscriptBlock_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("missedRepositoriesInBuildscriptBlock_before.gradle") - public void testMissedRepositoriesInBuildscriptBlock() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/missedRepositoriesInBuildscriptBlock_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("productFlavor_before.gradle") - public void testProductFlavor() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/productFlavor_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("idea/testData/configuration/android-gradle/gradleExamples") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class GradleExamples extends AbstractConfigureProjectByChangingFileTest { - public void testAllFilesPresentInGradleExamples() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/android-gradle/gradleExamples"), Pattern.compile("(\\w+)_before\\.gradle$"), true); - } - - @TestMetadata("gradleExample0_before.gradle") - public void testGradleExample0() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample0_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample18_before.gradle") - public void testGradleExample18() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample18_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample22_before.gradle") - public void testGradleExample22() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample22_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample44_before.gradle") - public void testGradleExample44() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample44_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample5_before.gradle") - public void testGradleExample5() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample5_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample50_before.gradle") - public void testGradleExample50() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample50_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample58_before.gradle") - public void testGradleExample58() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample58_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample65_before.gradle") - public void testGradleExample65() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample65_before.gradle"); - doTestAndroidGradle(fileName); - } - - @TestMetadata("gradleExample8_before.gradle") - public void testGradleExample8() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/android-gradle/gradleExamples/gradleExample8_before.gradle"); - doTestAndroidGradle(fileName); - } - } - } - @TestMetadata("idea/testData/configuration/gradle") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)