Skip to content

Commit

Permalink
[eclipse-lsp4e#254] Initial implementation of outline filters
Browse files Browse the repository at this point in the history
  • Loading branch information
travkin79 committed Aug 12, 2024
1 parent cb85702 commit 3f99a77
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 4 deletions.
21 changes: 21 additions & 0 deletions org.eclipse.lsp4e/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,27 @@
</visibleWhen>
</command>
</menuContribution>
<menuContribution
allPopups="false"
locationURI="menu:org.eclipse.ui.views.ContentOutline">
<menu
id="org.eclipse.lsp4e.outline.hideMenu"
label="Hide...">
<visibleWhen>
<reference
definitionId="org.eclipse.lsp4e.activePartHasCNFOutlinePage">
</reference>
</visibleWhen>
</menu>
</menuContribution>
<menuContribution
allPopups="false"
locationURI="menu:org.eclipse.lsp4e.outline.hideMenu">
<dynamic
class="org.eclipse.lsp4e.outline.OutlineViewFilterMenuContributor"
id="org.eclipse.lsp4e.filters.dynamic">
</dynamic>
</menuContribution>
<menuContribution
allPopups="true"
locationURI="popup:org.eclipse.ui.genericeditor.source.menu?after=additions">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class CNFOutlinePage implements IContentOutlinePage, ILabelProviderListen
public static final String LINK_WITH_EDITOR_PREFERENCE = ID + ".linkWithEditor"; //$NON-NLS-1$
public static final String SHOW_KIND_PREFERENCE = ID + ".showKind"; //$NON-NLS-1$
public static final String SORT_OUTLINE_PREFERENCE = ID + ".sortOutline"; //$NON-NLS-1$
public static final String HIDE_DOCUMENT_SYMBOL_KIND_PREFERENCE_PREFIX = ID + ".hide"; //$NON-NLS-1$

private CommonViewer outlineViewer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -51,10 +54,12 @@
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.LanguageServerWrapper;
import org.eclipse.lsp4e.internal.CancellationUtil;
import org.eclipse.lsp4e.outline.SymbolsModel.DocumentSymbolWithURI;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.DocumentSymbolParams;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.ui.IMemento;
Expand Down Expand Up @@ -144,6 +149,39 @@ public void documentAboutToBeChanged(DocumentEvent event) {
public void documentChanged(DocumentEvent event) {
refreshTreeContentFromLS();
}

}

private final class PreferencesChangedOutlineUpdater implements IPreferenceChangeListener, IOutlineUpdater {

@Override
public void install() {
IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID);
preferences.addPreferenceChangeListener(this);
}

@Override
public void uninstall() {
IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID);
preferences.removePreferenceChangeListener(this);
}

@Override
public void preferenceChange(PreferenceChangeEvent event) {
if (viewer == null || outlineViewerInput == null) {
return;
}

if (event.getKey().startsWith(CNFOutlinePage.HIDE_DOCUMENT_SYMBOL_KIND_PREFERENCE_PREFIX)) {
viewer.getControl().getDisplay().asyncExec(() -> {
if(viewer.getTree().isDisposed()) {
return;
}

viewer.refresh();
});
}
}
}

private final class ReconcilerOutlineUpdater extends AbstractReconciler implements IOutlineUpdater {
Expand Down Expand Up @@ -230,17 +268,20 @@ public void resourceChanged(IResourceChangeEvent event) {
private final boolean refreshOnResourceChanged;
private boolean isQuickOutline;
private IOutlineUpdater outlineUpdater;
private IOutlineUpdater preferencesDependantOutlineUpdater;

public LSSymbolsContentProvider() {
this(false);
}

public LSSymbolsContentProvider(boolean refreshOnResourceChanged) {
this.refreshOnResourceChanged = refreshOnResourceChanged;
this.preferencesDependantOutlineUpdater = new PreferencesChangedOutlineUpdater();
}

@Override
public void init(ICommonContentExtensionSite aConfig) {
preferencesDependantOutlineUpdater.install();
}

@Override
Expand Down Expand Up @@ -292,12 +333,34 @@ public Object[] getElements(Object inputElement) {
if (this.lastError != null && symbolsModel.getElements().length == 0) {
return new Object[] { "An error occured, see log for details" }; //$NON-NLS-1$
}
return symbolsModel.getElements();
return Arrays.stream(symbolsModel.getElements())
.filter(element -> !hideElement(element))
.toArray(Object[]::new);
}

@Override
public Object[] getChildren(Object parentElement) {
return symbolsModel.getChildren(parentElement);
return Arrays.stream(symbolsModel.getChildren(parentElement))
.filter(element -> !hideElement(element))
.toArray(Object[]::new);
}

private boolean hideElement(Object element) {
SymbolKind kind = null;

if (element instanceof DocumentSymbol) {
kind = ((DocumentSymbol) element).getKind();
} else if (element instanceof DocumentSymbolWithURI) {
kind = ((DocumentSymbolWithURI) element).symbol.getKind();
} else if (element instanceof SymbolInformation) {
kind = ((SymbolInformation) element).getKind();
}

if (OutlineViewFilterMenuContributor.isHideSymbolKind(kind)) {
return true;
}

return false;
}

@Override
Expand Down Expand Up @@ -344,10 +407,12 @@ protected void refreshTreeContentFromLS() {
TreePath[] expandedElements = viewer.getExpandedTreePaths();
TreePath[] initialSelection = ((ITreeSelection) viewer.getSelection()).getPaths();
viewer.refresh();
viewer.setExpandedTreePaths(Arrays.stream(expandedElements).map(symbolsModel::toUpdatedSymbol)
viewer.setExpandedTreePaths(Arrays.stream(expandedElements)
.map(symbolsModel::toUpdatedSymbol)
.filter(Objects::nonNull).toArray(TreePath[]::new));
viewer.setSelection(new TreeSelection(Arrays.stream(initialSelection)
.map(symbolsModel::toUpdatedSymbol).filter(Objects::nonNull).toArray(TreePath[]::new)));
.map(symbolsModel::toUpdatedSymbol)
.filter(Objects::nonNull).toArray(TreePath[]::new)));
}

if (linkWithEditor) {
Expand Down Expand Up @@ -375,6 +440,7 @@ public void dispose() {
if (outlineUpdater != null) {
outlineUpdater.uninstall();
}
preferencesDependantOutlineUpdater.uninstall();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright (c) 2024 Advantest Europe GmbH. All rights reserved.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dietrich Travkin (Solunar GmbH) - initial implementation
*******************************************************************************/
package org.eclipse.lsp4e.outline;

import java.util.Arrays;

import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4j.SymbolKind;
import org.eclipse.ui.actions.CompoundContributionItem;

public class OutlineViewFilterMenuContributor extends CompoundContributionItem {

@Override
protected IContributionItem[] getContributionItems() {
return Arrays.stream(SymbolKind.values())
.map(kind -> createHideSymbolKindContributionItem(kind))
.toArray(IContributionItem[]::new);
}

private IContributionItem createHideSymbolKindContributionItem(SymbolKind kind) {
return new ActionContributionItem(new HideSymbolKindAction(kind));
}

static boolean isHideSymbolKind(SymbolKind kind) {
IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID);
return preferences.getBoolean(CNFOutlinePage.HIDE_DOCUMENT_SYMBOL_KIND_PREFERENCE_PREFIX + kind.name(), false);
}

static boolean toggleHideSymbolKind(SymbolKind kind) {
IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID);
boolean oldValue = isHideSymbolKind(kind);

preferences.putBoolean(CNFOutlinePage.HIDE_DOCUMENT_SYMBOL_KIND_PREFERENCE_PREFIX + kind.name(), !oldValue);

return !oldValue;
}

private static class HideSymbolKindAction extends Action {
private final SymbolKind kind;

HideSymbolKindAction(SymbolKind kind) {
super(kind.name(), IAction.AS_CHECK_BOX);
this.kind = kind;
this.setChecked(isHideSymbolKind(kind));
}

@Override
public void run() {
boolean checkedState = toggleHideSymbolKind(kind);
setChecked(checkedState);
}

}

}

0 comments on commit 3f99a77

Please sign in to comment.