diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index e6561b91d43c..62492845588c 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots.impl; import com.intellij.icons.AllIcons; @@ -189,8 +189,7 @@ public final class JavaSdkImpl extends JavaSdk { @Override public String suggestHomePath() { - Collection paths = suggestHomePaths(); - return paths.isEmpty() ? null : paths.iterator().next(); + return JavaHomeFinder.defaultJavaLocation(); } @NotNull diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkFinder.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkFinder.java index b7b7f7c70551..649a6d1ff0d0 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkFinder.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkFinder.java @@ -3,6 +3,7 @@ package com.intellij.openapi.projectRoots; import com.intellij.openapi.application.ApplicationManager; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -12,9 +13,16 @@ public interface JdkFinder { return ApplicationManager.getApplication().getService(JdkFinder.class); } + /** + * @return a default install location for JDKs, ETD-friendly + */ + @Nullable + String defaultJavaLocation(); + /** * Tries to find existing Java SDKs on this computer. * If no JDK found, returns possible folders to start file chooser. + * The method is heavy, it is not recommended to run it from EDT thread. * @return suggested sdk home paths (sorted) */ @NotNull diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java index b67f8dd0b98c..301870819fdf 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SdkType.java @@ -1,9 +1,10 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.OrderRootType; @@ -39,6 +40,10 @@ public abstract class SdkType implements SdkTypeId { *

* E.g. for Python SDK on Unix the method may return either {@code "/usr/bin"} or {@code "/usr/bin/python"} * (if there is only one Python interpreter installed on a host). + *

+ * This method should work fast and allow running from the EDT thread. See the {@link #suggestHomePaths()} + * for more advanced scenarios + * @see #suggestHomePaths() */ @Nullable public abstract String suggestHomePath(); @@ -47,6 +52,11 @@ public abstract class SdkType implements SdkTypeId { * Returns a list of all valid SDKs found on this host. *

* E.g. for Python SDK on Unix the method may return {@code ["/usr/bin/python2", "/usr/bin/python3"]}. + *

+ * This method may take significant time to execute. The implementation may check {@link ProgressManager#checkCanceled()} + * for possible interruption request. It is not recommended to call this method from a ETD thread. See + * an alternative {@link #suggestHomePath()} method for EDT-friendly calls. + * @see #suggestHomePath() */ @NotNull public Collection suggestHomePaths() { diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java index f1b3e08224da..650705472453 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/SimpleJavaSdkType.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots; import com.intellij.openapi.project.ProjectBundle; @@ -68,10 +68,10 @@ public class SimpleJavaSdkType extends SdkType implements JavaSdkType { return new File(sdk.getHomePath(), "bin/java").getPath(); } + @Nullable @Override public String suggestHomePath() { - Collection paths = suggestHomePaths(); - return paths.isEmpty() ? null : paths.iterator().next(); + return JdkFinder.getInstance().defaultJavaLocation(); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinder.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinder.java index c524c878f55f..43998f891fdd 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinder.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinder.java @@ -6,6 +6,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.lang.JavaVersion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -40,11 +41,12 @@ public abstract class JavaHomeFinder { return paths; } + private static boolean isDetectorEnabled(boolean forceEmbeddedJava) { + return forceEmbeddedJava || Registry.is("java.detector.enabled", true); + } + private static JavaHomeFinderBasic getFinder(boolean forceEmbeddedJava) { - boolean detectorIsEnabled = forceEmbeddedJava || Registry.is("java.detector.enabled", true); - if (!detectorIsEnabled) { - return null; - } + if (!isDetectorEnabled(forceEmbeddedJava)) return null; if (SystemInfo.isWindows) { return new JavaHomeFinderWindows(forceEmbeddedJava); @@ -61,4 +63,24 @@ public abstract class JavaHomeFinder { return new JavaHomeFinderBasic(forceEmbeddedJava); } + + @Nullable + public static String defaultJavaLocation() { + if (SystemInfo.isWindows) { + return JavaHomeFinderWindows.defaultJavaLocation; + } + if (SystemInfo.isMac) { + return JavaHomeFinderMac.defaultJavaLocation; + } + + if (SystemInfo.isLinux) { + return "/opt/java"; + } + + if (SystemInfo.isSolaris) { + return "/usr/jdk"; + } + + return null; + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderMac.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderMac.java index 1f45365a7ce0..e4f0b62a3a13 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderMac.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderMac.java @@ -14,9 +14,11 @@ import java.util.*; class JavaHomeFinderMac extends JavaHomeFinderBasic { public static final String JAVA_HOME_FIND_UTIL = "/usr/libexec/java_home"; + static String defaultJavaLocation = "/Library/Java/JavaVirtualMachines"; + JavaHomeFinderMac(boolean forceEmbeddedJava) { super(forceEmbeddedJava, - "/Library/Java/JavaVirtualMachines", + defaultJavaLocation, "/System/Library/Java/JavaVirtualMachines", FileUtil.expandUserHome("~/Library/Java/JavaVirtualMachines") ); diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderWindows.kt b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderWindows.kt index 489568e7a248..d469b77e5295 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderWindows.kt +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JavaHomeFinderWindows.kt @@ -15,6 +15,7 @@ import kotlin.text.RegexOption.MULTILINE class JavaHomeFinderWindows : JavaHomeFinderBasic { companion object { + const val defaultJavaLocation = "C:\\Program Files" @Suppress("SpellCheckingInspection") private const val regCommand = """reg query HKLM\SOFTWARE\JavaSoft\JDK /s /v JavaHome""" @@ -39,7 +40,6 @@ class JavaHomeFinderWindows : JavaHomeFinderBasic { } return paths } - } constructor(forceEmbeddedJava: Boolean) : super(forceEmbeddedJava) { diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JdkFinderImpl.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JdkFinderImpl.java index b883336725b0..ebf19e02b952 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JdkFinderImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/JdkFinderImpl.java @@ -3,6 +3,7 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.openapi.projectRoots.JdkFinder; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -12,4 +13,10 @@ public class JdkFinderImpl implements JdkFinder { public List suggestHomePaths() { return JavaHomeFinder.suggestHomePaths(); } + + @Nullable + @Override + public String defaultJavaLocation() { + return JavaHomeFinder.defaultJavaLocation(); + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java index cc0fda6ffbb1..041f2376bf92 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2015 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. - */ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.projectRoots.impl; import com.intellij.openapi.application.ApplicationManager; @@ -249,10 +235,11 @@ public class SdkConfigurationUtil { } } for (SdkType sdkType : sdkTypes) { - final String suggestedHomePath = sdkType.suggestHomePath(); - if (suggestedHomePath != null && sdkType.isValidSdkHome(suggestedHomePath)) { - Sdk an_sdk = createAndAddSDK(suggestedHomePath, sdkType); - if (an_sdk != null) return an_sdk; + for(String suggestedHomePath : sdkType.suggestHomePaths()) { + if (sdkType.isValidSdkHome(suggestedHomePath)) { + Sdk an_sdk = createAndAddSDK(suggestedHomePath, sdkType); + if (an_sdk != null) return an_sdk; + } } } return null; diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index 60e65b43299c..0059944399fe 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.sdk; import com.google.common.collect.Lists; @@ -13,6 +13,7 @@ import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooserDescriptor; @@ -58,10 +59,8 @@ import javax.swing.*; import java.awt.*; import java.io.File; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.*; import java.util.List; -import java.util.Map; import java.util.regex.Pattern; /** @@ -121,13 +120,20 @@ public final class PythonSdkType extends SdkType { @NonNls @Nullable public String suggestHomePath() { - final Sdk[] existingSdks = ProjectJdkTable.getInstance().getAllJdks(); + return null; + } + + @NotNull + @Override + public Collection suggestHomePaths() { + final Sdk[] existingSdks = ReadAction.compute(() -> ProjectJdkTable.getInstance().getAllJdks()); final List sdks = PySdkExtKt.detectSystemWideSdks(null, Arrays.asList(existingSdks)); + //return all detected items after PY-41218 is fixed final PyDetectedSdk latest = StreamEx.of(sdks).findFirst().orElse(null); if (latest != null) { - return latest.getHomePath(); + return Collections.singleton(latest.getHomePath()); } - return null; + return Collections.emptyList(); } @Override