Skip to content

Commit f3b9ca2

Browse files
committed
Improve diagnostic performance
1 parent 88525d6 commit f3b9ca2

File tree

2 files changed

+66
-44
lines changed

2 files changed

+66
-44
lines changed

src/DiagnosticCollection.ts

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as vscodeOniguruma from 'vscode-oniguruma';
44
import * as textmateOnigmo from 'vscode-onigmo';
55
import * as PCRE from '@syntropiq/libpcre-ts';
66
import * as onigurumaToES from 'oniguruma-to-es';
7-
import { closeEnoughQuestionMark, DocumentSelector, getPackageJSON, JSONParseStringRelaxed, stringify, wagnerFischer } from "./extension";
7+
import { closeEnoughQuestionMark, DocumentSelector, getPackageJSON, JSONParseStringRelaxed, stringify, tryCatch, wagnerFischer } from "./extension";
88
import { getLastNode, getTrees, queryNode, toRange, trees } from "./TreeSitter";
99
import { ignoreDiagnosticsUnusedRepos } from "./Providers/CodeActionsProvider";
1010
import { unicodeproperties } from "./UNICODE_PROPERTIES";
@@ -125,6 +125,7 @@ const activeDocuments: {
125125
};
126126
} = {};
127127

128+
128129
const DiagnosticCollection = vscode.languages.createDiagnosticCollection("textmate");
129130
export async function initDiagnostics(context: vscode.ExtensionContext) {
130131
// vscode.window.showInformationMessage(JSON.stringify("initDiagnostics"));
@@ -139,19 +140,20 @@ export async function initDiagnostics(context: vscode.ExtensionContext) {
139140
}
140141

141142
context.subscriptions.push(
142-
vscode.workspace.onDidOpenTextDocument((document: vscode.TextDocument) => {
143-
// vscode.window.showInformationMessage(`open\n${JSON.stringify(document)}`);
144-
debouncedDiagnostics(document);
145-
}),
143+
vscode.workspace.onDidOpenTextDocument(debouncedDiagnostics),
146144
vscode.workspace.onDidChangeTextDocument((edits: vscode.TextDocumentChangeEvent) => {
147-
// vscode.window.showInformationMessage(`edit\n${JSON.stringify(edits)}`);
148145
debouncedDiagnostics(edits.document);
149146
}),
150147
vscode.workspace.onDidCloseTextDocument((document: vscode.TextDocument) => {
151-
// vscode.window.showInformationMessage(`close\n${JSON.stringify(document)}`);
152148
delete activeDocuments[document.uri.toString()];
153149
DiagnosticCollection.delete(document.uri);
154-
})
150+
}),
151+
vscode.window.onDidChangeActiveTextEditor((textEditor: vscode.TextEditor | undefined) => {
152+
if (textEditor) {
153+
const document = textEditor.document;
154+
debouncedDiagnostics(document);
155+
}
156+
}),
155157
);
156158
}
157159

@@ -171,7 +173,7 @@ export function debouncedDiagnostics(document: vscode.TextDocument) {
171173
activeDocument.countDown++; // waits longer the more edits there are
172174

173175
// Debounce recently repeated requests
174-
if (activeDocument.timeout == undefined) {
176+
if (activeDocument.timeout === undefined) {
175177

176178
// Wait 50ms and repeatedly execute CallBack
177179
activeDocument.timeout = setInterval(
@@ -180,8 +182,8 @@ export function debouncedDiagnostics(document: vscode.TextDocument) {
180182

181183
if (activeDocument.countDown < 0) {
182184
clearInterval(activeDocument.timeout); // timeout.refresh() doesn't work in VSCode web
183-
await Diagnostics(activeDocument.document);
184185
activeDocument.timeout = undefined;
186+
await Diagnostics(activeDocument.document);
185187
}
186188

187189
activeDocument.countDown -= 2;
@@ -200,29 +202,23 @@ async function Diagnostics(document: vscode.TextDocument) {
200202

201203
const diagnostics: vscode.Diagnostic[] = [];
202204

203-
const results = await Promise.allSettled([
204-
diagnosticsMismatchingRootScopeName(diagnostics, rootNode, document),
205-
diagnosticsTreeSitterJSONErrors(diagnostics, rootNode),
206-
diagnosticsTreeSitterRegexErrors(diagnostics, trees),
207-
diagnosticsRegularExpressionErrors(diagnostics, trees),
208-
diagnosticsBrokenIncludes(diagnostics, rootNode),
209-
diagnosticsUnusedRepos(diagnostics, rootNode),
210-
diagnosticsLinguistCaptures(diagnostics, rootNode),
211-
diagnosticsDeadTextMateCode(diagnostics, rootNode),
205+
await Promise.allSettled([
206+
tryCatch(diagnosticsMismatchingRootScopeName(diagnostics, rootNode, document), "Diagnostics error:", "MismatchingPackageJSONInfo"),
207+
tryCatch(diagnosticsTreeSitterJSONErrors(diagnostics, rootNode), "Diagnostics error:", "TreeSitterJSONErrors"),
208+
tryCatch(diagnosticsTreeSitterRegexErrors(diagnostics, trees), "Diagnostics error:", "TreeSitterRegexErrors"),
209+
tryCatch(diagnosticsRegularExpressionErrors(diagnostics, trees), "Diagnostics error:", "OnigurumaRegexErrors"),
210+
tryCatch(diagnosticsBrokenIncludes(diagnostics, rootNode), "Diagnostics error:", "BrokenIncludes"),
211+
tryCatch(diagnosticsUnusedRepos(diagnostics, rootNode), "Diagnostics error:", "UnusedRepos"),
212+
tryCatch(diagnosticsLinguistCaptures(diagnostics, rootNode), "Diagnostics error:", "LinguistCaptures"),
213+
tryCatch(diagnosticsDeadTextMateCode(diagnostics, rootNode), "Diagnostics error:", "DeadTextMateCode"),
212214
]);
213215

214-
for (const result of results) {
215-
if (result.status == 'rejected') {
216-
console.warn("JSON TextMate: Diagnostics error\n", result.reason);
217-
}
218-
}
219-
220216
DiagnosticCollection.set(document.uri, diagnostics);
221217
// vscode.window.showInformationMessage(`Diagnostics ${(performance.now() - start).toFixed(3)}ms\n${JSON.stringify(diagnostics)}`);
222218
}
223219

224220

225-
async function diagnosticsTreeSitterJSONErrors(diagnostics: vscode.Diagnostic[], rootNode: webTreeSitter.Node) {
221+
function diagnosticsTreeSitterJSONErrors(diagnostics: vscode.Diagnostic[], rootNode: webTreeSitter.Node) {
226222
// vscode.window.showInformationMessage(JSON.stringify("diagnostics JSON"));
227223
// const start = performance.now();
228224
const jsonQuery = `;scm
@@ -270,7 +266,7 @@ async function diagnosticsTreeSitterJSONErrors(diagnostics: vscode.Diagnostic[],
270266
// vscode.window.showInformationMessage(`JSON ${(performance.now() - start).toFixed(3)}ms`);
271267
}
272268

273-
async function diagnosticsTreeSitterRegexErrors(diagnostics: vscode.Diagnostic[], trees: trees) {
269+
function diagnosticsTreeSitterRegexErrors(diagnostics: vscode.Diagnostic[], trees: trees) {
274270
// vscode.window.showInformationMessage(JSON.stringify("diagnostics Regex"));
275271
// const start = performance.now();
276272
const regexTrees = trees.regexTrees;
@@ -660,7 +656,7 @@ async function diagnosticsRegularExpressionErrors(diagnostics: vscode.Diagnostic
660656
// vscode.window.showInformationMessage(`Oniguruma ${(performance.now() - start).toFixed(3)}ms`);
661657
}
662658

663-
async function diagnosticsBrokenIncludes(diagnostics: vscode.Diagnostic[], rootNode: webTreeSitter.Node) {
659+
function diagnosticsBrokenIncludes(diagnostics: vscode.Diagnostic[], rootNode: webTreeSitter.Node) {
664660
// vscode.window.showInformationMessage(JSON.stringify("diagnostics #includes"))
665661
// const start = performance.now();
666662

src/extension.ts

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,13 @@ https://www.npmjs.com/package/json-asty
217217
https://www.npmjs.com/package/json-cst
218218
*/
219219

220-
export async function getPackageJSON(baseUri: vscode.TextDocument | vscode.Uri, ...pathSegments: string[]) {
220+
export async function getPackageJSON(baseUri: vscode.TextDocument | vscode.Uri, ...pathSegments: string[]): Promise<{
221+
packageJSON: IRelaxedExtensionManifest;
222+
packageUri: vscode.Uri;
223+
} | {
224+
packageJSON?: undefined;
225+
packageUri?: undefined;
226+
}> {
221227
if ('isUntitled' in baseUri) {
222228
if (baseUri.isUntitled) {
223229
return {};
@@ -227,28 +233,48 @@ export async function getPackageJSON(baseUri: vscode.TextDocument | vscode.Uri,
227233
const uri = 'uri' in baseUri ? baseUri.uri : baseUri;
228234
const newUri = uri.with({ query: '' }); // 'git file changes' document adds a query property. that then ruins readFile()
229235

230-
const packageUri1 = vscode.Uri.joinPath(newUri, ...pathSegments, '..', '..', 'package.json');
231-
const packageUri2 = vscode.Uri.joinPath(newUri, ...pathSegments, '..', 'package.json'); // Maybe grammar file is at the same level as `package.json`
236+
let packageUri = vscode.Uri.joinPath(newUri, ...pathSegments, '..', '..', 'package.json');
237+
let file = await tryCatch(vscode.workspace.fs.readFile(packageUri));
232238

233-
const file1 = await vscode.workspace.fs.readFile(packageUri1).then(null, () => { });
234-
const file = file1 || await vscode.workspace.fs.readFile(packageUri2).then(null, () => { });
235239
if (!file) {
240+
packageUri = vscode.Uri.joinPath(newUri, ...pathSegments, '..', 'package.json'); // Maybe `package.json` is at the same level as the grammar file
241+
file = await tryCatch(vscode.workspace.fs.readFile(packageUri));
242+
243+
if (!file) {
244+
return {};
245+
}
246+
}
247+
248+
const decoder = new TextDecoder(); // Works in VSCode web
249+
const text = decoder.decode(file);
250+
const packageJSON = await tryCatch(
251+
JSON.parse(text) as IRelaxedExtensionManifest,
252+
"Failed to parse package.json",
253+
);
254+
255+
if (!packageJSON) {
236256
return {};
237257
}
238258

239-
const packageUri = file1 ? packageUri1 : packageUri2;
259+
return {
260+
packageJSON: packageJSON,
261+
packageUri: packageUri,
262+
};
263+
}
240264

241-
try {
242-
const decoder = new TextDecoder(); // Works in VSCode web
243-
const text = decoder.decode(file);
244265

245-
const packageJSON: IRelaxedExtensionManifest = JSON.parse(text);
246-
if (packageJSON) {
247-
return { packageJSON: packageJSON, packageUri: packageUri };
266+
// https://gist.github.com/t3dotgg/a486c4ae66d32bf17c09c73609dacc5b
267+
export async function tryCatch<T>(
268+
promise: Promise<T> | Thenable<T> | T,
269+
...consoleLogMessage: any[]
270+
): Promise<T | null> {
271+
try {
272+
const data = await promise;
273+
return data;
274+
} catch (error: any) {
275+
if (consoleLogMessage.length) {
276+
console.warn('JSON TextMate Extension:', ...consoleLogMessage, '\n', error);
248277
}
249-
} catch (error) {
250-
console.warn("TextMate: Failed to parse package.json\n", error);
278+
return null;
251279
}
252-
253-
return {};
254280
}

0 commit comments

Comments
 (0)