Transform for the smart pipeline operator proposal (#9179)
This commit is contained in:
parent
ba4141934f
commit
e9331aa0c0
@ -1,64 +1,19 @@
|
||||
import { declare } from "@babel/helper-plugin-utils";
|
||||
import syntaxPipelineOperator from "@babel/plugin-syntax-pipeline-operator";
|
||||
import { types as t } from "@babel/core";
|
||||
import minimalVisitor from "./minimalVisitor";
|
||||
import smartVisitor from "./smartVisitor";
|
||||
|
||||
export default declare(api => {
|
||||
const visitorsPerProposal = {
|
||||
minimal: minimalVisitor,
|
||||
smart: smartVisitor,
|
||||
};
|
||||
|
||||
export default declare((api, options) => {
|
||||
api.assertVersion(7);
|
||||
|
||||
return {
|
||||
name: "proposal-pipeline-operator",
|
||||
inherits: syntaxPipelineOperator,
|
||||
|
||||
visitor: {
|
||||
BinaryExpression(path) {
|
||||
const { scope } = path;
|
||||
const { node } = path;
|
||||
const { operator, left } = node;
|
||||
let { right } = node;
|
||||
if (operator !== "|>") return;
|
||||
|
||||
let optimizeArrow =
|
||||
t.isArrowFunctionExpression(right) &&
|
||||
t.isExpression(right.body) &&
|
||||
!right.async &&
|
||||
!right.generator;
|
||||
let param;
|
||||
|
||||
if (optimizeArrow) {
|
||||
const { params } = right;
|
||||
if (params.length === 1 && t.isIdentifier(params[0])) {
|
||||
param = params[0];
|
||||
} else if (params.length > 0) {
|
||||
optimizeArrow = false;
|
||||
}
|
||||
} else if (t.isIdentifier(right, { name: "eval" })) {
|
||||
right = t.sequenceExpression([t.numericLiteral(0), right]);
|
||||
}
|
||||
|
||||
if (optimizeArrow && !param) {
|
||||
// Arrow function with 0 arguments
|
||||
path.replaceWith(t.sequenceExpression([left, right.body]));
|
||||
return;
|
||||
}
|
||||
|
||||
const placeholder = scope.generateUidIdentifierBasedOnNode(
|
||||
param || left,
|
||||
);
|
||||
scope.push({ id: placeholder });
|
||||
if (param) {
|
||||
path.get("right").scope.rename(param.name, placeholder.name);
|
||||
}
|
||||
|
||||
const call = optimizeArrow
|
||||
? right.body
|
||||
: t.callExpression(right, [t.cloneNode(placeholder)]);
|
||||
path.replaceWith(
|
||||
t.sequenceExpression([
|
||||
t.assignmentExpression("=", t.cloneNode(placeholder), left),
|
||||
call,
|
||||
]),
|
||||
);
|
||||
},
|
||||
},
|
||||
visitor: visitorsPerProposal[options.proposal],
|
||||
};
|
||||
});
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
import { types as t } from "@babel/core";
|
||||
|
||||
const minimalVisitor = {
|
||||
BinaryExpression: {
|
||||
exit(path) {
|
||||
const { scope } = path;
|
||||
const { node } = path;
|
||||
const { operator, left } = node;
|
||||
let { right } = node;
|
||||
if (operator !== "|>") return;
|
||||
|
||||
let optimizeArrow =
|
||||
t.isArrowFunctionExpression(right) &&
|
||||
t.isExpression(right.body) &&
|
||||
!right.async &&
|
||||
!right.generator;
|
||||
let param;
|
||||
|
||||
if (optimizeArrow) {
|
||||
const { params } = right;
|
||||
if (params.length === 1 && t.isIdentifier(params[0])) {
|
||||
param = params[0];
|
||||
} else if (params.length > 0) {
|
||||
optimizeArrow = false;
|
||||
}
|
||||
} else if (t.isIdentifier(right, { name: "eval" })) {
|
||||
right = t.sequenceExpression([t.numericLiteral(0), right]);
|
||||
}
|
||||
|
||||
if (optimizeArrow && !param) {
|
||||
// Arrow function with 0 arguments
|
||||
path.replaceWith(t.sequenceExpression([left, right.body]));
|
||||
return;
|
||||
}
|
||||
|
||||
const placeholder = scope.generateUidIdentifierBasedOnNode(param || left);
|
||||
scope.push({ id: placeholder });
|
||||
if (param) {
|
||||
path.get("right").scope.rename(param.name, placeholder.name);
|
||||
}
|
||||
|
||||
const call = optimizeArrow
|
||||
? right.body
|
||||
: t.callExpression(right, [t.cloneNode(placeholder)]);
|
||||
path.replaceWith(
|
||||
t.sequenceExpression([
|
||||
t.assignmentExpression("=", t.cloneNode(placeholder), left),
|
||||
call,
|
||||
]),
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default minimalVisitor;
|
||||
@ -0,0 +1,42 @@
|
||||
import { types as t } from "@babel/core";
|
||||
import minimalVisitor from "./minimalVisitor";
|
||||
|
||||
const updateTopicReferenceVisitor = {
|
||||
PipelinePrimaryTopicReference(path) {
|
||||
path.replaceWith(this.topicId);
|
||||
},
|
||||
AwaitExpression(path) {
|
||||
throw path.buildCodeFrameError(
|
||||
"await is not supported inside pipeline expressions yet",
|
||||
);
|
||||
},
|
||||
YieldExpression(path) {
|
||||
throw path.buildCodeFrameError(
|
||||
"yield is not supported inside pipeline expressions yet",
|
||||
);
|
||||
},
|
||||
PipelineTopicExpression(path) {
|
||||
path.skip();
|
||||
},
|
||||
};
|
||||
|
||||
const smartVisitor = {
|
||||
...minimalVisitor,
|
||||
PipelineTopicExpression(path) {
|
||||
const topicId = path.scope.generateUidIdentifier("topic");
|
||||
|
||||
path.traverse(updateTopicReferenceVisitor, { topicId });
|
||||
|
||||
const arrowFunctionExpression = t.arrowFunctionExpression(
|
||||
[topicId],
|
||||
path.node.expression,
|
||||
);
|
||||
|
||||
path.replaceWith(arrowFunctionExpression);
|
||||
},
|
||||
PipelineBareFunction(path) {
|
||||
path.replaceWith(path.node.callee);
|
||||
},
|
||||
};
|
||||
|
||||
export default smartVisitor;
|
||||
@ -1,6 +1,6 @@
|
||||
var _sum, _ref, _ref2;
|
||||
var _ref, _ref2, _sum;
|
||||
|
||||
var result = (_sum = (_ref = (_ref2 = [5, 10], _ref2.map(x => x * 2)), _ref.reduce((a, b) => a + b)), _sum + 1);
|
||||
var result = (_sum = (_ref2 = (_ref = [5, 10], _ref.map(x => x * 2)), _ref2.reduce((a, b) => a + b)), _sum + 1);
|
||||
expect(result).toBe(31);
|
||||
|
||||
var inc = x => x + 1;
|
||||
@ -8,7 +8,7 @@ var inc = x => x + 1;
|
||||
var double = x => x * 2;
|
||||
|
||||
var result2 = [4, 9].map(x => {
|
||||
var _ref3, _x;
|
||||
var _x, _ref3;
|
||||
|
||||
return _ref3 = (_x = x, inc(_x)), double(_ref3);
|
||||
});
|
||||
@ -1,4 +1,4 @@
|
||||
var _ref, _;
|
||||
var _, _ref;
|
||||
|
||||
function then(fn) {
|
||||
return async value => {
|
||||
@ -1,4 +1,4 @@
|
||||
var _ref, _;
|
||||
var _, _ref;
|
||||
|
||||
var inc = x => x + 1;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
var _ref, _a;
|
||||
var _a, _ref;
|
||||
|
||||
var a = 1,
|
||||
b = 2,
|
||||
@ -1,4 +1,4 @@
|
||||
var _ref, _ref2, _;
|
||||
var _ref, _, _ref2;
|
||||
|
||||
var inc = x => x + 1;
|
||||
|
||||
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/await/input.js
vendored
Normal file
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/await/input.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
async function myFunction() {
|
||||
const value = -5.9
|
||||
|> abs
|
||||
|> await Math.floor(#);
|
||||
}
|
||||
6
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/await/options.json
vendored
Normal file
6
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/await/options.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"throws": "await is not supported inside pipeline expressions yet",
|
||||
"plugins": [
|
||||
["proposal-pipeline-operator", { "proposal": "smart" }]
|
||||
]
|
||||
}
|
||||
7
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/bare-function/exec.js
vendored
Normal file
7
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/bare-function/exec.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
const abs = Math.abs;
|
||||
|
||||
const value = -5.9
|
||||
|> abs
|
||||
|> Math.floor;
|
||||
|
||||
expect(value).toBe(5);
|
||||
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/bare-function/input.js
vendored
Normal file
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/bare-function/input.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
const abs = Math.abs;
|
||||
|
||||
const value = -5.9
|
||||
|> abs
|
||||
|> Math.floor;
|
||||
4
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/bare-function/output.js
vendored
Normal file
4
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/bare-function/output.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
var _ref, _ref2;
|
||||
|
||||
const abs = Math.abs;
|
||||
const value = (_ref2 = (_ref = -5.9, abs(_ref)), Math.floor(_ref2));
|
||||
6
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/basic/exec.js
vendored
Normal file
6
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/basic/exec.js
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
var result = 5
|
||||
|> # + 1
|
||||
|> # + #
|
||||
|> Math.pow(((x) => (x * 7))(#), 2)
|
||||
|
||||
expect(result).toBe(7056);
|
||||
4
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/basic/input.js
vendored
Normal file
4
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/basic/input.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
var result = 5
|
||||
|> # + 1
|
||||
|> # + #
|
||||
|> Math.pow(((x) => (x * 7))(#), 2)
|
||||
3
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/basic/output.js
vendored
Normal file
3
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/basic/output.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
var _topic2, _topic4, _topic6;
|
||||
|
||||
var result = (_topic6 = (_topic4 = (_topic2 = 5, _topic2 + 1), _topic4 + _topic4), Math.pow((x => x * 7)(_topic6), 2));
|
||||
7
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/nested/exec.js
vendored
Normal file
7
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/nested/exec.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
var result = 5
|
||||
|> Math.pow(#, 2)
|
||||
|> [ 10, 20, 30, 40, 50 ].filter(n => #
|
||||
|> n > #
|
||||
|> !#);
|
||||
|
||||
expect(result).toEqual([10, 20]);
|
||||
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/nested/input.js
vendored
Normal file
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/nested/input.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
var result = 5
|
||||
|> Math.pow(#, 2)
|
||||
|> [ 10, 20, 30, 40, 50 ].filter(n => #
|
||||
|> n > #
|
||||
|> !#);
|
||||
7
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/nested/output.js
vendored
Normal file
7
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/nested/output.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
var _topic2, _topic8;
|
||||
|
||||
var result = (_topic8 = (_topic2 = 5, Math.pow(_topic2, 2)), [10, 20, 30, 40, 50].filter(n => {
|
||||
var _topic5, _topic7;
|
||||
|
||||
return _topic7 = (_topic5 = _topic8, n > _topic5), !_topic7;
|
||||
}));
|
||||
10
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/object-literal/exec.js
vendored
Normal file
10
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/object-literal/exec.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
function area(rect) {
|
||||
return rect.width * rect.height;
|
||||
}
|
||||
|
||||
const result = -5
|
||||
|> Math.abs
|
||||
|> ({ width: #, height: # + 3 })
|
||||
|> area;
|
||||
|
||||
expect(result).toBe(40);
|
||||
8
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/object-literal/input.js
vendored
Normal file
8
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/object-literal/input.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
function area(rect) {
|
||||
return rect.width * rect.height;
|
||||
}
|
||||
|
||||
const result = -5
|
||||
|> Math.abs
|
||||
|> ({ width: #, height: # + 3 })
|
||||
|> area;
|
||||
10
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/object-literal/output.js
vendored
Normal file
10
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/object-literal/output.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
var _ref, _topic2, _ref2;
|
||||
|
||||
function area(rect) {
|
||||
return rect.width * rect.height;
|
||||
}
|
||||
|
||||
const result = (_ref2 = (_topic2 = (_ref = -5, Math.abs(_ref)), {
|
||||
width: _topic2,
|
||||
height: _topic2 + 3
|
||||
}), area(_ref2));
|
||||
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/options.json
vendored
Normal file
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/options.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": [
|
||||
["proposal-pipeline-operator", { "proposal": "smart" }]
|
||||
]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
v |> #.method |> f;
|
||||
@ -0,0 +1,3 @@
|
||||
var _topic2, _ref;
|
||||
|
||||
_ref = (_topic2 = v, _topic2.method), f(_ref);
|
||||
@ -0,0 +1,7 @@
|
||||
const result = -2.2 // -2.2
|
||||
|> Math.floor // -3
|
||||
|> (() => Math.pow(#, 5)) // () => -243
|
||||
|> #() // -243
|
||||
|> Math.sign; // -1
|
||||
|
||||
expect(result).toBe(-1);
|
||||
@ -0,0 +1,5 @@
|
||||
const result = -2.2 // -2.2
|
||||
|> Math.floor // -3
|
||||
|> (() => Math.pow(#, 5)) // () => -243
|
||||
|> #() // -243
|
||||
|> Math.sign; // -1
|
||||
@ -0,0 +1,7 @@
|
||||
var _ref, _topic2, _topic4, _ref2;
|
||||
|
||||
const result = (_ref2 = (_topic4 = (_topic2 = (_ref = -2.2 // -2.2
|
||||
, Math.floor(_ref) // -3
|
||||
), () => Math.pow(_topic2, 5) // () => -243
|
||||
), _topic4() // -243
|
||||
), Math.sign(_ref2)); // -1
|
||||
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/yield/input.js
vendored
Normal file
5
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/yield/input.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
function *myGenerator() {
|
||||
return v
|
||||
|> (yield #)
|
||||
|> g;
|
||||
}
|
||||
6
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/yield/options.json
vendored
Normal file
6
packages/babel-plugin-proposal-pipeline-operator/test/fixtures/smart/yield/options.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"throws": "yield is not supported inside pipeline expressions yet",
|
||||
"plugins": [
|
||||
["proposal-pipeline-operator", { "proposal": "smart" }]
|
||||
]
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { declare } from "@babel/helper-plugin-utils";
|
||||
|
||||
export const proposals = ["minimal"];
|
||||
export const proposals = ["minimal", "smart"];
|
||||
|
||||
export default declare((api, { proposal }) => {
|
||||
api.assertVersion(7);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user