Python remove redundant classes

GitOrigin-RevId: 05a6480b47113f21416c46db043ab88581202ba6
This commit is contained in:
Ilya.Kazakevich
2024-09-23 19:09:00 +00:00
committed by intellij-monorepo-bot
parent 1cfdf56833
commit d8edf9e902
2 changed files with 0 additions and 475 deletions
@@ -26,9 +26,6 @@ class PythonInterpreterDetailsConfigurable(project: Project,
override fun isModified(): Boolean = initialSdkName != currentSdkName || underlyingConfigurable.isModified
/**
* TODO Shouldn't be here the association updated (see [com.jetbrains.python.configuration.PythonSdkDetailsDialog.editSdk]).
*/
override fun apply() {
underlyingConfigurable.apply()
@@ -1,472 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.configuration;
import com.google.common.collect.Sets;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.DumbAwareToggleAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModel;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Disposer;
import com.intellij.remote.RemoteSdkAdditionalData;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.NullableConsumer;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.packaging.PyPackageManagers;
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
import com.jetbrains.python.sdk.*;
import com.jetbrains.python.sdk.add.PyAddSdkDialog;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
public class PythonSdkDetailsDialog extends DialogWrapper {
private static final Logger LOG = Logger.getInstance(PythonSdkDetailsDialog.class);
private boolean myModified = false;
private final @NotNull Project myProject;
private final @Nullable Module myModule;
private final @NotNull NullableConsumer<? super Sdk> mySelectedSdkCallback;
private final @NotNull Consumer<Boolean> myCancelCallback;
private final @NotNull SdkModel.Listener mySdkModelListener;
private final @NotNull PyConfigurableInterpreterList myInterpreterList;
private final @NotNull ProjectSdksModel myProjectSdksModel;
private final @NotNull JBList<Sdk> mySdkList;
private final @NotNull JPanel myMainPanel;
private boolean myHideOtherProjectVirtualenvs = false;
public PythonSdkDetailsDialog(@NotNull Project project,
@Nullable Module module,
@NotNull NullableConsumer<? super Sdk> selectedSdkCallback,
@NotNull Consumer<Boolean> cancelCallback) {
super(project);
setTitle(PyBundle.message("sdk.details.dialog.title"));
myProject = project;
myModule = module;
mySelectedSdkCallback = selectedSdkCallback;
myCancelCallback = cancelCallback;
// there is an assumption that dialog started with unmodified sdks model
// otherwise processing `Cancel` will be more complicated
// to correctly revert changes
mySdkModelListener = new MySdkModelListener();
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
myProjectSdksModel = myInterpreterList.getModel();
myProjectSdksModel.addListener(mySdkModelListener);
mySdkList = buildSdkList(e -> updateOkButton());
myMainPanel = buildPanel(
mySdkList,
new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
addSdk();
updateOkButton();
}
},
new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
editSdk();
updateOkButton();
}
},
new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
removeSdk();
updateOkButton();
}
},
new ToggleVirtualEnvFilterButton(),
new ShowPathButton()
);
init();
refreshSdkList();
updateOkButton();
}
@Override
protected void dispose() {
myProjectSdksModel.removeListener(mySdkModelListener);
super.dispose();
}
private static @NotNull JBList<Sdk> buildSdkList(@NotNull ListSelectionListener selectionListener) {
final JBList<Sdk> result = new JBList<>();
result.setCellRenderer(new PySdkListCellRenderer());
result.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
result.addListSelectionListener(selectionListener);
ListSpeedSearch.installOn(result);
return result;
}
private static @NotNull JPanel buildPanel(@NotNull JBList<Sdk> sdkList,
@NotNull AnActionButtonRunnable addAction,
@NotNull AnActionButtonRunnable editAction,
@NotNull AnActionButtonRunnable removeAction,
AnAction @NotNull ... extraActions) {
return ToolbarDecorator.createDecorator(sdkList)
.disableUpDownActions()
.setAddAction(addAction)
.setEditAction(editAction)
.setRemoveAction(removeAction)
.addExtraActions(extraActions)
.setPreferredSize(new Dimension(600, 500))
.createPanel();
}
@Override
protected @Nullable JComponent createCenterPanel() {
return myMainPanel;
}
@Override
public @Nullable JComponent getPreferredFocusedComponent() {
return mySdkList;
}
private void updateOkButton() {
super.setOKActionEnabled(myModified || myProjectSdksModel.isModified() || isAnotherSdkSelected());
}
/**
* Checks whether the selection has changed from the initial one.
* <p>
* Note that multiple selection is ambiguous to treat it as the indication for the current project interpreter.
*
* @return {@code true} if the selection has changed and {@code false} otherwise
*/
private boolean isAnotherSdkSelected() {
if (mySdkList.getSelectedValuesList().size() > 1) {
return false;
}
Sdk originalSelectedSdk = getOriginalSelectedSdk();
return originalSelectedSdk != null && originalSelectedSdk != getSdk();
}
@Override
protected void doOKAction() {
apply();
super.doOKAction();
}
@Override
public void doCancelAction() {
final boolean modified = myModified || myProjectSdksModel.isModified();
if (modified) {
myProjectSdksModel.reset(myProject);
}
myModified = false;
myCancelCallback.accept(modified);
super.doCancelAction();
}
private void apply() {
try {
myProjectSdksModel.apply();
}
catch (ConfigurationException e) {
LOG.error(e);
}
myModified = false;
final Sdk sdk = getOriginalSelectedSdk();
mySelectedSdkCallback.consume(sdk);
if (sdk != null) {
PyPackageManagers.getInstance().clearCache(sdk);
}
Disposer.dispose(getDisposable());
}
private @Nullable Sdk getOriginalSelectedSdk() {
final Sdk editableSdk = getEditableSelectedSdk();
return editableSdk == null ? null : myProjectSdksModel.findSdk(editableSdk);
}
private @Nullable Sdk getEditableSelectedSdk() {
return getTheOnlyItemOrNull(mySdkList.getSelectedValuesList());
}
private static @Nullable <T> T getTheOnlyItemOrNull(@NotNull List<T> collection) {
if (collection.size() == 1) {
return collection.get(0);
}
else {
return null;
}
}
private void refreshSdkList() {
final List<Sdk> allPythonSdks = myInterpreterList.getAllPythonSdks(myProject, myModule);
Sdk projectSdk = getSdk();
final List<Sdk> notAssociatedWithOtherProjects = StreamEx
.of(allPythonSdks)
.filter(sdk -> !PySdkExtKt.isAssociatedWithAnotherModule(sdk, myModule))
.toList();
final List<Sdk> pythonSdks = myHideOtherProjectVirtualenvs ? notAssociatedWithOtherProjects : allPythonSdks;
mySdkList.setModel(new CollectionListModel<>(pythonSdks));
if (projectSdk != null) {
projectSdk = myProjectSdksModel.findSdk(projectSdk.getName());
mySdkList.clearSelection();
mySdkList.setSelectedValue(projectSdk, true);
mySdkList.updateUI();
}
}
private @Nullable Sdk getSdk() {
if (myModule == null) {
return ProjectRootManager.getInstance(myProject).getProjectSdk();
}
final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule);
return rootManager.getSdk();
}
private void addSdk() {
PyAddSdkDialog.show(myProject, myModule, Arrays.asList(myProjectSdksModel.getSdks()), new SdkAddedCallback());
}
private void setSelectedSdk(@Nullable Sdk selectedSdk) {
mySdkList.setSelectedValue(selectedSdk == null ? null : myProjectSdksModel.findSdk(selectedSdk.getName()), true);
}
private void editSdk() {
final Sdk currentSdk = getEditableSelectedSdk();
if (currentSdk != null) {
if (currentSdk.getSdkAdditionalData() instanceof RemoteSdkAdditionalData) {
editRemoteSdk(currentSdk);
}
else {
editSdk(currentSdk);
}
}
}
private void editRemoteSdk(Sdk currentSdk) {
PythonRemoteInterpreterManager remoteInterpreterManager = PythonRemoteInterpreterManager.getInstance();
if (remoteInterpreterManager != null) {
final SdkModificator modificator = currentSdk.getSdkModificator();
Set<Sdk> existingSdks = Sets.newHashSet(myProjectSdksModel.getSdks());
existingSdks.remove(currentSdk);
if (remoteInterpreterManager.editSdk(myProject, modificator, existingSdks)) {
commitAndRefresh(modificator);
}
}
}
private void editSdk(final Sdk currentSdk) {
final SdkModificator modificator = currentSdk.getSdkModificator();
final EditSdkDialog dialog = new EditSdkDialog(myProject, modificator, s -> {
if (isDuplicateSdkName(s, currentSdk)) {
return PyBundle.message("sdk.details.dialog.error.duplicate.name");
}
return null;
});
if (dialog.showAndGet()) {
final boolean pathChanged = !Objects.equals(currentSdk.getHomePath(), dialog.getHomePath());
if (!modificator.getName().equals(dialog.getName()) || pathChanged || dialog.isAssociateChanged()) {
modificator.setName(dialog.getName());
modificator.setHomePath(dialog.getHomePath());
if (dialog.isAssociateChanged()) {
setSdkAssociated(modificator, dialog.associateWithProject());
}
commitAndRefresh(modificator);
if (pathChanged) {
reloadSdk(currentSdk);
}
}
}
}
private void setSdkAssociated(SdkModificator modificator, boolean isAssociated) {
PythonSdkAdditionalData additionalData = (PythonSdkAdditionalData)modificator.getSdkAdditionalData();
if (additionalData == null) {
additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(modificator.getHomePath()));
modificator.setSdkAdditionalData(additionalData);
}
if (isAssociated && myModule != null) {
additionalData.associateWithModule(myModule);
}
else if (isAssociated) {
additionalData.setAssociatedModulePath(myProject.getBasePath());
}
else {
additionalData.resetAssociatedModulePath();
}
}
private boolean isDuplicateSdkName(String s, Sdk sdk) {
for (Sdk existingSdk : myProjectSdksModel.getSdks()) {
if (existingSdk == sdk) {
continue;
}
if (existingSdk.getName().equals(s)) {
return true;
}
}
return false;
}
private void removeSdk() {
final List<Sdk> selectedSdks = mySdkList.getSelectedValuesList();
if (!selectedSdks.isEmpty()) {
selectedSdks.forEach(selectedSdk -> myProjectSdksModel.removeSdk(selectedSdk));
refreshSdkList();
final Sdk currentSdk = getSdk();
if (currentSdk != null) {
mySdkList.setSelectedValue(currentSdk, true);
}
}
}
private void reloadSdk() {
final Sdk currentSdk = getEditableSelectedSdk();
if (currentSdk != null) {
reloadSdk(currentSdk);
}
}
private void reloadSdk(@NotNull Sdk currentSdk) {
PythonSdkUpdater.updateVersionAndPathsSynchronouslyAndScheduleRemaining(currentSdk, myProject);
}
private void commitAndRefresh(@NotNull SdkModificator modificator) {
modificator.commitChanges();
myModified = true;
refreshSdkList();
}
private class ToggleVirtualEnvFilterButton extends DumbAwareToggleAction {
ToggleVirtualEnvFilterButton() {
super(PyBundle.messagePointer("sdk.details.dialog.hide.all.virtual.envs"), Presentation.NULL_STRING, AllIcons.General.Filter);
}
@Override
public boolean isSelected(AnActionEvent e) {
return myHideOtherProjectVirtualenvs;
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
myHideOtherProjectVirtualenvs = state;
refreshSdkList();
updateOkButton();
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.EDT;
}
}
private class ShowPathButton extends DumbAwareAction {
ShowPathButton() {
super(PyBundle.messagePointer("sdk.details.dialog.show.interpreter.paths"), AllIcons.Actions.ShowAsTree);
}
@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(getEditableSelectedSdk() != null);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Sdk sdk = getEditableSelectedSdk();
if (sdk == null) return;
final PythonPathEditor pathEditor = createPathEditor(sdk);
final SdkModificator sdkModificator = sdk.getSdkModificator();
PythonPathDialog dialog = new PythonPathDialog(myProject, pathEditor);
pathEditor.reset(sdkModificator);
if (dialog.showAndGet()) {
if (pathEditor.isModified()) {
pathEditor.apply(sdkModificator);
commitAndRefresh(sdkModificator);
reloadSdk(sdk);
}
}
updateOkButton();
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.EDT;
}
}
private @NotNull PythonPathEditor createPathEditor(final @NotNull Sdk sdk) {
PythonPathEditor pathEditor;
if (PythonSdkUtil.isRemote(sdk)) {
pathEditor = new PyRemotePathEditor(myProject, sdk);
}
else {
pathEditor = new PythonPathEditor(PyBundle.message("python.sdk.configuration.tab.title"), OrderRootType.CLASSES,
FileChooserDescriptorFactory.createAllButJarContentsDescriptor());
}
pathEditor.addReloadPathsActionCallback(this::reloadSdk);
return pathEditor;
}
private class MySdkModelListener implements SdkModel.Listener {
@Override
public void sdkAdded(@NotNull Sdk sdk) {
refreshSdkList();
}
@Override
public void sdkChanged(@NotNull Sdk sdk, String previousName) {
refreshSdkList();
}
}
private class SdkAddedCallback implements Consumer<Sdk> {
@Override
public void accept(@Nullable Sdk sdk) {
if (sdk != null && myProjectSdksModel.findSdk(sdk.getName()) == null) {
myProjectSdksModel.addSdk(sdk);
setSelectedSdk(sdk);
}
}
}
}