Skip to content

Commit 632a041

Browse files
committed
Move expression logic from RecursiveStatementVisitor to RecursiveAstVisitor
1 parent 7900dda commit 632a041

File tree

3 files changed

+221
-240
lines changed

3 files changed

+221
-240
lines changed

lib/src/visitor/recursive_ast.dart

Lines changed: 178 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// MIT-style license that can be found in the LICENSE file or at
33
// https://opensource.org/licenses/MIT.
44

5+
import 'package:meta/meta.dart';
6+
7+
import '../util/nullable.dart';
58
import '../ast/sass.dart';
69
import 'interface/expression.dart';
710
import 'recursive_statement.dart';
@@ -10,13 +13,134 @@ import 'recursive_statement.dart';
1013
/// AST.
1114
///
1215
/// This extends [RecursiveStatementVisitor] to traverse each expression in
13-
/// addition to each statement.
16+
/// addition to each statement. It adds even more protected methods:
17+
///
18+
/// * [visitArgumentInvocation]
19+
/// * [visitSupportsCondition]
20+
/// * [visitInterpolation]
1421
///
1522
/// {@category Visitor}
1623
abstract class RecursiveAstVisitor extends RecursiveStatementVisitor
1724
implements ExpressionVisitor<void> {
1825
const RecursiveAstVisitor();
1926

27+
void visitAtRootRule(AtRootRule node) {
28+
super.visitAtRootRule(node);
29+
}
30+
31+
void visitAtRule(AtRule node) {
32+
visitInterpolation(node.name);
33+
node.value.andThen(visitInterpolation);
34+
super.visitAtRule(node);
35+
}
36+
37+
void visitContentRule(ContentRule node) {
38+
visitArgumentInvocation(node.arguments);
39+
}
40+
41+
void visitDebugRule(DebugRule node) {
42+
visitExpression(node.expression);
43+
}
44+
45+
void visitDeclaration(Declaration node) {
46+
visitInterpolation(node.name);
47+
node.value.andThen(visitExpression);
48+
super.visitDeclaration(node);
49+
}
50+
51+
void visitEachRule(EachRule node) {
52+
visitExpression(node.list);
53+
super.visitEachRule(node);
54+
}
55+
56+
void visitErrorRule(ErrorRule node) {
57+
visitExpression(node.expression);
58+
}
59+
60+
void visitExtendRule(ExtendRule node) {
61+
visitInterpolation(node.selector);
62+
}
63+
64+
void visitForRule(ForRule node) {
65+
visitExpression(node.from);
66+
visitExpression(node.to);
67+
super.visitForRule(node);
68+
}
69+
70+
void visitIfRule(IfRule node) {
71+
for (var clause in node.clauses) {
72+
visitExpression(clause.expression);
73+
for (var child in clause.children) {
74+
child.accept(this);
75+
}
76+
}
77+
78+
node.lastClause.andThen((lastClause) {
79+
for (var child in lastClause.children) {
80+
child.accept(this);
81+
}
82+
});
83+
}
84+
85+
void visitImportRule(ImportRule node) {
86+
for (var import in node.imports) {
87+
if (import is StaticImport) {
88+
visitInterpolation(import.url);
89+
import.supports.andThen(visitSupportsCondition);
90+
import.media.andThen(visitInterpolation);
91+
}
92+
}
93+
}
94+
95+
void visitIncludeRule(IncludeRule node) {
96+
visitArgumentInvocation(node.arguments);
97+
super.visitIncludeRule(node);
98+
}
99+
100+
void visitLoudComment(LoudComment node) {
101+
visitInterpolation(node.text);
102+
}
103+
104+
void visitMediaRule(MediaRule node) {
105+
visitInterpolation(node.query);
106+
super.visitMediaRule(node);
107+
}
108+
109+
void visitMixinRule(MixinRule node) => visitCallableDeclaration(node);
110+
111+
void visitReturnRule(ReturnRule node) {
112+
visitExpression(node.expression);
113+
}
114+
115+
void visitStyleRule(StyleRule node) {
116+
visitInterpolation(node.selector);
117+
super.visitStyleRule(node);
118+
}
119+
120+
void visitSupportsRule(SupportsRule node) {
121+
visitSupportsCondition(node.condition);
122+
super.visitSupportsRule(node);
123+
}
124+
125+
void visitUseRule(UseRule node) {
126+
for (var variable in node.configuration) {
127+
variable.expression.accept(this);
128+
}
129+
}
130+
131+
void visitVariableDeclaration(VariableDeclaration node) {
132+
visitExpression(node.expression);
133+
}
134+
135+
void visitWarnRule(WarnRule node) {
136+
visitExpression(node.expression);
137+
}
138+
139+
void visitWhileRule(WhileRule node) {
140+
visitExpression(node.condition);
141+
super.visitWhileRule(node);
142+
}
143+
20144
void visitExpression(Expression expression) {
21145
expression.accept(this);
22146
}
@@ -76,13 +200,61 @@ abstract class RecursiveAstVisitor extends RecursiveStatementVisitor
76200
node.operand.accept(this);
77201
}
78202

79-
void visitUseRule(UseRule node) {
80-
for (var variable in node.configuration) {
81-
variable.expression.accept(this);
203+
void visitValueExpression(ValueExpression node) {}
204+
205+
void visitVariableExpression(VariableExpression node) {}
206+
207+
@protected
208+
void visitCallableDeclaration(CallableDeclaration node) {
209+
for (var argument in node.arguments.arguments) {
210+
argument.defaultValue.andThen(visitExpression);
82211
}
212+
super.visitCallableDeclaration(node);
83213
}
84214

85-
void visitValueExpression(ValueExpression node) {}
215+
/// Visits each expression in an [invocation].
216+
///
217+
/// The default implementation of the visit methods calls this to visit any
218+
/// argument invocation in a statement.
219+
@protected
220+
void visitArgumentInvocation(ArgumentInvocation invocation) {
221+
for (var expression in invocation.positional) {
222+
visitExpression(expression);
223+
}
224+
for (var expression in invocation.named.values) {
225+
visitExpression(expression);
226+
}
227+
invocation.rest.andThen(visitExpression);
228+
invocation.keywordRest.andThen(visitExpression);
229+
}
86230

87-
void visitVariableExpression(VariableExpression node) {}
231+
/// Visits each expression in [condition].
232+
///
233+
/// The default implementation of the visit methods call this to visit any
234+
/// [SupportsCondition] they encounter.
235+
@protected
236+
void visitSupportsCondition(SupportsCondition condition) {
237+
if (condition is SupportsOperation) {
238+
visitSupportsCondition(condition.left);
239+
visitSupportsCondition(condition.right);
240+
} else if (condition is SupportsNegation) {
241+
visitSupportsCondition(condition.condition);
242+
} else if (condition is SupportsInterpolation) {
243+
visitExpression(condition.expression);
244+
} else if (condition is SupportsDeclaration) {
245+
visitExpression(condition.name);
246+
visitExpression(condition.value);
247+
}
248+
}
249+
250+
/// Visits each expression in an [interpolation].
251+
///
252+
/// The default implementation of the visit methods call this to visit any
253+
/// interpolation in a statement.
254+
@protected
255+
void visitInterpolation(Interpolation interpolation) {
256+
for (var node in interpolation.contents) {
257+
if (node is Expression) visitExpression(node);
258+
}
259+
}
88260
}

0 commit comments

Comments
 (0)