Skip to content

Commit 649f000

Browse files
committed
Adopt to new file watcher
1 parent 084fc08 commit 649f000

3 files changed

Lines changed: 81 additions & 18 deletions

File tree

src/vs/platform/configuration/node/configuration.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,8 @@ export class NodeBasedUserConfiguration extends Disposable {
4949
reload(): Promise<ConfigurationModel> {
5050
return this.initialize().then(() => new Promise<ConfigurationModel>(c => this.userConfigModelWatcher.reload(userConfigModelParser => c(userConfigModelParser.configurationModel))));
5151
}
52+
53+
getConfigurationModel(): ConfigurationModel {
54+
return this.userConfigModelWatcher.getConfig().configurationModel;
55+
}
5256
}

src/vs/workbench/services/configuration/node/configuration.ts

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event';
99
import * as pfs from 'vs/base/node/pfs';
1010
import * as errors from 'vs/base/common/errors';
1111
import * as collections from 'vs/base/common/collections';
12-
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
12+
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
1313
import { RunOnceScheduler, Delayer } from 'vs/base/common/async';
1414
import { FileChangeType, FileChangesEvent, IContent, IFileService } from 'vs/platform/files/common/files';
1515
import { ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels';
@@ -53,10 +53,19 @@ export class LocalUserConfiguration extends Disposable {
5353

5454
async adopt(fileService: IFileService): Promise<ConfigurationModel | null> {
5555
if (this.userConfiguration instanceof NodeBasedUserConfiguration) {
56+
const oldConfigurationModel = this.userConfiguration.getConfigurationModel();
5657
this.userConfiguration.dispose();
5758
dispose(this.changeDisposable);
59+
60+
let newConfigurationModel = new ConfigurationModel();
5861
this.userConfiguration = this._register(new FileServiceBasedUserConfiguration(this.userConfigurationResource, fileService));
5962
this.changeDisposable = this._register(this.userConfiguration.onDidChangeConfiguration(configurationModel => this._onDidChangeConfiguration.fire(configurationModel)));
63+
newConfigurationModel = await this.userConfiguration.initialize();
64+
65+
const { added, updated, removed } = compare(oldConfigurationModel, newConfigurationModel);
66+
if (added.length > 0 || updated.length > 0 || removed.length > 0) {
67+
return newConfigurationModel;
68+
}
6069
}
6170
return null;
6271
}
@@ -120,6 +129,9 @@ export class FileServiceBasedUserConfiguration extends Disposable {
120129
protected readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
121130
readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event;
122131

132+
private fileWatcherDisposable: IDisposable = Disposable.None;
133+
private directoryWatcherDisposable: IDisposable = Disposable.None;
134+
123135
constructor(
124136
private readonly configurationResource: URI,
125137
private readonly fileService: IFileService
@@ -128,38 +140,80 @@ export class FileServiceBasedUserConfiguration extends Disposable {
128140

129141
this._register(fileService.onFileChanges(e => this.handleFileEvents(e)));
130142
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reload().then(configurationModel => this._onDidChangeConfiguration.fire(configurationModel)), 50));
131-
this._register(this.fileService.watch(this.configurationResource));
143+
this._register(toDisposable(() => {
144+
this.stopWatchingResource();
145+
this.stopWatchingDirectory();
146+
}));
132147
}
133148

134-
initialize(): Promise<ConfigurationModel> {
149+
private watchResource(): void {
150+
this.fileWatcherDisposable = this.fileService.watch(this.configurationResource);
151+
}
152+
153+
private stopWatchingResource(): void {
154+
this.fileWatcherDisposable.dispose();
155+
this.fileWatcherDisposable = Disposable.None;
156+
}
157+
158+
private watchDirectory(): void {
159+
const directory = resources.dirname(this.configurationResource);
160+
this.directoryWatcherDisposable = this.fileService.watch(directory);
161+
}
162+
163+
private stopWatchingDirectory(): void {
164+
this.directoryWatcherDisposable.dispose();
165+
this.directoryWatcherDisposable = Disposable.None;
166+
}
167+
168+
async initialize(): Promise<ConfigurationModel> {
169+
const exists = await this.fileService.exists(this.configurationResource);
170+
this.onResourceExists(exists);
135171
return this.reload();
136172
}
137173

138-
reload(): Promise<ConfigurationModel> {
139-
return this.fileService.resolveContent(this.configurationResource)
140-
.then(content => content.value, () => {
141-
// File not found
142-
return '';
143-
}).then(content => {
144-
const parser = new ConfigurationModelParser(this.configurationResource.toString());
145-
parser.parse(content);
146-
return parser.configurationModel;
147-
});
174+
async reload(): Promise<ConfigurationModel> {
175+
try {
176+
const content = await this.fileService.resolveContent(this.configurationResource);
177+
const parser = new ConfigurationModelParser(this.configurationResource.toString());
178+
parser.parse(content.value);
179+
return parser.configurationModel;
180+
} catch (e) {
181+
return new ConfigurationModel();
182+
}
148183
}
149184

150-
private handleFileEvents(event: FileChangesEvent): void {
185+
private async handleFileEvents(event: FileChangesEvent): Promise<void> {
151186
const events = event.changes;
152187

153188
let affectedByChanges = false;
154-
// Find changes that affect workspace file
155-
for (let i = 0, len = events.length; i < len && !affectedByChanges; i++) {
156-
affectedByChanges = resources.isEqual(this.configurationResource, events[i].resource);
189+
190+
// Find changes that affect the resource
191+
for (const event of events) {
192+
affectedByChanges = resources.isEqual(this.configurationResource, event.resource);
193+
if (affectedByChanges) {
194+
if (event.type === FileChangeType.ADDED) {
195+
this.onResourceExists(true);
196+
} else if (event.type === FileChangeType.DELETED) {
197+
this.onResourceExists(false);
198+
}
199+
break;
200+
}
157201
}
158202

159203
if (affectedByChanges) {
160204
this.reloadConfigurationScheduler.schedule();
161205
}
162206
}
207+
208+
private onResourceExists(exists: boolean): void {
209+
if (exists) {
210+
this.stopWatchingDirectory();
211+
this.watchResource();
212+
} else {
213+
this.stopWatchingResource();
214+
this.watchDirectory();
215+
}
216+
}
163217
}
164218

165219
class CachedUserConfiguration extends Disposable {

src/vs/workbench/services/configuration/node/configurationService.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,12 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
299299
this.fileService = fileService;
300300
const changedWorkspaceFolders: IWorkspaceFolder[] = [];
301301
if (this.localUserConfiguration) {
302-
this.localUserConfiguration.adopt(fileService);
302+
this.localUserConfiguration.adopt(fileService)
303+
.then(changedModel => {
304+
if (changedModel) {
305+
this.onLocalUserConfigurationChanged(changedModel);
306+
}
307+
});
303308
}
304309
Promise.all([this.workspaceConfiguration.adopt(fileService), ...this.cachedFolderConfigs.values()
305310
.map(folderConfiguration => folderConfiguration.adopt(fileService)

0 commit comments

Comments
 (0)