Skip to content

Commit a02fd57

Browse files
author
Keen Yee Liau
committed
fix: Produce diagnostics only after user stops typing
This commit creates a timer to keep track of the last change made by the user, and sends the diagnostics only after user stops typing. Currently, it triggers for every change, and slows down the entire operation. A default delay of 200ms is consistent with TypeScript. PR closes #432
1 parent fe9cdfa commit a02fd57

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

server/src/session.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const EMPTY_RANGE = lsp.Range.create(0, 0, 0, 0);
3838
export class Session {
3939
private readonly connection: lsp.IConnection;
4040
private readonly projectService: ProjectService;
41+
private diagnosticsTimeout: NodeJS.Timeout|null = null;
4142

4243
constructor(options: SessionOptions) {
4344
// Create a connection for the server. The connection uses Node's IPC as a transport.
@@ -91,16 +92,38 @@ export class Session {
9192
case ts.server.ProjectsUpdatedInBackgroundEvent:
9293
// ProjectsUpdatedInBackgroundEvent is sent whenever diagnostics are
9394
// requested via project.refreshDiagnostics()
94-
this.refreshDiagnostics(event.data.openFiles);
95+
this.triggerDiagnostics(event.data.openFiles);
9596
break;
9697
}
9798
}
9899

99100
/**
100-
* Retrieve Angular diagnostics for the specified `openFiles`.
101+
* Retrieve Angular diagnostics for the specified `openFiles` after a specific
102+
* `delay`, or renew the request if there's already a pending one.
101103
* @param openFiles
104+
* @param delay time to wait before sending request (milliseconds)
102105
*/
103-
private refreshDiagnostics(openFiles: string[]) {
106+
private triggerDiagnostics(openFiles: string[], delay: number = 200) {
107+
// Do not immediately send a diagnostics request. Send only after user has
108+
// stopped typing after the specified delay.
109+
if (this.diagnosticsTimeout) {
110+
// If there's an existing timeout, cancel it
111+
clearTimeout(this.diagnosticsTimeout);
112+
}
113+
// Set a new timeout
114+
this.diagnosticsTimeout = setTimeout(() => {
115+
this.diagnosticsTimeout = null; // clear the timeout
116+
this.sendPendingDiagnostics(openFiles);
117+
// Default delay is 200ms, consistent with TypeScript. See
118+
// https://github.com/microsoft/vscode/blob/7b944a16f52843b44cede123dd43ae36c0405dfd/extensions/typescript-language-features/src/features/bufferSyncSupport.ts#L493)
119+
}, delay);
120+
}
121+
122+
/**
123+
* Execute diagnostics request for each of the specified `openFiles`.
124+
* @param openFiles
125+
*/
126+
private sendPendingDiagnostics(openFiles: string[]) {
104127
for (const fileName of openFiles) {
105128
const scriptInfo = this.projectService.getScriptInfo(fileName);
106129
if (!scriptInfo) {

0 commit comments

Comments
 (0)