diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java index 131559bfab1..a9f766d0c56 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithGradleConfigurator.java @@ -22,6 +22,8 @@ import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.DependencyScope; +import com.intellij.openapi.roots.ExternalLibraryDescriptor; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -33,6 +35,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.idea.KotlinPluginUtil; import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion; import org.jetbrains.kotlin.idea.project.ProjectStructureUtil; import org.jetbrains.plugins.gradle.util.GradleConstants; @@ -104,6 +107,83 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi } } + public static void addKotlinLibraryToModule(final Module module, final DependencyScope scope, final ExternalLibraryDescriptor libraryDescriptor) { + String gradleFilePath = getDefaultPathToBuildGradleFile(module); + final GroovyFile gradleFile = getBuildGradleFile(module.getProject(), gradleFilePath); + + if (gradleFile != null && canConfigureFile(gradleFile)) { + new WriteCommandAction(gradleFile.getProject()) { + @Override + protected void run(@NotNull Result result) { + String groovyScope; + switch (scope) { + case COMPILE: + groovyScope = "compile"; + break; + case TEST: + if (KotlinPluginUtil.isAndroidGradleModule(module)) { + // TODO we should add testCompile or androidTestCompile + groovyScope = "compile"; + } + else { + groovyScope = "testCompile"; + } + break; + case RUNTIME: + groovyScope = "runtime"; + break; + case PROVIDED: + groovyScope = "compile"; + break; + default: + groovyScope = "compile"; + } + + String dependencyString = String.format( + "%s \"%s:%s:%s\"", + groovyScope, libraryDescriptor.getLibraryGroupId(), libraryDescriptor.getLibraryArtifactId(), libraryDescriptor.getMaxVersion()); + + GrClosableBlock dependenciesBlock = getDependenciesBlock(gradleFile); + addLastExpressionInBlockIfNeeded(dependencyString, dependenciesBlock); + + CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(gradleFile); + } + }.execute(); + + VirtualFile virtualFile = gradleFile.getVirtualFile(); + if (virtualFile != null) { + showInfoNotification(gradleFile.getProject(), virtualFile.getPath() + " was modified"); + } + } + } + + @Nullable + public static String getKotlinStdlibVersion(@NotNull Module module) { + String gradleFilePath = getDefaultPathToBuildGradleFile(module); + GroovyFile gradleFile = getBuildGradleFile(module.getProject(), gradleFilePath); + + if (gradleFile == null) return null; + + String versionProperty = "$kotlin_version"; + GrClosableBlock block = getBuildScriptBlock(gradleFile); + if (block.getText().contains("ext.kotlin_version = ")) { + return versionProperty; + } + + GrStatement[] dependencies = getDependenciesBlock(gradleFile).getStatements(); + String stdlibArtifactPrefix = "org.jetbrains.kotlin:kotlin-stdlib:"; + for (GrStatement dependency : dependencies) { + String dependencyText = dependency.getText(); + int startIndex = dependencyText.indexOf(stdlibArtifactPrefix) + stdlibArtifactPrefix.length(); + int endIndex = dependencyText.length() - 1; + if (startIndex != -1 && endIndex != -1) { + return dependencyText.substring(startIndex, endIndex); + } + } + + return null; + } + private void addElements(@NotNull GroovyFile file, @NotNull String version) { GrClosableBlock buildScriptBlock = getBuildScriptBlock(file); addFirstExpressionInBlockIfNeeded(VERSION.replace(VERSION_TEMPLATE, version), buildScriptBlock); @@ -180,7 +260,7 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi protected void changeGradleFile(@NotNull final GroovyFile groovyFile, @NotNull final String version) { new WriteCommandAction(groovyFile.getProject()) { @Override - protected void run(Result result) { + protected void run(@NotNull Result result) { addElements(groovyFile, version); CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(groovyFile); @@ -258,7 +338,6 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi if (allExpressions != null) { for (GrMethodCallExpression expression : allExpressions) { GrExpression invokedExpression = expression.getInvokedExpression(); - if (invokedExpression == null) continue; if (expression.getClosureArguments().length == 0) continue; String expressionText = invokedExpression.getText(); @@ -293,7 +372,7 @@ public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfi if (applyStatement == null) return null; for (GrApplicationStatement callExpression : applyStatement) { GrExpression invokedExpression = callExpression.getInvokedExpression(); - if (invokedExpression != null && invokedExpression.getText().equals("apply")) { + if (invokedExpression.getText().equals("apply")) { return callExpression; } } diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt index d36dea329e3..6ddbf59021c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/AddKotlinLibQuickFix.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.idea.KotlinPluginUtil import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtils import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator +import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory @@ -99,7 +100,7 @@ public abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixA protected abstract fun hasLibJarInLibrary(library: Library): Boolean protected abstract fun getLibraryDescriptor(module: Module): MavenExternalLibraryDescriptor - class MavenExternalLibraryDescriptor(groupId: String, artifactId: String, version: String? = null) : + class MavenExternalLibraryDescriptor(groupId: String, artifactId: String, version: String) : ExternalLibraryDescriptor(groupId, artifactId, version, version) { override fun getLibraryClassesRoots(): List = emptyList() } @@ -113,6 +114,13 @@ public abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixA return } + + if (KotlinPluginUtil.isGradleModule(module) || KotlinPluginUtil.isAndroidGradleModule(module)) { + val scope = OrderEntryFix.suggestScopeByLocation(module, element) + KotlinWithGradleConfigurator.addKotlinLibraryToModule(module, scope, getLibraryDescriptor(module)) + + return + } } val libFile = getLibFile() @@ -146,12 +154,25 @@ public abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixA } companion object { - fun getKotlinStdlibVersion(module: Module): String? { + fun getKotlinStdlibVersion(module: Module): String { if (KotlinPluginUtil.isMavenModule(module)) { - return getMavenKotlinStdlibVersion(module) + val mavenVersion = getMavenKotlinStdlibVersion(module) + if (mavenVersion != null) { + return mavenVersion + } + } + else if (KotlinPluginUtil.isGradleModule(module) || KotlinPluginUtil.isAndroidGradleModule(module)) { + val gradleVersion = KotlinWithGradleConfigurator.getKotlinStdlibVersion(module) + if (gradleVersion != null) { + return gradleVersion + } } - return null + val pluginVersion = KotlinRuntimeLibraryUtil.bundledRuntimeVersion() + if ("@snapshot@" == pluginVersion) { + return "0.1-SNAPSHOT" + } + return pluginVersion } fun getMavenKotlinStdlibVersion(module: Module): String? {