Skip to content

Commit 68b1a22

Browse files
committed
fix(consistent-selector-style): fixed an infinite loop
1 parent ea47a1a commit 68b1a22

File tree

2 files changed

+70
-116
lines changed

2 files changed

+70
-116
lines changed

packages/eslint-plugin-svelte/src/utils/expression-affixes.ts

Lines changed: 64 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { TSESTree } from '@typescript-eslint/types';
22
import { findVariable } from './ast-utils.js';
33
import type { RuleContext } from '../types.js';
44
import type { AST } from 'svelte-eslint-parser';
5+
import { ASTSearchHelper } from './ast-search-helper.js';
56

67
// Variable prefix extraction
78

@@ -76,134 +77,81 @@ function extractTemplateLiteralPrefixVariable(
7677
return null;
7778
}
7879

79-
// Literal prefix extraction
80-
8180
export function extractExpressionPrefixLiteral(
8281
context: RuleContext,
8382
expression: AST.SvelteLiteral | TSESTree.Node
8483
): string | null {
85-
switch (expression.type) {
86-
case 'BinaryExpression':
87-
return extractBinaryExpressionPrefixLiteral(context, expression);
88-
case 'Identifier':
89-
return extractVariablePrefixLiteral(context, expression);
90-
case 'Literal':
91-
return typeof expression.value === 'string' ? expression.value : null;
92-
case 'SvelteLiteral':
93-
return expression.value;
94-
case 'TemplateLiteral':
95-
return extractTemplateLiteralPrefixLiteral(context, expression);
96-
default:
97-
return null;
98-
}
99-
}
100-
101-
function extractBinaryExpressionPrefixLiteral(
102-
context: RuleContext,
103-
expression: TSESTree.BinaryExpression
104-
): string | null {
105-
return expression.left.type !== 'PrivateIdentifier'
106-
? extractExpressionPrefixLiteral(context, expression.left)
107-
: null;
108-
}
109-
110-
function extractVariablePrefixLiteral(
111-
context: RuleContext,
112-
expression: TSESTree.Identifier
113-
): string | null {
114-
const variable = findVariable(context, expression);
115-
if (
116-
variable === null ||
117-
variable.identifiers.length !== 1 ||
118-
variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
119-
variable.identifiers[0].parent.init === null
120-
) {
121-
return null;
122-
}
123-
return extractExpressionPrefixLiteral(context, variable.identifiers[0].parent.init);
124-
}
125-
126-
function extractTemplateLiteralPrefixLiteral(
127-
context: RuleContext,
128-
expression: TSESTree.TemplateLiteral
129-
): string | null {
130-
const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) =>
131-
a.range[0] < b.range[0] ? -1 : 1
132-
);
133-
for (const part of literalParts) {
134-
if (part.type === 'TemplateElement') {
135-
if (part.value.raw === '') {
136-
// Skip empty quasi
137-
continue;
84+
return ASTSearchHelper(expression, {
85+
BinaryExpression: (node, searchAnotherNode) =>
86+
node.left.type !== 'PrivateIdentifier' ? searchAnotherNode(node.left) : null,
87+
Identifier: (node, searchAnotherNode) => {
88+
const variable = findVariable(context, node);
89+
if (
90+
variable === null ||
91+
variable.identifiers.length !== 1 ||
92+
variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
93+
variable.identifiers[0].parent.init === null
94+
) {
95+
return null;
96+
}
97+
return searchAnotherNode(variable.identifiers[0].parent.init);
98+
},
99+
Literal: (node) => (typeof node.value === 'string' ? node.value : null),
100+
SvelteLiteral: (node) => node.value,
101+
TemplateLiteral: (node, searchAnotherNode) => {
102+
const literalParts = [...node.expressions, ...node.quasis].sort((a, b) =>
103+
a.range[0] < b.range[0] ? -1 : 1
104+
);
105+
for (const part of literalParts) {
106+
if (part.type === 'TemplateElement') {
107+
if (part.value.raw === '') {
108+
// Skip empty quasi
109+
continue;
110+
}
111+
return part.value.raw;
112+
}
113+
return searchAnotherNode(part);
138114
}
139-
return part.value.raw;
115+
return null;
140116
}
141-
return extractExpressionPrefixLiteral(context, part);
142-
}
143-
return null;
117+
});
144118
}
145119

146-
// Literal suffix extraction
147-
148120
export function extractExpressionSuffixLiteral(
149121
context: RuleContext,
150122
expression: AST.SvelteLiteral | TSESTree.Node
151123
): string | null {
152-
switch (expression.type) {
153-
case 'BinaryExpression':
154-
return extractBinaryExpressionSuffixLiteral(context, expression);
155-
case 'Identifier':
156-
return extractVariableSuffixLiteral(context, expression);
157-
case 'Literal':
158-
return typeof expression.value === 'string' ? expression.value : null;
159-
case 'SvelteLiteral':
160-
return expression.value;
161-
case 'TemplateLiteral':
162-
return extractTemplateLiteralSuffixLiteral(context, expression);
163-
default:
164-
return null;
165-
}
166-
}
167-
168-
function extractBinaryExpressionSuffixLiteral(
169-
context: RuleContext,
170-
expression: TSESTree.BinaryExpression
171-
): string | null {
172-
return extractExpressionSuffixLiteral(context, expression.right);
173-
}
174-
175-
function extractVariableSuffixLiteral(
176-
context: RuleContext,
177-
expression: TSESTree.Identifier
178-
): string | null {
179-
const variable = findVariable(context, expression);
180-
if (
181-
variable === null ||
182-
variable.identifiers.length !== 1 ||
183-
variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
184-
variable.identifiers[0].parent.init === null
185-
) {
186-
return null;
187-
}
188-
return extractExpressionSuffixLiteral(context, variable.identifiers[0].parent.init);
189-
}
190-
191-
function extractTemplateLiteralSuffixLiteral(
192-
context: RuleContext,
193-
expression: TSESTree.TemplateLiteral
194-
): string | null {
195-
const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) =>
196-
a.range[0] < b.range[0] ? -1 : 1
197-
);
198-
for (const part of literalParts.reverse()) {
199-
if (part.type === 'TemplateElement') {
200-
if (part.value.raw === '') {
201-
// Skip empty quasi
202-
continue;
124+
return ASTSearchHelper(expression, {
125+
BinaryExpression: (node, searchAnotherNode) => searchAnotherNode(node.right),
126+
Identifier: (node, searchAnotherNode) => {
127+
const variable = findVariable(context, node);
128+
if (
129+
variable === null ||
130+
variable.identifiers.length !== 1 ||
131+
variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
132+
variable.identifiers[0].parent.init === null
133+
) {
134+
return null;
135+
}
136+
return searchAnotherNode(variable.identifiers[0].parent.init);
137+
},
138+
Literal: (node) => (typeof node.value === 'string' ? node.value : null),
139+
SvelteLiteral: (node) => node.value,
140+
TemplateLiteral: (node, searchAnotherNode) => {
141+
const literalParts = [...node.expressions, ...node.quasis].sort((a, b) =>
142+
a.range[0] < b.range[0] ? -1 : 1
143+
);
144+
for (const part of literalParts.reverse()) {
145+
if (part.type === 'TemplateElement') {
146+
if (part.value.raw === '') {
147+
// Skip empty quasi
148+
continue;
149+
}
150+
return part.value.raw;
151+
}
152+
return searchAnotherNode(part);
203153
}
204-
return part.value.raw;
154+
return null;
205155
}
206-
return extractExpressionSuffixLiteral(context, part);
207-
}
208-
return null;
156+
});
209157
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
const a = derived;
3+
const derived = a;
4+
</script>
5+
6+
<a id={derived}>Click me!</a>

0 commit comments

Comments
 (0)