UnknownSdkTracker - handle unset SDKs, fix more tests

GitOrigin-RevId: 95f42e222bf7411535046ca59027452d244d553c
This commit is contained in:
Eugene Petrenko
2019-12-18 10:32:28 +00:00
committed by intellij-monorepo-bot
parent fcbf5a8013
commit 8fcbb0f1f3
4 changed files with 261 additions and 158 deletions
@@ -1,6 +1,7 @@
// 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.
package com.intellij.java.codeInsight.daemon.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
@@ -14,6 +15,8 @@ import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,9 +48,7 @@ public class SdkSetupNotificationTest extends JavaCodeInsightFixtureTestCase {
final List<SdkFixInfo> fixes = detectMissingSdks();
assertThat(fixes)
.withFailMessage(String.valueOf(fixes))
.hasSize(1)
.first()
.returns("missingSDK", SdkFixInfo::getSdkName);
.hasSize(1);
}
public void testMissingModuleJdk() {
@@ -60,9 +61,7 @@ public class SdkSetupNotificationTest extends JavaCodeInsightFixtureTestCase {
final List<SdkFixInfo> fixes = detectMissingSdks();
assertThat(fixes)
.withFailMessage(String.valueOf(fixes))
.hasSize(1)
.first()
.returns("missingSDK", SdkFixInfo::getSdkName);
.hasSize(1);
}
public void testNoProjectSdk() {
@@ -73,20 +72,10 @@ public class SdkSetupNotificationTest extends JavaCodeInsightFixtureTestCase {
assertThat(fixes)
.withFailMessage(String.valueOf(fixes))
.isNotEmpty();
/*
final IntentionActionWithOptions action = fixes.getIntentionAction();
assertThat(action).isNotNull();
final String text = action.getText();
assertThat(text).isNotNull();
if (!text.startsWith("Setup SDK")) {
final int length = Math.min(text.length(), "Setup SDK".length());
assertThat(text.substring(0, length)).isEqualTo("Setup SDK");
}*/
}
public void testModuleSdk() {
Sdk sdk = IdeaTestUtil.getMockJdk18();
Sdk sdk = addSdkIfNeeded(IdeaTestUtil.getMockJdk18());
ModuleRootModificationUtil.setModuleSdk(getModule(), sdk);
final List<SdkFixInfo> fixes = detectMissingSdks();
@@ -102,15 +91,6 @@ public class SdkSetupNotificationTest extends JavaCodeInsightFixtureTestCase {
assertThat(fixes)
.withFailMessage(String.valueOf(fixes))
.isNotEmpty();
/*final IntentionActionWithOptions action = panel.getIntentionAction();
assertThat(action).isNotNull();
final String text = action.getText();
assertThat(text).isNotNull();
if (!text.startsWith("Setup SDK")) {
final int length = Math.min(text.length(), "Setup SDK".length());
assertThat(text.substring(0, length)).isEqualTo("Setup SDK");
}*/
}
@Override
@@ -129,16 +109,29 @@ public class SdkSetupNotificationTest extends JavaCodeInsightFixtureTestCase {
private void setProjectSdk(@Nullable Sdk sdk) {
WriteAction.run(() -> {
ProjectJdkTable jdkTable = ProjectJdkTable.getInstance();
if (sdk != null) {
final Sdk foundJdk = jdkTable.findJdk(sdk.getName());
if (foundJdk == null) {
jdkTable.addJdk(sdk, myFixture.getProjectDisposable());
}
}
ProjectRootManager.getInstance(getProject()).setProjectSdk(sdk);
ProjectRootManager.getInstance(getProject()).setProjectSdk(addSdkIfNeeded(sdk));
});
}
@Contract("null->null;!null->!null")
private Sdk addSdkIfNeeded(Sdk sdk) {
if (sdk == null) return null;
ProjectJdkTable jdkTable = ProjectJdkTable.getInstance();
final Sdk foundJdk = jdkTable.findJdk(sdk.getName());
if (foundJdk != null) return sdk;
ThrowableRunnable<RuntimeException> addSdk = () -> {
jdkTable.addJdk(sdk, myFixture.getProjectDisposable());
};
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
addSdk.run();
} else {
WriteAction.run(addSdk);
}
return sdk;
}
}
@@ -1,16 +1,17 @@
// 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.
package com.intellij.openapi.projectRoots.impl;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleJdkOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
import java.util.ArrayList;
import java.util.Collections;
@@ -39,16 +40,31 @@ public class SdkUsagesCollector {
List<SdkUsage> contributeUsages(@NotNull Project project);
}
public static class SdkUsage {
public static final class SdkUsage {
private final String myUsagePresentableText;
private final String mySdkName;
private final String mySdkTypeName;
private Consumer<Sdk> mySdkSetAction = null;
private Runnable myProjectSdkSetAction = null;
public SdkUsage(@NotNull String sdkName, @Nullable String sdkTypeName) {
public SdkUsage(@NotNull String usagePresentableText,
@Nullable String sdkName,
@Nullable String sdkTypeName) {
myUsagePresentableText = usagePresentableText;
mySdkName = sdkName;
mySdkTypeName = sdkTypeName;
}
/**
* @return UI friendly description of the SDK-using entity,
* e.g. Project SDK or Module SDK
*/
@NotNull
public String getUsagePresentableText() {
return myUsagePresentableText;
}
@Nullable
public String getSdkName() {
return mySdkName;
}
@@ -57,6 +73,45 @@ public class SdkUsagesCollector {
public String getSdkTypeName() {
return mySdkTypeName;
}
/**
* @return an action to change the currently selected SDK
* to a given SDK. Return {@code null} to disallow that action
*/
@Nullable
public Consumer<Sdk> getSdkSetAction() {
return mySdkSetAction;
}
/**
* Sets the action for {@link #getSdkSetAction()}
* @see #getSdkSetAction()
*/
@NotNull
public SdkUsage withSetSdkAction(@NotNull Consumer<Sdk> setSdkAction) {
mySdkSetAction = setSdkAction;
return this;
}
/**
* @return an action to change the currently selected SDK
* to a project SDK. The action should work no matter if project SDK is valid or not.
* Return {@code null} to diasllow that action
*/
@Nullable
public Runnable getProjectSdkSetAction() {
return myProjectSdkSetAction;
}
/**
* Sets the action for {@link #getProjectSdkSetAction()}
* @see #getProjectSdkSetAction()
*/
@NotNull
public SdkUsage withSetProjectSdkAction(@NotNull Runnable setProjectSdkAction) {
myProjectSdkSetAction = setProjectSdkAction;
return this;
}
}
/**
@@ -77,10 +132,10 @@ public class SdkUsagesCollector {
String sdkName = manager.getProjectSdkName();
String sdkType = manager.getProjectSdkTypeName();
if (sdkName != null) {
return Collections.singletonList(new SdkUsage(sdkName, sdkType));
}
return Collections.emptyList();
SdkUsage usage = new SdkUsage("Project SDK", sdkName, sdkType)
.withSetSdkAction(sdk -> WriteAction.run(() -> ProjectRootManager.getInstance(project).setProjectSdk(sdk)));
return Collections.singletonList(usage);
}
}
@@ -90,18 +145,48 @@ public class SdkUsagesCollector {
public List<SdkUsage> contributeUsages(@NotNull Project project) {
List<SdkUsage> usages = new ArrayList<>();
for (Module module : ModuleManager.getInstance(project).getModules()) {
ModuleRootManager manager = ModuleRootManager.getInstance(module);
for (OrderEntry orderEntry : manager.getOrderEntries()) {
if (orderEntry instanceof ModuleJdkOrderEntry) {
String jdkName = ((ModuleJdkOrderEntry)orderEntry).getJdkName();
String jdkType = ((ModuleJdkOrderEntry)orderEntry).getJdkTypeName();
if (jdkName != null) {
usages.add(new SdkUsage(jdkName, jdkType));
}
}
}
contributeForModule(module, usages);
}
return usages;
}
private void contributeForModule(@NotNull Module module, @NotNull List<SdkUsage> usages) {
ModuleRootManager manager = ModuleRootManager.getInstance(module);
String jdkName = null;
String jdkType = null;
for (OrderEntry orderEntry : manager.getOrderEntries()) {
if (!(orderEntry instanceof JdkOrderEntry)) continue;
if (orderEntry instanceof InheritedJdkOrderEntry) return;
if (orderEntry instanceof ModuleJdkOrderEntry) {
jdkName = ((ModuleJdkOrderEntry)orderEntry).getJdkName();
jdkType = ((ModuleJdkOrderEntry)orderEntry).getJdkTypeName();
continue;
}
Logger.getInstance(getClass()).error("Unexpected OrderEntry: " + orderEntry.getClass().getName() + ": " + orderEntry);
}
SdkUsage usage = new SdkUsage("module \"" + module.getName() + "\"", jdkName, jdkType)
.withSetProjectSdkAction(() -> {
WriteAction.run(() -> {
if (module.isDisposed()) return;
ModifiableRootModel mod = ModuleRootManager.getInstance(module).getModifiableModel();
mod.inheritSdk();
mod.commit();
});
})
.withSetSdkAction(sdk -> {
WriteAction.run(() -> {
if (module.isDisposed()) return;
ModifiableRootModel mod = ModuleRootManager.getInstance(module).getModifiableModel();
mod.setSdk(sdk);
mod.commit();
});
});
usages.add(usage);
}
}
}
@@ -7,11 +7,12 @@ import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkType;
import com.intellij.openapi.projectRoots.impl.SdkUsagesCollector.SdkUsage;
import com.intellij.openapi.projectRoots.impl.UnknownSdkResolver.DownloadSdkFix;
import com.intellij.openapi.projectRoots.impl.UnknownSdkResolver.UnknownSdk;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.util.SmartList;
@@ -22,6 +23,7 @@ import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.function.Consumer;
public class UnknownSdkEditorNotification implements Disposable {
public static final Key<List<MissingSdkNotificationPanel>> NOTIFICATIONS = Key.create("notifications added to the editor");
@@ -34,7 +36,7 @@ public class UnknownSdkEditorNotification implements Disposable {
private final Project myProject;
private final FileEditorManager myFileEditorManager;
private final Map<String, SdkFixInfo> myNotifications = new TreeMap<>();
private final Set<SdkFixInfo> myNotifications = new LinkedHashSet<>();
UnknownSdkEditorNotification(@NotNull Project project) {
myProject = project;
@@ -51,23 +53,17 @@ public class UnknownSdkEditorNotification implements Disposable {
});
}
@NotNull
private MissingSdkNotificationPanel createPanelFor(@NotNull SdkFixInfo info) {
Pair<UnknownSdk, DownloadSdkFix> fixInfo = info.getFixInfo();
String sdkName = info.getSdkName();
private void setupPanel(@NotNull MissingSdkNotificationPanel panel,
@NotNull String sdkName,
@Nullable UnknownSdk unknownSdk,
@Nullable DownloadSdkFix fix) {
SdkType sdkType = fixInfo != null ? fixInfo.first.getSdkType() : null;
SdkType sdkType = unknownSdk != null ? unknownSdk.getSdkType() : null;
String sdkTypeName = sdkType != null ? sdkType.getPresentableName() : "SDK";
MissingSdkNotificationPanel panel = new MissingSdkNotificationPanel(info);
panel.setProject(myProject);
panel.setProviderKey(EDITOR_NOTIFICATIONS_KEY);
panel.setText(sdkTypeName + " \"" + sdkName + "\" is missing");
if (fixInfo != null) {
UnknownSdk unknownSdk = fixInfo.first;
DownloadSdkFix fix = fixInfo.second;
if (fix != null && unknownSdk != null) {
panel.createActionLabel("Download " + sdkTypeName + " (" + fix.getDownloadDescription() + ")", () -> {
removeNotification(panel);
UnknownSdkTracker.getInstance(myProject).applyDownloadableFix(unknownSdk, fix);
@@ -85,8 +81,37 @@ public class UnknownSdkEditorNotification implements Disposable {
.showSdkSelectionPopup(sdkName, sdkType, container, () -> removeNotification(panel));
}
);
}
return panel;
private void setupPanel(@NotNull MissingSdkNotificationPanel panel,
@NotNull String source,
@Nullable Runnable setProjectSdk,
@Nullable Consumer<Sdk> setSdk) {
panel.setProviderKey(EDITOR_NOTIFICATIONS_KEY);
panel.setText("SDK is not set for " + source);
if (setProjectSdk != null) {
panel.createActionLabel("Use Project SDK", () -> {
setProjectSdk.run();
removeNotification(panel);
});
}
if (setSdk != null) {
panel.createActionLabel("Configure...", () -> {
//FileEditorManager#addTopComponent wraps the panel to implement borders, unwrapping
Container container = panel.getParent();
if (container == null) container = panel;
UnknownSdkTracker
.getInstance(myProject)
.showSdkSelectionPopup(null, container, sdk -> {
setSdk.accept(sdk);
removeNotification(panel);
});
});
}
}
@Override
@@ -94,19 +119,56 @@ public class UnknownSdkEditorNotification implements Disposable {
@NotNull
public List<SdkFixInfo> getNotifications() {
return ImmutableList.copyOf(myNotifications.values());
return ImmutableList.copyOf(myNotifications);
}
public void showNotifications(@NotNull List<String> unifiableSdkNames,
public void showNotifications(@NotNull List<SdkUsage> unsetSdks,
@NotNull List<String> unifiableSdkNames,
@NotNull Map<UnknownSdk, DownloadSdkFix> files) {
myNotifications.clear();
for (SdkUsage usage : unsetSdks) {
myNotifications.add(new SdkFixInfo() {
@Override
public void setupNotificationPanel(@NotNull MissingSdkNotificationPanel panel) {
setupPanel(panel, usage.getUsagePresentableText(), usage.getProjectSdkSetAction(), usage.getSdkSetAction());
}
@Override
public String toString() {
return "SdkFixInfo { sdkUsage: " + usage.getUsagePresentableText() + " }";
}
});
}
for (String name : unifiableSdkNames) {
myNotifications.put(name, SdkFixInfo.forBroken(name));
myNotifications.add(new SdkFixInfo() {
@Override
public void setupNotificationPanel(@NotNull MissingSdkNotificationPanel panel) {
setupPanel(panel, name, (UnknownSdk)null, null);
}
@Override
public String toString() {
return "SdkFixInfo { unknownName: '" + name + "' }";
}
});
}
for (Map.Entry<UnknownSdk, DownloadSdkFix> e : files.entrySet()) {
myNotifications.put(e.getKey().getSdkName(), SdkFixInfo.forFix(e));
UnknownSdk key = e.getKey();
DownloadSdkFix fix = e.getValue();
myNotifications.add(new SdkFixInfo() {
@Override
public void setupNotificationPanel(@NotNull MissingSdkNotificationPanel panel) {
setupPanel(panel, key.getSdkName(), key, fix);
}
@Override
public String toString() {
return "SdkFixInfo { name: '" + key.getSdkName() + "', fix: " + fix.getDownloadDescription() + " }";
}
});
}
for (FileEditor editor : myFileEditorManager.getAllEditors()) {
@@ -115,7 +177,7 @@ public class UnknownSdkEditorNotification implements Disposable {
}
private void removeNotification(@NotNull MissingSdkNotificationPanel expiredPanel) {
myNotifications.remove(expiredPanel.myInfo.getSdkName());
myNotifications.remove(expiredPanel.myInfo);
for (FileEditor editor : myFileEditorManager.getAllEditors()) {
List<MissingSdkNotificationPanel> notifications = editor.getUserData(NOTIFICATIONS);
@@ -145,8 +207,11 @@ public class UnknownSdkEditorNotification implements Disposable {
editor.putUserData(NOTIFICATIONS, notifications);
}
for (SdkFixInfo info : myNotifications.values()) {
MissingSdkNotificationPanel notification = createPanelFor(info);
for (SdkFixInfo info : myNotifications) {
MissingSdkNotificationPanel notification = new MissingSdkNotificationPanel(info);
notification.setProject(myProject);
notification.setProviderKey(EDITOR_NOTIFICATIONS_KEY);
info.setupNotificationPanel(notification);
notifications.add(notification);
myFileEditorManager.addTopComponent(editor, notification);
@@ -166,56 +231,7 @@ public class UnknownSdkEditorNotification implements Disposable {
}
}
public static class SdkFixInfo {
@NotNull
static SdkFixInfo forBroken(@NotNull String sdkName) {
return new SdkFixInfo(sdkName);
}
@NotNull
static SdkFixInfo forFix(@NotNull Map.Entry<? extends UnknownSdk, DownloadSdkFix> e) {
UnknownSdk sdk = e.getKey();
DownloadSdkFix fix = e.getValue();
return new SdkFixInfo(sdk.getSdkName()) {
@NotNull
@Override
public Pair<UnknownSdk, DownloadSdkFix> getFixInfo() {
return Pair.create(sdk, fix);
}
};
}
private final String mySdkName;
private SdkFixInfo(@NotNull String sdkName) {
mySdkName = sdkName;
}
@NotNull
public String getSdkName() {
return mySdkName;
}
@Nullable
public Pair<UnknownSdk, DownloadSdkFix> getFixInfo() {
return null;
}
@Override
public final int hashCode() {
return Objects.hashCode(mySdkName);
}
@Override
public final boolean equals(Object obj) {
return obj instanceof SdkFixInfo && Objects.equals(((SdkFixInfo)obj).mySdkName, mySdkName);
}
@Override
public String toString() {
return "SdkFixInfo{" +
"mySdkName='" + mySdkName + '\'' +
'}';
}
public interface SdkFixInfo {
void setupNotificationPanel(@NotNull MissingSdkNotificationPanel panel);
}
}
@@ -1,9 +1,9 @@
// 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.
package com.intellij.openapi.projectRoots.impl;
import com.google.common.collect.*;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SetMultimap;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.WriteAction;
@@ -27,17 +27,16 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.SdkDownloadTracke
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.Consumer;
import com.intellij.util.TripleFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import static com.intellij.openapi.progress.PerformInBackgroundOption.ALWAYS_BACKGROUND;
import static com.intellij.openapi.projectRoots.impl.UnknownSdkResolver.UnknownSdk;
@@ -69,28 +68,28 @@ public class UnknownSdkTracker {
}
private void updateUnknownSdksWithProgress(@NotNull ProgressIndicator indicator) {
List<String> totallyUnknownSdks = new ArrayList<>();
List<SdkUsage> unsetSdks = new ArrayList<>();
List<String> missingSdks = new ArrayList<>();
List<UnknownSdk> fixable = new ArrayList<>();
ReadAction.run(() -> collectAndGroupSdkUsages(totallyUnknownSdks, fixable));
ReadAction.run(() -> collectAndGroupSdkUsages(unsetSdks, missingSdks, fixable));
List<UnknownSdkLookup> lookups = collectSdkLookups(indicator);
Map<UnknownSdk, LocalSdkFix> localFixes = findFixesAndRemoveFixable(indicator, fixable, lookups, UnknownSdkLookup::proposeLocalFix);
Map<UnknownSdk, DownloadSdkFix> downloadFixes = findFixesAndRemoveFixable(indicator, fixable, lookups, UnknownSdkLookup::proposeDownload);
fixable.forEach(it -> totallyUnknownSdks.add(it.getSdkName()));
fixable.forEach(it -> missingSdks.add(it.getSdkName()));
ApplicationManager.getApplication().invokeLater(() -> {
indicator.setText("Configuring SDKs...");
configureLocalSdks(localFixes);
UnknownSdkBalloonNotification.getInstance(myProject).notifyFixedSdks(localFixes);
UnknownSdkEditorNotification.getInstance(myProject).showNotifications(totallyUnknownSdks, downloadFixes);
UnknownSdkEditorNotification.getInstance(myProject).showNotifications(unsetSdks, missingSdks, downloadFixes);
});
}
@NotNull
private List<UnknownSdkLookup> collectSdkLookups(@NotNull ProgressIndicator indicator) {
List<UnknownSdkLookup> lookups = new ArrayList<>();
UnknownSdkResolver.EP_NAME.forEachExtensionSafe(ext -> {
UnknownSdkLookup resolver = ext.createResolver(myProject, indicator);
if (resolver != null) {
@@ -100,7 +99,15 @@ public class UnknownSdkTracker {
return lookups;
}
private void collectAndGroupSdkUsages(@NotNull List<String> totallyUnknownSdks,
/**
* Collects all SDK usages from the project model and splits them
* into the specified groups
* @param undefinedSdks all usages where SDK is not set, e.g. lack of Project or Module SDK
* @param totallyUnknownSdks all named SDKs that are not present and where SdkType is missing or contains different values
* @param resolvableSdks all usages where fix extension points from {@link UnknownSdkResolver#EP_NAME} are possible to apply
*/
private void collectAndGroupSdkUsages(@NotNull List<SdkUsage> undefinedSdks,
@NotNull List<String> totallyUnknownSdks,
@NotNull List<UnknownSdk> resolvableSdks) {
SetMultimap<String, String> sdkToTypes = MultimapBuilder
.treeKeys(String.CASE_INSENSITIVE_ORDER)
@@ -111,6 +118,11 @@ public class UnknownSdkTracker {
for (SdkUsage usage : SdkUsagesCollector.getInstance(myProject).collectSdkUsages()) {
String sdkName = usage.getSdkName();
if (sdkName == null) {
undefinedSdks.add(usage);
continue;
}
//we do not track existing SDKs
if (jdkTable.findJdk(sdkName) != null) continue;
@@ -177,6 +189,15 @@ public class UnknownSdkTracker {
@Nullable SdkType sdkType,
@NotNull Container underneathRightOfComponent,
@NotNull Runnable onSelectionMade) {
showSdkSelectionPopup(sdkType, underneathRightOfComponent, sdk -> {
registerNewSdkInJdkTable(sdkName, sdk);
onSelectionMade.run();
});
}
public void showSdkSelectionPopup(@Nullable SdkType sdkType,
@NotNull Container underneathRightOfComponent,
@NotNull Consumer<? super Sdk> onSelectionMade) {
ProjectSdksModel model = new ProjectSdksModel();
SdkListModelBuilder modelBuilder = new SdkListModelBuilder(
myProject,
@@ -191,21 +212,22 @@ public class UnknownSdkTracker {
modelBuilder
);
AtomicBoolean wasSdkCreated = new AtomicBoolean(false);
AtomicReference<Sdk> wasSdkCreated = new AtomicReference<>(null);
model.addListener(new SdkModel.Listener() {
@Override
public void sdkAdded(@NotNull Sdk sdk) {
//TODO: handle if an existing item is selected!
//it is easier and safer than committing the ProjectSdksModel instance
registerNewSdkInJdkTable(sdkName, sdk);
wasSdkCreated.set(true);
wasSdkCreated.set(sdk);
}
});
popup.showUnderneathToTheRightOf(
underneathRightOfComponent,
() -> {
if (wasSdkCreated.get()) {
onSelectionMade.run();
Sdk sdk = wasSdkCreated.get();
if (sdk != null) {
onSelectionMade.consume(sdk);
}
}
);
@@ -299,18 +321,5 @@ public class UnknownSdkTracker {
public SdkType getSdkType() {
return mySdkType;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MissingSdkInfo)) return false;
MissingSdkInfo info = (MissingSdkInfo)o;
return mySdkName.equals(info.mySdkName);
}
@Override
public int hashCode() {
return Objects.hash(mySdkName);
}
}
}