'use strict';
var should = require('should');

var esprima = require('esprima');
var j = require('junify');

var assert = require('assert');

function match(patterns) {
  return function(it) {
    return patterns.some(function(pattern) {
      return  j.unify(pattern, it);
    })
  }
}

function identifier(binding) {
  return { type: 'Identifier', name: binding };
}

function HasBinding(binding, ast) {
  return declarationsOf(ast).some(match([
    { type: 'FunctionDeclaration', id: identifier(binding), _: j._ },
    {
      type: 'VariableDeclaration',
      declarations: [{
        type: 'VariableDeclarator',
        id: identifier(binding),
        init: j._ }],
        _: j._
      }]));
}

function declarationsOf(ast) {
  return ast.body.filter(match([
    {type: 'VariableDeclaration', _: j._},
    {type: 'FunctionDeclaration', _: j._}]));
}

function p(code) {
  return esprima.parse(code)
}

describe('HasBinding', function () {

  it("hasBinding when function declaration exists for binding", function(){
    assert(HasBinding('foo', p('function foo(){}')));
  })

  it("not hasBinding when function declaration exist for other binding", function(){
    assert(!HasBinding('bar', p('function foo(){}')));
  })

  it("not hasBinding when code is empty", function(){
    assert(!HasBinding('bar', p('')));
  })

  it("hasBinding when code has variable for binding", function(){
    assert(HasBinding('bar', p('var bar = 4')));
  })

  it("not hasBinding when code has variable for other binding", function(){
    assert(!HasBinding('bar', p('var foo = 4')));
  })

  it("not hasBinding when code has expression", function(){
    assert(!HasBinding('bar', p('5 + 2')));
  })
});

@@ -7,16 +7,17 @@
 trict';%0A
+%0A
 var shou
@@ -274,20 +274,22 @@
 ;%0A    %7D)
+;
 %0A  %7D
+;
 %0A%7D%0A%0Afunc
@@ -375,17 +375,17 @@
 unction 
-H
+h
 asBindin
@@ -902,16 +902,17 @@
 se(code)
+;
 %0A%7D%0A%0Adesc
@@ -917,17 +917,17 @@
 scribe('
-H
+h
 asBindin
@@ -946,25 +946,25 @@
  () %7B%0A%0A  it(
-%22
+'
 hasBinding w
@@ -998,33 +998,33 @@
 ists for binding
-%22
+'
 , function()%7B%0A  
@@ -1024,33 +1024,33 @@
 n()%7B%0A    assert(
-H
+h
 asBinding('foo',
@@ -1075,32 +1075,33 @@
 %7B%7D')));%0A  %7D)
+;
 %0A%0A  it(
-%22
+'
 not hasBindi
@@ -1144,33 +1144,33 @@
 or other binding
-%22
+'
 , function()%7B%0A  
@@ -1171,33 +1171,33 @@
 ()%7B%0A    assert(!
-H
+h
 asBinding('bar',
@@ -1222,32 +1222,33 @@
 %7B%7D')));%0A  %7D)
+;
 %0A%0A  it(
-%22
+'
 not hasBindi
@@ -1268,17 +1268,17 @@
 is empty
-%22
+'
 , functi
@@ -1287,33 +1287,33 @@
 ()%7B%0A    assert(!
-H
+h
 asBinding('bar',
@@ -1326,24 +1326,25 @@
 ));%0A  %7D)
+;
 %0A%0A  it(
-%22
+'
 hasBindi
@@ -1372,33 +1372,33 @@
 able for binding
-%22
+'
 , function()%7B%0A  
@@ -1406,17 +1406,17 @@
  assert(
-H
+h
 asBindin
@@ -1444,32 +1444,33 @@
  4')));%0A  %7D)
+;
 %0A%0A  it(
-%22
+'
 not hasBindi
@@ -1512,17 +1512,17 @@
  binding
-%22
+'
 , functi
@@ -1531,33 +1531,33 @@
 ()%7B%0A    assert(!
-H
+h
 asBinding('bar',
@@ -1585,16 +1585,17 @@
   %7D)
+;
 %0A%0A  it(
-%22
+'
 not 
@@ -1633,9 +1633,9 @@
 sion
-%22
+'
 , fu
@@ -1660,9 +1660,9 @@
 rt(!
-H
+h
 asBi
@@ -1692,13 +1692,14 @@
 ));%0A  %7D)
+;
 %0A%7D);%0A

fix linter