Skip to content

Commit 4f666b4

Browse files
committed
InvalidComparisonSyntax
1 parent 5b35482 commit 4f666b4

File tree

2 files changed

+35
-45
lines changed

2 files changed

+35
-45
lines changed

packages/theme-check-common/src/checks/invalid-comparison-syntax/index.spec.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { highlightedOffenses, runLiquidCheck } from '../../test';
33
import { InvalidComparisonSyntax } from './index';
44

55
describe('Module: InvalidComparisonSyntax', () => {
6-
it('should report an offense when include tag is used', async () => {
6+
it('should report an offense an invalid token is used', async () => {
77
const sourceCode = `
88
{% if a > b foobar %}
99
{% endif %}
@@ -13,4 +13,20 @@ describe('Module: InvalidComparisonSyntax', () => {
1313
expect(offenses).toHaveLength(1);
1414
expect(offenses[0].message).toEqual(`Invalid token 'foobar' after comparison`);
1515
});
16+
17+
it('should suggest removing the invalid token', async () => {
18+
const sourceCode = `
19+
{% if a > b foobar %}
20+
{% endif %}
21+
`;
22+
const offenses = await runLiquidCheck(InvalidComparisonSyntax, sourceCode);
23+
24+
expect(offenses).toHaveLength(1);
25+
26+
expect(offenses[0]!.suggest![0]!.message).toEqual(`Remove 'foobar'`);
27+
28+
const highlights = highlightedOffenses({ 'file.liquid': sourceCode }, offenses);
29+
expect(highlights).toHaveLength(1);
30+
expect(highlights[0]).toBe('foobar');
31+
});
1632
});

packages/theme-check-common/src/checks/invalid-comparison-syntax/index.ts

+18-44
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,31 @@ export const InvalidComparisonSyntax: LiquidCheckDefinition = {
2222
return;
2323
}
2424

25-
// We need to examine the markup string directly
2625
const markup = node.markup.toString();
2726

28-
// Find the offsets of any invalid tokens after comparisons
29-
const positions = findInvalidTokenPositionsAfterComparisons(markup);
27+
const regex =
28+
/(>=|<=|>|<|==|!=)\s+([^\s]+)\s+([^\s]+)(?!\s+(and|or|%}|contains|startswith|endswith))/g;
3029

31-
if (positions.length > 0) {
32-
// Calculate markup position in the source
33-
const markupStart = node.position.start + (node.name.length + 3); // {% + name + space
30+
let match;
31+
while ((match = regex.exec(markup)) !== null) {
32+
const invalidToken = match[3];
33+
34+
if (!isValidComparisonConnector(invalidToken)) {
35+
const invalidTokenOffset = match.index + match[0].lastIndexOf(invalidToken);
36+
37+
const markupStart = node.position.start + node.name.length + 3;
38+
const startIndex = markupStart + invalidTokenOffset + 1;
39+
const endIndex = startIndex + invalidToken.length;
3440

35-
// Report each invalid token
36-
for (const pos of positions) {
3741
context.report({
38-
message: `Invalid token '${pos.token}' after comparison`,
39-
startIndex: markupStart + pos.start,
40-
endIndex: markupStart + pos.end,
42+
message: `Invalid token '${invalidToken}' after comparison`,
43+
startIndex,
44+
endIndex,
4145
suggest: [
4246
{
43-
message: `Remove '${pos.token}'`,
47+
message: `Remove '${invalidToken}'`,
4448
fix: (corrector) => {
45-
corrector.remove(markupStart + pos.start, markupStart + pos.end);
49+
corrector.remove(startIndex, endIndex + 1);
4650
},
4751
},
4852
],
@@ -54,37 +58,7 @@ export const InvalidComparisonSyntax: LiquidCheckDefinition = {
5458
},
5559
};
5660

57-
// Helper function to find all invalid tokens after comparisons in the markup
58-
function findInvalidTokenPositionsAfterComparisons(markup) {
59-
const positions = [];
60-
61-
// Regex to find comparison operations with potentially invalid tokens after them
62-
const regex =
63-
/(>=|<=|>|<|==|!=)\s+([^\s]+)\s+(\w+)(?!\s+(and|or|%}|contains|startswith|endswith))/g;
64-
65-
let match;
66-
while ((match = regex.exec(markup)) !== null) {
67-
const invalidToken = match[3];
68-
69-
if (!isValidComparisonConnector(invalidToken)) {
70-
// Find the position of the token within the match
71-
const matchStart = match.index;
72-
const beforeInvalidToken = match[0].substring(0, match[0].lastIndexOf(invalidToken));
73-
const tokenStart = matchStart + beforeInvalidToken.length;
74-
const tokenEnd = tokenStart + invalidToken.length;
75-
76-
positions.push({
77-
token: invalidToken,
78-
start: tokenStart,
79-
end: tokenEnd,
80-
});
81-
}
82-
}
83-
84-
return positions;
85-
}
86-
87-
function isValidComparisonConnector(token) {
61+
function isValidComparisonConnector(token: string): boolean {
8862
const validConnectors = ['and', 'or', '%}', 'contains', 'startswith', 'endswith'];
8963
return validConnectors.some((connector) => token.includes(connector));
9064
}

0 commit comments

Comments
 (0)