You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.4 KiB

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