Ensure markers use right LS to compute resolutions
+ Code cleanup and fun with streams
Change-Id: I1cd99ddfe316f3c66244ee4401c1a6221785dfe7
Signed-off-by: Mickael Istria <mistria@redhat.com>
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServersRegistry.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServersRegistry.java
index 67fbfb6..ec1f3a6 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServersRegistry.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServersRegistry.java
@@ -13,8 +13,6 @@
import java.io.IOException;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -199,18 +197,18 @@
connections.add(new ContentTypeToLanguageServerDefinition(contentType, serverDefinition));
}
- public List<ContentTypeToLSPLaunchConfigEntry> getContentTypeToLSPLaunches() {
- return Arrays.asList(this.connections.stream().filter(element -> element instanceof ContentTypeToLSPLaunchConfigEntry).toArray(size -> new ContentTypeToLSPLaunchConfigEntry[size]));
- }
-
public void setAssociations(List<ContentTypeToLSPLaunchConfigEntry> wc) {
- this.connections.removeIf(entry -> entry instanceof ContentTypeToLSPLaunchConfigEntry);
+ this.connections.removeIf(ContentTypeToLSPLaunchConfigEntry.class::isInstance);
this.connections.addAll(wc);
persistContentTypeToLaunchConfigurationMapping();
}
+ public List<ContentTypeToLSPLaunchConfigEntry> getContentTypeToLSPLaunches() {
+ return this.connections.stream().filter(ContentTypeToLSPLaunchConfigEntry.class::isInstance).map(ContentTypeToLSPLaunchConfigEntry.class::cast).collect(Collectors.toList());
+ }
+
public List<ContentTypeToLanguageServerDefinition> getContentTypeToLSPExtensions() {
- return Collections.unmodifiableList(connections);
+ return this.connections.stream().filter(mapping -> mapping.getValue() instanceof ExtensionLanguageServerDefinition).collect(Collectors.toList());
}
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServiceAccessor.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServiceAccessor.java
index 2119db2..c23ec3d 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServiceAccessor.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/LanguageServiceAccessor.java
@@ -190,7 +190,7 @@
if (file.exists()) {
fileUri = LSPEclipseUtils.toUri(file);
try {
- ProjectSpecificLanguageServerWrapper wrapper = getLSWrapper(file, capabilityRequest);
+ ProjectSpecificLanguageServerWrapper wrapper = getLSWrapper(file, capabilityRequest, null);
if (wrapper != null) {
wrapper.connect(file.getLocation(), document);
@Nullable
@@ -209,8 +209,8 @@
return null;
}
- public static LanguageServer getLanguageServer(@NonNull IFile file, Predicate<ServerCapabilities> request) throws Exception {
- ProjectSpecificLanguageServerWrapper wrapper = getLSWrapper(file, request);
+ public static @Nullable LanguageServer getLanguageServer(@NonNull IFile file, Predicate<ServerCapabilities> request) throws IOException {
+ ProjectSpecificLanguageServerWrapper wrapper = getLSWrapper(file, request, null);
if (wrapper != null) {
wrapper.connect(file.getLocation(), null);
return wrapper.getServer();
@@ -218,8 +218,27 @@
return null;
}
- @Nullable private static ProjectSpecificLanguageServerWrapper getLSWrapper(@NonNull IFile file, @Nullable Predicate<ServerCapabilities> request) throws IOException {
+ /**
+ *
+ * @param file
+ * @param request
+ * @param serverId
+ * @return a LanguageServer for the given file, which is defined with provided server ID and conforms to specified requst
+ */
+ public static @Nullable LanguageServer getLanguageServer(@NonNull IFile file, Predicate<ServerCapabilities> request, @NonNull String serverId) throws IOException {
+ ProjectSpecificLanguageServerWrapper wrapper = getLSWrapper(file, request, serverId);
+ if (wrapper != null) {
+ wrapper.connect(file.getLocation(), null);
+ return wrapper.getServer();
+ }
+ return null;
+ }
+
+ @Nullable private static ProjectSpecificLanguageServerWrapper getLSWrapper(@NonNull IFile file, @Nullable Predicate<ServerCapabilities> request, @Nullable String serverId) throws IOException {
IProject project = file.getProject();
+ if (project == null) {
+ return null;
+ }
IContentType[] fileContentTypes = null;
try (InputStream contents = file.getContents()) {
fileContentTypes = Platform.getContentTypeManager().findContentTypesFor(contents, file.getName()); //TODO consider using document as inputstream
@@ -227,14 +246,17 @@
LanguageServerPlugin.logError(e);
return null;
}
- ProjectSpecificLanguageServerWrapper wrapper = getMatchingStartedWrapper(project, fileContentTypes, request);
+ ProjectSpecificLanguageServerWrapper wrapper = getMatchingStartedWrapper(project, fileContentTypes, request, serverId);
if (wrapper != null) {
return wrapper;
}
for (IContentType contentType : fileContentTypes) {
+ if (contentType == null) {
+ continue;
+ }
for (LanguageServerDefinition serverDefinition : LanguageServersRegistry.getInstance().findProviderFor(contentType)) {
- if (serverDefinition != null) {
+ if (serverDefinition != null && (serverId == null || serverDefinition.getId().equals(serverId))) {
wrapper = getLSWrapperForConnection(project, contentType, serverDefinition);
if (request == null
|| wrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
@@ -282,14 +304,14 @@
}
private static ProjectSpecificLanguageServerWrapper getMatchingStartedWrapper(IProject project,
- IContentType[] fileContentTypes, Predicate<ServerCapabilities> request) {
+ IContentType[] fileContentTypes, Predicate<ServerCapabilities> request, @Nullable String serverId) {
for (IContentType contentType : fileContentTypes) {
WrapperEntryKey key = new WrapperEntryKey(project, contentType);
if (!projectServers.containsKey(key)) {
projectServers.put(key, new ArrayList<>());
}
for (ProjectSpecificLanguageServerWrapper aWrapper : projectServers.get(key)) {
- if (aWrapper != null && (request == null
+ if (aWrapper != null && (serverId == null || aWrapper.serverDefinition.getId().equals(serverId)) && (request == null
|| aWrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
|| request.test(aWrapper.getServerCapabilities())
)) {
@@ -319,7 +341,7 @@
continue;
}
if ((request == null
- || wrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
+ || wrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
|| request.test(wrapper.getServerCapabilities()))) {
serverInfos.add(new LSPServerInfo(project, server, wrapper.getServerCapabilities()));
}
@@ -333,4 +355,5 @@
protected static LanguageServerDefinition getInfo(@NonNull StreamConnectionProvider provider) {
return connectionsInfo.get(provider);
}
+
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java
index f0fe661..eb06b14 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/codeactions/LSPCodeActionMarkerResolution.java
@@ -42,7 +42,6 @@
public class LSPCodeActionMarkerResolution implements IMarkerResolutionGenerator2 {
private static final String LSP_REMEDIATION = "lspCodeActions"; //$NON-NLS-1$
- private static final String LS = "languageServer"; //$NON-NLS-1$
private static final IMarkerResolution2 COMPUTING = new IMarkerResolution2() {
@@ -74,11 +73,9 @@
@Override
public IMarkerResolution[] getResolutions(IMarker marker) {
Object att;
- LanguageServer languageServer = null;
try {
checkMarkerResoultion(marker);
att = marker.getAttribute(LSP_REMEDIATION);
- languageServer = (LanguageServer) marker.getAttribute(LS);
} catch (Exception e) {
LanguageServerPlugin.logError(e);
return new IMarkerResolution[0];
@@ -102,27 +99,37 @@
private void checkMarkerResoultion(IMarker marker) throws Exception {
if (marker.getAttribute(LSP_REMEDIATION) != null) {
return;
- } else if (marker.getResource().getType() == IResource.FILE) {
- LanguageServer lsp = LanguageServiceAccessor.getLanguageServer((IFile)marker.getResource(), (capabilities) -> Boolean.TRUE.equals(capabilities.getCodeActionProvider()));
- if (lsp != null) {
- marker.setAttribute(LSP_REMEDIATION, COMPUTING);
- marker.setAttribute(LS, lsp);
- Diagnostic diagnostic = (Diagnostic)marker.getAttribute(LSPDiagnosticsToMarkers.LSP_DIAGNOSTIC);
- CodeActionContext context = new CodeActionContext(Collections.singletonList(diagnostic));
- CodeActionParams params = new CodeActionParams();
- params.setContext(context);
- params.setTextDocument(new TextDocumentIdentifier(LSPEclipseUtils.toUri(marker.getResource()).toString()));
- params.setRange(diagnostic.getRange());
- CompletableFuture<List<? extends Command>> codeAction = lsp.getTextDocumentService().codeAction(params);
- codeAction.thenAccept(actions -> {
- try {
- marker.setAttribute(LSP_REMEDIATION, actions);
- } catch (CoreException e) {
- LanguageServerPlugin.logError(e);
- }
- });
- // wait a bit to avoid showing too much "Computing" without looking like a freeze
- codeAction.get(300, TimeUnit.MILLISECONDS);
+ } else {
+ IResource res = marker.getResource();
+ if (res != null && res.getType() == IResource.FILE) {
+ IFile file = (IFile)res;
+ String languageServerId = marker.getAttribute(LSPDiagnosticsToMarkers.LANGUAGE_SERVER_ID, null);
+ LanguageServer ls = null;
+ if (languageServerId != null) { // try to use same LS as the one that created the marker
+ LanguageServiceAccessor.getLanguageServer(file, (capabilities) -> Boolean.TRUE.equals(capabilities.getCodeActionProvider()), languageServerId);
+ }
+ if (ls == null) { // if it's not there, try any other server
+ ls = LanguageServiceAccessor.getLanguageServer(file, (capabilities) -> Boolean.TRUE.equals(capabilities.getCodeActionProvider()));
+ }
+ if (ls != null) {
+ marker.setAttribute(LSP_REMEDIATION, COMPUTING);
+ Diagnostic diagnostic = (Diagnostic)marker.getAttribute(LSPDiagnosticsToMarkers.LSP_DIAGNOSTIC);
+ CodeActionContext context = new CodeActionContext(Collections.singletonList(diagnostic));
+ CodeActionParams params = new CodeActionParams();
+ params.setContext(context);
+ params.setTextDocument(new TextDocumentIdentifier(LSPEclipseUtils.toUri(marker.getResource()).toString()));
+ params.setRange(diagnostic.getRange());
+ CompletableFuture<List<? extends Command>> codeAction = ls.getTextDocumentService().codeAction(params);
+ codeAction.thenAccept(actions -> {
+ try {
+ marker.setAttribute(LSP_REMEDIATION, actions);
+ } catch (CoreException e) {
+ LanguageServerPlugin.logError(e);
+ }
+ });
+ // wait a bit to avoid showing too much "Computing" without looking like a freeze
+ codeAction.get(300, TimeUnit.MILLISECONDS);
+ }
}
}
}
@@ -132,7 +139,7 @@
try {
checkMarkerResoultion(marker);
Object remediation = marker.getAttribute(LSP_REMEDIATION);
- return remediation == COMPUTING || (remediation instanceof Collection && !((Collection)remediation).isEmpty());
+ return remediation == COMPUTING || (remediation instanceof Collection && !((Collection<?>)remediation).isEmpty());
} catch (Exception ex) {
LanguageServerPlugin.logError(ex);
}
diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java
index c73d282..1aa187a 100644
--- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java
+++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java
@@ -38,7 +38,7 @@
public class LSPDiagnosticsToMarkers implements Consumer<PublishDiagnosticsParams> {
public static final String LSP_DIAGNOSTIC = "lspDiagnostic"; //$NON-NLS-1$
- private static final String LSP_SERVER_ID = "languageServerId"; //$NON-NLS-1$
+ public static final String LANGUAGE_SERVER_ID = "languageServerId"; //$NON-NLS-1$
public static final String LS_DIAGNOSTIC_MARKER_TYPE = "org.eclipse.lsp4e.diagnostic"; //$NON-NLS-1$
private final @NonNull IProject project;
private final @NonNull String languageServerId;
@@ -59,7 +59,7 @@
}
Set<IMarker> remainingMarkers = new HashSet<>(
Arrays.asList(resource.findMarkers(LS_DIAGNOSTIC_MARKER_TYPE, false, IResource.DEPTH_ONE)));
- remainingMarkers.removeIf(marker -> !Objects.equals(marker.getAttribute(LSP_SERVER_ID, ""), languageServerId)); //$NON-NLS-1$
+ remainingMarkers.removeIf(marker -> !Objects.equals(marker.getAttribute(LANGUAGE_SERVER_ID, ""), languageServerId)); //$NON-NLS-1$
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
IMarker associatedMarker = getExistingMarkerFor(resource, diagnostic, remainingMarkers);
if (associatedMarker == null) {
@@ -80,7 +80,7 @@
protected void updateMarker(IResource resource, Diagnostic diagnostic, IMarker marker) {
try {
marker.setAttribute(LSP_DIAGNOSTIC, diagnostic);
- marker.setAttribute(LSP_SERVER_ID, this.languageServerId);
+ marker.setAttribute(LANGUAGE_SERVER_ID, this.languageServerId);
marker.setAttribute(IMarker.MESSAGE, diagnostic.getMessage());
marker.setAttribute(IMarker.SEVERITY, LSPEclipseUtils.toEclipseMarkerSeverity(diagnostic.getSeverity()));
if (resource.getType() != IResource.FILE) {
@@ -125,7 +125,7 @@
&& LSPEclipseUtils.toOffset(diagnostic.getRange().getStart(), document) == startOffset + 1
&& LSPEclipseUtils.toOffset(diagnostic.getRange().getEnd(), document) == endOffset + 1
&& Objects.equals(marker.getAttribute(IMarker.MESSAGE), diagnostic.getMessage())
- && Objects.equals(marker.getAttribute(LSP_SERVER_ID), this.languageServerId)) {
+ && Objects.equals(marker.getAttribute(LANGUAGE_SERVER_ID), this.languageServerId)) {
return marker;
}
} catch (CoreException | BadLocationException e) {