add scope renaming helper method - fixes #645 - @RReverser

This commit is contained in:
Sebastian McKenzie 2015-02-10 22:39:07 +11:00
parent 329b4e9d21
commit 49a53b26bb
2 changed files with 59 additions and 5 deletions

View File

@ -14,8 +14,15 @@ function CommonJSFormatter() {
util.inherits(CommonJSFormatter, DefaultFormatter);
CommonJSFormatter.prototype.init = function () {
var file = this.file;
var scope = file.scope;
if (scope.hasBinding("module")) {
scope.rename("module", file.generateUidIdentifier("module").name);
}
if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
this.file.ast.program.body.push(util.template("exports-module-declaration", true));
file.ast.program.body.push(util.template("exports-module-declaration", true));
}
};

View File

@ -143,6 +143,35 @@ Scope.prototype.checkBlockScopedCollisions = function (kind, key, id) {
}
};
Scope.prototype.rename = function (oldName, newName) {
var info = this.getBindingWithScope(oldName);
console.log(info);
if (!info) return;
var binding = info.binding;
var scope = info.scope;
scope.references[newName] = binding;
scope.bindings[newName] = binding;
delete scope.references[oldName];
delete scope.bindings[oldName];
binding.name = newName;
scope.traverse(scope.block, {
enter: function (node, parent, scope) {
if (t.isReferencedIdentifier(node, parent) && node.name === oldName) {
node.name = newName;
} else if (t.isScope(node)) {
if (t.getBinding(oldName) !== binding) {
this.skip();
}
}
}
});
};
Scope.prototype.inferType = function (node) {
var target;
@ -150,10 +179,6 @@ Scope.prototype.inferType = function (node) {
target = node.init;
}
if (t.isLiteral(target) || t.isArrayExpression(target) || t.isObjectExpression(target)) {
// todo: possibly call some helper that will resolve these to a flow type annotation
}
if (t.isCallExpression(target)) {
// todo: resolve this to a return type
}
@ -411,6 +436,28 @@ Scope.prototype.addBindingToFunctionScope = function (node, kind) {
if (kind) extend(scope.bindingKinds[kind], ids);
};
/**
* Walk up the scope tree and check to see if it has a binding with the provided
* name, if it does return the binding identifier and scope.
*
* @param {String} name
* @returns {Object} { binding, scope }
*/
Scope.prototype.getBindingWithScope = function (name) {
var scope = this;
do {
binding = scope.getOwnBinding(name);
var if (binding) {
return {
binding: binding,
scope: scope
};
}
} while (scope = scope.parent);
};
/**
* Walk up the scope tree until we hit either a Function or reach the
* very top and hit Program.