Shared selection tracking for GotoSymbolsView...

... and a fix for https://www.pivotaltracker.com/story/show/173266410
This commit is contained in:
Kris De Volder
2020-06-17 11:48:44 -07:00
parent 3fbf536373
commit 8b7448fbb2
5 changed files with 153 additions and 71 deletions

View File

@@ -37,15 +37,16 @@ import reactor.core.publisher.Mono;
public class InProjectSymbolsProvider implements SymbolsProvider {
public static InProjectSymbolsProvider createFor(LiveExpression<IProject> project) {
LiveExpression<List<LanguageServer>> languageServers = project.apply(p ->
p == null
LiveExpression<List<LanguageServer>> languageServers = project.apply(p -> {
System.out.println("project = "+(p==null?null:p.getName()));
return p == null
? ImmutableList.of()
: LanguageServiceAccessor.getLanguageServers(
project.getValue(),
capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()),
true
)
);
);
});
return new InProjectSymbolsProvider(languageServers::getValue, project::getValue);
}

View File

@@ -0,0 +1,113 @@
/*******************************************************************************
* Copyright (c) 2020 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.springframework.ide.eclipse.boot.dash.model.AbstractDisposable;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
import org.springsource.ide.eclipse.commons.livexp.util.Log;
public class SelectionTracker extends AbstractDisposable {
private static Map<IWorkbenchWindow, SelectionTracker> INSTANCES = new HashMap<>();
public static synchronized SelectionTracker getInstance(IWorkbenchWindow wbw) {
return INSTANCES.computeIfAbsent(wbw, _wbw -> {
return new SelectionTracker(wbw);
});
}
private static synchronized void disposeInstance(IWorkbenchWindow wbw) {
SelectionTracker removed = INSTANCES.remove(wbw);
if (removed!=null) {
removed.dispose();
}
}
private final LiveVariable<IResource> currentResource = new LiveVariable<>();
public final LiveExpression<IProject> currentProject = currentResource.apply(r -> r==null ? null : r.getProject());
private SelectionTracker(IWorkbenchWindow wbw) {
ISelectionService selectionService = wbw.getSelectionService();
ISelectionListener selectionListener = new ISelectionListener() {
@Override
public void selectionChanged(IWorkbenchPart arg0, ISelection selection) {
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object element = ss.getFirstElement();
IResource rsrc = getResource(element);
if (rsrc!=null) {
currentResource.setValue(rsrc);
}
} else if (selection instanceof ITextSelection) {
//Let's assume the selection is in the active editor
try {
IEditorPart editor = wbw.getActivePage().getActiveEditor();
if (editor!=null) {
IEditorInput input = editor.getEditorInput();
currentResource.setValue(input.getAdapter(IResource.class));
}
} catch (Exception e) {
Log.log(e);
}
}
}
private IResource getResource(Object element) {
if (element instanceof IResource) {
return (IResource) element;
} else if (element instanceof IAdaptable) {
return ((IAdaptable) element).getAdapter(IResource.class);
}
return null;
}
};
selectionService.addSelectionListener(selectionListener);
onDispose(de -> {
selectionService.removeSelectionListener(selectionListener);
});
wbw.getShell().addDisposeListener(de -> {
disposeInstance(wbw);
});
//Code below tries to determine the 'initial' selection.
//Unfortunately, doesn't work. Mostly just getting null here, seems to be no way to get
// 'initial' selection reliably.
ISelection initialSelection = selectionService.getSelection();
if (initialSelection!=null) {
selectionListener.selectionChanged(null, initialSelection);
}
}
public LiveExpression<IResource> currentResource() {
return currentResource;
}
}

View File

@@ -0,0 +1,5 @@
package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
public class SymbolsProviders {
}

View File

@@ -14,24 +14,15 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.springframework.ide.eclipse.boot.dash.BootDashActivator;
import org.springframework.ide.eclipse.boot.dash.views.sections.ViewPartWithSections;
@@ -58,10 +49,7 @@ public class SpringSymbolsView extends ViewPartWithSections {
*/
private static final boolean ENABLE_SCROLLING = false;
private final SpringSymbolsViewModel model = new SpringSymbolsViewModel();
{
model.gotoSymbols.setOkHandler(GotoSymbolDialogModel.OPEN_IN_EDITOR_OK_HANDLER);
}
private SpringSymbolsViewModel model;
Action a = new Action("New View", BootDashActivator.getImageDescriptor("icons/add_target.png")) {
@Override
@@ -77,42 +65,7 @@ public class SpringSymbolsView extends ViewPartWithSections {
}
};
private ISelectionListener selectionListener = new ISelectionListener() {
@Override
public void selectionChanged(IWorkbenchPart arg0, ISelection selection) {
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object element = ss.getFirstElement();
IResource rsrc = getResource(element);
if (rsrc!=null) {
model.currentResource.setValue(rsrc);
}
} else if (selection instanceof ITextSelection) {
//Let's assume the selection is in the active editor
try {
IEditorPart editor = getSite().getWorkbenchWindow().getActivePage().getActiveEditor();
if (editor!=null) {
IEditorInput input = editor.getEditorInput();
model.currentResource.setValue(input.getAdapter(IResource.class));
}
} catch (Exception e) {
Log.log(e);
}
}
}
private IResource getResource(Object element) {
if (element instanceof IResource) {
return (IResource) element;
} else if (element instanceof IAdaptable) {
return ((IAdaptable) element).getAdapter(IResource.class);
}
return null;
}
};
private List<Disposable> disposables = new ArrayList<>();
private List<Disposable> disposables = new ArrayList<>(); //TODO: Remove... unused?
public SpringSymbolsView() {
super(ENABLE_SCROLLING);
@@ -142,11 +95,6 @@ public class SpringSymbolsView extends ViewPartWithSections {
})
);
sections.add(new GotoSymbolSection(this, model.gotoSymbols).enableStatusLine(false));
ISelectionService selectitonService = getSite().getWorkbenchWindow().getSelectionService();
selectitonService.addSelectionListener(selectionListener);
this.disposables.add(() -> {
selectitonService.removeSelectionListener(selectionListener);
});
return sections;
}
@@ -185,4 +133,11 @@ public class SpringSymbolsView extends ViewPartWithSections {
super.dispose();
}
@Override
public void init(IViewSite site) throws PartInitException {
super.init(site);
model = new SpringSymbolsViewModel(getSite().getWorkbenchWindow());
model.gotoSymbols.setOkHandler(GotoSymbolDialogModel.OPEN_IN_EDITOR_OK_HANDLER);
}
}

View File

@@ -12,25 +12,33 @@ package org.springframework.tooling.ls.eclipse.gotosymbol.view;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.ui.IWorkbenchWindow;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolDialogModel;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InFileSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InProjectSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InWorkspaceSymbolsProvider;
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.SelectionTracker;
import org.springframework.tooling.ls.eclipse.gotosymbol.favourites.FavouritesPreference;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
public class SpringSymbolsViewModel {
public final SelectionTracker currentSelection;
public final GotoSymbolDialogModel gotoSymbols;
public final LiveVariable<IResource> currentResource = new LiveVariable<>();
public final LiveExpression<IProject> currentProject = currentResource.apply(r -> r==null ? null : r.getProject());
public final GotoSymbolDialogModel gotoSymbols = new GotoSymbolDialogModel(null,
InWorkspaceSymbolsProvider.createFor(currentProject::getValue),
InProjectSymbolsProvider.createFor(currentProject),
InFileSymbolsProvider.createFor(currentResource)
)
.setFavourites(FavouritesPreference.INSTANCE);
{
gotoSymbols.unfilteredSymbols.dependsOn(currentProject);
public SpringSymbolsViewModel(IWorkbenchWindow wbw) {
currentSelection = SelectionTracker.getInstance(wbw);
LiveExpression<IResource> currentResource = currentSelection.currentResource();
LiveExpression<IProject> currentProject = currentSelection.currentProject;
gotoSymbols = new GotoSymbolDialogModel(null,
InWorkspaceSymbolsProvider.createFor(currentProject::getValue),
InProjectSymbolsProvider.createFor(currentProject),
InFileSymbolsProvider.createFor(currentResource)
)
.setFavourites(FavouritesPreference.INSTANCE);
{
gotoSymbols.unfilteredSymbols.dependsOn(currentResource);
gotoSymbols.unfilteredSymbols.dependsOn(currentProject);
}
}
}