KotlinWithGradleConfigurator: J2K
This commit is contained in:
+3
-3
@@ -61,13 +61,13 @@ public class KotlinAndroidGradleModuleConfigurator extends KotlinWithGradleConfi
|
||||
@Override
|
||||
protected boolean addSourceSetsBlock(@NotNull GroovyFile file) {
|
||||
GrClosableBlock androidBlock = getAndroidBlock(file);
|
||||
return addLastExpressionInBlockIfNeeded(SOURCE_SET, getSourceSetsBlock(androidBlock));
|
||||
return Companion.addLastExpressionInBlockIfNeeded(Companion.getSOURCE_SET(), Companion.getSourceSetsBlock(androidBlock));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addElementsToFile(@NotNull GroovyFile groovyFile, boolean isTopLevelProjectFile, @NotNull String version) {
|
||||
if (isTopLevelProjectFile) {
|
||||
return addElementsToProjectFile(groovyFile, version);
|
||||
return Companion.addElementsToProjectFile(groovyFile, version);
|
||||
}
|
||||
else {
|
||||
return addElementsToModuleFile(groovyFile, version);
|
||||
@@ -76,7 +76,7 @@ public class KotlinAndroidGradleModuleConfigurator extends KotlinWithGradleConfi
|
||||
|
||||
@NotNull
|
||||
private static GrClosableBlock getAndroidBlock(@NotNull GroovyFile file) {
|
||||
return getBlockOrCreate(file, "android");
|
||||
return Companion.getBlockOrCreate(file, "android");
|
||||
}
|
||||
|
||||
KotlinAndroidGradleModuleConfigurator() {
|
||||
|
||||
+2
-2
@@ -45,10 +45,10 @@ class GradleKotlinJavaFrameworkSupportProvider() : GradleFrameworkSupportProvide
|
||||
val additionalRepository: String? = when {
|
||||
kotlinVersion == "@snapshot@" -> {
|
||||
kotlinVersion = "1.1-SNAPSHOT"
|
||||
KotlinWithGradleConfigurator.SNAPSHOT_REPOSITORY
|
||||
KotlinWithGradleConfigurator.SNAPSHOT_REPOSITORY_SNIPPET
|
||||
}
|
||||
isEap(kotlinVersion) -> {
|
||||
KotlinWithGradleConfigurator.EAP_REPOSITORY
|
||||
KotlinWithGradleConfigurator.EAP_REPOSITORY_SNIPPET
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
|
||||
+3
-3
@@ -60,14 +60,14 @@ public class KotlinGradleModuleConfigurator extends KotlinWithGradleConfigurator
|
||||
|
||||
@Override
|
||||
protected boolean addSourceSetsBlock(@NotNull GroovyFile file) {
|
||||
GrClosableBlock sourceSetBlock = getSourceSetsBlock(file);
|
||||
return addLastExpressionInBlockIfNeeded(SOURCE_SET, sourceSetBlock);
|
||||
GrClosableBlock sourceSetBlock = Companion.getSourceSetsBlock(file);
|
||||
return Companion.addLastExpressionInBlockIfNeeded(Companion.getSOURCE_SET(), sourceSetBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addElementsToFile(@NotNull GroovyFile groovyFile, boolean isTopLevelProjectFile, @NotNull String version) {
|
||||
if (!isTopLevelProjectFile) {
|
||||
boolean wasModified = addElementsToProjectFile(groovyFile, version);
|
||||
boolean wasModified = Companion.addElementsToProjectFile(groovyFile, version);
|
||||
wasModified |= addElementsToModuleFile(groovyFile, version);
|
||||
return wasModified;
|
||||
}
|
||||
|
||||
+360
-409
@@ -14,483 +14,434 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.configuration;
|
||||
package org.jetbrains.kotlin.idea.configuration
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilCore;
|
||||
import com.intellij.ide.actions.OpenFileAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
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.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.WritingAccessProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
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.plugins.gradle.util.GradleConstants;
|
||||
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;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
|
||||
import com.intellij.codeInsight.CodeInsightUtilCore
|
||||
import com.intellij.ide.actions.OpenFileAction
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
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.roots.ModuleRootManager
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.WritingAccessProvider
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||
import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
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.blocks.GrClosableBlock
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
abstract class KotlinWithGradleConfigurator : KotlinProjectConfigurator {
|
||||
|
||||
public abstract class KotlinWithGradleConfigurator implements KotlinProjectConfigurator {
|
||||
private static final String VERSION_TEMPLATE = "$VERSION$";
|
||||
|
||||
public static final String GROUP_ID = "org.jetbrains.kotlin";
|
||||
public static final String GRADLE_PLUGIN_ID = "kotlin-gradle-plugin";
|
||||
|
||||
protected static final String CLASSPATH = "classpath \"" + GROUP_ID + ":" + GRADLE_PLUGIN_ID + ":$kotlin_version\"";
|
||||
|
||||
protected static final String SNAPSHOT_REPOSITORY = "maven {\nurl '" + ConfigureKotlinInProjectUtilsKt.SNAPSHOT_REPOSITORY.getUrl() + "'\n}";
|
||||
protected static final String EAP_REPOSITORY = "maven {\nurl '" + ConfigureKotlinInProjectUtilsKt.EAP_REPOSITORY.getUrl() + "'\n}";
|
||||
|
||||
private static final String MAVEN_CENTRAL = "mavenCentral()\n";
|
||||
private 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";
|
||||
private static final String VERSION = String.format("ext.kotlin_version = '%s'", VERSION_TEMPLATE);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ConfigureKotlinStatus getStatus(@NotNull Module module) {
|
||||
override fun getStatus(module: Module): ConfigureKotlinStatus {
|
||||
if (!isApplicable(module)) {
|
||||
return ConfigureKotlinStatus.NON_APPLICABLE;
|
||||
return ConfigureKotlinStatus.NON_APPLICABLE
|
||||
}
|
||||
|
||||
if (ConfigureKotlinInProjectUtilsKt.hasKotlinJvmRuntimeInScope(module)) {
|
||||
return ConfigureKotlinStatus.CONFIGURED;
|
||||
if (hasKotlinJvmRuntimeInScope(module)) {
|
||||
return ConfigureKotlinStatus.CONFIGURED
|
||||
}
|
||||
|
||||
GroovyFile moduleGradleFile = getBuildGradleFile(module.getProject(), getModuleFilePath(module));
|
||||
val moduleGradleFile = getBuildGradleFile(module.project, getModuleFilePath(module))
|
||||
if (moduleGradleFile != null && !isFileConfigured(moduleGradleFile)) {
|
||||
return ConfigureKotlinStatus.CAN_BE_CONFIGURED;
|
||||
return ConfigureKotlinStatus.CAN_BE_CONFIGURED
|
||||
}
|
||||
|
||||
GroovyFile projectGradleFile = getBuildGradleFile(module.getProject(), getTopLevelProjectFilePath(module.getProject()));
|
||||
val projectGradleFile = getBuildGradleFile(module.project, getTopLevelProjectFilePath(module.project))
|
||||
if (projectGradleFile != null && !isFileConfigured(projectGradleFile)) {
|
||||
return ConfigureKotlinStatus.CAN_BE_CONFIGURED;
|
||||
return ConfigureKotlinStatus.CAN_BE_CONFIGURED
|
||||
}
|
||||
|
||||
return ConfigureKotlinStatus.BROKEN;
|
||||
return ConfigureKotlinStatus.BROKEN
|
||||
}
|
||||
|
||||
protected abstract boolean isApplicable(@NotNull Module module);
|
||||
protected abstract fun isApplicable(module: Module): Boolean
|
||||
|
||||
private boolean isFileConfigured(GroovyFile projectGradleFile) {
|
||||
String fileText = projectGradleFile.getText();
|
||||
return containsDirective(fileText, getApplyPluginDirective()) && fileText.contains(LIBRARY);
|
||||
private fun isFileConfigured(projectGradleFile: GroovyFile): Boolean {
|
||||
val fileText = projectGradleFile.text
|
||||
return containsDirective(fileText, applyPluginDirective) && fileText.contains(LIBRARY)
|
||||
}
|
||||
|
||||
private static boolean containsDirective(@NotNull String fileText, @NotNull String directive) {
|
||||
return fileText.contains(directive)
|
||||
|| fileText.contains(directive.replace("\"", "'"))
|
||||
|| fileText.contains(directive.replace("'", "\""));
|
||||
}
|
||||
@JvmSuppressWildcards
|
||||
override fun configure(project: Project, excludeModules: Collection<Module>) {
|
||||
val dialog = ConfigureDialogWithModulesAndVersion(project, this, excludeModules)
|
||||
|
||||
@Override
|
||||
public void configure(@NotNull final Project project, Collection<Module> excludeModules) {
|
||||
final ConfigureDialogWithModulesAndVersion dialog =
|
||||
new ConfigureDialogWithModulesAndVersion(project, this, excludeModules);
|
||||
dialog.show()
|
||||
if (!dialog.isOK) return
|
||||
|
||||
dialog.show();
|
||||
if (!dialog.isOK()) return;
|
||||
CommandProcessor.getInstance().executeCommand(project, {
|
||||
val collector = createConfigureKotlinNotificationCollector(project)
|
||||
val changedFiles = HashSet<GroovyFile>()
|
||||
val projectGradleFile = getBuildGradleFile(project, getTopLevelProjectFilePath(project))
|
||||
if (projectGradleFile != null && canConfigureFile(projectGradleFile)) {
|
||||
val isModified = changeGradleFile(projectGradleFile, true, dialog.kotlinVersion, collector)
|
||||
if (isModified) {
|
||||
changedFiles.add(projectGradleFile)
|
||||
}
|
||||
}
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(project);
|
||||
Set<GroovyFile> changedFiles = new HashSet<GroovyFile>();
|
||||
GroovyFile projectGradleFile = getBuildGradleFile(project, getTopLevelProjectFilePath(project));
|
||||
if (projectGradleFile != null && canConfigureFile(projectGradleFile)) {
|
||||
boolean isModified = changeGradleFile(projectGradleFile, true, dialog.getKotlinVersion(), collector);
|
||||
for (module in dialog.modulesToConfigure) {
|
||||
val file = getBuildGradleFile(project, getModuleFilePath(module))
|
||||
if (file != null && canConfigureFile(file)) {
|
||||
val isModified = changeGradleFile(file, false, dialog.kotlinVersion, collector)
|
||||
if (isModified) {
|
||||
changedFiles.add(projectGradleFile);
|
||||
changedFiles.add(file)
|
||||
}
|
||||
}
|
||||
|
||||
for (Module module : dialog.getModulesToConfigure()) {
|
||||
GroovyFile file = getBuildGradleFile(project, getModuleFilePath(module));
|
||||
if (file != null && canConfigureFile(file)) {
|
||||
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();
|
||||
}
|
||||
}, "Configure Kotlin", null);
|
||||
}
|
||||
|
||||
public static void addKotlinLibraryToModule(final Module module, final DependencyScope scope, final ExternalLibraryDescriptor libraryDescriptor) {
|
||||
String gradleFilePath = getModuleFilePath(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) {
|
||||
NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(gradleFile.getProject())
|
||||
.addMessage(virtualFile.getPath() + " was modified")
|
||||
.showNotification();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getKotlinStdlibVersion(@NotNull Module module) {
|
||||
String gradleFilePath = getModuleFilePath(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;
|
||||
}
|
||||
|
||||
protected static boolean addElementsToProjectFile(@NotNull GroovyFile file, @NotNull String version) {
|
||||
boolean wasModified;
|
||||
|
||||
GrClosableBlock buildScriptBlock = getBuildScriptBlock(file);
|
||||
wasModified = addFirstExpressionInBlockIfNeeded(VERSION.replace(VERSION_TEMPLATE, version), buildScriptBlock);
|
||||
|
||||
GrClosableBlock buildScriptRepositoriesBlock = getBuildScriptRepositoriesBlock(file);
|
||||
if (ConfigureKotlinInProjectUtilsKt.isSnapshot(version)) {
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(SNAPSHOT_REPOSITORY, buildScriptRepositoriesBlock);
|
||||
}
|
||||
else if (ConfigureKotlinInProjectUtilsKt.isEap(version)) {
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(EAP_REPOSITORY, buildScriptRepositoriesBlock);
|
||||
}
|
||||
else if (!isRepositoryConfigured(buildScriptRepositoriesBlock)) {
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(MAVEN_CENTRAL, buildScriptRepositoriesBlock);
|
||||
}
|
||||
|
||||
GrClosableBlock buildScriptDependenciesBlock = getBuildScriptDependenciesBlock(file);
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(CLASSPATH, buildScriptDependenciesBlock);
|
||||
|
||||
return wasModified;
|
||||
}
|
||||
|
||||
protected boolean addElementsToModuleFile(@NotNull GroovyFile file, @NotNull String version) {
|
||||
boolean wasModified = false;
|
||||
|
||||
if (!containsDirective(file.getText(), getApplyPluginDirective())) {
|
||||
GrExpression apply = GroovyPsiElementFactory.getInstance(file.getProject()).createExpressionFromText(getApplyPluginDirective());
|
||||
GrApplicationStatement applyStatement = getApplyStatement(file);
|
||||
if (applyStatement != null) {
|
||||
file.addAfter(apply, applyStatement);
|
||||
wasModified = true;
|
||||
}
|
||||
else {
|
||||
GrClosableBlock buildScript = getBlockByName(file, "buildscript");
|
||||
if (buildScript != null) {
|
||||
file.addAfter(apply, buildScript.getParent());
|
||||
wasModified = true;
|
||||
}
|
||||
else {
|
||||
GrStatement[] statements = file.getStatements();
|
||||
if (statements.length > 0) {
|
||||
file.addAfter(apply, statements[statements.length - 1]);
|
||||
showErrorMessage(project, "Cannot find build.gradle file for module " + module.name)
|
||||
}
|
||||
}
|
||||
|
||||
for (file in changedFiles) {
|
||||
OpenFileAction.openFile(file.virtualFile, project)
|
||||
}
|
||||
collector.showNotification()
|
||||
}, "Configure Kotlin", null)
|
||||
}
|
||||
|
||||
protected fun addElementsToModuleFile(file: GroovyFile, version: String): Boolean {
|
||||
var wasModified = false
|
||||
|
||||
if (!containsDirective(file.text, applyPluginDirective)) {
|
||||
val apply = GroovyPsiElementFactory.getInstance(file.project).createExpressionFromText(applyPluginDirective)
|
||||
val applyStatement = getApplyStatement(file)
|
||||
if (applyStatement != null) {
|
||||
file.addAfter(apply, applyStatement)
|
||||
wasModified = true
|
||||
}
|
||||
else {
|
||||
val buildScript = getBlockByName(file, "buildscript")
|
||||
if (buildScript != null) {
|
||||
file.addAfter(apply, buildScript.parent)
|
||||
wasModified = true
|
||||
}
|
||||
else {
|
||||
val statements = file.statements
|
||||
if (statements.size > 0) {
|
||||
file.addAfter(apply, statements[statements.size - 1])
|
||||
}
|
||||
else {
|
||||
file.addAfter(apply, file.getFirstChild());
|
||||
file.addAfter(apply, file.firstChild)
|
||||
}
|
||||
wasModified = true;
|
||||
wasModified = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrClosableBlock repositoriesBlock = getRepositoriesBlock(file);
|
||||
if (ConfigureKotlinInProjectUtilsKt.isSnapshot(version)) {
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(SNAPSHOT_REPOSITORY, repositoriesBlock);
|
||||
val repositoriesBlock = getRepositoriesBlock(file)
|
||||
if (isSnapshot(version)) {
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(SNAPSHOT_REPOSITORY_SNIPPET, repositoriesBlock)
|
||||
}
|
||||
else if (ConfigureKotlinInProjectUtilsKt.isEap(version)) {
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(EAP_REPOSITORY, repositoriesBlock);
|
||||
else if (isEap(version)) {
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(EAP_REPOSITORY_SNIPPET, repositoriesBlock)
|
||||
}
|
||||
else if (!isRepositoryConfigured(repositoriesBlock)) {
|
||||
wasModified |= addLastExpressionInBlockIfNeeded(MAVEN_CENTRAL, repositoriesBlock);
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(MAVEN_CENTRAL, repositoriesBlock)
|
||||
}
|
||||
|
||||
GrClosableBlock dependenciesBlock = getDependenciesBlock(file);
|
||||
wasModified |= addExpressionInBlockIfNeeded(LIBRARY, dependenciesBlock, false);
|
||||
val dependenciesBlock = getDependenciesBlock(file)
|
||||
wasModified = wasModified or addExpressionInBlockIfNeeded(LIBRARY, dependenciesBlock, false)
|
||||
|
||||
wasModified |= addSourceSetsBlock(file);
|
||||
wasModified = wasModified or addSourceSetsBlock(file)
|
||||
|
||||
return wasModified;
|
||||
return wasModified
|
||||
}
|
||||
|
||||
private static boolean isRepositoryConfigured(GrClosableBlock repositoriesBlock) {
|
||||
return repositoriesBlock.getText().contains(MAVEN_CENTRAL) || repositoriesBlock.getText().contains(JCENTER);
|
||||
}
|
||||
protected abstract val applyPluginDirective: String
|
||||
|
||||
protected abstract String getApplyPluginDirective();
|
||||
protected abstract fun addSourceSetsBlock(file: GroovyFile): Boolean
|
||||
|
||||
protected abstract boolean addSourceSetsBlock(@NotNull GroovyFile file);
|
||||
protected abstract fun addElementsToFile(
|
||||
groovyFile: GroovyFile,
|
||||
isTopLevelProjectFile: Boolean,
|
||||
version: String
|
||||
): Boolean
|
||||
|
||||
protected abstract boolean addElementsToFile(
|
||||
@NotNull GroovyFile groovyFile,
|
||||
boolean isTopLevelProjectFile,
|
||||
@NotNull String version
|
||||
);
|
||||
fun changeGradleFile(
|
||||
groovyFile: GroovyFile,
|
||||
isTopLevelProjectFile: Boolean,
|
||||
version: String,
|
||||
collector: NotificationMessageCollector
|
||||
): Boolean {
|
||||
val isModified = groovyFile.project.executeWriteCommand("Configure build.gradle", null) {
|
||||
val isModified = addElementsToFile(groovyFile, isTopLevelProjectFile, version)
|
||||
|
||||
private static boolean canConfigureFile(@NotNull GroovyFile file) {
|
||||
return WritingAccessProvider.isPotentiallyWritable(file.getVirtualFile(), null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GroovyFile getBuildGradleFile(Project project, @Nullable String path) {
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile file = VfsUtil.findFileByIoFile(new File(path), true);
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (!(psiFile instanceof GroovyFile)) return null;
|
||||
return (GroovyFile) psiFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getTopLevelProjectFilePath(@NotNull Project project) {
|
||||
return project.getBasePath() + "/" + GradleConstants.DEFAULT_SCRIPT_NAME;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getModuleFilePath(@NotNull Module module) {
|
||||
String moduleDir = new File(module.getModuleFilePath()).getParent();
|
||||
File buildGradleFile = new File(moduleDir + "/" + GradleConstants.DEFAULT_SCRIPT_NAME);
|
||||
if (buildGradleFile.exists()) {
|
||||
return buildGradleFile.getPath();
|
||||
CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(groovyFile)
|
||||
isModified
|
||||
}
|
||||
|
||||
// since IDEA 145 module file is located in .idea directory
|
||||
for (VirtualFile file : ModuleRootManager.getInstance(module).getContentRoots()) {
|
||||
buildGradleFile = new File(file.getPath() + "/" + GradleConstants.DEFAULT_SCRIPT_NAME);
|
||||
val virtualFile = groovyFile.virtualFile
|
||||
if (virtualFile != null && isModified) {
|
||||
collector.addMessage(virtualFile.path + " was modified")
|
||||
}
|
||||
return isModified
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val VERSION_TEMPLATE = "\$VERSION$"
|
||||
|
||||
val GROUP_ID = "org.jetbrains.kotlin"
|
||||
val GRADLE_PLUGIN_ID = "kotlin-gradle-plugin"
|
||||
|
||||
val CLASSPATH = "classpath \"$GROUP_ID:$GRADLE_PLUGIN_ID:\$kotlin_version\""
|
||||
|
||||
val SNAPSHOT_REPOSITORY_SNIPPET = "maven {\nurl '" + SNAPSHOT_REPOSITORY.url + "'\n}"
|
||||
val EAP_REPOSITORY_SNIPPET = "maven {\nurl '" + EAP_REPOSITORY.url + "'\n}"
|
||||
|
||||
private val MAVEN_CENTRAL = "mavenCentral()\n"
|
||||
private val JCENTER = "jcenter()\n"
|
||||
val LIBRARY = "compile \"org.jetbrains.kotlin:kotlin-stdlib:\$kotlin_version\""
|
||||
val SOURCE_SET = "main.java.srcDirs += 'src/main/kotlin'\n"
|
||||
private val VERSION = String.format("ext.kotlin_version = '%s'", VERSION_TEMPLATE)
|
||||
|
||||
private fun containsDirective(fileText: String, directive: String): Boolean {
|
||||
return fileText.contains(directive)
|
||||
|| fileText.contains(directive.replace("\"", "'"))
|
||||
|| fileText.contains(directive.replace("'", "\""))
|
||||
}
|
||||
|
||||
fun addKotlinLibraryToModule(module: Module, scope: DependencyScope, libraryDescriptor: ExternalLibraryDescriptor) {
|
||||
val gradleFilePath = getModuleFilePath(module)
|
||||
val gradleFile = getBuildGradleFile(module.project, gradleFilePath)
|
||||
|
||||
if (gradleFile != null && canConfigureFile(gradleFile)) {
|
||||
gradleFile.project.executeWriteCommand("Add Kotlin library") {
|
||||
val groovyScope: String
|
||||
when (scope) {
|
||||
DependencyScope.COMPILE -> groovyScope = "compile"
|
||||
DependencyScope.TEST -> if (KotlinPluginUtil.isAndroidGradleModule(module)) {
|
||||
// TODO we should add testCompile or androidTestCompile
|
||||
groovyScope = "compile"
|
||||
}
|
||||
else {
|
||||
groovyScope = "testCompile"
|
||||
}
|
||||
DependencyScope.RUNTIME -> groovyScope = "runtime"
|
||||
DependencyScope.PROVIDED -> groovyScope = "compile"
|
||||
else -> groovyScope = "compile"
|
||||
}
|
||||
|
||||
val dependencyString = String.format(
|
||||
"%s \"%s:%s:%s\"",
|
||||
groovyScope, libraryDescriptor.libraryGroupId, libraryDescriptor.libraryArtifactId,
|
||||
libraryDescriptor.maxVersion)
|
||||
|
||||
val dependenciesBlock = getDependenciesBlock(gradleFile)
|
||||
addLastExpressionInBlockIfNeeded(dependencyString, dependenciesBlock)
|
||||
|
||||
CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(gradleFile)
|
||||
}
|
||||
|
||||
val virtualFile = gradleFile.virtualFile
|
||||
if (virtualFile != null) {
|
||||
createConfigureKotlinNotificationCollector(gradleFile.project)
|
||||
.addMessage(virtualFile.path + " was modified")
|
||||
.showNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getKotlinStdlibVersion(module: Module): String? {
|
||||
val gradleFilePath = getModuleFilePath(module)
|
||||
val gradleFile = getBuildGradleFile(module.project, gradleFilePath) ?: return null
|
||||
|
||||
val versionProperty = "\$kotlin_version"
|
||||
val block = getBuildScriptBlock(gradleFile)
|
||||
if (block.text.contains("ext.kotlin_version = ")) {
|
||||
return versionProperty
|
||||
}
|
||||
|
||||
val dependencies = getDependenciesBlock(gradleFile).statements
|
||||
val stdlibArtifactPrefix = "org.jetbrains.kotlin:kotlin-stdlib:"
|
||||
for (dependency in dependencies) {
|
||||
val dependencyText = dependency.text
|
||||
val startIndex = dependencyText.indexOf(stdlibArtifactPrefix) + stdlibArtifactPrefix.length
|
||||
val endIndex = dependencyText.length - 1
|
||||
if (startIndex != -1 && endIndex != -1) {
|
||||
return dependencyText.substring(startIndex, endIndex)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun addElementsToProjectFile(file: GroovyFile, version: String): Boolean {
|
||||
var wasModified: Boolean
|
||||
|
||||
val buildScriptBlock = getBuildScriptBlock(file)
|
||||
wasModified = addFirstExpressionInBlockIfNeeded(VERSION.replace(VERSION_TEMPLATE, version), buildScriptBlock)
|
||||
|
||||
val buildScriptRepositoriesBlock = getBuildScriptRepositoriesBlock(file)
|
||||
if (isSnapshot(version)) {
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(SNAPSHOT_REPOSITORY_SNIPPET, buildScriptRepositoriesBlock)
|
||||
}
|
||||
else if (isEap(version)) {
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(EAP_REPOSITORY_SNIPPET, buildScriptRepositoriesBlock)
|
||||
}
|
||||
else if (!isRepositoryConfigured(buildScriptRepositoriesBlock)) {
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(MAVEN_CENTRAL, buildScriptRepositoriesBlock)
|
||||
}
|
||||
|
||||
val buildScriptDependenciesBlock = getBuildScriptDependenciesBlock(file)
|
||||
wasModified = wasModified or addLastExpressionInBlockIfNeeded(CLASSPATH, buildScriptDependenciesBlock)
|
||||
|
||||
return wasModified
|
||||
}
|
||||
|
||||
private fun isRepositoryConfigured(repositoriesBlock: GrClosableBlock): Boolean {
|
||||
return repositoriesBlock.text.contains(MAVEN_CENTRAL) || repositoriesBlock.text.contains(JCENTER)
|
||||
}
|
||||
|
||||
private fun canConfigureFile(file: GroovyFile): Boolean {
|
||||
return WritingAccessProvider.isPotentiallyWritable(file.virtualFile, null)
|
||||
}
|
||||
|
||||
private fun getBuildGradleFile(project: Project, path: String?): GroovyFile? {
|
||||
if (path == null) {
|
||||
return null
|
||||
}
|
||||
val file = VfsUtil.findFileByIoFile(File(path), true) ?: return null
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) as? GroovyFile ?: return null
|
||||
return psiFile
|
||||
}
|
||||
|
||||
private fun getTopLevelProjectFilePath(project: Project): String {
|
||||
return project.basePath + "/" + GradleConstants.DEFAULT_SCRIPT_NAME
|
||||
}
|
||||
|
||||
private fun getModuleFilePath(module: Module): String? {
|
||||
val moduleDir = File(module.moduleFilePath).parent
|
||||
var buildGradleFile = File(moduleDir + "/" + GradleConstants.DEFAULT_SCRIPT_NAME)
|
||||
if (buildGradleFile.exists()) {
|
||||
return buildGradleFile.getPath();
|
||||
return buildGradleFile.path
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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) {
|
||||
isModified[0] = addElementsToFile(groovyFile, isTopLevelProjectFile, version);
|
||||
|
||||
CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(groovyFile);
|
||||
// since IDEA 145 module file is located in .idea directory
|
||||
for (file in ModuleRootManager.getInstance(module).contentRoots) {
|
||||
buildGradleFile = File(file.path + "/" + GradleConstants.DEFAULT_SCRIPT_NAME)
|
||||
if (buildGradleFile.exists()) {
|
||||
return buildGradleFile.path
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
VirtualFile virtualFile = groovyFile.getVirtualFile();
|
||||
if (virtualFile != null && isModified[0]) {
|
||||
collector.addMessage(virtualFile.getPath() + " was modified");
|
||||
return null
|
||||
}
|
||||
return isModified[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GrClosableBlock getDependenciesBlock(@NotNull GrStatementOwner file) {
|
||||
return getBlockOrCreate(file, "dependencies");
|
||||
}
|
||||
private fun getDependenciesBlock(file: GrStatementOwner): GrClosableBlock {
|
||||
return getBlockOrCreate(file, "dependencies")
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static GrClosableBlock getSourceSetsBlock(@NotNull GrStatementOwner parent) {
|
||||
return getBlockOrCreate(parent, "sourceSets");
|
||||
}
|
||||
fun getSourceSetsBlock(parent: GrStatementOwner): GrClosableBlock {
|
||||
return getBlockOrCreate(parent, "sourceSets")
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GrClosableBlock getBuildScriptBlock(@NotNull GrStatementOwner file) {
|
||||
return getBlockOrCreate(file, "buildscript");
|
||||
}
|
||||
private fun getBuildScriptBlock(file: GrStatementOwner): GrClosableBlock {
|
||||
return getBlockOrCreate(file, "buildscript")
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GrClosableBlock getBuildScriptDependenciesBlock(@NotNull GrStatementOwner file) {
|
||||
GrClosableBlock buildScript = getBuildScriptBlock(file);
|
||||
return getBlockOrCreate(buildScript, "dependencies");
|
||||
}
|
||||
private fun getBuildScriptDependenciesBlock(file: GrStatementOwner): GrClosableBlock {
|
||||
val buildScript = getBuildScriptBlock(file)
|
||||
return getBlockOrCreate(buildScript, "dependencies")
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GrClosableBlock getBuildScriptRepositoriesBlock(@NotNull GrStatementOwner file) {
|
||||
GrClosableBlock buildScript = getBuildScriptBlock(file);
|
||||
return getBlockOrCreate(buildScript, "repositories");
|
||||
}
|
||||
private fun getBuildScriptRepositoriesBlock(file: GrStatementOwner): GrClosableBlock {
|
||||
val buildScript = getBuildScriptBlock(file)
|
||||
return getBlockOrCreate(buildScript, "repositories")
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static GrClosableBlock getRepositoriesBlock(@NotNull GrStatementOwner file) {
|
||||
return getBlockOrCreate(file, "repositories");
|
||||
}
|
||||
private fun getRepositoriesBlock(file: GrStatementOwner): GrClosableBlock {
|
||||
return getBlockOrCreate(file, "repositories")
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static GrClosableBlock getBlockOrCreate(@NotNull GrStatementOwner parent, @NotNull String name) {
|
||||
GrClosableBlock block = getBlockByName(parent, name);
|
||||
if (block == null) {
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(parent.getProject());
|
||||
GrExpression newBlock = factory.createExpressionFromText(name + "{\n}\n");
|
||||
GrStatement[] statements = parent.getStatements();
|
||||
if (statements.length > 0) {
|
||||
parent.addAfter(newBlock, statements[statements.length - 1]);
|
||||
fun getBlockOrCreate(parent: GrStatementOwner, name: String): GrClosableBlock {
|
||||
var block = getBlockByName(parent, name)
|
||||
if (block == null) {
|
||||
val factory = GroovyPsiElementFactory.getInstance(parent.project)
|
||||
val newBlock = factory.createExpressionFromText("$name{\n}\n")
|
||||
val statements = parent.statements
|
||||
if (statements.size > 0) {
|
||||
parent.addAfter(newBlock, statements[statements.size - 1])
|
||||
}
|
||||
else {
|
||||
parent.addAfter(newBlock, parent.firstChild)
|
||||
}
|
||||
block = getBlockByName(parent, name)!!
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
||||
fun addLastExpressionInBlockIfNeeded(text: String, block: GrClosableBlock): Boolean {
|
||||
return addExpressionInBlockIfNeeded(text, block, false)
|
||||
}
|
||||
|
||||
private fun addFirstExpressionInBlockIfNeeded(text: String, block: GrClosableBlock): Boolean {
|
||||
return addExpressionInBlockIfNeeded(text, block, true)
|
||||
}
|
||||
|
||||
private fun getBlockByName(parent: PsiElement, name: String): GrClosableBlock? {
|
||||
val allExpressions = PsiTreeUtil.getChildrenOfType(parent, GrMethodCallExpression::class.java)
|
||||
if (allExpressions != null) {
|
||||
for (expression in allExpressions) {
|
||||
val invokedExpression = expression.invokedExpression
|
||||
if (expression.closureArguments.size == 0) continue
|
||||
|
||||
val expressionText = invokedExpression.text
|
||||
if (expressionText == name) return expression.closureArguments[0]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun addExpressionInBlockIfNeeded(text: String, block: GrClosableBlock, isFirst: Boolean): Boolean {
|
||||
if (block.text.contains(text)) return false
|
||||
val newStatement = GroovyPsiElementFactory.getInstance(block.project).createExpressionFromText(text)
|
||||
CodeStyleManager.getInstance(block.project).reformat(newStatement)
|
||||
val statements = block.statements
|
||||
if (!isFirst && statements.size > 0) {
|
||||
val lastStatement = statements[statements.size - 1]
|
||||
if (lastStatement != null) {
|
||||
block.addAfter(newStatement, lastStatement)
|
||||
}
|
||||
}
|
||||
else {
|
||||
parent.addAfter(newBlock, parent.getFirstChild());
|
||||
val firstChild = block.firstChild
|
||||
if (firstChild != null) {
|
||||
block.addAfter(newStatement, firstChild)
|
||||
}
|
||||
}
|
||||
block = getBlockByName(parent, name);
|
||||
assert block != null : "Block should be non-null because it is created";
|
||||
return true
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
protected static boolean addLastExpressionInBlockIfNeeded(@NotNull String text, @NotNull GrClosableBlock block) {
|
||||
return addExpressionInBlockIfNeeded(text, block, false);
|
||||
}
|
||||
|
||||
private static boolean addFirstExpressionInBlockIfNeeded(@NotNull String text, @NotNull GrClosableBlock block) {
|
||||
return addExpressionInBlockIfNeeded(text, block, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrClosableBlock getBlockByName(@NotNull PsiElement parent, @NotNull String name) {
|
||||
GrMethodCallExpression[] allExpressions = PsiTreeUtil.getChildrenOfType(parent, GrMethodCallExpression.class);
|
||||
if (allExpressions != null) {
|
||||
for (GrMethodCallExpression expression : allExpressions) {
|
||||
GrExpression invokedExpression = expression.getInvokedExpression();
|
||||
if (expression.getClosureArguments().length == 0) continue;
|
||||
|
||||
String expressionText = invokedExpression.getText();
|
||||
if (expressionText.equals(name)) return expression.getClosureArguments()[0];
|
||||
private fun getApplyStatement(file: GroovyFile): GrApplicationStatement? {
|
||||
val applyStatement = PsiTreeUtil.getChildrenOfType(file, GrApplicationStatement::class.java) ?: return null
|
||||
for (callExpression in applyStatement) {
|
||||
val invokedExpression = callExpression.invokedExpression
|
||||
if (invokedExpression.text == "apply") {
|
||||
return callExpression
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean addExpressionInBlockIfNeeded(@NotNull String text, @NotNull GrClosableBlock block, boolean isFirst) {
|
||||
if (block.getText().contains(text)) return false;
|
||||
GrExpression newStatement = GroovyPsiElementFactory.getInstance(block.getProject()).createExpressionFromText(text);
|
||||
CodeStyleManager.getInstance(block.getProject()).reformat(newStatement);
|
||||
GrStatement[] statements = block.getStatements();
|
||||
if (!isFirst && statements.length > 0) {
|
||||
GrStatement lastStatement = statements[statements.length - 1];
|
||||
if (lastStatement != null) {
|
||||
block.addAfter(newStatement, lastStatement);
|
||||
}
|
||||
private fun showErrorMessage(project: Project, message: String?) {
|
||||
Messages.showErrorDialog(project,
|
||||
"<html>Couldn't configure kotlin-gradle plugin automatically.<br/>" +
|
||||
(if (message != null) message + "<br/>" else "") +
|
||||
"<br/>See manual installation instructions <a href=\"https://kotlinlang.org/docs/reference/using-gradle.html\">here</a>.</html>",
|
||||
"Configure Kotlin-Gradle Plugin")
|
||||
}
|
||||
else {
|
||||
PsiElement firstChild = block.getFirstChild();
|
||||
if (firstChild != null) {
|
||||
block.addAfter(newStatement, firstChild);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrApplicationStatement getApplyStatement(@NotNull GroovyFile file) {
|
||||
GrApplicationStatement[] applyStatement = PsiTreeUtil.getChildrenOfType(file, GrApplicationStatement.class);
|
||||
if (applyStatement == null) return null;
|
||||
for (GrApplicationStatement callExpression : applyStatement) {
|
||||
GrExpression invokedExpression = callExpression.getInvokedExpression();
|
||||
if (invokedExpression.getText().equals("apply")) {
|
||||
return callExpression;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void showErrorMessage(@NotNull Project project, @Nullable String message) {
|
||||
Messages.showErrorDialog(project,
|
||||
"<html>Couldn't configure kotlin-gradle plugin automatically.<br/>" +
|
||||
(message != null ? (message + "<br/>") : "") +
|
||||
"<br/>See manual installation instructions <a href=\"https://kotlinlang.org/docs/reference/using-gradle.html\">here</a>.</html>",
|
||||
"Configure Kotlin-Gradle Plugin");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user