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 }) {
|
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 {
|
return {
|
||||||
visitor: {
|
visitor: {
|
||||||
MemberExpression(path) {
|
MemberExpression(path, state) {
|
||||||
|
if (!isNodeOptional(path.node)) {
|
||||||
if (isNodeOptional(path.node)) {
|
return;
|
||||||
let { object } = path.node;
|
|
||||||
|
|
||||||
do {
|
|
||||||
object = createCheck(
|
|
||||||
object,
|
|
||||||
object.object
|
|
||||||
);
|
|
||||||
|
|
||||||
} while (t.isMemberExpression(object) && isNodeOptional(object));
|
|
||||||
|
|
||||||
path.replaceWith(
|
|
||||||
createCheck(path.node, object)
|
|
||||||
);
|
|
||||||
|
|
||||||
path.stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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