From c60c4dd375a137ae3926679622a496fce1d13bcb Mon Sep 17 00:00:00 2001 From: Behrang Yarahmadi Date: Mon, 14 Jan 2019 17:54:21 +0100 Subject: [PATCH] Partial Application Syntax: Stage 1 (#9343) * add partial application syntax and some tests * remove unnecessary error message and hasPartial function from parseNewArguments * add types for PartialExpression * Update the tests * rename PartialExpression to Partial * move Partial from expressions to types and rename to ArgumentPlaceholder * add tests for ArgumentPlaceholder in babel-generator * rename Partial to ArgumentPlaceholder * update the tests * remove alias from the type and undo changes in generated folder * adds a nice error message * better definition for the type * auto-generated files * update the conditional for allowPlaceholder message and tests * update CallExpression definition to accept ArgumentPlaceholder * change description * clean up * indent ArgumentPlaceholder entry and revert unwanted changes --- .../babel-generator/src/generators/types.js | 4 + .../types/ArgumentPlaceholder/input.js | 12 + .../types/ArgumentPlaceholder/options.json | 1 + .../types/ArgumentPlaceholder/output.js | 14 + packages/babel-parser/ast/spec.md | 9 + .../babel-parser/src/parser/expression.js | 13 +- packages/babel-parser/src/types.js | 2 + .../partial-application/call-expr/input.js | 1 + .../call-expr/options.json | 3 + .../partial-application/call-expr/output.json | 99 ++++++ .../call-on-SuperProperty/input.js | 5 + .../call-on-SuperProperty/options.json | 3 + .../call-on-SuperProperty/output.json | 305 ++++++++++++++++++ .../partial-application/for-any-arg/input.js | 3 + .../for-any-arg/options.json | 3 + .../for-any-arg/output.json | 260 +++++++++++++++ .../partial-application/from-left/input.js | 3 + .../from-left/options.json | 3 + .../partial-application/from-left/output.json | 230 +++++++++++++ .../partial-application/from-right/input.js | 3 + .../from-right/options.json | 3 + .../from-right/output.json | 230 +++++++++++++ .../partial-application/in-SuperCall/input.js | 6 + .../in-SuperCall/options.json | 4 + .../partial-application/in-new/input.js | 1 + .../partial-application/in-new/options.json | 4 + .../input.js | 1 + .../options.json | 4 + .../top-level-argument-method-call/input.js | 1 + .../options.json | 4 + .../.npmignore | 3 + .../README.md | 19 ++ .../package.json | 23 ++ .../src/index.js | 13 + .../src/asserts/generated/index.js | 6 + .../src/builders/generated/index.js | 4 + packages/babel-types/src/definitions/core.js | 7 +- .../src/definitions/experimental.js | 2 + .../src/validators/generated/index.js | 14 + 39 files changed, 1323 insertions(+), 2 deletions(-) create mode 100644 packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/input.js create mode 100644 packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/options.json create mode 100644 packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/output.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/from-left/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/from-left/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/from-left/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/from-right/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/from-right/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/from-right/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/in-new/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/in-new/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/options.json create mode 100644 packages/babel-plugin-syntax-partial-application/.npmignore create mode 100644 packages/babel-plugin-syntax-partial-application/README.md create mode 100644 packages/babel-plugin-syntax-partial-application/package.json create mode 100644 packages/babel-plugin-syntax-partial-application/src/index.js diff --git a/packages/babel-generator/src/generators/types.js b/packages/babel-generator/src/generators/types.js index 491ae75138..fdd090dd41 100644 --- a/packages/babel-generator/src/generators/types.js +++ b/packages/babel-generator/src/generators/types.js @@ -7,6 +7,10 @@ export function Identifier(node: Object) { }); } +export function ArgumentPlaceholder() { + this.token("?"); +} + export function RestElement(node: Object) { this.token("..."); this.print(node.argument, node); diff --git a/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/input.js b/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/input.js new file mode 100644 index 0000000000..29e9b90f83 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/input.js @@ -0,0 +1,12 @@ +foo(?); +foo(?, x); +foo(x, ?); +foo(?, x, ?); +obj.foo(x, ?); +obj.foo(?, x); +obj.foo(?, x, ?); +class foo { + constructor() { + baz(this, () => super.bar(?)); + } +} diff --git a/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/options.json b/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/options.json new file mode 100644 index 0000000000..eff0645122 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/options.json @@ -0,0 +1 @@ +{ "plugins": ["partialApplication"] } diff --git a/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/output.js b/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/output.js new file mode 100644 index 0000000000..7cb1b16bd5 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/ArgumentPlaceholder/output.js @@ -0,0 +1,14 @@ +foo(?); +foo(?, x); +foo(x, ?); +foo(?, x, ?); +obj.foo(x, ?); +obj.foo(?, x); +obj.foo(?, x, ?); + +class foo { + constructor() { + baz(this, () => super.bar(?)); + } + +} \ No newline at end of file diff --git a/packages/babel-parser/ast/spec.md b/packages/babel-parser/ast/spec.md index 7160972803..b4f5372cb4 100644 --- a/packages/babel-parser/ast/spec.md +++ b/packages/babel-parser/ast/spec.md @@ -72,6 +72,7 @@ These are the core @babel/parser (babylon) AST node types. - [LogicalExpression](#logicalexpression) - [LogicalOperator](#logicaloperator) - [SpreadElement](#spreadelement) + - [ArgumentPlaceholder](#argumentplaceholder) - [MemberExpression](#memberexpression) - [BindExpression](#bindexpression) - [ConditionalExpression](#conditionalexpression) @@ -862,6 +863,14 @@ interface SpreadElement <: Node { } ``` +### ArgumentPlaceholder + +```js +interface ArgumentPlaceholder <: Node { + type: "ArgumentPlaceholder"; +} +``` + ### MemberExpression ```js diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 9b05a76d56..516aba3aa2 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -323,7 +323,6 @@ export default class ExpressionParser extends LValParser { const operator = this.state.value; node.left = left; node.operator = operator; - if ( operator === "**" && left.type === "UnaryExpression" && @@ -634,6 +633,7 @@ export default class ExpressionParser extends LValParser { tt.parenR, possibleAsync, base.type === "Import", + base.type !== "Super", ); if (!state.optionalChainMember) { this.finishCallExpression(node); @@ -744,6 +744,7 @@ export default class ExpressionParser extends LValParser { close: TokenType, possibleAsyncArrow: boolean, dynamicImport?: boolean, + allowPlaceholder?: boolean, ): $ReadOnlyArray { const elts = []; let innerParenStart; @@ -776,6 +777,7 @@ export default class ExpressionParser extends LValParser { false, possibleAsyncArrow ? { start: 0 } : undefined, possibleAsyncArrow ? { start: 0 } : undefined, + allowPlaceholder, ), ); } @@ -1945,6 +1947,7 @@ export default class ExpressionParser extends LValParser { allowEmpty: ?boolean, refShorthandDefaultPos: ?Pos, refNeedsArrowPos: ?Pos, + allowPlaceholder: ?boolean, ): ?N.Expression { let elt; if (allowEmpty && this.match(tt.comma)) { @@ -1957,6 +1960,14 @@ export default class ExpressionParser extends LValParser { spreadNodeStartPos, spreadNodeStartLoc, ); + } else if (this.match(tt.question)) { + this.expectPlugin("partialApplication"); + if (!allowPlaceholder) { + this.raise(this.state.start, "Unexpected argument placeholder"); + } + const node = this.startNode(); + this.next(); + elt = this.finishNode(node, "ArgumentPlaceholder"); } else { elt = this.parseMaybeAssign( false, diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index 696589b3e6..35d79c9ce9 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -340,6 +340,8 @@ export type VariableDeclarator = NodeBase & { // Misc +export type ArgumentPlaceholder = NodeBase & { type: "ArgumentPlaceholder" }; + export type Decorator = NodeBase & { type: "Decorator", expression: Expression, diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/input.js new file mode 100644 index 0000000000..74512f8aac --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/input.js @@ -0,0 +1 @@ +foo(?) diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/options.json new file mode 100644 index 0000000000..87414aef43 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["partialApplication"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/output.json b/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/output.json new file mode 100644 index 0000000000..1846d67548 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/call-expr/output.json @@ -0,0 +1,99 @@ +{ + "type": "File", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "callee": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "arguments": [ + { + "type": "ArgumentPlaceholder", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + } + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/input.js new file mode 100644 index 0000000000..ed9915fb3c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/input.js @@ -0,0 +1,5 @@ +class foo { + constructor() { + baz(this, () => super.bar(?)); + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/options.json new file mode 100644 index 0000000000..87414aef43 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["partialApplication"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/output.json b/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/output.json new file mode 100644 index 0000000000..185313af12 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/call-on-SuperProperty/output.json @@ -0,0 +1,305 @@ +{ + "type": "File", + "start": 0, + "end": 78, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 78, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 78, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 9 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 10, + "end": 78, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "body": [ + { + "type": "ClassMethod", + "start": 16, + "end": 76, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + }, + "static": false, + "key": { + "type": "Identifier", + "start": 16, + "end": 27, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 15 + }, + "identifierName": "constructor" + }, + "name": "constructor" + }, + "computed": false, + "kind": "constructor", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 30, + "end": 76, + "loc": { + "start": { + "line": 2, + "column": 18 + }, + "end": { + "line": 4, + "column": 5 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 40, + "end": 70, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 38 + } + }, + "expression": { + "type": "CallExpression", + "start": 40, + "end": 69, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 37 + } + }, + "callee": { + "type": "Identifier", + "start": 40, + "end": 43, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 11 + }, + "identifierName": "baz" + }, + "name": "baz" + }, + "arguments": [ + { + "type": "ThisExpression", + "start": 44, + "end": 48, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 16 + } + } + }, + { + "type": "ArrowFunctionExpression", + "start": 50, + "end": 68, + "loc": { + "start": { + "line": 3, + "column": 18 + }, + "end": { + "line": 3, + "column": 36 + } + }, + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "CallExpression", + "start": 56, + "end": 68, + "loc": { + "start": { + "line": 3, + "column": 24 + }, + "end": { + "line": 3, + "column": 36 + } + }, + "callee": { + "type": "MemberExpression", + "start": 56, + "end": 65, + "loc": { + "start": { + "line": 3, + "column": 24 + }, + "end": { + "line": 3, + "column": 33 + } + }, + "object": { + "type": "Super", + "start": 56, + "end": 61, + "loc": { + "start": { + "line": 3, + "column": 24 + }, + "end": { + "line": 3, + "column": 29 + } + } + }, + "property": { + "type": "Identifier", + "start": 62, + "end": 65, + "loc": { + "start": { + "line": 3, + "column": 30 + }, + "end": { + "line": 3, + "column": 33 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "computed": false + }, + "arguments": [ + { + "type": "ArgumentPlaceholder", + "start": 66, + "end": 67, + "loc": { + "start": { + "line": 3, + "column": 34 + }, + "end": { + "line": 3, + "column": 35 + } + } + } + ] + } + } + ] + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/input.js new file mode 100644 index 0000000000..58db6e91a9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/input.js @@ -0,0 +1,3 @@ +foo(?,x,?) + +bar.foo(?, x, ?) diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/options.json new file mode 100644 index 0000000000..87414aef43 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["partialApplication"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/output.json b/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/output.json new file mode 100644 index 0000000000..29f5266444 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/for-any-arg/output.json @@ -0,0 +1,260 @@ +{ + "type": "File", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "callee": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "arguments": [ + { + "type": "ArgumentPlaceholder", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + } + } + }, + { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "x" + }, + "name": "x" + }, + { + "type": "ArgumentPlaceholder", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + } + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 12, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "expression": { + "type": "CallExpression", + "start": 12, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "callee": { + "type": "MemberExpression", + "start": 12, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "object": { + "type": "Identifier", + "start": 12, + "end": 15, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 3 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "property": { + "type": "Identifier", + "start": 16, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 7 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "computed": false + }, + "arguments": [ + { + "type": "ArgumentPlaceholder", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "Identifier", + "start": 23, + "end": 24, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 12 + }, + "identifierName": "x" + }, + "name": "x" + }, + { + "type": "ArgumentPlaceholder", + "start": 26, + "end": 27, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/input.js new file mode 100644 index 0000000000..c689537246 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/input.js @@ -0,0 +1,3 @@ +foo(x,?) + +bar.foo(x,?) diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/options.json new file mode 100644 index 0000000000..87414aef43 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["partialApplication"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/output.json b/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/output.json new file mode 100644 index 0000000000..d90ab651ee --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/from-left/output.json @@ -0,0 +1,230 @@ +{ + "type": "File", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "arguments": [ + { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + }, + "identifierName": "x" + }, + "name": "x" + }, + { + "type": "ArgumentPlaceholder", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 10, + "end": 22, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "expression": { + "type": "CallExpression", + "start": 10, + "end": 22, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "callee": { + "type": "MemberExpression", + "start": 10, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "object": { + "type": "Identifier", + "start": 10, + "end": 13, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 3 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "property": { + "type": "Identifier", + "start": 14, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 7 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "computed": false + }, + "arguments": [ + { + "type": "Identifier", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + }, + "identifierName": "x" + }, + "name": "x" + }, + { + "type": "ArgumentPlaceholder", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/input.js new file mode 100644 index 0000000000..b566c1df5b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/input.js @@ -0,0 +1,3 @@ +foo(?,x) + +bar.foo(?,x) diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/options.json new file mode 100644 index 0000000000..87414aef43 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["partialApplication"] +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/output.json b/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/output.json new file mode 100644 index 0000000000..ec82545ec3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/from-right/output.json @@ -0,0 +1,230 @@ +{ + "type": "File", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "arguments": [ + { + "type": "ArgumentPlaceholder", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + } + } + }, + { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "x" + }, + "name": "x" + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 10, + "end": 22, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "expression": { + "type": "CallExpression", + "start": 10, + "end": 22, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "callee": { + "type": "MemberExpression", + "start": 10, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "object": { + "type": "Identifier", + "start": 10, + "end": 13, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 3 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "property": { + "type": "Identifier", + "start": 14, + "end": 17, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 7 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "computed": false + }, + "arguments": [ + { + "type": "ArgumentPlaceholder", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + } + }, + { + "type": "Identifier", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + }, + "identifierName": "x" + }, + "name": "x" + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/input.js new file mode 100644 index 0000000000..eac2ab9cb7 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/input.js @@ -0,0 +1,6 @@ +class Foo extends Bar { + constructor(x){ + super(x, 1, ?, ?); + this.x = x; + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/options.json new file mode 100644 index 0000000000..58192a87fd --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/in-SuperCall/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["partialApplication"], + "throws": "Unexpected argument placeholder (3:16)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/in-new/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/in-new/input.js new file mode 100644 index 0000000000..36314ea529 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/in-new/input.js @@ -0,0 +1 @@ +new bar(x, ?, 2, ?) diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/in-new/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/in-new/options.json new file mode 100644 index 0000000000..3b09c84c03 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/in-new/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["partialApplication"], + "throws": "Unexpected argument placeholder (1:11)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/input.js new file mode 100644 index 0000000000..a511c8bf7d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/input.js @@ -0,0 +1 @@ +? + x diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/options.json new file mode 100644 index 0000000000..8abbd07898 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-binary-expression/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["partialApplication"], + "throws": "Unexpected token (1:0)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/input.js b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/input.js new file mode 100644 index 0000000000..3308d87808 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/input.js @@ -0,0 +1 @@ +?.f() diff --git a/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/options.json b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/options.json new file mode 100644 index 0000000000..8abbd07898 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/partial-application/top-level-argument-method-call/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["partialApplication"], + "throws": "Unexpected token (1:0)" +} diff --git a/packages/babel-plugin-syntax-partial-application/.npmignore b/packages/babel-plugin-syntax-partial-application/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-syntax-partial-application/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-syntax-partial-application/README.md b/packages/babel-plugin-syntax-partial-application/README.md new file mode 100644 index 0000000000..d502846179 --- /dev/null +++ b/packages/babel-plugin-syntax-partial-application/README.md @@ -0,0 +1,19 @@ +# @babel/plugin-syntax-partial-application + +> Allow parsing of optional properties + +See our website [@babel/plugin-syntax-partial-application](https://babeljs.io/docs/en/next/babel-plugin-syntax-partial-application.html) for more information. + +## Install + +Using npm: + +```sh +npm install --save-dev @babel/plugin-syntax-partial-application +``` + +or using yarn: + +```sh +yarn add @babel/plugin-syntax-partial-application --dev +``` diff --git a/packages/babel-plugin-syntax-partial-application/package.json b/packages/babel-plugin-syntax-partial-application/package.json new file mode 100644 index 0000000000..603cc408c8 --- /dev/null +++ b/packages/babel-plugin-syntax-partial-application/package.json @@ -0,0 +1,23 @@ +{ + "name": "@babel/plugin-syntax-partial-application", + "version": "7.2.0", + "description": "Allow parsing of partial application syntax", + "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-partial-application", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "lib/index.js", + "keywords": [ + "babel-plugin" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "devDependencies": { + "@babel/core": "^7.2.0" + } +} diff --git a/packages/babel-plugin-syntax-partial-application/src/index.js b/packages/babel-plugin-syntax-partial-application/src/index.js new file mode 100644 index 0000000000..aafcfc315e --- /dev/null +++ b/packages/babel-plugin-syntax-partial-application/src/index.js @@ -0,0 +1,13 @@ +import { declare } from "@babel/helper-plugin-utils"; + +export default declare(api => { + api.assertVersion(7); + + return { + name: "syntax-partial-application", + + manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("partialApplication"); + }, + }; +}); diff --git a/packages/babel-types/src/asserts/generated/index.js b/packages/babel-types/src/asserts/generated/index.js index 890e3d6e8d..34a6a125a2 100644 --- a/packages/babel-types/src/asserts/generated/index.js +++ b/packages/babel-types/src/asserts/generated/index.js @@ -660,6 +660,12 @@ export function assertParenthesizedExpression( ): void { assert("ParenthesizedExpression", node, opts); } +export function assertArgumentPlaceholder( + node: Object, + opts?: Object = {}, +): void { + assert("ArgumentPlaceholder", node, opts); +} export function assertAwaitExpression(node: Object, opts?: Object = {}): void { assert("AwaitExpression", node, opts); } diff --git a/packages/babel-types/src/builders/generated/index.js b/packages/babel-types/src/builders/generated/index.js index a77b43cbb6..6b787e0bb3 100644 --- a/packages/babel-types/src/builders/generated/index.js +++ b/packages/babel-types/src/builders/generated/index.js @@ -596,6 +596,10 @@ export function ParenthesizedExpression(...args: Array): Object { return builder("ParenthesizedExpression", ...args); } export { ParenthesizedExpression as parenthesizedExpression }; +export function ArgumentPlaceholder(...args: Array): Object { + return builder("ArgumentPlaceholder", ...args); +} +export { ArgumentPlaceholder as argumentPlaceholder }; export function AwaitExpression(...args: Array): Object { return builder("AwaitExpression", ...args); } diff --git a/packages/babel-types/src/definitions/core.js b/packages/babel-types/src/definitions/core.js index a92e8d2725..214fa6ccd4 100644 --- a/packages/babel-types/src/definitions/core.js +++ b/packages/babel-types/src/definitions/core.js @@ -138,7 +138,12 @@ defineType("CallExpression", { validate: chain( assertValueType("array"), assertEach( - assertNodeType("Expression", "SpreadElement", "JSXNamespacedName"), + assertNodeType( + "Expression", + "SpreadElement", + "JSXNamespacedName", + "ArgumentPlaceholder", + ), ), ), }, diff --git a/packages/babel-types/src/definitions/experimental.js b/packages/babel-types/src/definitions/experimental.js index 6498e9c329..ed088af74b 100644 --- a/packages/babel-types/src/definitions/experimental.js +++ b/packages/babel-types/src/definitions/experimental.js @@ -10,6 +10,8 @@ import { classMethodOrDeclareMethodCommon, } from "./es2015"; +defineType("ArgumentPlaceholder", {}); + defineType("AwaitExpression", { builder: ["argument"], visitor: ["argument"], diff --git a/packages/babel-types/src/validators/generated/index.js b/packages/babel-types/src/validators/generated/index.js index ab74610518..c23ddcf11d 100644 --- a/packages/babel-types/src/validators/generated/index.js +++ b/packages/babel-types/src/validators/generated/index.js @@ -2093,6 +2093,20 @@ export function isParenthesizedExpression( return false; } +export function isArgumentPlaceholder(node: ?Object, opts?: Object): boolean { + if (!node) return false; + + const nodeType = node.type; + if (nodeType === "ArgumentPlaceholder") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isAwaitExpression(node: ?Object, opts?: Object): boolean { if (!node) return false;