scopenodes
=====

Find the AST nodes from a string of JavaScript that define scope. E.g. The outer Program scope and functions.

Example
---

```javascript
var scopenodes = require("./scopenodes")
var fs = require("fs")

var filename = process.argv[2] || "./test/lib/nested.js"
var content = fs.readFileSync(filename).toString()
var out = scopenodes(content)
console.log(out)

/*
  [ { type: 'Program',
    body: [ [Object], [Object] ],
    range: [ 0, 116 ],
    loc: { start: [Object], end: [Object] },
    path: [],
    parent: null },
  { type: 'BlockStatement',
    body: [ [Object] ],
    range: [ 21, 69 ],
    loc: { start: [Object], end: [Object] },
    path: [ [Object] ],
    parent:
     { type: 'FunctionDeclaration',
       id: [Object],
       params: [Object],
  ...

*/

```

API
===

`scopenodes(jsString)`
---

Will return a list of nodes from an AST (Esprima) that define scoped blocks of the provided JavaScript string.

It will add some properties to each node:
  * fnName: An attempted guess at the function name. It should always be right if the function is named.
  * path: A list of outer scopes in order of scopechain for this node
  * parent: For a FunctionDeclaration or FunctionExpression node, the declaration or expression.
  * isStrict: a boolean value as to whether *THIS SCOPE SPECIFICALLY* has declared strict mode. Does not account for inherited strict mode.

Naming generally works like the following, and may change as we go:
  1. If the function is named, use that name.
  2. If it is an assigment, use what it is assigned to
  3. If it is a function call argument or `new` argument, call it "fnName() fn argument" where fnName is the function called.
  4. If the call is complex (contains a parenthesis) attempt to remove all but the last bit. (e.g. foo.map(...).sort(...).forEach(...) will become ".forEach() fn argument")
  5. If the function looks like listener for an on event (e.g. `foo.on('exit', ...))` call it `foo.on 'exit' listener`
  6. In any of the above cases if that name has already been assigned, start indexing the names like so: foo, foo{2}, foo{3}, etc.

Naming nests with scope, so if you have code such as this:

```js
function foo() {
  function bar() {
    // ...
  }
}
```

The two functions would be named `foo` and `foo>bar` denoting that this bar is the one defind in the scope of `foo`.

