Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 9d3d23f4d4d78fe9fe1f44e691fc24b36162a4ca (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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);
	}
}

Back to the top