From 9047d2f00cd9e5d8fee6c0b53123cfb29ad1001b Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 1 Dec 2017 18:09:49 +0300 Subject: [PATCH] IDEA-149592 Select Gradle JVM java automatically --- .../execution/ExternalSystemJdkUtil.java | 14 ++-- .../AbstractExternalProjectImportBuilder.java | 18 ++++- .../wizard/ExternalModuleSettingsStep.java | 1 + ...bstractExternalProjectSettingsControl.java | 16 ++++- ...stractImportFromExternalSystemControl.java | 8 ++- .../service/ui/ExternalSystemJdkComboBox.java | 55 +++++++++------ .../util/ExternalSystemSettingsControl.java | 9 +++ .../wizard/GradleProjectImportBuilder.java | 68 +++++++++++++++++-- .../GradleProjectSettingsControl.java | 9 ++- .../GradleProjectSettingsControlBuilder.java | 10 ++- ...eaGradleProjectSettingsControlBuilder.java | 24 +++++-- 11 files changed, 188 insertions(+), 44 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkUtil.java index 55afe98ed0fb..702e9c5eb391 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemJdkUtil.java @@ -53,7 +53,7 @@ public class ExternalSystemJdkUtil { } } - if (project == null) { + if (project == null || project.isDefault()) { Sdk recent = ProjectJdkTable.getInstance().findMostRecentSdkOfType(JavaSdk.getInstance()); return recent != null ? recent : JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk(); } @@ -93,6 +93,12 @@ public class ExternalSystemJdkUtil { } } + Sdk mostRecentSdk = ProjectJdkTable.getInstance().findMostRecentSdk( + sdk -> sdk.getSdkType() == JavaSdk.getInstance() && isValidJdk(sdk.getHomePath())); + if (mostRecentSdk != null) { + return Pair.create(mostRecentSdk.getName(), mostRecentSdk); + } + if (!ApplicationManager.getApplication().isUnitTestMode()) { String javaHome = System.getenv("JAVA_HOME"); if (isValidJdk(javaHome)) { @@ -100,12 +106,6 @@ public class ExternalSystemJdkUtil { } } - for (Sdk projectJdk : ProjectJdkTable.getInstance().getAllJdks()) { - if (isValidJdk(projectJdk.getHomePath())) { - return Pair.create(projectJdk.getName(), projectJdk); - } - } - return Pair.create(USE_INTERNAL_JAVA, JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk()); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java index 45c92f48406b..4e68d547c4cb 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java @@ -12,6 +12,7 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo; import com.intellij.openapi.externalSystem.model.project.ProjectData; +import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.externalSystem.service.project.*; import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl; @@ -27,11 +28,13 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -107,13 +110,26 @@ public abstract class AbstractExternalProjectImportBuilder sdkPair = ExternalSystemJdkUtil.getAvailableJdk(project); + if (!ExternalSystemJdkUtil.USE_INTERNAL_JAVA.equals(sdkPair.first)) { + return sdkPair.second; + } + return null; + } + protected abstract void doPrepare(@NotNull WizardContext context); @Override diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/ExternalModuleSettingsStep.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/ExternalModuleSettingsStep.java index 2161445233d3..f5c1b9aee72f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/ExternalModuleSettingsStep.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/ExternalModuleSettingsStep.java @@ -89,6 +89,7 @@ public class ExternalModuleSettingsStep exten if (contentPath != null) { myControl.getInitialSettings().setExternalProjectPath(contentPath); } + myControl.reset(true, myContext); } @Override diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java index 5cebf6ce80b0..b0261af41af3 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.externalSystem.service.settings; +import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemSettingsControl; @@ -117,7 +118,16 @@ public abstract class AbstractExternalProjectSettingsControl creationFilter) { + setSetupButton(setUpButton, jdksModel, actionGroupTitle, creationFilter, null); + } + + public void setSetupButton(@NotNull JButton setUpButton, + @NotNull ProjectSdksModel jdksModel, + @Nullable String actionGroupTitle, + @Nullable Condition creationFilter, + @Nullable WizardContext wizardContext) { Arrays.stream(setUpButton.getActionListeners()).forEach(setUpButton::removeActionListener); setUpButton.addActionListener(e -> { @@ -121,7 +130,7 @@ public class ExternalSystemJdkComboBox extends ComboBoxWithWidePopup 1) { @@ -156,7 +165,11 @@ public class ExternalSystemJdkComboBox extends ComboBoxWithWidePopup jdkMap = collectComboBoxItem(); + refreshData(selectedValue, null); + } + + public void refreshData(@Nullable String selectedValue, @Nullable Sdk projectJdk) { + Map jdkMap = collectComboBoxItem(projectJdk); if (selectedValue != null && !jdkMap.containsKey(selectedValue)) { assert selectedValue.length() > 0; jdkMap.put(selectedValue, new JdkComboBoxItem(selectedValue, selectedValue, "", false)); @@ -164,19 +177,19 @@ public class ExternalSystemJdkComboBox extends ComboBoxWithWidePopup comboBoxModel = getModel(); for (Map.Entry entry : jdkMap.entrySet()) { - //noinspection unchecked - ((DefaultComboBoxModel)getModel()).addElement(entry.getValue()); + ((MutableComboBoxModel)comboBoxModel).addElement(entry.getValue()); } - select((DefaultComboBoxModel)getModel(), selectedValue); + select(comboBoxModel, selectedValue); } - private static void select(DefaultComboBoxModel model, Object value) { + private static void select(ComboBoxModel model, Object value) { for (int i = 0; i < model.getSize(); i++) { - JdkComboBoxItem comboBoxUtil = (JdkComboBoxItem)model.getElementAt(i); - if (comboBoxUtil.jdkName.equals(value)) { - model.setSelectedItem(comboBoxUtil); + JdkComboBoxItem item = model.getElementAt(i); + if (item.jdkName.equals(value)) { + model.setSelectedItem(item); return; } } @@ -192,13 +205,13 @@ public class ExternalSystemJdkComboBox extends ComboBoxWithWidePopup collectComboBoxItem() { + private Map collectComboBoxItem(@Nullable Sdk projectSdk) { Map result = new LinkedHashMap<>(); - for (Sdk projectJdk : ProjectJdkTable.getInstance().getSdksOfType(JavaSdk.getInstance())) { - String name = projectJdk.getName(); - String comment = buildComment(projectJdk); - result.put(name, new JdkComboBoxItem(name, name, comment, ((SdkType)projectJdk.getSdkType()).sdkHasValidPath(projectJdk))); + for (Sdk sdk : ProjectJdkTable.getInstance().getSdksOfType(JavaSdk.getInstance())) { + String name = sdk.getName(); + String comment = buildComment(sdk); + result.put(name, new JdkComboBoxItem(name, name, comment, ((SdkType)sdk.getSdkType()).sdkHasValidPath(sdk))); } if(suggestJre) { @@ -213,13 +226,15 @@ public class ExternalSystemJdkComboBox extends ComboBoxWithWidePopup { */ void reset(); + /** + * Asks current control to reset its state to the initial one. + */ + default void reset(@Nullable WizardContext wizardContext) { + reset(); + } + /** * @return {@code true} if settings exposed by the current control have been modified; {@code false} otherwise */ diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java index 0ef0b1195529..132cd5e7a039 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectImportBuilder.java @@ -17,13 +17,19 @@ import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelecto import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; +import com.intellij.util.ObjectUtils; +import gnu.trove.THashSet; import icons.GradleIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,14 +41,20 @@ import org.jetbrains.plugins.gradle.util.GradleConstants; import javax.swing.*; import java.io.File; +import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; /** - * @author Denis Zhdanov * @since 4/15/13 2:29 PM */ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBuilder { + private static final Pattern JAVA_VERSION = Pattern.compile("java version \"(\\d.*)\""); + /** * @deprecated use {@link GradleProjectImportBuilder#GradleProjectImportBuilder(ProjectDataManager)} */ @@ -65,6 +77,45 @@ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBui return GradleIcons.Gradle; } + @Nullable + @Override + protected Sdk resolveProjectJdk(@NotNull WizardContext context) { + // gradle older than 4.2.1 doesn't support new java the version number format like 9.0.1, see https://github.com/gradle/gradle/issues/2992 + Condition sdkCondition = sdk -> { + String version = getVersion(sdk); + return StringUtil.compareVersionNumbers(version, "1.6") > 0 && + StringUtil.compareVersionNumbers(version, "9") < 0; + }; + + Sdk mostRecentSdk = ProjectJdkTable.getInstance().findMostRecentSdk( + sdk -> sdk.getSdkType() == JavaSdk.getInstance() && sdkCondition.value(sdk)); + if (mostRecentSdk != null) { + return mostRecentSdk; + } + + Set existingPaths = + new THashSet<>(Arrays.stream(ProjectJdkTable.getInstance().getAllJdks()).map(sdk -> sdk.getHomePath()).collect(Collectors.toSet()), + FileUtil.PATH_HASHING_STRATEGY); + + for (String javaHome : JavaSdk.getInstance().suggestHomePaths()) { + if (!existingPaths.contains(FileUtil.toCanonicalPath(javaHome))) { + JavaSdk javaSdk = JavaSdk.getInstance(); + Sdk jdk = javaSdk.createJdk(ObjectUtils.notNull(javaSdk.suggestSdkName(null, javaHome), ""), javaHome); + if (sdkCondition.value(jdk)) { + ApplicationManager.getApplication().runWriteAction(() -> ProjectJdkTable.getInstance().addJdk(jdk)); + return jdk; + } + } + } + + Project project = context.getProject() != null ? context.getProject() : ProjectManager.getInstance().getDefaultProject(); + final Pair sdkPair = ExternalSystemJdkUtil.getAvailableJdk(project); + if (!ExternalSystemJdkUtil.USE_INTERNAL_JAVA.equals(sdkPair.first)) { + return sdkPair.second; + } + return null; + } + @Override protected void doPrepare(@NotNull WizardContext context) { String pathToUse = getFileToImport(); @@ -75,10 +126,6 @@ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBui final ImportFromGradleControl importFromGradleControl = getControl(context.getProject()); importFromGradleControl.setLinkedProjectPath(pathToUse); - final Pair sdkPair = ExternalSystemJdkUtil.getAvailableJdk(context.getProject()); - if (sdkPair != null && !ExternalSystemJdkUtil.USE_INTERNAL_JAVA.equals(sdkPair.first)) { - importFromGradleControl.getProjectSettings().setGradleJvm(sdkPair.first); - } } @Override @@ -191,4 +238,15 @@ public class GradleProjectImportBuilder extends AbstractExternalProjectImportBui } return project; } + + @Nullable + private static String getVersion(Sdk sdk) { + String versionString = sdk.getVersionString(); + if (versionString == null) return null; + Matcher matcher = JAVA_VERSION.matcher(versionString.trim()); + if (matcher.matches()) { + return matcher.group(1); + } + return versionString; + } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java index 257bb0144e81..a5ee9c8adf4e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControl.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.gradle.service.settings; +import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.externalSystem.service.settings.AbstractExternalProjectSettingsControl; import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl; import com.intellij.openapi.externalSystem.util.PaintAwarePanel; @@ -68,7 +69,12 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting @Override protected void resetExtraSettings(boolean isDefaultModuleCreation) { - myBuilder.reset(getProject(), getInitialSettings(), isDefaultModuleCreation); + resetExtraSettings(isDefaultModuleCreation, null); + } + + @Override + protected void resetExtraSettings(boolean isDefaultModuleCreation, @Nullable WizardContext wizardContext) { + myBuilder.reset(getProject(), getInitialSettings(), isDefaultModuleCreation, wizardContext); } public void update(@Nullable String linkedProjectPath, boolean isDefaultModuleCreation) { @@ -86,7 +92,6 @@ public class GradleProjectSettingsControl extends AbstractExternalProjectSetting */ public void setCurrentProject(@Nullable Project project) { super.setCurrentProject(project); - myBuilder.reset(getProject(), getInitialSettings(), false); } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java index 6c904d61c089..1c5f84cec2ce 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleProjectSettingsControlBuilder.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.gradle.service.settings; +import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.externalSystem.service.settings.ExternalSystemSettingsControlCustomizer; import com.intellij.openapi.externalSystem.util.PaintAwarePanel; import com.intellij.openapi.options.ConfigurationException; @@ -65,7 +66,14 @@ public interface GradleProjectSettingsControlBuilder { */ boolean isModified(); - void reset(Project project, GradleProjectSettings settings, boolean isDefaultModuleCreation); + void reset(@Nullable Project project, GradleProjectSettings settings, boolean isDefaultModuleCreation); + + default void reset(@Nullable Project project, + GradleProjectSettings settings, + boolean isDefaultModuleCreation, + @Nullable WizardContext wizardContext) { + reset(project, settings, isDefaultModuleCreation); + } void createAndFillControls(PaintAwarePanel content, int indentLevel); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java index 79af0ed52588..d9744ee1e3ef 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/IdeaGradleProjectSettingsControlBuilder.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.gradle.service.settings; +import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.components.ServiceManager; @@ -28,6 +29,7 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.JavaSdk; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; import com.intellij.openapi.ui.FixedSizeButton; @@ -458,7 +460,15 @@ public class IdeaGradleProjectSettingsControlBuilder implements GradleProjectSet } @Override - public void reset(Project project, GradleProjectSettings settings, boolean isDefaultModuleCreation) { + public void reset(@Nullable Project project, GradleProjectSettings settings, boolean isDefaultModuleCreation) { + reset(project, settings, isDefaultModuleCreation, null); + } + + @Override + public void reset(@Nullable Project project, + GradleProjectSettings settings, + boolean isDefaultModuleCreation, + @Nullable WizardContext wizardContext) { String gradleHome = settings.getGradleHome(); if (myGradleHomePathField != null) { myGradleHomePathField.setText(gradleHome == null ? "" : gradleHome); @@ -471,7 +481,7 @@ public class IdeaGradleProjectSettingsControlBuilder implements GradleProjectSet myStoreExternallyCheckBox.setSelected(settings.isStoreProjectFilesExternally()); } - resetGradleJdkComboBox(project, settings); + resetGradleJdkComboBox(project, settings, wizardContext); resetWrapperControls(settings.getExternalProjectPath(), settings, isDefaultModuleCreation); if (myUseLocalDistributionButton != null && !myUseLocalDistributionButton.isSelected()) { @@ -535,15 +545,19 @@ public class IdeaGradleProjectSettingsControlBuilder implements GradleProjectSet return this; } - private void resetGradleJdkComboBox(@Nullable final Project project, GradleProjectSettings settings) { + private void resetGradleJdkComboBox(@Nullable final Project project, + GradleProjectSettings settings, + @Nullable WizardContext wizardContext) { if (myGradleJdkComboBox == null) return; final String gradleJvm = settings.getGradleJvm(); myGradleJdkComboBox.setProject(project); - final String sdkItem = ObjectUtils.nullizeByCondition(gradleJvm, s -> (project == null && StringUtil.equals(USE_PROJECT_JDK, s)) || StringUtil.isEmpty(s)); + Sdk projectJdk = wizardContext != null ? wizardContext.getProjectJdk() : null; + final String sdkItem = ObjectUtils.nullizeByCondition(gradleJvm, s -> + (projectJdk == null && project == null && StringUtil.equals(USE_PROJECT_JDK, s)) || StringUtil.isEmpty(s)); - myGradleJdkComboBox.refreshData(sdkItem); + myGradleJdkComboBox.refreshData(sdkItem, projectJdk); if (myGradleJdkSetUpButton != null) { ProjectSdksModel sdksModel = ProjectStructureConfigurable.getInstance( project == null || project.isDisposed() ? ProjectManager.getInstance().getDefaultProject() : project).getProjectJdksModel();