e3d3eda2e1
Converts the tool chain to use babel, eslint, and webpack vs. the previous proprietary solutions. Additionally begins enforcing additional linting concerns as well as updates the code to reflect these rules. Fixes #855 Fixes #993
120 lines
2.8 KiB
JavaScript
120 lines
2.8 KiB
JavaScript
import Exception from '../exception';
|
|
import AST from './ast';
|
|
|
|
function Visitor() {
|
|
this.parents = [];
|
|
}
|
|
|
|
Visitor.prototype = {
|
|
constructor: Visitor,
|
|
mutating: false,
|
|
|
|
// Visits a given value. If mutating, will replace the value if necessary.
|
|
acceptKey: function(node, name) {
|
|
var value = this.accept(node[name]);
|
|
if (this.mutating) {
|
|
// Hacky sanity check:
|
|
if (value && (!value.type || !AST[value.type])) {
|
|
throw new Exception('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
|
|
}
|
|
node[name] = value;
|
|
}
|
|
},
|
|
|
|
// Performs an accept operation with added sanity check to ensure
|
|
// required keys are not removed.
|
|
acceptRequired: function(node, name) {
|
|
this.acceptKey(node, name);
|
|
|
|
if (!node[name]) {
|
|
throw new Exception(node.type + ' requires ' + name);
|
|
}
|
|
},
|
|
|
|
// Traverses a given array. If mutating, empty respnses will be removed
|
|
// for child elements.
|
|
acceptArray: function(array) {
|
|
for (var i = 0, l = array.length; i < l; i++) {
|
|
this.acceptKey(array, i);
|
|
|
|
if (!array[i]) {
|
|
array.splice(i, 1);
|
|
i--;
|
|
l--;
|
|
}
|
|
}
|
|
},
|
|
|
|
accept: function(object) {
|
|
if (!object) {
|
|
return;
|
|
}
|
|
|
|
if (this.current) {
|
|
this.parents.unshift(this.current);
|
|
}
|
|
this.current = object;
|
|
|
|
var ret = this[object.type](object);
|
|
|
|
this.current = this.parents.shift();
|
|
|
|
if (!this.mutating || ret) {
|
|
return ret;
|
|
} else if (ret !== false) {
|
|
return object;
|
|
}
|
|
},
|
|
|
|
Program: function(program) {
|
|
this.acceptArray(program.body);
|
|
},
|
|
|
|
MustacheStatement: function(mustache) {
|
|
this.acceptRequired(mustache, 'path');
|
|
this.acceptArray(mustache.params);
|
|
this.acceptKey(mustache, 'hash');
|
|
},
|
|
|
|
BlockStatement: function(block) {
|
|
this.acceptRequired(block, 'path');
|
|
this.acceptArray(block.params);
|
|
this.acceptKey(block, 'hash');
|
|
|
|
this.acceptKey(block, 'program');
|
|
this.acceptKey(block, 'inverse');
|
|
},
|
|
|
|
PartialStatement: function(partial) {
|
|
this.acceptRequired(partial, 'name');
|
|
this.acceptArray(partial.params);
|
|
this.acceptKey(partial, 'hash');
|
|
},
|
|
|
|
ContentStatement: function(/* content */) {},
|
|
CommentStatement: function(/* comment */) {},
|
|
|
|
SubExpression: function(sexpr) {
|
|
this.acceptRequired(sexpr, 'path');
|
|
this.acceptArray(sexpr.params);
|
|
this.acceptKey(sexpr, 'hash');
|
|
},
|
|
|
|
PathExpression: function(/* path */) {},
|
|
|
|
StringLiteral: function(/* string */) {},
|
|
NumberLiteral: function(/* number */) {},
|
|
BooleanLiteral: function(/* bool */) {},
|
|
UndefinedLiteral: function(/* literal */) {},
|
|
NullLiteral: function(/* literal */) {},
|
|
|
|
Hash: function(hash) {
|
|
this.acceptArray(hash.pairs);
|
|
},
|
|
HashPair: function(pair) {
|
|
this.acceptRequired(pair, 'value');
|
|
}
|
|
};
|
|
|
|
export default Visitor;
|