diff --git a/apps/oxlint/src-js/plugins/tokens.ts b/apps/oxlint/src-js/plugins/tokens.ts index d969c203ba59b..7158dcb2e955f 100644 --- a/apps/oxlint/src-js/plugins/tokens.ts +++ b/apps/oxlint/src-js/plugins/tokens.ts @@ -388,7 +388,7 @@ export function getFirstToken(node: Node, skipOptions?: SkipOptions | number | F if (token.range[0] >= rangeEnd) break; // Token is outside the node if (filter(token)) { if (skip === 0) return token; - skip -= 1; + skip--; } } } @@ -484,13 +484,10 @@ export function getFirstTokens(node: Node, countOptions?: CountOptions | number } } else { firstTokens = []; - for (let i = sliceStart; i < sliceEnd; i++) { + for (let i = sliceStart; i < sliceEnd && firstTokens.length < count; i++) { const token = nodeTokens[i]; if (filter(token)) { firstTokens.push(token); - if (firstTokens.length === count) { - break; - } } } } @@ -689,13 +686,10 @@ export function getLastTokens(node: Node, countOptions?: CountOptions | number | } else { lastTokens = []; // Count is the number of tokens within range from the end so we iterate in reverse - for (let i = sliceEnd - 1; i >= sliceStart; i--) { + for (let i = sliceEnd - 1; i >= sliceStart && lastTokens.length < count; i--) { const token = nodeTokens[i]; if (filter(token)) { lastTokens.unshift(token); - if (lastTokens.length === count) { - break; - } } } } @@ -767,7 +761,7 @@ export function getTokenBefore( } } - beforeIndex -= 1; + beforeIndex--; if (typeof filter !== 'function') { if (typeof skip !== 'number') { @@ -782,16 +776,16 @@ export function getTokenBefore( if (filter(token)) { return token; } - beforeIndex -= 1; + beforeIndex--; } } else { while (beforeIndex >= 0) { const token = nodeTokens[beforeIndex]; if (filter(token)) { if (skip === 0) return token; - skip -= 1; + skip--; } - beforeIndex -= 1; + beforeIndex--; } } } @@ -899,14 +893,11 @@ export function getTokensBefore( } else { tokensBefore = []; // Count is the number of preceding tokens so we iterate in reverse - for (let i = sliceEnd - 1; i >= 0; i--) { + for (let i = sliceEnd - 1; i >= 0 && tokensBefore.length < count; i--) { const token = nodeTokens[i]; if (filter(token)) { tokensBefore.unshift(token); } - if (tokensBefore.length === count) { - break; - } } } } @@ -1100,14 +1091,11 @@ export function getTokensAfter( } } else { nodeTokensAfter = []; - for (let i = sliceStart; i < nodeTokens.length; i++) { + for (let i = sliceStart; i < nodeTokens.length && nodeTokensAfter.length < count; i++) { const token = nodeTokens[i]; if (filter(token)) { nodeTokensAfter.push(token); } - if (nodeTokensAfter.length === count) { - break; - } } } } diff --git a/apps/oxlint/test/tokens.test.ts b/apps/oxlint/test/tokens.test.ts index ac127dfdd728e..382571e9676a0 100644 --- a/apps/oxlint/test/tokens.test.ts +++ b/apps/oxlint/test/tokens.test.ts @@ -196,6 +196,15 @@ describe('when calling getTokensBefore', () => { ).toEqual(['var', '=']); }); + it('should retrieve zero tokens before a node with a filter when count is 0', () => { + expect( + getTokensBefore(BinaryExpression, { + count: 0, + filter: () => true, + }).map((token) => token.value), + ).toEqual([]); + }); + it('should retrieve no tokens before the root node', () => { expect(getTokensBefore(Program, { count: 1 }).map((token) => token.value)).toEqual([]); }); @@ -439,6 +448,15 @@ describe('when calling getTokensAfter', () => { ).toEqual(['a', 'b']); }); + it('should retrieve zero tokens after a node with a filter when count is 0', () => { + expect( + getTokensAfter(VariableDeclaratorIdentifier, { + count: 0, + filter: () => true, + }).map((token) => token.value), + ).toEqual([]); + }); + it('should retrieve all tokens and comments after a node with includeComments option', () => { expect( getTokensAfter(VariableDeclaratorIdentifier, { @@ -518,6 +536,15 @@ describe('when calling getFirstTokens', () => { ).toEqual(['a', 'D', '*', 'b']); }); + it("should retrieve zero tokens from a node's token stream with a filter when count is 0", () => { + expect( + getFirstTokens(BinaryExpression, { + count: 0, + filter: () => true, + }).map((token) => token.value), + ).toEqual([]); + }); + it("should retrieve several tokens and comments from a node's token stream with includeComments and count options", () => { expect( getFirstTokens(BinaryExpression, { @@ -692,6 +719,15 @@ describe('when calling getLastTokens', () => { ).toEqual(['b']); }); + it("should retrieve zero tokens from the end of a node's token stream with a filter when count is 0", () => { + expect( + getLastTokens(BinaryExpression, { + count: 0, + filter: () => true, + }).map((token) => token.value), + ).toEqual([]); + }); + it("should retrieve all tokens from the end of a node's token stream with includeComments option", () => { expect( getLastTokens(BinaryExpression, {