Skip to content

Commit

Permalink
Start implementing Array API
Browse files Browse the repository at this point in the history
  • Loading branch information
SBoudrias committed Feb 26, 2014
1 parent 1a24152 commit 0e9f1a5
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ helpers.removeExtraComma = function( node ) {
.replace(/(var\s*)(,\s?)*/gi, "$1") // comma following a `var`
.replace(/(,\s?)(\s*\})/gi, "$2") // comma ending an object literal
.replace(/(\{\s*)(,\s?)/, "$1") // comma starting an object literal
.replace(/(\[\s*)(,\s?)/, "$1") // comma starting an array literal
.replace(/(,\s?)(\s*\])/gi, "$2") // comma ending an array literal
.replace(/(,)\s?;/gi, ";"); // ending comma
node.update( src );
};
10 changes: 9 additions & 1 deletion lib/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,12 @@ Tree.prototype.object = function() {
return token;
};


/**
* Add an array token to the queue
* @return {Var token} Selected variable token
*/
Tree.prototype.array = function() {
var token = new types.Array();
this.tokens.push( token );
return token;
};
92 changes: 92 additions & 0 deletions lib/types/array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
var helpers = require("../helpers");
var Property = require("./_property");

/**
* Create an array token
* @constructor
*/
function ArrayObj() {
this.check = function() { return true; };
this.action = function() {};
}

module.exports = ArrayObj;

/**
* Standard run function used when tokens are applied.
* @param {AST node} node
* @return {null}
*/
ArrayObj.prototype.use = function( node ) {
if ( node.type === "ArrayExpression" && this.check(node) ) {
this.action( node );
}
};

/**
* Scope to select only object assigned to a variable
* @param {Stirng} name variable name
* @return {types.Array}
*/
ArrayObj.prototype.assignedTo = function( name ) {
this.check = function( node ) {
return (node.parent.type === "VariableDeclarator" && node.parent.id.name === name);
};
return this;
};

/**
* Scope to select only object passed to a function or a method
* TODO: Selecting method only work for two level deeps - should be better
* @param {String} name variable name
* @return {types.Array}
*/
ArrayObj.prototype.passedTo = function( name ) {
this.check = function( node ) {
var top = node.parent;
if ( top.type !== "CallExpression" ) return false;
if ( top.callee.type === "Identifier" && top.callee.name === name ) return true;
if ( top.callee.type === "MemberExpression" &&
name === top.callee.object.name + "." + top.callee.property.name ) return true;
return false;
};
return this;
};

/**
* push an element at the end of the array
* @param {String} item - Item to push source
* @return {types.Array}
*/
ArrayObj.prototype.push = function( item ) {
this.action = function( node ) {
var src = node.source().replace(/\]$/, "") + ", " + item + "]";
node.update( src );
helpers.removeExtraComma(node);
};
};

/**
* unshift an element at the beginning of the array
* @param {String} item - Item to unshift source
* @return {types.Array}
*/
ArrayObj.prototype.unshift = function( item ) {
this.action = function( node ) {
var src = "[" + item + ", " + node.source().replace(/^\[/, "");
node.update( src );
helpers.removeExtraComma(node);
};
};

/**
* unshift an element at the beginning of the array
* @param {String} item - Item to unshift source
* @return {types.Array}
*/
ArrayObj.prototype.pop = function( item ) {
this.action = function( node ) {
node.elements.pop();
node.update(node.source());
};
};
1 change: 1 addition & 0 deletions lib/types/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
module.exports.Var = require("./var");
module.exports.Object = require("./object");
module.exports.Array = require("./array");
64 changes: 64 additions & 0 deletions test/specs/types/array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
var expect = require("chai").expect;
var Tree = require("../../../lib/tree");

describe("array modification API", function() {
it("should select array assigned to a variable", function() {
var src = "var foo = ['foo'];";
var tree = new Tree(src);
tree.array().assignedTo("foo");
tree.action = function( node ) {
expect(node.source()).to.equal("['foo']");
};
tree.toString();
});

it("should select array passed to a function", function() {
var src = "foo(['doe']);";
var tree = new Tree(src);
tree.array().passedTo("foo");
tree.action = function( node ) {
expect(node.source()).to.equal("['doe']");
};
tree.toString();
});

it("should select array passed to a method", function() {
var src = "grunt.init(['john']);";
var tree = new Tree(src);
tree.array().passedTo("grunt.init");
tree.action = function( node ) {
expect(node.source()).to.equal("['john']");
};
tree.toString();
});

it("should push an item at the end of an array", function() {
var tree = new Tree("var a = ['bar'];");
tree.array().push("'foo'");
expect(tree.toString()).to.equal("var a = ['bar', 'foo'];");
});

it("should push an item in an empty array", function() {
var tree = new Tree("var a = [];");
tree.array().push("'foo'");
expect(tree.toString()).to.equal("var a = ['foo'];");
});

it("should unshift an item at the beginning of an array", function() {
var tree = new Tree("var a = ['bar'];");
tree.array().unshift("'foo'");
expect(tree.toString()).to.equal("var a = ['foo', 'bar'];");
});

it("should unshift an item at the beginning of an empty array", function() {
var tree = new Tree("var a = [];");
tree.array().unshift("'foo'");
expect(tree.toString()).to.equal("var a = ['foo'];");
});

it("should pop an element the end of an array", function() {
var tree = new Tree("var a = ['bar', 'foo'];");
tree.array().pop();
expect(tree.toString()).to.equal("var a = ['bar'];");
});
});

0 comments on commit 0e9f1a5

Please sign in to comment.