Skip to content

Commit 17046d0

Browse files
authored
fix: correct parent typing for rule visitors (#313)
1 parent deefc38 commit 17046d0

File tree

2 files changed

+154
-115
lines changed

2 files changed

+154
-115
lines changed

src/types.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
RuleVisitor,
1414
} from "@eslint/core";
1515

16-
import type { CssNodePlain, CssNodeNames } from "@eslint/css-tree";
16+
import type { CssNodePlain, StyleSheetPlain } from "@eslint/css-tree";
1717

1818
import type { CSSLanguageOptions, CSSSourceCode } from "./index.js";
1919

@@ -38,9 +38,9 @@ type WithExit<RuleVisitorType extends RuleVisitor> = {
3838
export type CSSSyntaxElement = CssNodePlain;
3939

4040
type CSSNodeVisitor = {
41-
[Type in CssNodeNames]: (
42-
node: Extract<CssNodePlain, { type: Type }>,
43-
) => void;
41+
[Node in CssNodePlain as Node["type"]]: Node extends StyleSheetPlain
42+
? ((node: Node) => void) | undefined
43+
: ((node: Node, parent: CssNodePlain) => void) | undefined;
4444
};
4545

4646
/**
@@ -62,7 +62,7 @@ export type CSSRuleDefinition<
6262
LangOptions: CSSLanguageOptions;
6363
Code: CSSSourceCode;
6464
Visitor: CSSRuleVisitor;
65-
Node: CssNodePlain;
65+
Node: CSSSyntaxElement;
6666
},
6767
Options
6868
>;

tests/types/types.test.ts

Lines changed: 149 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ css.configs.recommended.plugins satisfies object;
9494
sourceCode.lines satisfies string[];
9595
sourceCode.text satisfies string;
9696

97-
function testVisitor<NodeType extends CssNodePlain>(node: NodeType) {
97+
function testVisitor<NodeType extends CssNodePlain>(
98+
node: NodeType,
99+
parent?: CssNodePlain,
100+
) {
98101
sourceCode.getLoc(node) satisfies SourceLocation;
99102
sourceCode.getLocFromIndex(0) satisfies {
100103
line: number;
@@ -114,115 +117,151 @@ css.configs.recommended.plugins satisfies object;
114117
}
115118

116119
return {
117-
AnPlusB: node => testVisitor<AnPlusB>(node),
118-
"AnPlusB:exit": node => testVisitor<AnPlusB>(node),
119-
Atrule: node => testVisitor<AtrulePlain>(node),
120-
"Atrule:exit": node => testVisitor<AtrulePlain>(node),
121-
AtrulePrelude: node => testVisitor<AtrulePreludePlain>(node),
122-
"AtrulePrelude:exit": node => testVisitor<AtrulePreludePlain>(node),
123-
AttributeSelector: node => testVisitor<AttributeSelector>(node),
124-
"AttributeSelector:exit": node =>
125-
testVisitor<AttributeSelector>(node),
126-
Block: node => testVisitor<BlockPlain>(node),
127-
"Block:exit": node => testVisitor<BlockPlain>(node),
128-
Brackets: node => testVisitor<BracketsPlain>(node),
129-
"Brackets:exit": node => testVisitor<BracketsPlain>(node),
130-
CDC: node => testVisitor<CDC>(node),
131-
"CDC:exit": node => testVisitor<CDC>(node),
132-
CDO: node => testVisitor<CDO>(node),
133-
"CDO:exit": node => testVisitor<CDO>(node),
134-
ClassSelector: node => testVisitor<ClassSelector>(node),
135-
"ClassSelector:exit": node => testVisitor<ClassSelector>(node),
136-
Combinator: node => testVisitor<Combinator>(node),
137-
"Combinator:exit": node => testVisitor<Combinator>(node),
138-
Comment: node => testVisitor<Comment>(node),
139-
"Comment:exit": node => testVisitor<Comment>(node),
140-
Condition: node => testVisitor<ConditionPlain>(node),
141-
"Condition:exit": node => testVisitor<ConditionPlain>(node),
142-
Declaration: node => testVisitor<DeclarationPlain>(node),
143-
"Declaration:exit": node => testVisitor<DeclarationPlain>(node),
144-
DeclarationList: node => testVisitor<DeclarationListPlain>(node),
145-
"DeclarationList:exit": node =>
146-
testVisitor<DeclarationListPlain>(node),
147-
Dimension: node => testVisitor<Dimension>(node),
148-
"Dimension:exit": node => testVisitor<Dimension>(node),
149-
Feature: node => testVisitor<Feature>(node),
150-
"Feature:exit": node => testVisitor<Feature>(node),
151-
FeatureFunction: node => testVisitor<FeatureFunctionPlain>(node),
152-
"FeatureFunction:exit": node =>
153-
testVisitor<FeatureFunctionPlain>(node),
154-
FeatureRange: node => testVisitor<FeatureRange>(node),
155-
"FeatureRange:exit": node => testVisitor<FeatureRange>(node),
156-
Function: node => testVisitor<FunctionNodePlain>(node),
157-
"Function:exit": node => testVisitor<FunctionNodePlain>(node),
158-
GeneralEnclosed: node => testVisitor<any>(node),
159-
"GeneralEnclosed:exit": node => testVisitor<any>(node),
160-
Hash: node => testVisitor<Hash>(node),
161-
"Hash:exit": node => testVisitor<Hash>(node),
162-
IdSelector: node => testVisitor<IdSelector>(node),
163-
"IdSelector:exit": node => testVisitor<IdSelector>(node),
164-
Identifier: node => testVisitor<Identifier>(node),
165-
"Identifier:exit": node => testVisitor<Identifier>(node),
166-
Layer: node => testVisitor<Layer>(node),
167-
"Layer:exit": node => testVisitor<Layer>(node),
168-
LayerList: node => testVisitor<LayerListPlain>(node),
169-
"LayerList:exit": node => testVisitor<LayerListPlain>(node),
170-
MediaFeature: node => testVisitor<MediaFeature>(node),
171-
"MediaFeature:exit": node => testVisitor<MediaFeature>(node),
172-
MediaQuery: node => testVisitor<MediaQueryPlain>(node),
173-
"MediaQuery:exit": node => testVisitor<MediaQueryPlain>(node),
174-
MediaQueryList: node => testVisitor<MediaQueryListPlain>(node),
175-
"MediaQueryList:exit": node =>
176-
testVisitor<MediaQueryListPlain>(node),
177-
NestingSelector: node => testVisitor<NestingSelector>(node),
178-
"NestingSelector:exit": node => testVisitor<NestingSelector>(node),
179-
Nth: node => testVisitor<NthPlain>(node),
180-
"Nth:exit": node => testVisitor<NthPlain>(node),
181-
Number: node => testVisitor<NumberNode>(node),
182-
"Number:exit": node => testVisitor<NumberNode>(node),
183-
Operator: node => testVisitor<Operator>(node),
184-
"Operator:exit": node => testVisitor<Operator>(node),
185-
Parentheses: node => testVisitor<ParenthesesPlain>(node),
186-
"Parentheses:exit": node => testVisitor<ParenthesesPlain>(node),
187-
Percentage: node => testVisitor<Percentage>(node),
188-
"Percentage:exit": node => testVisitor<Percentage>(node),
189-
PseudoClassSelector: node =>
190-
testVisitor<PseudoClassSelectorPlain>(node),
191-
"PseudoClassSelector:exit": node =>
192-
testVisitor<PseudoClassSelectorPlain>(node),
193-
PseudoElementSelector: node =>
194-
testVisitor<PseudoElementSelectorPlain>(node),
195-
"PseudoElementSelector:exit": node =>
196-
testVisitor<PseudoElementSelectorPlain>(node),
197-
Ratio: node => testVisitor<Ratio>(node),
198-
"Ratio:exit": node => testVisitor<Ratio>(node),
199-
Raw: node => testVisitor<Raw>(node),
200-
"Raw:exit": node => testVisitor<Raw>(node),
201-
Rule: node => testVisitor<RulePlain>(node),
202-
"Rule:exit": node => testVisitor<RulePlain>(node),
203-
Scope: node => testVisitor<any>(node),
204-
"Scope:exit": node => testVisitor<any>(node),
205-
Selector: node => testVisitor<SelectorPlain>(node),
206-
"Selector:exit": node => testVisitor<SelectorPlain>(node),
207-
SelectorList: node => testVisitor<SelectorListPlain>(node),
208-
"SelectorList:exit": node => testVisitor<SelectorListPlain>(node),
209-
String: node => testVisitor<StringNode>(node),
210-
"String:exit": node => testVisitor<StringNode>(node),
211-
StyleSheet: node => testVisitor<StyleSheetPlain>(node),
212-
"StyleSheet:exit": node => testVisitor<StyleSheetPlain>(node),
213-
SupportsDeclaration: node => testVisitor<SupportsDeclaration>(node),
214-
"SupportsDeclaration:exit": node =>
215-
testVisitor<SupportsDeclaration>(node),
216-
TypeSelector: node => testVisitor<TypeSelector>(node),
217-
"TypeSelector:exit": node => testVisitor<TypeSelector>(node),
218-
UnicodeRange: node => testVisitor<UnicodeRange>(node),
219-
"UnicodeRange:exit": node => testVisitor<UnicodeRange>(node),
220-
Url: node => testVisitor<Url>(node),
221-
"Url:exit": node => testVisitor<Url>(node),
222-
Value: node => testVisitor<ValuePlain>(node),
223-
"Value:exit": node => testVisitor<ValuePlain>(node),
224-
WhiteSpace: node => testVisitor<WhiteSpace>(node),
225-
"WhiteSpace:exit": node => testVisitor<WhiteSpace>(node),
120+
AnPlusB: (...args) => testVisitor<AnPlusB>(...args),
121+
"AnPlusB:exit": (...args) => testVisitor<AnPlusB>(...args),
122+
Atrule: (...args) => testVisitor<AtrulePlain>(...args),
123+
"Atrule:exit": (...args) => testVisitor<AtrulePlain>(...args),
124+
AtrulePrelude: (...args) =>
125+
testVisitor<AtrulePreludePlain>(...args),
126+
"AtrulePrelude:exit": (...args) =>
127+
testVisitor<AtrulePreludePlain>(...args),
128+
AttributeSelector: (...args) =>
129+
testVisitor<AttributeSelector>(...args),
130+
"AttributeSelector:exit": (...args) =>
131+
testVisitor<AttributeSelector>(...args),
132+
Block: (...args) => testVisitor<BlockPlain>(...args),
133+
"Block:exit": (...args) => testVisitor<BlockPlain>(...args),
134+
Brackets: (...args) => testVisitor<BracketsPlain>(...args),
135+
"Brackets:exit": (...args) => testVisitor<BracketsPlain>(...args),
136+
CDC: (...args) => testVisitor<CDC>(...args),
137+
"CDC:exit": (...args) => testVisitor<CDC>(...args),
138+
CDO: (...args) => testVisitor<CDO>(...args),
139+
"CDO:exit": (...args) => testVisitor<CDO>(...args),
140+
ClassSelector: (...args) => testVisitor<ClassSelector>(...args),
141+
"ClassSelector:exit": (...args) =>
142+
testVisitor<ClassSelector>(...args),
143+
Combinator: (...args) => testVisitor<Combinator>(...args),
144+
"Combinator:exit": (...args) => testVisitor<Combinator>(...args),
145+
Comment: (...args) => testVisitor<Comment>(...args),
146+
"Comment:exit": (...args) => testVisitor<Comment>(...args),
147+
Condition: (...args) => testVisitor<ConditionPlain>(...args),
148+
"Condition:exit": (...args) => testVisitor<ConditionPlain>(...args),
149+
Declaration: (...args) => testVisitor<DeclarationPlain>(...args),
150+
"Declaration:exit": (...args) =>
151+
testVisitor<DeclarationPlain>(...args),
152+
DeclarationList: (...args) =>
153+
testVisitor<DeclarationListPlain>(...args),
154+
"DeclarationList:exit": (...args) =>
155+
testVisitor<DeclarationListPlain>(...args),
156+
Dimension: (...args) => testVisitor<Dimension>(...args),
157+
"Dimension:exit": (...args) => testVisitor<Dimension>(...args),
158+
Feature: (...args) => testVisitor<Feature>(...args),
159+
"Feature:exit": (...args) => testVisitor<Feature>(...args),
160+
FeatureFunction: (...args) =>
161+
testVisitor<FeatureFunctionPlain>(...args),
162+
"FeatureFunction:exit": (...args) =>
163+
testVisitor<FeatureFunctionPlain>(...args),
164+
FeatureRange: (...args) => testVisitor<FeatureRange>(...args),
165+
"FeatureRange:exit": (...args) =>
166+
testVisitor<FeatureRange>(...args),
167+
Function: (...args) => testVisitor<FunctionNodePlain>(...args),
168+
"Function:exit": (...args) =>
169+
testVisitor<FunctionNodePlain>(...args),
170+
GeneralEnclosed: (node: any, parent: CssNodePlain) =>
171+
testVisitor<any>(node, parent),
172+
"GeneralEnclosed:exit": (node: any, parent: CssNodePlain) =>
173+
testVisitor<any>(node, parent),
174+
Hash: (...args) => testVisitor<Hash>(...args),
175+
"Hash:exit": (...args) => testVisitor<Hash>(...args),
176+
IdSelector: (...args) => testVisitor<IdSelector>(...args),
177+
"IdSelector:exit": (...args) => testVisitor<IdSelector>(...args),
178+
Identifier: (...args) => testVisitor<Identifier>(...args),
179+
"Identifier:exit": (...args) => testVisitor<Identifier>(...args),
180+
Layer: (...args) => testVisitor<Layer>(...args),
181+
"Layer:exit": (...args) => testVisitor<Layer>(...args),
182+
LayerList: (...args) => testVisitor<LayerListPlain>(...args),
183+
"LayerList:exit": (...args) => testVisitor<LayerListPlain>(...args),
184+
MediaFeature: (...args) => testVisitor<MediaFeature>(...args),
185+
"MediaFeature:exit": (...args) =>
186+
testVisitor<MediaFeature>(...args),
187+
MediaQuery: (...args) => testVisitor<MediaQueryPlain>(...args),
188+
"MediaQuery:exit": (...args) =>
189+
testVisitor<MediaQueryPlain>(...args),
190+
MediaQueryList: (...args) =>
191+
testVisitor<MediaQueryListPlain>(...args),
192+
"MediaQueryList:exit": (...args) =>
193+
testVisitor<MediaQueryListPlain>(...args),
194+
NestingSelector: (...args) => testVisitor<NestingSelector>(...args),
195+
"NestingSelector:exit": (...args) =>
196+
testVisitor<NestingSelector>(...args),
197+
Nth: (...args) => testVisitor<NthPlain>(...args),
198+
"Nth:exit": (...args) => testVisitor<NthPlain>(...args),
199+
Number: (...args) => testVisitor<NumberNode>(...args),
200+
"Number:exit": (...args) => testVisitor<NumberNode>(...args),
201+
Operator: (...args) => testVisitor<Operator>(...args),
202+
"Operator:exit": (...args) => testVisitor<Operator>(...args),
203+
Parentheses: (...args) => testVisitor<ParenthesesPlain>(...args),
204+
"Parentheses:exit": (...args) =>
205+
testVisitor<ParenthesesPlain>(...args),
206+
Percentage: (...args) => testVisitor<Percentage>(...args),
207+
"Percentage:exit": (...args) => testVisitor<Percentage>(...args),
208+
PseudoClassSelector: (...args) =>
209+
testVisitor<PseudoClassSelectorPlain>(...args),
210+
"PseudoClassSelector:exit": (...args) =>
211+
testVisitor<PseudoClassSelectorPlain>(...args),
212+
PseudoElementSelector: (...args) =>
213+
testVisitor<PseudoElementSelectorPlain>(...args),
214+
"PseudoElementSelector:exit": (...args) =>
215+
testVisitor<PseudoElementSelectorPlain>(...args),
216+
Ratio: (...args) => testVisitor<Ratio>(...args),
217+
"Ratio:exit": (...args) => testVisitor<Ratio>(...args),
218+
Raw: (...args) => testVisitor<Raw>(...args),
219+
"Raw:exit": (...args) => testVisitor<Raw>(...args),
220+
Rule: (...args) => testVisitor<RulePlain>(...args),
221+
"Rule:exit": (...args) => testVisitor<RulePlain>(...args),
222+
Scope: (node: any, parent: CssNodePlain) =>
223+
testVisitor<any>(node, parent),
224+
"Scope:exit": (node: any, parent: CssNodePlain) =>
225+
testVisitor<any>(node, parent),
226+
Selector: (...args) => testVisitor<SelectorPlain>(...args),
227+
"Selector:exit": (...args) => testVisitor<SelectorPlain>(...args),
228+
SelectorList: (...args) => testVisitor<SelectorListPlain>(...args),
229+
"SelectorList:exit": (...args) =>
230+
testVisitor<SelectorListPlain>(...args),
231+
String: (...args) => testVisitor<StringNode>(...args),
232+
"String:exit": (...args) => testVisitor<StringNode>(...args),
233+
StyleSheet: (...args) => testVisitor<StyleSheetPlain>(...args),
234+
"StyleSheet:exit": (...args) =>
235+
testVisitor<StyleSheetPlain>(...args),
236+
SupportsDeclaration: (...args) =>
237+
testVisitor<SupportsDeclaration>(...args),
238+
"SupportsDeclaration:exit": (...args) =>
239+
testVisitor<SupportsDeclaration>(...args),
240+
TypeSelector: (...args) => testVisitor<TypeSelector>(...args),
241+
"TypeSelector:exit": (...args) =>
242+
testVisitor<TypeSelector>(...args),
243+
UnicodeRange: (...args) => testVisitor<UnicodeRange>(...args),
244+
"UnicodeRange:exit": (...args) =>
245+
testVisitor<UnicodeRange>(...args),
246+
Url: (...args) => testVisitor<Url>(...args),
247+
"Url:exit": (...args) => testVisitor<Url>(...args),
248+
Value: (...args) => testVisitor<ValuePlain>(...args),
249+
"Value:exit": (...args) => testVisitor<ValuePlain>(...args),
250+
WhiteSpace: (...args) => testVisitor<WhiteSpace>(...args),
251+
"WhiteSpace:exit": (...args) => testVisitor<WhiteSpace>(...args),
252+
253+
// Combined selectors allowed
254+
"Atrule[name=import]"(node: AtrulePlain, parent: CssNodePlain) {},
255+
"*"(node: CssNodePlain) {},
256+
"Selector:first-child"(node: SelectorPlain) {},
257+
"Selector:last-child"(node: SelectorPlain) {},
258+
"Value Number"(node: NumberNode) {},
259+
"String, Number"(node: StringNode | NumberNode) {},
260+
261+
// Unknown selectors allowed
262+
ForStatement(node) {},
263+
Unknown(node) {},
264+
ValueNode(node) {},
226265
};
227266
},
228267
});

0 commit comments

Comments
 (0)