Skip to content

Commit e30b235

Browse files
authored
Add logging for TS extension file watcher creation (microsoft#185813)
Add logging for extension file watcher creation
1 parent 31478ce commit e30b235

File tree

4 files changed

+46
-17
lines changed

4 files changed

+46
-17
lines changed

extensions/typescript-language-features/src/extension.browser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<Api> {
7878
logDirectoryProvider: noopLogDirectoryProvider,
7979
cancellerFactory: noopRequestCancellerFactory,
8080
versionProvider,
81-
processFactory: new WorkerServerProcessFactory(context.extensionUri),
81+
processFactory: new WorkerServerProcessFactory(context.extensionUri, logger),
8282
activeJsTsEditorTracker,
8383
serviceConfigurationProvider: new BrowserServiceConfigurationProvider(),
8484
experimentTelemetryReporter,

extensions/typescript-language-features/src/tsServer/fileWatchingManager.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as vscode from 'vscode';
77
import { Utils } from 'vscode-uri';
88
import { Schemes } from '../configuration/schemes';
9+
import { Logger } from '../logging/logger';
910
import { disposeAll, IDisposable } from '../utils/dispose';
1011
import { ResourceMap } from '../utils/resourceMap';
1112

@@ -18,19 +19,27 @@ type DirWatcherEntry = {
1819
export class FileWatcherManager {
1920

2021
private readonly _fileWatchers = new Map<number, {
22+
readonly uri: vscode.Uri;
2123
readonly watcher: vscode.FileSystemWatcher;
2224
readonly dirWatchers: DirWatcherEntry[];
2325
}>();
2426

2527
private readonly _dirWatchers = new ResourceMap<{
28+
readonly uri: vscode.Uri;
2629
readonly watcher: vscode.FileSystemWatcher;
2730
refCount: number;
2831
}>(uri => uri.toString(), { onCaseInsensitiveFileSystem: false });
2932

33+
constructor(
34+
private readonly logger: Logger,
35+
) { }
36+
3037
create(id: number, uri: vscode.Uri, watchParentDirs: boolean, isRecursive: boolean, listeners: { create?: (uri: vscode.Uri) => void; change?: (uri: vscode.Uri) => void; delete?: (uri: vscode.Uri) => void }): void {
38+
this.logger.trace(`Creating file watcher for ${uri.toString()}`);
39+
3140
const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(uri, isRecursive ? '**' : '*'), !listeners.create, !listeners.change, !listeners.delete);
3241
const parentDirWatchers: DirWatcherEntry[] = [];
33-
this._fileWatchers.set(id, { watcher, dirWatchers: parentDirWatchers });
42+
this._fileWatchers.set(id, { uri, watcher, dirWatchers: parentDirWatchers });
3443

3544
if (listeners.create) { watcher.onDidCreate(listeners.create); }
3645
if (listeners.change) { watcher.onDidChange(listeners.change); }
@@ -43,9 +52,10 @@ export class FileWatcherManager {
4352

4453
let parentDirWatcher = this._dirWatchers.get(dirUri);
4554
if (!parentDirWatcher) {
55+
this.logger.trace(`Creating parent dir watcher for ${dirUri.toString()}`);
4656
const glob = new vscode.RelativePattern(Utils.dirname(dirUri), Utils.basename(dirUri));
4757
const parentWatcher = vscode.workspace.createFileSystemWatcher(glob, !listeners.create, true, !listeners.delete);
48-
parentDirWatcher = { refCount: 0, watcher: parentWatcher };
58+
parentDirWatcher = { uri: dirUri, refCount: 0, watcher: parentWatcher };
4959
this._dirWatchers.set(dirUri, parentDirWatcher);
5060
}
5161
parentDirWatcher.refCount++;
@@ -75,15 +85,19 @@ export class FileWatcherManager {
7585
}
7686
}
7787

88+
7889
delete(id: number): void {
7990
const entry = this._fileWatchers.get(id);
8091
if (entry) {
92+
this.logger.trace(`Deleting file watcher for ${entry.uri}`);
93+
8194
for (const dirWatcher of entry.dirWatchers) {
8295
disposeAll(dirWatcher.listeners);
8396

8497
const dirWatcherEntry = this._dirWatchers.get(dirWatcher.uri);
8598
if (dirWatcherEntry) {
8699
if (--dirWatcherEntry.refCount <= 0) {
100+
this.logger.trace(`Deleting parent dir ${dirWatcherEntry.uri}`);
87101
dirWatcherEntry.watcher.dispose();
88102
this._dirWatchers.delete(dirWatcher.uri);
89103
}

extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ServiceConnection } from '@vscode/sync-api-common/browser';
77
import { ApiService, Requests } from '@vscode/sync-api-service';
88
import * as vscode from 'vscode';
99
import { TypeScriptServiceConfiguration } from '../configuration/configuration';
10+
import { Logger } from '../logging/logger';
1011
import { FileWatcherManager } from './fileWatchingManager';
1112
import type * as Proto from './protocol/protocol';
1213
import { TsServerLog, TsServerProcess, TsServerProcessFactory, TsServerProcessKind } from './server';
@@ -30,6 +31,7 @@ type BrowserWatchEvent = {
3031
export class WorkerServerProcessFactory implements TsServerProcessFactory {
3132
constructor(
3233
private readonly _extensionUri: vscode.Uri,
34+
private readonly _logger: Logger,
3335
) { }
3436

3537
public fork(
@@ -47,7 +49,7 @@ export class WorkerServerProcessFactory implements TsServerProcessFactory {
4749
// Explicitly give TS Server its path so it can
4850
// load local resources
4951
'--executingFilePath', tsServerPath,
50-
], tsServerLog);
52+
], tsServerLog, this._logger);
5153
}
5254
}
5355

@@ -60,7 +62,7 @@ class WorkerServerProcess implements TsServerProcess {
6062
private readonly _onDataHandlers = new Set<(data: Proto.Response) => void>();
6163
private readonly _onErrorHandlers = new Set<(err: Error) => void>();
6264
private readonly _onExitHandlers = new Set<(code: number | null, signal: string | null) => void>();
63-
private readonly watches = new FileWatcherManager();
65+
private readonly _watches: FileWatcherManager;
6466

6567
private readonly worker: Worker;
6668

@@ -77,9 +79,12 @@ class WorkerServerProcess implements TsServerProcess {
7779
extensionUri: vscode.Uri,
7880
args: readonly string[],
7981
private readonly tsServerLog: TsServerLog | undefined,
82+
logger: Logger,
8083
) {
8184
this.worker = new Worker(tsServerPath, { name: `TS ${kind} server #${this.id}` });
8285

86+
this._watches = new FileWatcherManager(logger);
87+
8388
const tsserverChannel = new MessageChannel();
8489
const watcherChannel = new MessageChannel();
8590
const syncChannel = new MessageChannel();
@@ -100,12 +105,12 @@ class WorkerServerProcess implements TsServerProcess {
100105
this.watcher.onmessage = (event: MessageEvent<BrowserWatchEvent>) => {
101106
switch (event.data.type) {
102107
case 'dispose': {
103-
this.watches.delete(event.data.id);
108+
this._watches.delete(event.data.id);
104109
break;
105110
}
106111
case 'watchDirectory':
107112
case 'watchFile': {
108-
this.watches.create(event.data.id, vscode.Uri.from(event.data.uri), /*watchParentDirs*/ true, !!event.data.recursive, {
113+
this._watches.create(event.data.id, vscode.Uri.from(event.data.uri), /*watchParentDirs*/ true, !!event.data.recursive, {
109114
change: uri => this.watcher.postMessage({ type: 'watch', event: 'change', uri }),
110115
create: uri => this.watcher.postMessage({ type: 'watch', event: 'create', uri }),
111116
delete: uri => this.watcher.postMessage({ type: 'watch', event: 'delete', uri }),

extensions/typescript-language-features/web/webServer.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,34 @@ function fromResource(extensionUri: URI, uri: URI) {
4646
}
4747
return `/${uri.scheme}/${uri.authority}${uri.path}`;
4848
}
49+
4950
function updateWatch(event: 'create' | 'change' | 'delete', uri: URI, extensionUri: URI) {
50-
const kind = event === 'create' ? ts.FileWatcherEventKind.Created
51-
: event === 'change' ? ts.FileWatcherEventKind.Changed
52-
: event === 'delete' ? ts.FileWatcherEventKind.Deleted
53-
: ts.FileWatcherEventKind.Changed;
51+
const kind = toTsWatcherKind(event);
5452
const path = fromResource(extensionUri, uri);
55-
if (watchFiles.has(path)) {
56-
watchFiles.get(path)!.callback(path, kind);
53+
54+
const fileWatcher = watchFiles.get(path);
55+
if (fileWatcher) {
56+
fileWatcher.callback(path, kind);
5757
return;
5858
}
59-
let found = false;
59+
6060
for (const watch of Array.from(watchDirectories.keys()).filter(dir => path.startsWith(dir))) {
6161
watchDirectories.get(watch)!.callback(path);
62-
found = true;
62+
return;
6363
}
64-
if (!found) {
65-
console.error(`no watcher found for ${path}`);
64+
65+
console.error(`no watcher found for ${path}`);
66+
}
67+
68+
function toTsWatcherKind(event: 'create' | 'change' | 'delete') {
69+
if (event === 'create') {
70+
return ts.FileWatcherEventKind.Created;
71+
} else if (event === 'change') {
72+
return ts.FileWatcherEventKind.Changed;
73+
} else if (event === 'delete') {
74+
return ts.FileWatcherEventKind.Deleted;
6675
}
76+
throw new Error(`Unknown event: ${event}`);
6777
}
6878

6979
type ServerHostWithImport = ts.server.ServerHost & { importPlugin(root: string, moduleName: string): Promise<ts.server.ModuleImportResult> };

0 commit comments

Comments
 (0)