UNPKG

4.5 kBMarkdownView Raw
1# scope-analyzer
2
3simple scope analysis for javascript ASTs. tracks scopes and collects references to variables.
4
5Caveats and/or todos:
6
7 - May be missing edge cases.
8 - Things like `label:`s are not considered at all, but ideally in the future they will!
9
10[![stability][stability-image]][stability-url]
11[![npm][npm-image]][npm-url]
12[![travis][travis-image]][travis-url]
13[![standard][standard-image]][standard-url]
14
15[stability-image]: https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square
16[stability-url]: https://nodejs.org/api/documentation.html#documentation_stability_index
17[npm-image]: https://img.shields.io/npm/v/scope-analyzer.svg?style=flat-square
18[npm-url]: https://www.npmjs.com/package/scope-analyzer
19[travis-image]: https://img.shields.io/travis/goto-bus-stop/scope-analyzer.svg?style=flat-square
20[travis-url]: https://travis-ci.org/goto-bus-stop/scope-analyzer
21[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
22[standard-url]: http://npm.im/standard
23
24## Install
25
26```
27npm install scope-analyzer
28```
29
30## Usage
31
32Note: AST nodes passed to `scope-analyzer` functions are expected to reference the parent node on a `node.parent` property.
33Nodes from [falafel](https://github.com/substack/node-falafel) or [transform-ast](https://github.com/goto-bus-stop/transform-ast) have a `.parent` property, but others may not. You can use [estree-assign-parent](https://github.com/goto-bus-stop/estree-assign-parent) to quickly assign a parent property to all nodes in an AST.
34
35```js
36var scan = require('scope-analyzer')
37
38var ast = parse('...')
39// Initialize node module variables
40scan.createScope(ast, ['module', 'exports', '__dirname', '__filename'])
41scan.analyze(ast)
42
43var binding = scan.getBinding(ast, 'exports')
44binding.getReferences().forEach(function (reference) {
45 // Assume for the sake of the example that all references to `exports` are assignments like
46 // `exports.xyz = abc`
47 console.log('found export:', reference.parent.property.name)
48})
49```
50
51## API
52
53### `crawl(ast)`
54
55Walk the ast and analyze all scopes. This will immediately allow you to use the `get*` methods on any node in the tree.
56
57### `visitScope(node)`
58
59Visit a node to check if it initialises any scopes.
60For example, a function declaration will initialise a new scope to hold bindings for its parameters.
61Use this if you are already walking the AST manually, and if you don't need the scope information during this walk.
62
63### `visitBinding(node)`
64
65Visit a node to check if it is a reference to an existing binding.
66If it is, the reference is added to the parent scope.
67Use this if you are already walking the AST manually.
68
69### `createScope(node, bindings)`
70
71Initialise a new scope at the given node. `bindings` is an array of variable names.
72This can be useful to make the scope analyzer aware of preexisting global variables.
73In that case, call `createScope` on the root node with the names of globals:
74
75```js
76var ast = parse('xyz')
77scopeAnalyzer.createScope(ast, ['HTMLElement', 'Notification', ...])
78```
79
80### `scope(node)`
81
82Get the [Scope](#scope) initialised by the given node.
83
84### `getBinding(node)`
85
86Get the [Binding](#binding) referenced by the `Identifier` `node`.
87
88### Scope
89
90#### `scope.has(name)`
91
92Check if this scope defines `name`.
93
94#### `scope.getBinding(name)`
95
96Get the [Binding](#binding) named `name` that is declared by this scope.
97
98#### `scope.getReferences(name)`
99
100Get a list of all nodes referencing the `name` binding that is declared by this scope.
101
102#### `scope.getUndeclaredNames()`
103
104Get a list of all names that were used in this scope, but not defined anywhere in the AST.
105
106#### `scope.forEach(cb(binding, name))`
107
108Loop over all bindings declared by this scope.
109
110#### `scope.forEachAvailable(cb(binding, name))`
111
112Loop over all bindings available to this scope, declared in this scope or any parent scope.
113
114### Binding
115
116#### `binding.definition`
117
118The node that defined this binding. If this binding was not declared in the AST, `binding.definition` will be undefined.
119
120#### `binding.getReferences()`
121
122Return an array of nodes that reference this binding.
123
124#### `binding.isReferenced()`
125
126Check if the binding is referenced, i.e., if there are any identifier Nodes (other than `binding.definition`) referencing this binding.
127
128#### `binding.remove(node)`
129
130Remove a reference to this binding. Use this when you are replacing the node referencing the binding with something else.
131
132## License
133
134[Apache-2.0](LICENSE.md)