Skip to content

Commit 28d439a

Browse files
authored
(fix) split tscheck-regex to avoid heavy compution (#367)
#337
1 parent cd0998f commit 28d439a

File tree

3 files changed

+91
-14
lines changed

3 files changed

+91
-14
lines changed

packages/language-server/src/plugins/typescript/DocumentSnapshot.ts

+8-14
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import {
1414
} from '../../lib/documents';
1515
import { pathToUrl } from '../../utils';
1616
import { ConsumerDocumentMapper } from './DocumentMapper';
17-
import { getScriptKindFromAttributes, getScriptKindFromFileName, isSvelteFilePath } from './utils';
17+
import {
18+
getScriptKindFromAttributes,
19+
getScriptKindFromFileName,
20+
isSvelteFilePath,
21+
getTsCheckComment,
22+
} from './utils';
1823

1924
/**
2025
* An error which occured while trying to parse/preprocess the svelte file contents.
@@ -120,10 +125,9 @@ function preprocessSvelteFile(document: Document, options: SvelteSnapshotOptions
120125
if (tsxMap) {
121126
tsxMap.sources = [document.uri];
122127

123-
const tsCheck = document.scriptInfo?.content.match(tsCheckRegex);
128+
const tsCheck = getTsCheckComment(document.scriptInfo?.content);
124129
if (tsCheck) {
125-
// second-last entry is the capturing group with the exact ts-check wording
126-
text = `//${tsCheck[tsCheck.length - 3]}${ts.sys.newLine}` + text;
130+
text = tsCheck + text;
127131
nrPrependedLines = 1;
128132
}
129133
}
@@ -330,13 +334,3 @@ export class SvelteSnapshotFragment implements SnapshotFragment {
330334
}
331335
}
332336
}
333-
334-
// The following regex matches @ts-check or @ts-nocheck if:
335-
// - it is before the first line of code (so other lines with comments before it are ok)
336-
// - must be @ts-(no)check
337-
// - the comment which has @ts-(no)check can have any type of whitespace before it, but not other characters
338-
// - what's coming after @ts-(no)check is irrelevant as long there is any kind of whitespace or line break, so this would be picked up, too: // @ts-check asdasd
339-
// [ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]
340-
// is just \s (a.k.a any whitespace character) without linebreak and vertical tab
341-
// eslint-disable-next-line
342-
const tsCheckRegex = /^(\s*(\/\/[ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff\S]*)*\s*)*(\/\/[ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]*(@ts-(no)?check)($|\s))/;

packages/language-server/src/plugins/typescript/utils.ts

+26
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,29 @@ export function mapSeverity(category: ts.DiagnosticCategory): DiagnosticSeverity
260260

261261
return DiagnosticSeverity.Error;
262262
}
263+
264+
// Matches comments that come before any non-comment content
265+
const commentsRegex = /^(\s*\/\/.*\s*)*/;
266+
// The following regex matches @ts-check or @ts-nocheck if:
267+
// - must be @ts-(no)check
268+
// - the comment which has @ts-(no)check can have any type of whitespace before it, but not other characters
269+
// - what's coming after @ts-(no)check is irrelevant as long there is any kind of whitespace or line break, so this would be picked up, too: // @ts-check asdasd
270+
// [ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]
271+
// is just \s (a.k.a any whitespace character) without linebreak and vertical tab
272+
// eslint-disable-next-line max-len
273+
const tsCheckRegex = /\/\/[ \t\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]*(@ts-(no)?check)($|\s)/;
274+
275+
/**
276+
* Returns `// @ts-check` or `// @ts-nocheck` if content starts with comments and has one of these
277+
* in its comments.
278+
*/
279+
export function getTsCheckComment(str = ''): string | undefined {
280+
const comments = str.match(commentsRegex)?.[0];
281+
if (comments) {
282+
const tsCheck = comments.match(tsCheckRegex);
283+
if (tsCheck) {
284+
// second-last entry is the capturing group with the exact ts-check wording
285+
return `// ${tsCheck[tsCheck.length - 3]}${ts.sys.newLine}`;
286+
}
287+
}
288+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { getTsCheckComment } from '../../../src/plugins/typescript/utils';
2+
import ts from 'typescript';
3+
import * as assert from 'assert';
4+
5+
describe('TypeScriptPlugin utils', () => {
6+
describe('#getTsCheckComment', () => {
7+
const tsCheckComment = `// @ts-check${ts.sys.newLine}`;
8+
const tsNocheckComment = `// @ts-nocheck${ts.sys.newLine}`;
9+
10+
it('should not return if ts-check is after non-comment-code', () => {
11+
assert.deepStrictEqual(
12+
getTsCheckComment(`qwd
13+
// @ts-check`),
14+
undefined,
15+
);
16+
});
17+
18+
it('should return @ts-check', () => {
19+
assert.deepStrictEqual(
20+
getTsCheckComment(`
21+
// @ts-check`),
22+
tsCheckComment,
23+
);
24+
});
25+
26+
it('should return @ts-nocheck', () => {
27+
assert.deepStrictEqual(
28+
getTsCheckComment(`
29+
// @ts-nocheck`),
30+
tsNocheckComment,
31+
);
32+
});
33+
34+
it('should return if ts-check is after some comments', () => {
35+
assert.deepStrictEqual(
36+
getTsCheckComment(`
37+
// hello
38+
39+
///
40+
// @ts-check`),
41+
tsCheckComment,
42+
);
43+
});
44+
45+
it('should not return if there are comments but without ts-check', () => {
46+
assert.deepStrictEqual(
47+
getTsCheckComment(`
48+
// nope
49+
// almost@ts-check
50+
// @ts-almostcheck
51+
///
52+
`),
53+
undefined,
54+
);
55+
});
56+
});
57+
});

0 commit comments

Comments
 (0)