refactor: improved transformation logic
This commit is contained in:
parent
72259ca5d3
commit
64ff5a080d
@ -1,61 +1,44 @@
|
||||
import createTemplate from "babel-template";
|
||||
import traverse from "babel-traverse";
|
||||
|
||||
const nullOrUndefinedCheck = createTemplate(`
|
||||
typeof CHECK !== "undefined" && CHECK !== null
|
||||
? NEXT
|
||||
: null
|
||||
`);
|
||||
|
||||
function isNodeOptional(node) {
|
||||
return node.optional === true;
|
||||
}
|
||||
|
||||
const nullOrUndefinedCheckVisitor = {
|
||||
noScope: true,
|
||||
|
||||
Identifier(path, replacements) {
|
||||
if (path.node.name in replacements) {
|
||||
path.replaceInline(replacements[path.node.name]);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function createCheck(node, object) {
|
||||
|
||||
const template = nullOrUndefinedCheck();
|
||||
|
||||
traverse(template, nullOrUndefinedCheckVisitor, null, {
|
||||
CHECK: object,
|
||||
NEXT: node,
|
||||
});
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
export default function ({ types: t }) {
|
||||
|
||||
function createCondition(ref, access, nextProperty) {
|
||||
|
||||
return t.conditionalExpression(
|
||||
createCheckAgainstNull(
|
||||
t.AssignmentExpression("=", ref, access)
|
||||
),
|
||||
|
||||
t.memberExpression(ref, nextProperty),
|
||||
t.NullLiteral()
|
||||
);
|
||||
}
|
||||
|
||||
function createCheckAgainstNull(left) {
|
||||
return t.BinaryExpression("!=", left, t.NullLiteral());
|
||||
}
|
||||
|
||||
function isNodeOptional(node) {
|
||||
return node.optional === true;
|
||||
}
|
||||
|
||||
return {
|
||||
visitor: {
|
||||
MemberExpression(path) {
|
||||
|
||||
if (isNodeOptional(path.node)) {
|
||||
let { object } = path.node;
|
||||
|
||||
do {
|
||||
object = createCheck(
|
||||
object,
|
||||
object.object
|
||||
);
|
||||
|
||||
} while (t.isMemberExpression(object) && isNodeOptional(object));
|
||||
|
||||
path.replaceWith(
|
||||
createCheck(path.node, object)
|
||||
);
|
||||
|
||||
path.stop();
|
||||
MemberExpression(path, state) {
|
||||
if (!isNodeOptional(path.node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { object, property } = path.node;
|
||||
|
||||
if (!state.optionalTemp) {
|
||||
const id = path.scope.generateUidIdentifier();
|
||||
|
||||
state.optionalTemp = id;
|
||||
path.scope.push({ id });
|
||||
}
|
||||
|
||||
path.replaceWith(
|
||||
createCondition(state.optionalTemp, object, property)
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -1 +1,3 @@
|
||||
typeof foo !== "undefined" && foo !== null ? foo.bar : null;
|
||||
var _temp;
|
||||
|
||||
(_temp = foo) != null ? _temp.bar : null;
|
||||
|
||||
@ -1 +1 @@
|
||||
foo?.bar?.vroum
|
||||
a?.b.c?.d.e
|
||||
|
||||
@ -1 +1,3 @@
|
||||
typeof (typeof foo !== "undefined" && foo !== null ? foo.bar : null) !== "undefined" && (typeof foo !== "undefined" && foo !== null ? foo.bar : null) !== null ? foo.bar.vroum : null;
|
||||
var _temp;
|
||||
|
||||
((_temp = ((_temp = a) != null ? _temp.b : null).c) != null ? _temp.d : null).e;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user