Skip to content

Commit

Permalink
Move expression logic from RecursiveStatementVisitor to RecursiveAstV…
Browse files Browse the repository at this point in the history
…isitor
  • Loading branch information
nex3 committed Jul 31, 2021
1 parent 7900dda commit 632a041
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 240 deletions.
184 changes: 178 additions & 6 deletions lib/src/visitor/recursive_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'package:meta/meta.dart';

import '../util/nullable.dart';
import '../ast/sass.dart';
import 'interface/expression.dart';
import 'recursive_statement.dart';
Expand All @@ -10,13 +13,134 @@ import 'recursive_statement.dart';
/// AST.
///
/// This extends [RecursiveStatementVisitor] to traverse each expression in
/// addition to each statement.
/// addition to each statement. It adds even more protected methods:
///
/// * [visitArgumentInvocation]
/// * [visitSupportsCondition]
/// * [visitInterpolation]
///
/// {@category Visitor}
abstract class RecursiveAstVisitor extends RecursiveStatementVisitor
implements ExpressionVisitor<void> {
const RecursiveAstVisitor();

void visitAtRootRule(AtRootRule node) {
super.visitAtRootRule(node);
}

void visitAtRule(AtRule node) {
visitInterpolation(node.name);
node.value.andThen(visitInterpolation);
super.visitAtRule(node);
}

void visitContentRule(ContentRule node) {
visitArgumentInvocation(node.arguments);
}

void visitDebugRule(DebugRule node) {
visitExpression(node.expression);
}

void visitDeclaration(Declaration node) {
visitInterpolation(node.name);
node.value.andThen(visitExpression);
super.visitDeclaration(node);
}

void visitEachRule(EachRule node) {
visitExpression(node.list);
super.visitEachRule(node);
}

void visitErrorRule(ErrorRule node) {
visitExpression(node.expression);
}

void visitExtendRule(ExtendRule node) {
visitInterpolation(node.selector);
}

void visitForRule(ForRule node) {
visitExpression(node.from);
visitExpression(node.to);
super.visitForRule(node);
}

void visitIfRule(IfRule node) {
for (var clause in node.clauses) {
visitExpression(clause.expression);
for (var child in clause.children) {
child.accept(this);
}
}

node.lastClause.andThen((lastClause) {
for (var child in lastClause.children) {
child.accept(this);
}
});
}

void visitImportRule(ImportRule node) {
for (var import in node.imports) {
if (import is StaticImport) {
visitInterpolation(import.url);
import.supports.andThen(visitSupportsCondition);
import.media.andThen(visitInterpolation);
}
}
}

void visitIncludeRule(IncludeRule node) {
visitArgumentInvocation(node.arguments);
super.visitIncludeRule(node);
}

void visitLoudComment(LoudComment node) {
visitInterpolation(node.text);
}

void visitMediaRule(MediaRule node) {
visitInterpolation(node.query);
super.visitMediaRule(node);
}

void visitMixinRule(MixinRule node) => visitCallableDeclaration(node);

void visitReturnRule(ReturnRule node) {
visitExpression(node.expression);
}

void visitStyleRule(StyleRule node) {
visitInterpolation(node.selector);
super.visitStyleRule(node);
}

void visitSupportsRule(SupportsRule node) {
visitSupportsCondition(node.condition);
super.visitSupportsRule(node);
}

void visitUseRule(UseRule node) {
for (var variable in node.configuration) {
variable.expression.accept(this);
}
}

void visitVariableDeclaration(VariableDeclaration node) {
visitExpression(node.expression);
}

void visitWarnRule(WarnRule node) {
visitExpression(node.expression);
}

void visitWhileRule(WhileRule node) {
visitExpression(node.condition);
super.visitWhileRule(node);
}

void visitExpression(Expression expression) {
expression.accept(this);
}
Expand Down Expand Up @@ -76,13 +200,61 @@ abstract class RecursiveAstVisitor extends RecursiveStatementVisitor
node.operand.accept(this);
}

void visitUseRule(UseRule node) {
for (var variable in node.configuration) {
variable.expression.accept(this);
void visitValueExpression(ValueExpression node) {}

void visitVariableExpression(VariableExpression node) {}

@protected
void visitCallableDeclaration(CallableDeclaration node) {
for (var argument in node.arguments.arguments) {
argument.defaultValue.andThen(visitExpression);
}
super.visitCallableDeclaration(node);
}

void visitValueExpression(ValueExpression node) {}
/// Visits each expression in an [invocation].
///
/// The default implementation of the visit methods calls this to visit any
/// argument invocation in a statement.
@protected
void visitArgumentInvocation(ArgumentInvocation invocation) {
for (var expression in invocation.positional) {
visitExpression(expression);
}
for (var expression in invocation.named.values) {
visitExpression(expression);
}
invocation.rest.andThen(visitExpression);
invocation.keywordRest.andThen(visitExpression);
}

void visitVariableExpression(VariableExpression node) {}
/// Visits each expression in [condition].
///
/// The default implementation of the visit methods call this to visit any
/// [SupportsCondition] they encounter.
@protected
void visitSupportsCondition(SupportsCondition condition) {
if (condition is SupportsOperation) {
visitSupportsCondition(condition.left);
visitSupportsCondition(condition.right);
} else if (condition is SupportsNegation) {
visitSupportsCondition(condition.condition);
} else if (condition is SupportsInterpolation) {
visitExpression(condition.expression);
} else if (condition is SupportsDeclaration) {
visitExpression(condition.name);
visitExpression(condition.value);
}
}

/// Visits each expression in an [interpolation].
///
/// The default implementation of the visit methods call this to visit any
/// interpolation in a statement.
@protected
void visitInterpolation(Interpolation interpolation) {
for (var node in interpolation.contents) {
if (node is Expression) visitExpression(node);
}
}
}
Loading

0 comments on commit 632a041

Please sign in to comment.