Visitar URL original
fix(check): skip Volar's cancellation polling sleep in `astro check` … · withastro/astro@044148d · GitHub
Skip to content

Commit 044148d

Browse files
fix(check): skip Volar's cancellation polling sleep in astro check (#18460)
Co-authored-by: factory[bot] <factory[bot]@users.noreply.github.com>
1 parent 8b77891 commit 044148d

3 files changed

Lines changed: 95 additions & 44 deletions

File tree

‎.changeset/quiet-volar-sleep.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/language-server': patch
3+
---
4+
5+
Speeds up `astro check` by skipping a 10 ms editor-cancellation wait that ran before checking each file

‎packages/language-tools/language-server/src/check.ts‎

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { existsSync } from 'node:fs';
2+
import { createRequire } from 'node:module';
23
import { homedir } from 'node:os';
34
import { dirname, resolve } from 'node:path';
45
import { pathToFileURL } from 'node:url';
@@ -13,6 +14,12 @@ import { create as createAstroService } from './plugins/astro.js';
1314
import { create as createTypeScriptServices } from './plugins/typescript/index.js';
1415
import { getAstroInstall } from './utils.js';
1516

17+
const volarCommon: typeof import('@volar/language-service/lib/utils/common.js') = createRequire(
18+
require.resolve('@volar/kit'),
19+
)('@volar/language-service/lib/utils/common.js');
20+
let activeChecks = 0;
21+
let originalSleep = volarCommon.sleep;
22+
1623
// Export those for downstream consumers
1724
export { Diagnostic, DiagnosticSeverity };
1825

@@ -83,59 +90,70 @@ export class AstroCheck {
8390
hints: 0,
8491
fileResult: [],
8592
};
86-
for (const file of files) {
87-
if (cancel()) {
88-
result.status = 'cancelled';
89-
return result;
90-
}
91-
const fileDiagnostics = await this.linter.check(file);
92-
93-
// Filter diagnostics based on the logErrors level
94-
const fileDiagnosticsToPrint = fileDiagnostics.filter((diag) => {
95-
const severity = diag.severity ?? DiagnosticSeverity.Error;
96-
switch (logErrors?.level ?? 'hint') {
97-
case 'error':
98-
return severity <= DiagnosticSeverity.Error;
99-
case 'warning':
100-
return severity <= DiagnosticSeverity.Warning;
101-
case 'hint':
102-
return severity <= DiagnosticSeverity.Hint;
93+
// Skip Volar's LSP cancellation wait in the CLI: https://github.com/withastro/astro/issues/18310
94+
if (activeChecks++ === 0) {
95+
originalSleep = volarCommon.sleep;
96+
volarCommon.sleep = () => Promise.resolve();
97+
}
98+
try {
99+
for (const file of files) {
100+
if (cancel()) {
101+
result.status = 'cancelled';
102+
return result;
103103
}
104-
});
104+
const fileDiagnostics = await this.linter.check(file);
105105

106-
if (fileDiagnostics.length > 0) {
107-
const errorText = this.linter.printErrors(file, fileDiagnosticsToPrint);
106+
// Filter diagnostics based on the logErrors level
107+
const fileDiagnosticsToPrint = fileDiagnostics.filter((diag) => {
108+
const severity = diag.severity ?? DiagnosticSeverity.Error;
109+
switch (logErrors?.level ?? 'hint') {
110+
case 'error':
111+
return severity <= DiagnosticSeverity.Error;
112+
case 'warning':
113+
return severity <= DiagnosticSeverity.Warning;
114+
case 'hint':
115+
return severity <= DiagnosticSeverity.Hint;
116+
}
117+
});
108118

109-
if (logErrors !== undefined && errorText) {
110-
console.info(errorText);
111-
}
119+
if (fileDiagnostics.length > 0) {
120+
const errorText = this.linter.printErrors(file, fileDiagnosticsToPrint);
112121

113-
const fileSnapshot = this.linter.language.scripts.get(URI.file(file))?.snapshot;
114-
const fileContent = fileSnapshot?.getText(0, fileSnapshot.getLength());
122+
if (logErrors !== undefined && errorText) {
123+
console.info(errorText);
124+
}
115125

116-
result.fileResult.push({
117-
errors: fileDiagnostics,
118-
fileContent: fileContent ?? '',
119-
fileUrl: pathToFileURL(file),
120-
text: errorText,
121-
});
126+
const fileSnapshot = this.linter.language.scripts.get(URI.file(file))?.snapshot;
127+
const fileContent = fileSnapshot?.getText(0, fileSnapshot.getLength());
128+
129+
result.fileResult.push({
130+
errors: fileDiagnostics,
131+
fileContent: fileContent ?? '',
132+
fileUrl: pathToFileURL(file),
133+
text: errorText,
134+
});
122135

123-
result.errors += fileDiagnostics.filter(
124-
(diag) => diag.severity === DiagnosticSeverity.Error,
125-
).length;
126-
result.warnings += fileDiagnostics.filter(
127-
(diag) => diag.severity === DiagnosticSeverity.Warning,
128-
).length;
129-
result.hints += fileDiagnostics.filter(
130-
(diag) => diag.severity === DiagnosticSeverity.Hint,
131-
).length;
136+
result.errors += fileDiagnostics.filter(
137+
(diag) => diag.severity === DiagnosticSeverity.Error,
138+
).length;
139+
result.warnings += fileDiagnostics.filter(
140+
(diag) => diag.severity === DiagnosticSeverity.Warning,
141+
).length;
142+
result.hints += fileDiagnostics.filter(
143+
(diag) => diag.severity === DiagnosticSeverity.Hint,
144+
).length;
145+
}
146+
147+
result.fileChecked += 1;
132148
}
133149

134-
result.fileChecked += 1;
150+
result.status = 'completed';
151+
return result;
152+
} finally {
153+
if (--activeChecks === 0) {
154+
volarCommon.sleep = originalSleep;
155+
}
135156
}
136-
137-
result.status = 'completed';
138-
return result;
139157
}
140158

141159
private initialize() {

‎packages/language-tools/language-server/test/check/check.test.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,31 @@ describe('AstroCheck with an incompatible TypeScript', () => {
108108
);
109109
});
110110
});
111+
112+
describe('AstroCheck cancellation polling', () => {
113+
it("Skips @volar/language-service's cancellation polling sleep while checking", async () => {
114+
const volarCommon = createRequire(require.resolve('@volar/kit'))(
115+
'@volar/language-service/lib/utils/common.js',
116+
);
117+
const originalSleep = volarCommon.sleep;
118+
let sleepCalls = 0;
119+
const countingSleep = (ms: number) => {
120+
sleepCalls++;
121+
return originalSleep(ms);
122+
};
123+
volarCommon.sleep = countingSleep;
124+
try {
125+
const checker = new AstroCheck(
126+
checkFixtureDir,
127+
require.resolve('typescript/lib/typescript.js'),
128+
undefined,
129+
);
130+
const result = await checker.lint({});
131+
assert.ok(result.fileChecked > 0);
132+
assert.strictEqual(sleepCalls, 0);
133+
assert.strictEqual(volarCommon.sleep, countingSleep);
134+
} finally {
135+
volarCommon.sleep = originalSleep;
136+
}
137+
});
138+
});

0 commit comments

Comments
 (0)