-
Notifications
You must be signed in to change notification settings - Fork 317
/
fileSystemWatcher.ts
124 lines (108 loc) · 4.46 KB
/
fileSystemWatcher.ts
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
119
120
121
122
123
124
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import {
workspace as Workspace, Disposable, FileSystemWatcher as VFileSystemWatcher
} from 'vscode';
import {
ClientCapabilities, DidChangeWatchedFilesNotification, DidChangeWatchedFilesRegistrationOptions, DocumentSelector, FileChangeType, FileEvent, RegistrationType,
ServerCapabilities, WatchKind
} from 'vscode-languageserver-protocol';
import {
FeatureClient, DynamicFeature, ensure, RegistrationData, FeatureState
} from './features';
export class FileSystemWatcherFeature implements DynamicFeature<DidChangeWatchedFilesRegistrationOptions> {
private readonly _client: FeatureClient<object>;
private readonly _notifyFileEvent: (event: FileEvent) => void;
private readonly _watchers: Map<string, Disposable[]>;
constructor(client: FeatureClient<object>, notifyFileEvent: (event: FileEvent) => void) {
this._client = client;
this._notifyFileEvent = notifyFileEvent;
this._watchers = new Map<string, Disposable[]>();
}
getState(): FeatureState {
return { kind: 'workspace', id: this.registrationType.method, registrations: this._watchers.size > 0 };
}
public get registrationType(): RegistrationType<DidChangeWatchedFilesRegistrationOptions> {
return DidChangeWatchedFilesNotification.type;
}
public fillClientCapabilities(capabilities: ClientCapabilities): void {
ensure(ensure(capabilities, 'workspace')!, 'didChangeWatchedFiles')!.dynamicRegistration = true;
ensure(ensure(capabilities, 'workspace')!, 'didChangeWatchedFiles')!.relativePatternSupport = true;
}
public initialize(_capabilities: ServerCapabilities, _documentSelector: DocumentSelector): void {
}
public register(data: RegistrationData<DidChangeWatchedFilesRegistrationOptions>): void {
if (!Array.isArray(data.registerOptions.watchers)) {
return;
}
const disposables: Disposable[] = [];
for (const watcher of data.registerOptions.watchers) {
const globPattern = this._client.protocol2CodeConverter.asGlobPattern(watcher.globPattern);
if (globPattern === undefined) {
continue;
}
let watchCreate: boolean = true, watchChange: boolean = true, watchDelete: boolean = true;
if (watcher.kind !== undefined && watcher.kind !== null) {
watchCreate = (watcher.kind & WatchKind.Create) !== 0;
watchChange = (watcher.kind & WatchKind.Change) !== 0;
watchDelete = (watcher.kind & WatchKind.Delete) !== 0;
}
const fileSystemWatcher: VFileSystemWatcher = Workspace.createFileSystemWatcher(globPattern, !watchCreate, !watchChange, !watchDelete);
this.hookListeners(fileSystemWatcher, watchCreate, watchChange, watchDelete, disposables);
disposables.push(fileSystemWatcher);
}
this._watchers.set(data.id, disposables);
}
public registerRaw(id: string, fileSystemWatchers: VFileSystemWatcher[]) {
const disposables: Disposable[] = [];
for (const fileSystemWatcher of fileSystemWatchers) {
this.hookListeners(fileSystemWatcher, true, true, true, disposables);
}
this._watchers.set(id, disposables);
}
private hookListeners(fileSystemWatcher: VFileSystemWatcher, watchCreate: boolean, watchChange: boolean, watchDelete: boolean, listeners?: Disposable[]): void {
if (watchCreate) {
fileSystemWatcher.onDidCreate((resource) => this._notifyFileEvent(
{
uri: this._client.code2ProtocolConverter.asUri(resource),
type: FileChangeType.Created
}
), null, listeners);
}
if (watchChange) {
fileSystemWatcher.onDidChange((resource) => this._notifyFileEvent(
{
uri: this._client.code2ProtocolConverter.asUri(resource),
type: FileChangeType.Changed
}
), null, listeners);
}
if (watchDelete) {
fileSystemWatcher.onDidDelete((resource) => this._notifyFileEvent(
{
uri: this._client.code2ProtocolConverter.asUri(resource),
type: FileChangeType.Deleted
}
), null, listeners);
}
}
public unregister(id: string): void {
const disposables = this._watchers.get(id);
if (disposables) {
this._watchers.delete(id);
for (const disposable of disposables) {
disposable.dispose();
}
}
}
public clear(): void {
this._watchers.forEach((disposables) => {
for (const disposable of disposables) {
disposable.dispose();
}
});
this._watchers.clear();
}
}