Skip to content

Commit

Permalink
Check if base visitor is defined (fix acornjs#829)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakub-g committed May 3, 2019
1 parent b2e8179 commit c215949
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 8 deletions.
17 changes: 17 additions & 0 deletions acorn-walk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,20 @@ the given position.
**findNodeAfter**`(node, pos, test, base, state)` is similar to
`findNodeAround`, but will match all nodes *after* the given position
(testing outer nodes before inner nodes).


## Walking with a plugin

When you use a parser plugin, e.g. `acorn-jsx`, you might see an error
message like `Base visitor for type JSXElement not found`.
In such case, you need to pass an additional `base` parameter,
in which you define the base visitors for all the types defined
by the plugin. For example, you can extend the default base in the
following way:

```js
walk.simple(parsedJsx, {}, {
...walk.base,
JSXElement: () => {}
})
````
23 changes: 15 additions & 8 deletions acorn-walk/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// AST walker module for Mozilla Parser API compatible trees

function assertBaseVisitor(baseVisitor, type) {
if (typeof baseVisitor[type] !== "function") {
throw new Error(`Base visitor for type ${type} not found. You should define it in the 'base' parameter.`)
}
return true
}

// A simple walk is one where you simply specify callbacks to be
// called on specific nodes. The last two arguments are optional. A
// simple use would be
Expand All @@ -20,7 +27,7 @@ export function simple(node, visitors, baseVisitor, state, override) {
if (!baseVisitor) baseVisitor = base
;(function c(node, st, override) {
let type = override || node.type, found = visitors[type]
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
if (found) found(node, st)
})(node, state, override)
}
Expand All @@ -35,7 +42,7 @@ export function ancestor(node, visitors, baseVisitor, state) {
let type = override || node.type, found = visitors[type]
let isNew = node !== ancestors[ancestors.length - 1]
if (isNew) ancestors.push(node)
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
if (found) found(node, st || ancestors, ancestors)
if (isNew) ancestors.pop()
})(node, state)
Expand Down Expand Up @@ -71,7 +78,7 @@ export function full(node, callback, baseVisitor, state, override) {
if (!baseVisitor) baseVisitor = base
;(function c(node, st, override) {
let type = override || node.type
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
if (!override) callback(node, st, type)
})(node, state, override)
}
Expand All @@ -85,7 +92,7 @@ export function fullAncestor(node, callback, baseVisitor, state) {
let type = override || node.type
let isNew = node !== ancestors[ancestors.length - 1]
if (isNew) ancestors.push(node)
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
if (!override) callback(node, st || ancestors, ancestors, type)
if (isNew) ancestors.pop()
})(node, state)
Expand All @@ -102,7 +109,7 @@ export function findNodeAt(node, start, end, test, baseVisitor, state) {
let type = override || node.type
if ((start == null || node.start <= start) &&
(end == null || node.end >= end))
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
if ((start == null || node.start === start) &&
(end == null || node.end === end) &&
test(type, node))
Expand All @@ -123,7 +130,7 @@ export function findNodeAround(node, pos, test, baseVisitor, state) {
(function c(node, st, override) {
let type = override || node.type
if (node.start > pos || node.end < pos) return
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
if (test(type, node)) throw new Found(node, st)
})(node, state)
} catch (e) {
Expand All @@ -141,7 +148,7 @@ export function findNodeAfter(node, pos, test, baseVisitor, state) {
if (node.end < pos) return
let type = override || node.type
if (node.start >= pos && test(type, node)) throw new Found(node, st)
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
})(node, state)
} catch (e) {
if (e instanceof Found) return e
Expand All @@ -159,7 +166,7 @@ export function findNodeBefore(node, pos, test, baseVisitor, state) {
let type = override || node.type
if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))
max = new Found(node, st)
baseVisitor[type](node, st, c)
assertBaseVisitor(baseVisitor, type) && baseVisitor[type](node, st, c)
})(node, state)
return max
}
Expand Down

0 comments on commit c215949

Please sign in to comment.