refactor(compiler): Remove NullAstVisitor and visitAstChildren (#35619)

This commit removes the `NullAstVisitor` and `visitAstChildren` exported
from `packages/compiler/src/expression_parser/ast.ts` because they
contain duplicate and buggy implementation, and their use cases could be
sufficiently covered by `RecursiveAstVisitor` if the latter implements the
`visit` method. This use case is only needed in the language service.

With this change, any visitor that extends `RecursiveAstVisitor` could
just define their own `visit` function and the parent class will behave
correctly.

A bit of historical context:
In language service, we need a way to tranverse the expression AST in a
selective manner based on where the user's cursor is. This means we need a
"filtering" function to decide which node to visit and which node to not
visit. Instead of refactoring `RecursiveAstVisitor` to support this,
`visitAstChildren` was created. `visitAstChildren` duplicates the
implementation of `RecursiveAstVisitor`, but introduced some bugs along
the way. For example, in `visitKeyedWrite`, it visits
```
obj -> key -> obj
```
instead of
```
obj -> key -> value
```

Moreover, because of the following line
```
visitor.visit && visitor.visit(ast, context) || ast.visit(visitor, context);
```
`visitAstChildren` visits every node *twice*.

PR Close #35619
This commit is contained in:
Keen Yee Liau
2020-02-21 10:20:52 -08:00
committed by atscott
parent de4e17b76e
commit 208ef7bd62
7 changed files with 134 additions and 144 deletions

View File

@ -17,6 +17,17 @@ class ExpressionSourceHumanizer extends e.RecursiveAstVisitor implements t.Visit
private recordAst(ast: e.AST) { this.result.push([unparse(ast), ast.sourceSpan]); }
// This method is defined to reconcile the type of ExpressionSourceHumanizer
// since both RecursiveAstVisitor and Visitor define the visit() method in
// their interfaces.
visit(node: e.AST|t.Node, context?: any) {
if (node instanceof e.AST) {
node.visit(this, context);
} else {
node.visit(this);
}
}
visitASTWithSource(ast: e.ASTWithSource) {
this.recordAst(ast);
this.visitAll([ast.ast], null);