Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc-Andre Laperle2017-09-24 01:44:05 +0000
committerMarc-André Laperle2017-09-26 18:07:03 +0000
commit9dbf2af399f944a081af7960de8bb3ba71b134b9 (patch)
tree91a88c9d8968b47afbaa37650a62fecb788c5a5f /lsp4e-cpp/org.eclipse.lsp4e.cpp.language
parent2fe856426c8bffeb986a1ea11071b0e3735d48fa (diff)
downloadorg.eclipse.cdt-9dbf2af399f944a081af7960de8bb3ba71b134b9.tar.gz
org.eclipse.cdt-9dbf2af399f944a081af7960de8bb3ba71b134b9.tar.xz
org.eclipse.cdt-9dbf2af399f944a081af7960de8bb3ba71b134b9.zip
lsp4e-cpp: Generate LSP FileEvents from ResourceChangeEvents
FileEvents are useful for indexing and lsp4e (so far) does not send them. It is not clear whether or not this will be implemented in lsp4e. In the mean time, lsp4e-cpp can have its own mechanism to generate the events. Change-Id: I09aac4fda7755260f47b73fd683ca6d2ad317f81 Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Diffstat (limited to 'lsp4e-cpp/org.eclipse.lsp4e.cpp.language')
-rw-r--r--lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPLanguageServer.java44
-rw-r--r--lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPResourceChangeListener.java118
2 files changed, 162 insertions, 0 deletions
diff --git a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPLanguageServer.java b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPLanguageServer.java
index 3bfaec637ae..24435caa24b 100644
--- a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPLanguageServer.java
+++ b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPLanguageServer.java
@@ -12,10 +12,15 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Platform;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
@@ -25,6 +30,8 @@ public class CPPLanguageServer extends ProcessStreamConnectionProvider {
private static final String CLANG_LANGUAGE_SERVER = "clangd"; //$NON-NLS-1$
+ private IResourceChangeListener fResourceListener;
+
public CPPLanguageServer() {
List<String> commands = new ArrayList<>();
File clangServerLocation = getClangServerLocation();
@@ -38,6 +45,43 @@ public class CPPLanguageServer extends ProcessStreamConnectionProvider {
}
@Override
+ public void stop() {
+ super.stop();
+ if (fResourceListener != null) {
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(fResourceListener);
+ fResourceListener = null;
+ }
+ }
+
+ @Override
+ public Object getInitializationOptions(URI rootPath) {
+ installResourceChangeListener(rootPath);
+ return super.getInitializationOptions(rootPath);
+ }
+
+ private void installResourceChangeListener(URI rootPath) {
+ if (rootPath == null || fResourceListener != null) {
+ return;
+ }
+
+ IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(rootPath);
+ if (containers.length == 0) {
+ return;
+ }
+
+ for (IContainer c : containers) {
+ if (!(c instanceof IProject)) {
+ continue;
+ }
+ IProject project = (IProject) c;
+ fResourceListener = new CPPResourceChangeListener(project);
+ project.getWorkspace().addResourceChangeListener(fResourceListener);
+
+ break;
+ }
+ }
+
+ @Override
public String toString() {
return "C/C++ Language Server: " + super.toString(); //$NON-NLS-1$
}
diff --git a/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPResourceChangeListener.java b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPResourceChangeListener.java
new file mode 100644
index 00000000000..9d3d23f4d4d
--- /dev/null
+++ b/lsp4e-cpp/org.eclipse.lsp4e.cpp.language/src/org/eclipse/lsp4e/cpp/language/CPPResourceChangeListener.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Ericsson and others.
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.lsp4e.cpp.language;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.lsp4e.LanguageServersRegistry;
+import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
+import org.eclipse.lsp4e.LanguageServiceAccessor;
+import org.eclipse.lsp4e.ProjectSpecificLanguageServerWrapper;
+import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
+import org.eclipse.lsp4j.FileChangeType;
+import org.eclipse.lsp4j.FileEvent;
+
+/**
+ * A resource listener used to generate FileEvents, as part of the LSP. This
+ * only listens to Added, Changed, Removed event on a specific project that as a
+ * C/C++ language server started.
+ */
+@SuppressWarnings("restriction")
+final class CPPResourceChangeListener implements IResourceChangeListener {
+ private final IProject fProject;
+
+ CPPResourceChangeListener(IProject project) {
+ fProject = project;
+ }
+
+ @Override
+ public void resourceChanged(IResourceChangeEvent event) {
+ LanguageServerDefinition definition = LanguageServersRegistry.getInstance().getDefinition(CPPLanguageServer.ID);
+ ProjectSpecificLanguageServerWrapper wrapper = getLanguageSeverWrapper(definition);
+ if (event.getType() != IResourceChangeEvent.POST_CHANGE || !isRelevantDelta(event.getDelta())
+ || wrapper == null) {
+ return;
+ }
+
+ sendFileEvents(wrapper, createFileEventsFromResourceEvent(event));
+ }
+
+ private static void sendFileEvents(ProjectSpecificLanguageServerWrapper wrapper, List<FileEvent> fileEvents) {
+ if (!fileEvents.isEmpty()) {
+ DidChangeWatchedFilesParams params = new DidChangeWatchedFilesParams(fileEvents);
+ wrapper.getServer().getWorkspaceService().didChangeWatchedFiles(params);
+ }
+ }
+
+ private static List<FileEvent> createFileEventsFromResourceEvent(IResourceChangeEvent event) {
+ List<FileEvent> fileEvents = new ArrayList<>();
+ try {
+ event.getDelta().accept((delta) -> {
+ if (delta.getResource() instanceof IFile && isRelevantDelta(delta)) {
+ FileEvent fileEvent = createFileEventFromDelta(delta);
+ if (fileEvent != null) {
+ fileEvents.add(fileEvent);
+ }
+ }
+ return true;
+ }, false);
+ } catch (CoreException e) {
+ // Do nothing
+ }
+ return fileEvents;
+ }
+
+ private ProjectSpecificLanguageServerWrapper getLanguageSeverWrapper(LanguageServerDefinition definition) {
+ try {
+ return LanguageServiceAccessor.getLSWrapperForConnection(fProject, definition, false);
+ } catch (IOException e) {
+ // Do nothing
+ return null;
+ }
+ }
+
+ private static boolean isRelevantDelta(IResourceDelta delta) {
+ int kind = delta.getKind();
+ int flags = delta.getFlags();
+ if (delta.getResource() instanceof IFile && kind == IResourceDelta.CHANGED) {
+ return (flags & IResourceDelta.CONTENT) != 0;
+ }
+
+ return kind == IResourceDelta.ADDED || kind == IResourceDelta.CHANGED || kind == IResourceDelta.REMOVED;
+ }
+
+ private static FileEvent createFileEventFromDelta(IResourceDelta delta) {
+ URI locationURI = delta.getResource().getLocationURI();
+ if (locationURI == null) {
+ return null;
+ }
+
+ FileChangeType changeType = null;
+ if (delta.getKind() == IResourceDelta.ADDED) {
+ changeType = FileChangeType.Created;
+ } else if (delta.getKind() == IResourceDelta.CHANGED) {
+ changeType = FileChangeType.Changed;
+ } else if (delta.getKind() == IResourceDelta.REMOVED) {
+ changeType = FileChangeType.Deleted;
+ } else {
+ throw new IllegalStateException("Unsupported resource delta kind: " + delta.getKind()); //$NON-NLS-1$
+ }
+
+ return new FileEvent(locationURI.toString(), changeType);
+ }
+} \ No newline at end of file

Back to the top