| 1 | # Acorn AST walker
|
|---|
| 2 |
|
|---|
| 3 | An abstract syntax tree walker for the
|
|---|
| 4 | [ESTree](https://github.com/estree/estree) format.
|
|---|
| 5 |
|
|---|
| 6 | ## Community
|
|---|
| 7 |
|
|---|
| 8 | Acorn is open source software released under an
|
|---|
| 9 | [MIT license](https://github.com/acornjs/acorn/blob/master/acorn-walk/LICENSE).
|
|---|
| 10 |
|
|---|
| 11 | You are welcome to
|
|---|
| 12 | [report bugs](https://github.com/acornjs/acorn/issues) or create pull
|
|---|
| 13 | requests on [github](https://github.com/acornjs/acorn). For questions
|
|---|
| 14 | and discussion, please use the
|
|---|
| 15 | [Tern discussion forum](https://discuss.ternjs.net).
|
|---|
| 16 |
|
|---|
| 17 | ## Installation
|
|---|
| 18 |
|
|---|
| 19 | The easiest way to install acorn is from [`npm`](https://www.npmjs.com/):
|
|---|
| 20 |
|
|---|
| 21 | ```sh
|
|---|
| 22 | npm install acorn-walk
|
|---|
| 23 | ```
|
|---|
| 24 |
|
|---|
| 25 | Alternately, you can download the source and build acorn yourself:
|
|---|
| 26 |
|
|---|
| 27 | ```sh
|
|---|
| 28 | git clone https://github.com/acornjs/acorn.git
|
|---|
| 29 | cd acorn
|
|---|
| 30 | npm install
|
|---|
| 31 | ```
|
|---|
| 32 |
|
|---|
| 33 | ## Interface
|
|---|
| 34 |
|
|---|
| 35 | An algorithm for recursing through a syntax tree is stored as an
|
|---|
| 36 | object, with a property for each tree node type holding a function
|
|---|
| 37 | that will recurse through such a node. There are several ways to run
|
|---|
| 38 | such a walker.
|
|---|
| 39 |
|
|---|
| 40 | **simple**`(node, visitors, base, state)` does a 'simple' walk over a
|
|---|
| 41 | tree. `node` should be the AST node to walk, and `visitors` an object
|
|---|
| 42 | with properties whose names correspond to node types in the [ESTree
|
|---|
| 43 | spec](https://github.com/estree/estree). The properties should contain
|
|---|
| 44 | functions that will be called with the node object and, if applicable
|
|---|
| 45 | the state at that point. The last two arguments are optional. `base`
|
|---|
| 46 | is a walker algorithm, and `state` is a start state. The default
|
|---|
| 47 | walker will simply visit all statements and expressions and not
|
|---|
| 48 | produce a meaningful state. (An example of a use of state is to track
|
|---|
| 49 | scope at each point in the tree.)
|
|---|
| 50 |
|
|---|
| 51 | ```js
|
|---|
| 52 | const acorn = require("acorn")
|
|---|
| 53 | const walk = require("acorn-walk")
|
|---|
| 54 |
|
|---|
| 55 | walk.simple(acorn.parse("let x = 10"), {
|
|---|
| 56 | Literal(node) {
|
|---|
| 57 | console.log(`Found a literal: ${node.value}`)
|
|---|
| 58 | }
|
|---|
| 59 | })
|
|---|
| 60 | ```
|
|---|
| 61 |
|
|---|
| 62 | **ancestor**`(node, visitors, base, state)` does a 'simple' walk over
|
|---|
| 63 | a tree, building up an array of ancestor nodes (including the current node)
|
|---|
| 64 | and passing the array to the callbacks as a third parameter.
|
|---|
| 65 |
|
|---|
| 66 | ```js
|
|---|
| 67 | const acorn = require("acorn")
|
|---|
| 68 | const walk = require("acorn-walk")
|
|---|
| 69 |
|
|---|
| 70 | walk.ancestor(acorn.parse("foo('hi')"), {
|
|---|
| 71 | Literal(_, ancestors) {
|
|---|
| 72 | console.log("This literal's ancestors are:", ancestors.map(n => n.type))
|
|---|
| 73 | }
|
|---|
| 74 | })
|
|---|
| 75 | ```
|
|---|
| 76 |
|
|---|
| 77 | **recursive**`(node, state, functions, base)` does a 'recursive'
|
|---|
| 78 | walk, where the walker functions are responsible for continuing the
|
|---|
| 79 | walk on the child nodes of their target node. `state` is the start
|
|---|
| 80 | state, and `functions` should contain an object that maps node types
|
|---|
| 81 | to walker functions. Such functions are called with `(node, state, c)`
|
|---|
| 82 | arguments, and can cause the walk to continue on a sub-node by calling
|
|---|
| 83 | the `c` argument on it with `(node, state)` arguments. The optional
|
|---|
| 84 | `base` argument provides the fallback walker functions for node types
|
|---|
| 85 | that aren't handled in the `functions` object. If not given, the
|
|---|
| 86 | default walkers will be used.
|
|---|
| 87 |
|
|---|
| 88 | **make**`(functions, base)` builds a new walker object by using the
|
|---|
| 89 | walker functions in `functions` and filling in the missing ones by
|
|---|
| 90 | taking defaults from `base`.
|
|---|
| 91 |
|
|---|
| 92 | **full**`(node, callback, base, state)` does a 'full' walk over a
|
|---|
| 93 | tree, calling the callback with the arguments (node, state, type) for
|
|---|
| 94 | each node
|
|---|
| 95 |
|
|---|
| 96 | **fullAncestor**`(node, callback, base, state)` does a 'full' walk
|
|---|
| 97 | over a tree, building up an array of ancestor nodes (including the
|
|---|
| 98 | current node) and passing the array to the callbacks as a third
|
|---|
| 99 | parameter.
|
|---|
| 100 |
|
|---|
| 101 | ```js
|
|---|
| 102 | const acorn = require("acorn")
|
|---|
| 103 | const walk = require("acorn-walk")
|
|---|
| 104 |
|
|---|
| 105 | walk.full(acorn.parse("1 + 1"), node => {
|
|---|
| 106 | console.log(`There's a ${node.type} node at ${node.ch}`)
|
|---|
| 107 | })
|
|---|
| 108 | ```
|
|---|
| 109 |
|
|---|
| 110 | **findNodeAt**`(node, start, end, test, base, state)` tries to locate
|
|---|
| 111 | a node in a tree at the given start and/or end offsets, which
|
|---|
| 112 | satisfies the predicate `test`. `start` and `end` can be either `null`
|
|---|
| 113 | (as wildcard) or a number. `test` may be a string (indicating a node
|
|---|
| 114 | type) or a function that takes `(nodeType, node)` arguments and
|
|---|
| 115 | returns a boolean indicating whether this node is interesting. `base`
|
|---|
| 116 | and `state` are optional, and can be used to specify a custom walker.
|
|---|
| 117 | Nodes are tested from inner to outer, so if two nodes match the
|
|---|
| 118 | boundaries, the inner one will be preferred.
|
|---|
| 119 |
|
|---|
| 120 | **findNodeAround**`(node, pos, test, base, state)` is a lot like
|
|---|
| 121 | `findNodeAt`, but will match any node that exists 'around' (spanning)
|
|---|
| 122 | the given position.
|
|---|
| 123 |
|
|---|
| 124 | **findNodeAfter**`(node, pos, test, base, state)` is similar to
|
|---|
| 125 | `findNodeAround`, but will match all nodes *after* the given position
|
|---|
| 126 | (testing outer nodes before inner nodes).
|
|---|