Skip to content

Commit 3fb347a

Browse files
authored
Merge pull request #80 from hildjj/fix-77
Make debouce time configurable. Fixes #77.
2 parents e3b8943 + 28ec7ee commit 3fb347a

File tree

5 files changed

+62
-43
lines changed

5 files changed

+62
-43
lines changed

client/preview.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { fileURLToPath } from "url";
1717
import fromMem from "@peggyjs/from-mem";
1818

1919
const PEGGY_INPUT_SCHEME = "peggyjsin";
20+
const ID = "peggyLanguageServer";
2021

2122
interface GrammarConfig {
2223
name: string;
@@ -226,10 +227,18 @@ export function activate(context: ExtensionContext): void {
226227
}
227228
});
228229

230+
const configChanged = workspace.onDidChangeConfiguration(e => {
231+
if (e.affectsConfiguration(ID)) {
232+
debounceExecution.wait = workspace.getConfiguration(ID).get("debounceMS");
233+
}
234+
});
235+
debounceExecution.wait = workspace.getConfiguration(ID).get("debounceMS");
236+
229237
context.subscriptions.push(
230-
visibleChanged,
238+
configChanged,
231239
documents_changed,
232240
peggy_output,
241+
visibleChanged,
233242
commands.registerTextEditorCommand("editor.peggyLive", async editor => {
234243
if (editor.document.languageId !== "peggy") {
235244
console.error(`Invalid document: ${editor.document.uri.toString()}`);

common/debounce.ts

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,28 @@
11
export type AnyFunction = (...args: any[]) => any;
22
export type AnyAsyncFunction = (...args: any[]) => Promise<any>;
33

4+
export type Debounced<T extends AnyAsyncFunction>
5+
= (...args: Parameters<T>) => ReturnType<T>;
6+
7+
export interface Wait {
8+
wait: number;
9+
}
10+
11+
export type DebouncedWait<T extends AnyAsyncFunction> = Debounced<T> & Wait;
12+
413
/**
514
* Creates a debounced function that delays fn after wait milliseconds have elapsed
615
* since the last time the debounced function was invoked.
716
*/
8-
export function debounce<T extends AnyFunction>(
9-
fn: T,
10-
wait: number
11-
): (...args: Parameters<T>) => void {
12-
let timeout: NodeJS.Timeout = undefined;
13-
14-
return (...args: Parameters<T>): void => {
15-
if (timeout) {
16-
clearTimeout(timeout);
17-
}
18-
timeout = setTimeout(() => {
19-
timeout = undefined;
20-
fn(...args);
21-
}, wait);
22-
};
23-
}
24-
2517
export function debouncePromise<T extends AnyAsyncFunction>(
2618
fn: T,
2719
wait: number
28-
): (...args: Parameters<T>) => ReturnType<T> {
20+
): DebouncedWait<T> {
2921
let timeout: NodeJS.Timeout = undefined;
3022
let resolvers: PromiseWithResolvers<Awaited<ReturnType<T>>> | undefined
3123
= undefined;
3224

33-
return (...args: Parameters<T>): ReturnType<T> => {
25+
function wrapper(...args: Parameters<T>): ReturnType<T> {
3426
if (timeout) {
3527
clearTimeout(timeout);
3628
}
@@ -44,10 +36,12 @@ export function debouncePromise<T extends AnyAsyncFunction>(
4436
} catch (e) {
4537
r.reject(e);
4638
}
47-
}, wait);
39+
}, wrapper.wait);
4840
if (!resolvers) {
4941
resolvers = Promise.withResolvers<Awaited<ReturnType<T>>>();
5042
}
5143
return resolvers.promise as ReturnType<T>;
52-
};
44+
}
45+
wrapper.wait = wait;
46+
return wrapper;
5347
}

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
"description": "Mark all diagnostics, even merely informative ones",
3939
"type": "boolean",
4040
"default": true
41+
},
42+
"peggyLanguageServer.debounceMS": {
43+
"description": "Time, in milliseconds, to debounce typing",
44+
"type": "integer",
45+
"default": 200
4146
}
4247
}
4348
},
@@ -155,7 +160,7 @@
155160
},
156161
"scripts": {
157162
"lint": "eslint .",
158-
"clean": "rimraf ./out ./dist",
163+
"clean": "rimraf ./out ./dist ./coverage",
159164
"vscode:prepublish": "pnpm run clean && pnpm run compile:production",
160165
"compile": "pnpm run check-types && pnpm run lint && node esbuild.js",
161166
"compile:production": "pnpm run check-types && pnpm run lint && node esbuild.js --production",

server/server.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
import { Position, TextDocument } from "vscode-languageserver-textdocument";
2525
import type { SourceNode } from "source-map-generator";
2626
import { WatchMap } from "./watchMap";
27-
import { debounce } from "../common/debounce";
27+
import { debouncePromise } from "../common/debounce";
2828

2929
function getSession(
3030
ast: peggy.ast.Grammar,
@@ -36,6 +36,7 @@ function getSession(
3636
ast.code = session as unknown as SourceNode;
3737
}
3838

39+
const ID = "peggyLanguageServer";
3940
const AST = new WatchMap<string, any>();
4041
const WORD_RE = /[^\s{}[\]()`~!@#%^&*+\-=|\\;:'",./<>?]+/g;
4142
const PASSES: peggy.compiler.Stages = {
@@ -60,6 +61,19 @@ const documents = new TextDocuments(TextDocument);
6061
// for open, change and close text document events
6162
documents.listen(connection);
6263

64+
interface PeggySettings {
65+
consoleInfo: boolean;
66+
markInfo: boolean;
67+
debounceMS: number;
68+
}
69+
70+
const defaultSettings: PeggySettings = {
71+
consoleInfo: false,
72+
markInfo: true,
73+
debounceMS: 200,
74+
};
75+
let globalSettings: PeggySettings = defaultSettings;
76+
6377
// After the server has started the client sends an initilize request. The
6478
// server receives in the passed params the rootPath of the workspace plus the
6579
// client capabilites.
@@ -77,16 +91,9 @@ connection.onInitialize((): InitializeResult => ({
7791
},
7892
}));
7993

80-
interface PeggySettings {
81-
consoleInfo: boolean;
82-
markInfo: boolean;
83-
}
84-
85-
const defaultSettings: PeggySettings = {
86-
consoleInfo: false,
87-
markInfo: true,
88-
};
89-
let globalSettings: PeggySettings = defaultSettings;
94+
connection.onInitialized(async () => {
95+
globalSettings = await connection.workspace.getConfiguration(ID);
96+
});
9097

9198
function peggyLoc_to_vscodeRange(loc: peggy.LocationRange): Range {
9299
if (!loc) {
@@ -143,7 +150,7 @@ function addProblemDiagnostics(
143150
}
144151
}
145152

146-
const validateTextDocument = debounce((doc: TextDocument): void => {
153+
async function validate(doc: TextDocument): Promise<void> {
147154
AST.delete(doc.uri); // Cancel any pending and start over.
148155

149156
const diagnostics: Diagnostic[] = [];
@@ -185,13 +192,17 @@ const validateTextDocument = debounce((doc: TextDocument): void => {
185192
}
186193

187194
// Send the computed diagnostics to VS Code.
188-
connection.sendDiagnostics({ uri: doc.uri, diagnostics });
189-
}, 150);
195+
await connection.sendDiagnostics({ uri: doc.uri, diagnostics });
196+
}
190197

191-
connection.onDidChangeConfiguration(change => {
192-
if (change.settings) {
193-
globalSettings = change.settings.peggyLanguageServer as PeggySettings;
194-
}
198+
const validateTextDocument = debouncePromise(
199+
validate,
200+
globalSettings.debounceMS
201+
);
202+
203+
connection.onDidChangeConfiguration(async () => {
204+
globalSettings = await connection.workspace.getConfiguration(ID);
205+
validateTextDocument.wait = globalSettings.debounceMS;
195206

196207
// Revalidate all open text documents
197208
documents.all().forEach(validateTextDocument);

test/extension.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as assert from "assert";
1+
import * as assert from "node:assert";
22
import * as vscode from "vscode";
33
import { activate, getDocUri, sleep } from "./helper.js";
44

@@ -12,7 +12,6 @@ suite("Extension Test Suite", () => {
1212
const docUri = getDocUri("bad.peggy");
1313
const editor = await activate(docUri);
1414
const actualDiagnostics = vscode.languages.getDiagnostics(docUri);
15-
console.error({ actualDiagnostics });
1615
assert.ok(actualDiagnostics);
1716
assert.ok(Array.isArray(actualDiagnostics));
1817
assert.equal(actualDiagnostics.length, 3);
@@ -52,6 +51,7 @@ suite("Extension Test Suite", () => {
5251
});
5352
await vscode.commands.executeCommand("editor.peggyLive");
5453

54+
// Still needed: check results for correctness.
5555
await sleep(1000);
5656
});
5757
});

0 commit comments

Comments
 (0)