blob: aece38fa5a91a9024c00e5401c2dd2a0c5822168 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2019 Rogue Wave Software Inc. and others.
* 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:
* Michał Niewrzał (Rogue Wave Software Inc.) - initial implementation
*******************************************************************************/
package org.eclipse.lsp4e.operations.symbols;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.BoldStylerProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.outline.CNFOutlinePage;
import org.eclipse.lsp4e.outline.SymbolsLabelProvider;
import org.eclipse.lsp4e.ui.Messages;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.WorkspaceSymbolParams;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
public class LSPSymbolInWorkspaceDialog extends FilteredItemsSelectionDialog {
private static final String DIALOG_SETTINGS = LSPSymbolInWorkspaceDialog.class.getName();
private static class InternalSymbolsLabelProvider extends SymbolsLabelProvider {
private String pattern;
private BoldStylerProvider stylerProvider;
public InternalSymbolsLabelProvider(BoldStylerProvider stylerProvider) {
super(true, InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID)
.getBoolean(CNFOutlinePage.SHOW_KIND_PREFERENCE, false));
this.stylerProvider = stylerProvider;
}
@Override
public StyledString getStyledText(Object element) {
StyledString styledString = super.getStyledText(element);
int index = styledString.getString().toLowerCase().indexOf(pattern);
if (index != -1) {
styledString.setStyle(index, pattern.length(), stylerProvider.getBoldStyler());
}
return styledString;
}
@Override
protected int getMaxSeverity(IResource resource, IDocument doc, Range range) throws CoreException, BadLocationException {
int maxSeverity = -1;
for (IMarker marker : resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)) {
int offset = marker.getAttribute(IMarker.CHAR_START, -1);
if (offset != -1) {
maxSeverity = Math.max(maxSeverity, marker.getAttribute(IMarker.SEVERITY, -1));
}
}
return maxSeverity;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
}
private class InternalItemsFilter extends ItemsFilter {
@Override
public boolean matchItem(Object item) {
if (!(item instanceof SymbolInformation)) {
return false;
}
SymbolInformation info = (SymbolInformation) item;
return info.getName().toLowerCase().indexOf(getPattern().toLowerCase()) != -1;
}
@Override
public boolean isConsistentItem(Object item) {
return true;
}
}
private List<@NonNull LanguageServer> languageServers;
private InternalSymbolsLabelProvider labelProvider;
public LSPSymbolInWorkspaceDialog(Shell shell, List<@NonNull LanguageServer> languageServers) {
super(shell);
this.languageServers = languageServers;
this.labelProvider = new InternalSymbolsLabelProvider(new BoldStylerProvider(shell.getFont()));
setMessage(Messages.LSPSymbolInWorkspaceDialog_DialogLabel);
setTitle(Messages.LSPSymbolInWorkspaceDialog_DialogTitle);
setListLabelProvider(labelProvider);
}
@Override
protected ItemsFilter createFilter() {
InternalItemsFilter itemsFilter = new InternalItemsFilter();
labelProvider.setPattern(itemsFilter.getPattern());
return itemsFilter;
}
@Override
protected void fillContentProvider(AbstractContentProvider contentProvider, ItemsFilter itemsFilter,
IProgressMonitor monitor) throws CoreException {
if (itemsFilter.getPattern().isEmpty()) {
return;
}
for (LanguageServer server : this.languageServers) {
if (monitor.isCanceled()) {
return;
}
WorkspaceSymbolParams params = new WorkspaceSymbolParams(itemsFilter.getPattern());
CompletableFuture<List<? extends SymbolInformation>> symbols = server.getWorkspaceService().symbol(params);
try {
List<?> items = symbols.get(1, TimeUnit.SECONDS);
if(items != null) {
for (Object item : items) {
if (item != null) {
contentProvider.add(item, itemsFilter);
}
}
}
} catch (ExecutionException | TimeoutException e) {
LanguageServerPlugin.logError(e);
} catch (InterruptedException e) {
LanguageServerPlugin.logError(e);
Thread.currentThread().interrupt();
}
}
}
@Override
public String getElementName(Object item) {
SymbolInformation info = (SymbolInformation) item;
return info.getName();
}
@Override
protected Comparator<SymbolInformation> getItemsComparator() {
return (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName());
}
@Override
protected IStatus validateItem(Object item) {
return Status.OK_STATUS;
}
@Override
protected IDialogSettings getDialogSettings() {
IDialogSettings settings = LanguageServerPlugin.getDefault().getDialogSettings().getSection(DIALOG_SETTINGS);
if (settings == null) {
settings = LanguageServerPlugin.getDefault().getDialogSettings().addNewSection(DIALOG_SETTINGS);
}
return settings;
}
@Override
protected Control createExtendedContentArea(Composite parent) {
return null;
}
}