I'm making a library which exports one function (make
) on global namespace (app
) for defining a module or referencing it, similar to what angular.module
does.
When I call it, I make sure to not store any reference to the make(name, [deps])
call so it will always use the main app
object.
Usage is like this:
// Define 'hello'
app.make('hello', []);
// Define 'one' in 'hello'
app.make('hello').
data('one', 'thing');
// Multiple calls
app.make('hello').
data('two', 'thing').
attr('third', 'no').
data('four', 'empty');
And I want the above code turn into it:
app.make('hello', []).
data('one', 'thing').
data('two', 'thing').
attr('third', 'no').
data('four', 'empty');
So it should turn multiple separated calls to the return from make
into just a big one (order doesn't matter and there are no side effects).
What I tried:
I'm planning to use esprima
, estraverse
and escodegen
, here's what I actually have:
const fs = require('fs'),
esprima = require('esprima'),
estraverse = require('estraverse');
const modules = Object.create(null);
fs.readFile('sample.js', 'utf8', (err, data) => {
const tree = esprima.parse(data);
// Find module definitions
estraverse.traverse(tree, {
enter(node) {
const args = node.arguments;
if (isDefinitionCall(node) && args.length == 2) {
modules[args[0].value] = {
node,
childs: []
};
}
}
});
// Find module usages
estraverse.traverse(tree, {
enter(node) {
if (isGetterCall(node)) {
// What to store here?
// And how to modify the AST to turn
// everything into just chained call?
}
}
});
console.log('Modules found: ' + Object.keys(modules).join(', '));
});
function isDefinitionCall(node) {
return node.type == 'CallExpression' &&
node.callee &&
node.callee.object &&
node.callee.property &&
node.callee.type == 'MemberExpression' &&
node.callee.object.name == 'app' &&
node.callee.object.type == 'Identifier' &&
node.callee.property.type == 'Identifier' &&
node.callee.property.name == 'make';
}
function isGetterCall(node) {
return node.type == 'CallExpression' &&
node.callee &&
node.callee.object &&
isDefinitionCall(node.callee.object);
}
My question is: how can I move around the AST and get what I want done? Thanks in advance!