How to use scoping and track variables
export default function ({ Plugin, types: t }) {
return new Plugin("foo-bar", {
visitor: {
FunctionDeclaration(node, parent, scope) {
scope.hasBinding("name");
}
}
});
}
This will walk up the scope tree and check for that particular binding.
You can also check if a scope has it's own binding:
export default function ({ Plugin, types: t }) {
return new Plugin("foo-bar", {
visitor: {
FunctionDeclaration(node, parent, scope) {
scope.hasOwnBinding("name");
}
}
});
}
export default function ({ Plugin, types: t }) {
return new Plugin("foo-bar", {
visitor: {
FunctionDeclaration(node, parent, scope) {
scope.generateUidIdentifier("foo");
}
}
});
}
This will generate an identifier that doesn't collide with any locally defined variables.
Sometimes you may want to push a VariableDeclaration
so you can assign to it inside of an expression.
For example the following transformer:
export default function ({ Plugin, types: t }) {
return new Plugin("foo-bar", {
visitor: {
CallExpression(node, parent, scope) {
var id = scope.generateUidIdentifierBasedOnNode(node);
scope.push({ id });
return t.assignmentExpression("=", id, node);
}
}
});
}
Will transform:
function foo() {
bar();
}
into:
function foo() {
var _bar;
_bar = bar();
}
export default function ({ Plugin, types: t }) {
return new Plugin("foo-bar", {
visitor: {
Program(node, parent, scope) {
// no second argument passed so this will generate a uid based on `foo`
scope.rename("foo");
// rename bar to foobar
scope.rename("bar", "foobar");
}
}
});
}
Will transform:
function bar() {
return "foo!";
}
function foo() {
bar();
}
foo();
into:
function foobar() {
return "foo!";
}
function _foo() {
foobar();
}
_foo();