<commit_before>escallmatch
================================

ECMAScript CallExpression matcher made from function/method signature

[![Build Status](https://travis-ci.org/twada/escallmatch.svg?branch=master)](https://travis-ci.org/twada/escallmatch)
[![NPM version](https://badge.fury.io/js/escallmatch.svg)](http://badge.fury.io/js/escallmatch)
[![Dependency Status](https://gemnasium.com/twada/escallmatch.svg)](https://gemnasium.com/twada/escallmatch)
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://twada.mit-license.org/)
[![Built with Gulp](http://img.shields.io/badge/built_with-gulp-brightgreen.svg)](http://gulpjs.com/)



EXAMPLE
---------------------------------------

Creating CallExpression matcher for method signature `'assert.equal(actual, expected, [message])'`.

Then match against `path/to/some_test.js`.

```javascript
var escallmatch = require('escallmatch'),
    esprima = require('esprima'),
    estraverse = require('estraverse'),
    fs = require('fs');

var matcher = escallmatch('assert.equal(actual, expected, [message])');

estraverse.traverse(esprima.parse(fs.readFileSync('path/to/some_test.js')), {
    enter: function (currentNode, parentNode) {
        if (matcher.test(currentNode)) {
            // currentNode is a CallExpression that matches to the signature
        }
        var argMatched = matcher.matchArgument(currentNode, parentNode);
        if (argMatched) {
            if (argMatched.kind === 'mandatory') {
                // mandatory arg (in this case, `actual` or `expected`)
            } else if (argMatched.kind === 'optional') {
                // optional arg (in this case, `message`)
            }
        }
    }
});
```

where content of `path/to/some_test.js` is:

```javascript
var assert = require('assert'),
    anotherAssert = assert,
    equal = assert.equal.bind(assert),
    foo = '2',
    bar = 2;

assert.equal(foo, bar);  // matches
assert.equal(bar, foo);  // matches
assert.equal(foo, bar, 'foo shoule be equal to bar');  // matches (with optional arg)

assert.equal();  // does not match (less args)
assert.equal(foo);  // does not match (less args)
assert.equal(foo, bar, 'hoge', 'fuga');  // does not match (too much args)

assert.notEqual(foo, bar);  // does not match (callee method name differs)
anotherAssert.equal(foo, bar);  // does not match (callee object name differs)
equal(foo, bar);  // does not match (callee does not match)
```

`escallmatch` is a spin-off product of [power-assert](http://github.com/twada/power-assert) project.

Pull-requests, issue reports and patches are always welcomed.


API
---------------------------------------

### var matcher = escallmatch(signatureStr)

Create matcher object for a given function/method signature string.

```javascript
var matcher = escallmatch('assert.equal(actual, expected, [message])');
```

Any arguments enclosed in bracket (for example, `[message]`) means optional parameters. Without bracket means mandatory parameters.

Returns `matcher` object having four methods, `test`, `matchArgument`, `calleeAst`, and `argumentSignatures`.


### var isMatched = matcher.test(node)

Tests whether `node` matches the signature or not.

 - Returns `true` if matched.
 - Returns `false` if not matched.

`node` should be an AST node object defined in [Mozilla JavaScript AST spec](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API).


### var argMatched = matcher.matchArgument(node, parentNode)

Returns match result object representing whether `node` (and its `parentNode`) matches some argument of the signature or not.

 - Returns `null` if not matched.
 - If matched, returns object like `{name: 'actual', kind: 'mandatory'}`, whose `name` is an argument name in the signature and `kind` is `'mandatory'` or `'optional'`.

`node` and `parentNode` should be AST node objects defined in [Mozilla JavaScript AST spec](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API).
<commit_msg>docs(README): document for `options.visitorKeys`<commit_after>escallmatch
================================

ECMAScript CallExpression matcher made from function/method signature

[![Build Status](https://travis-ci.org/twada/escallmatch.svg?branch=master)](https://travis-ci.org/twada/escallmatch)
[![NPM version](https://badge.fury.io/js/escallmatch.svg)](http://badge.fury.io/js/escallmatch)
[![Dependency Status](https://gemnasium.com/twada/escallmatch.svg)](https://gemnasium.com/twada/escallmatch)
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://twada.mit-license.org/)
[![Built with Gulp](http://img.shields.io/badge/built_with-gulp-brightgreen.svg)](http://gulpjs.com/)



EXAMPLE
---------------------------------------

Creating CallExpression matcher for method signature `'assert.equal(actual, expected, [message])'`.

Then match against `path/to/some_test.js`.

```javascript
var escallmatch = require('escallmatch'),
    esprima = require('esprima'),
    estraverse = require('estraverse'),
    fs = require('fs');

var matcher = escallmatch('assert.equal(actual, expected, [message])');

estraverse.traverse(esprima.parse(fs.readFileSync('path/to/some_test.js')), {
    enter: function (currentNode, parentNode) {
        if (matcher.test(currentNode)) {
            // currentNode is a CallExpression that matches to the signature
        }
        var argMatched = matcher.matchArgument(currentNode, parentNode);
        if (argMatched) {
            if (argMatched.kind === 'mandatory') {
                // mandatory arg (in this case, `actual` or `expected`)
            } else if (argMatched.kind === 'optional') {
                // optional arg (in this case, `message`)
            }
        }
    }
});
```

where content of `path/to/some_test.js` is:

```javascript
var assert = require('assert'),
    anotherAssert = assert,
    equal = assert.equal.bind(assert),
    foo = '2',
    bar = 2;

assert.equal(foo, bar);  // matches
assert.equal(bar, foo);  // matches
assert.equal(foo, bar, 'foo shoule be equal to bar');  // matches (with optional arg)

assert.equal();  // does not match (less args)
assert.equal(foo);  // does not match (less args)
assert.equal(foo, bar, 'hoge', 'fuga');  // does not match (too much args)

assert.notEqual(foo, bar);  // does not match (callee method name differs)
anotherAssert.equal(foo, bar);  // does not match (callee object name differs)
equal(foo, bar);  // does not match (callee does not match)
```

`escallmatch` is a spin-off product of [power-assert](http://github.com/twada/power-assert) project.

Pull-requests, issue reports and patches are always welcomed.


API
---------------------------------------

### var matcher = escallmatch(signatureStr, [options])

Create matcher object for a given function/method signature string.

```javascript
var matcher = escallmatch('assert.equal(actual, expected, [message])');
```

Any arguments enclosed in bracket (for example, `[message]`) means optional parameters. Without bracket means mandatory parameters.

Returns `matcher` object having four methods, `test`, `matchArgument`, `calleeAst`, and `argumentSignatures`.


#### options

an `object` for configuration options. If not passed, default options will be used.


#### options.visitorKeys

| type     | default value |
|:---------|:--------------|
| `object` | (return value of `estraverse.VisitorKeys`)   |

VisitorKeys for AST traversal. See [estraverse.VisitorKeys](https://github.com/estools/estraverse/blob/4.0.0/estraverse.js#L217-L288) and [babel.types.VISITOR_KEYS](https://github.com/babel/babel/blob/v5.1.11/src/babel/types/visitor-keys.json).


### var isMatched = matcher.test(node)

Tests whether `node` matches the signature or not.

 - Returns `true` if matched.
 - Returns `false` if not matched.

`node` should be an AST node object defined in [Mozilla JavaScript AST spec](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API).


### var argMatched = matcher.matchArgument(node, parentNode)

Returns match result object representing whether `node` (and its `parentNode`) matches some argument of the signature or not.

 - Returns `null` if not matched.
 - If matched, returns object like `{name: 'actual', kind: 'mandatory'}`, whose `name` is an argument name in the signature and `kind` is `'mandatory'` or `'optional'`.

`node` and `parentNode` should be AST node objects defined in [Mozilla JavaScript AST spec](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API).

{'fraction_non_alphanumeric': 0.16815721346199106, 'fraction_numerical': 0.002000470698987997, 'mean_word_length': 3.737458193979933, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 16, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6042402', 'n_tokens_mistral': 2615, 'n_tokens_neox': 2536, 'n_words': 703}