Reputation: 6996
Playing around with babel transforms and I've written this snippet to insert a VariableDeclaration
after my path
export default function (babel) {
const { types: t } = babel;
return {
name: "ast-transform", // not required
visitor: {
VariableDeclaration (path) {
if (path.node.kind !== 'var') {
return;
}
const _id = t.Identifier('qwe');
const _init = t.numericLiteral(42);
console.log(_id, _init);
const _node = t.variableDeclaration('var', [
t.variableDeclarator(
t.identifier("uid"),
t.numericLiteral(42)
)
]);
path
.unshiftContainer(
'body',
_node
)
}
}
};
}
Get the following error,
unknown: Cannot read property 'body' of undefined
Edit:
If I do the following instead of unshiftContainer
it works,
const _program = path.findParent(p => p.isProgram());
_program.node.body.unshift(_node);
Why doesn't unshiftContainer
work?
Link to gist on ast-explorer
Upvotes: 4
Views: 835
Reputation: 4138
In order to use unshiftContainer("body")
you have to have a node with "body". For example, Program
or FunctionDeclaration
(1, 2, 3)
But you were trying to do that on VariableDeclaration
which doesn't have body
as you can see in ast-explorer.
When you call path.get("body")
, it returns {..., node: undefined, ...}
and then, when you call unshiftContainer("body")
, it tries to get "body"
of node
, which is undefined
: container: this.node[listKey],
.
Your solution works because you're finding Program
object, which has body.
So, this also would work if you want to use unshiftContainer
:
const _program = path.findParent(p => p.isProgram());
_program.unshiftContainer("body", _node);
Also, you can do this:
const parentWithBody = path.findParent(
(p) => p.node !== undefined && p.node.body !== undefined
);
parentWithBody.unshiftContainer("body", _node);
It will detect not only Program
, but also FunctionDeclaration
:
Source:
var x = 10;
var y = 5;
function test() {
var z = 1;
}
Output:
var uid = 42;
var uid = 42;
var x = 10;
var y = 5;
function test() {
var uid = 42;
var z = 1;
}
Update regarding infinite loop,
Indeed, when you unshift container, you're adding new VariableDeclaration
, so it will go into the infinite loop:
var x = 10
-> add var uid = 42
var uid = 42
-> add var uid = 42
In order to break this loop, add this condition, where you check if the node.kind
is var
:
if (path.node.declarations[0].init.value === 42 && path.node.declarations[0].id.name === "uid") {
return;
}
(gist)
Upvotes: 6