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 { declare } from "@babel/helper-plugin-utils";
|
||||||
import syntaxPipelineOperator from "@babel/plugin-syntax-pipeline-operator";
|
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);
|
api.assertVersion(7);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "proposal-pipeline-operator",
|
name: "proposal-pipeline-operator",
|
||||||
inherits: syntaxPipelineOperator,
|
inherits: syntaxPipelineOperator,
|
||||||
|
visitor: visitorsPerProposal[options.proposal],
|
||||||
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,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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);
|
expect(result).toBe(31);
|
||||||
|
|
||||||
var inc = x => x + 1;
|
var inc = x => x + 1;
|
||||||
@ -8,7 +8,7 @@ var inc = x => x + 1;
|
|||||||
var double = x => x * 2;
|
var double = x => x * 2;
|
||||||
|
|
||||||
var result2 = [4, 9].map(x => {
|
var result2 = [4, 9].map(x => {
|
||||||
var _ref3, _x;
|
var _x, _ref3;
|
||||||
|
|
||||||
return _ref3 = (_x = x, inc(_x)), double(_ref3);
|
return _ref3 = (_x = x, inc(_x)), double(_ref3);
|
||||||
});
|
});
|
||||||
@ -1,4 +1,4 @@
|
|||||||
var _ref, _;
|
var _, _ref;
|
||||||
|
|
||||||
function then(fn) {
|
function then(fn) {
|
||||||
return async value => {
|
return async value => {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
var _ref, _;
|
var _, _ref;
|
||||||
|
|
||||||
var inc = x => x + 1;
|
var inc = x => x + 1;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
var _ref, _a;
|
var _a, _ref;
|
||||||
|
|
||||||
var a = 1,
|
var a = 1,
|
||||||
b = 2,
|
b = 2,
|
||||||
@ -1,4 +1,4 @@
|
|||||||
var _ref, _ref2, _;
|
var _ref, _, _ref2;
|
||||||
|
|
||||||
var inc = x => x + 1;
|
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";
|
import { declare } from "@babel/helper-plugin-utils";
|
||||||
|
|
||||||
export const proposals = ["minimal"];
|
export const proposals = ["minimal", "smart"];
|
||||||
|
|
||||||
export default declare((api, { proposal }) => {
|
export default declare((api, { proposal }) => {
|
||||||
api.assertVersion(7);
|
api.assertVersion(7);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user