Skip to content

Commit d185615

Browse files
committed
refactor(linter/plugins): reduce repeat code initializing tokensWithComments (#16017)
The same code was repeated in many places. Move it into a function. Function is only called when `tokensWithComments` is not already initialized (cold path), so no function call cost in majority of cases. In Rust, the pattern of moving code which is rarely called into a separate function is usually positive for perf. Not sure whether JS engine works the same way, but it might well be that V8 makes inlining decisions in much the same way.
1 parent 0c48e28 commit d185615

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

apps/oxlint/src-js/plugins/tokens.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,20 @@ function initTokens() {
167167
}));
168168
}
169169

170+
/**
171+
* Initialize `tokensWithComments`.
172+
*
173+
* Caller must ensure `tokens` and `comments` are initialized before calling this function.
174+
*/
175+
function initTokensWithComments() {
176+
debugAssertIsNonNull(tokens);
177+
debugAssertIsNonNull(comments);
178+
// TODO: `tokens` and `comments` are already sorted, so there's a more efficient algorithm to merge them.
179+
// That'd certainly be faster in Rust, but maybe here it's faster to leave it to JS engine to sort them?
180+
// TODO: Replace `range[0]` with `start` once we have our own tokens which have `start` property.
181+
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
182+
}
183+
170184
/**
171185
* Discard TS-ESLint tokens to free memory.
172186
*/
@@ -228,12 +242,8 @@ export function getTokens(
228242
// Source array of tokens to search in
229243
let nodeTokens: Token[] | null = null;
230244
if (includeComments) {
231-
if (tokensWithComments === null) {
232-
// TODO: `tokens` and `comments` are already sorted, so there's a more efficient algorithm to merge them.
233-
// That'd certainly be faster in Rust, but maybe here it's faster to leave it to JS engine to sort them?
234-
// TODO: Once we have our own tokens which have `start` and `end` properties, we can use them instead of `range`.
235-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
236-
}
245+
if (tokensWithComments === null) initTokensWithComments();
246+
debugAssertIsNonNull(tokensWithComments);
237247
nodeTokens = tokensWithComments;
238248
} else {
239249
nodeTokens = tokens;
@@ -316,9 +326,8 @@ export function getFirstToken(node: Node, skipOptions?: SkipOptions | number | F
316326
// Source array of tokens
317327
let nodeTokens: Token[] | null = null;
318328
if (includeComments) {
319-
if (tokensWithComments === null) {
320-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
321-
}
329+
if (tokensWithComments === null) initTokensWithComments();
330+
debugAssertIsNonNull(tokensWithComments);
322331
nodeTokens = tokensWithComments;
323332
} else {
324333
nodeTokens = tokens;
@@ -419,9 +428,8 @@ export function getFirstTokens(node: Node, countOptions?: CountOptions | number
419428

420429
let nodeTokens: Token[] | null = null;
421430
if (includeComments) {
422-
if (tokensWithComments === null) {
423-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
424-
}
431+
if (tokensWithComments === null) initTokensWithComments();
432+
debugAssertIsNonNull(tokensWithComments);
425433
nodeTokens = tokensWithComments;
426434
} else {
427435
nodeTokens = tokens;
@@ -536,9 +544,8 @@ export function getLastTokens(node: Node, countOptions?: CountOptions | number |
536544
// Source array of tokens to search in
537545
let nodeTokens: Token[] | null = null;
538546
if (includeComments) {
539-
if (tokensWithComments === null) {
540-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
541-
}
547+
if (tokensWithComments === null) initTokensWithComments();
548+
debugAssertIsNonNull(tokensWithComments);
542549
nodeTokens = tokensWithComments;
543550
} else {
544551
nodeTokens = tokens;
@@ -644,9 +651,8 @@ export function getTokenBefore(
644651
// Source array of tokens to search in
645652
let nodeTokens: Token[] | null = null;
646653
if (includeComments) {
647-
if (tokensWithComments === null) {
648-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
649-
}
654+
if (tokensWithComments === null) initTokensWithComments();
655+
debugAssertIsNonNull(tokensWithComments);
650656
nodeTokens = tokensWithComments;
651657
} else {
652658
nodeTokens = tokens;
@@ -757,9 +763,8 @@ export function getTokensBefore(
757763
// Source array of tokens to search in
758764
let nodeTokens: Token[] | null = null;
759765
if (includeComments) {
760-
if (tokensWithComments === null) {
761-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
762-
}
766+
if (tokensWithComments === null) initTokensWithComments();
767+
debugAssertIsNonNull(tokensWithComments);
763768
nodeTokens = tokensWithComments;
764769
} else {
765770
nodeTokens = tokens;
@@ -850,9 +855,8 @@ export function getTokenAfter(
850855
// Source array of tokens to search in
851856
let nodeTokens: Token[] | null = null;
852857
if (includeComments) {
853-
if (tokensWithComments === null) {
854-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
855-
}
858+
if (tokensWithComments === null) initTokensWithComments();
859+
debugAssertIsNonNull(tokensWithComments);
856860
nodeTokens = tokensWithComments;
857861
} else {
858862
nodeTokens = tokens;
@@ -958,9 +962,8 @@ export function getTokensAfter(
958962

959963
let nodeTokens: Token[];
960964
if (includeComments) {
961-
if (tokensWithComments === null) {
962-
tokensWithComments = [...tokens, ...comments].sort((a, b) => a.range[0] - b.range[0]);
963-
}
965+
if (tokensWithComments === null) initTokensWithComments();
966+
debugAssertIsNonNull(tokensWithComments);
964967
nodeTokens = tokensWithComments;
965968
} else {
966969
nodeTokens = tokens;

0 commit comments

Comments
 (0)