Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more parser test cases #11923

Merged
merged 7 commits into from Aug 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 3 additions & 37 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -1258,20 +1258,6 @@ export default class StatementParser extends ExpressionParser {
return this.finishNode(classBody, "ClassBody");
}

// Check grammar production:
// IdentifierName *_opt ClassElementName
// It is used in `parsePropertyDefinition` to detect AsyncMethod and Accessors
maybeClassModifier(prop: N.ObjectProperty): boolean {
return (
!prop.computed &&
prop.key.type === "Identifier" &&
(this.isLiteralPropertyName() ||
this.match(tt.bracketL) ||
this.match(tt.star) ||
this.match(tt.hash))
);
}

// returns true if the current identifier is a method/field name,
// false if it is a modifier
parseClassMemberFromModifier(
Expand Down Expand Up @@ -1611,11 +1597,6 @@ export default class StatementParser extends ExpressionParser {
methodOrProp: N.ClassMethod | N.ClassProperty,
): void {}

// Overridden in typescript.js
parseAccessModifier(): ?N.Accessibility {
return undefined;
}

parseClassPrivateProperty(
node: N.ClassPrivateProperty,
): N.ClassPrivateProperty {
Expand Down Expand Up @@ -1784,19 +1765,9 @@ export default class StatementParser extends ExpressionParser {

maybeParseExportDeclaration(node: N.Node): boolean {
if (this.shouldParseExportDeclaration()) {
if (this.isContextual("async")) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These checks are redundant because shouldParseExportDeclaration will check isAsyncFunction

shouldParseExportDeclaration(): boolean {
if (this.match(tt.at)) {
this.expectOnePlugin(["decorators", "decorators-legacy"]);
if (this.hasPlugin("decorators")) {
if (this.getPluginOption("decorators", "decoratorsBeforeExport")) {
this.unexpected(this.state.start, Errors.DecoratorBeforeExport);
} else {
return true;
}
}
}
return (
this.state.type.keyword === "var" ||
this.state.type.keyword === "const" ||
this.state.type.keyword === "function" ||
this.state.type.keyword === "class" ||
this.isLet() ||
this.isAsyncFunction()
);
}

When this.isContextual("async") is true, isAsyncFunction() must be true and async must be followed by a function token, therefore this.unexpected(next, tt._function); is never reached.

const next = this.nextTokenStart();

// export async;
if (!this.isUnparsedContextual(next, "function")) {
this.unexpected(next, tt._function);
}
}

node.specifiers = [];
node.source = null;
node.declaration = this.parseExportDeclaration(node);

return true;
}
return false;
Expand Down Expand Up @@ -1999,15 +1970,10 @@ export default class StatementParser extends ExpressionParser {
const currentContextDecorators = this.state.decoratorStack[
this.state.decoratorStack.length - 1
];
// If node.declaration is a class, it will take all decorators in the current context.
// Thus we should throw if we see non-empty decorators here.
if (currentContextDecorators.length) {
const isClass =
node.declaration &&
(node.declaration.type === "ClassDeclaration" ||
node.declaration.type === "ClassExpression");
if (!node.declaration || !isClass) {
throw this.raise(node.start, Errors.UnsupportedDecoratorExport);
}
this.takeDecorators(node.declaration);
throw this.raise(node.start, Errors.UnsupportedDecoratorExport);
}
}

Expand Down
@@ -0,0 +1,2 @@
// prettier-ignore
await +42
@@ -0,0 +1,3 @@
{
"sourceType": "module"
}
@@ -0,0 +1,33 @@
{
"type": "AwaitExpression",
"start":19,"end":28,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":9}},
"argument": {
"type": "UnaryExpression",
"start":25,"end":28,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":9}},
"operator": "+",
"prefix": true,
"argument": {
"type": "NumericLiteral",
"start":26,"end":28,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":9}},
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
}
},
"leadingComments": [
{
"type": "CommentLine",
"value": " prettier-ignore",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}
}
],
"comments": [
{
"type": "CommentLine",
"value": " prettier-ignore",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}
}
]
}
@@ -0,0 +1,3 @@
{
"plugins": ["topLevelAwait"]
}
@@ -0,0 +1,2 @@
// prettier-ignore
await +42
JLHwung marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,3 @@
{
"sourceType": "script"
}
@@ -0,0 +1,33 @@
{
"type": "BinaryExpression",
"start":19,"end":28,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":9}},
"left": {
"type": "Identifier",
"start":19,"end":24,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5},"identifierName":"await"},
"name": "await"
},
"operator": "+",
"right": {
"type": "NumericLiteral",
"start":26,"end":28,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":9}},
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
},
"leadingComments": [
{
"type": "CommentLine",
"value": " prettier-ignore",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}
}
],
"comments": [
{
"type": "CommentLine",
"value": " prettier-ignore",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}
}
]
}
@@ -0,0 +1,2 @@
// prettier-ignore
await +42
@@ -0,0 +1,3 @@
{
"sourceType": "unambiguous"
}
@@ -0,0 +1,33 @@
{
"type": "BinaryExpression",
"start":19,"end":28,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":9}},
"left": {
"type": "Identifier",
"start":19,"end":24,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5},"identifierName":"await"},
"name": "await"
},
"operator": "+",
"right": {
"type": "NumericLiteral",
"start":26,"end":28,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":9}},
"extra": {
"rawValue": 42,
"raw": "42"
},
"value": 42
},
"leadingComments": [
{
"type": "CommentLine",
"value": " prettier-ignore",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}
}
],
"comments": [
{
"type": "CommentLine",
"value": " prettier-ignore",
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}}
}
]
}
@@ -0,0 +1 @@
const { foo() {} } = foo();
@@ -0,0 +1,3 @@
{
"throws": "Unexpected token (1:11)"
}
@@ -0,0 +1 @@
export * as foo,
@@ -0,0 +1,3 @@
{
"throws": "Unexpected token, expected \"{\" (1:16)"
}
@@ -0,0 +1 @@
::a?.b;
@@ -0,0 +1,6 @@
{
"plugins": [
"functionBind"
],
"throws": "Binding should be performed on object property. (1:2)"
}
@@ -0,0 +1,3 @@
{
"plugins": ["functionBind"]
}
@@ -0,0 +1 @@
({ @foo ...foo });
@@ -0,0 +1,4 @@
{
"plugins": ["decorators-legacy"],
"throws": "Unexpected token (1:8)"
}
@@ -0,0 +1 @@
export default,
@@ -0,0 +1,3 @@
{
"throws": "Unexpected token, expected \"{\" (1:15)"
}
@@ -0,0 +1 @@
x |> # + 1
@@ -0,0 +1,3 @@
{
"plugins": [["pipelineOperator", { "proposal": "fsharp" }]]
}
@@ -0,0 +1,49 @@
{
"type": "File",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"errors": [
"SyntaxError: Primary Topic Reference found but pipelineOperator not passed 'smart' for 'proposal' option. (1:5)",
"SyntaxError: Topic reference was used in a lexical context without topic binding (1:5)"
],
"program": {
"type": "Program",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"expression": {
"type": "BinaryExpression",
"start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}},
"left": {
"type": "Identifier",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":1},"identifierName":"x"},
"name": "x"
},
"operator": "|>",
"right": {
"type": "BinaryExpression",
"start":5,"end":10,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":10}},
"left": {
"type": "PipelinePrimaryTopicReference",
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6}}
},
"operator": "+",
"right": {
"type": "NumericLiteral",
"start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10}},
"extra": {
"rawValue": 1,
"raw": "1"
},
"value": 1
}
}
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
#{ __proto__: null }
@@ -0,0 +1,3 @@
{
"plugins": [["recordAndTuple", { "syntaxType": "hash" }]]
}
@@ -0,0 +1,42 @@
{
"type": "File",
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
"errors": [
"SyntaxError: '__proto__' is not allowed in Record expressions (1:3)"
],
"program": {
"type": "Program",
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
"expression": {
"type": "RecordExpression",
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
"properties": [
{
"type": "ObjectProperty",
"start":3,"end":18,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":18}},
"method": false,
"key": {
"type": "Identifier",
"start":3,"end":12,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":12},"identifierName":"__proto__"},
"name": "__proto__"
},
"computed": false,
"shorthand": false,
"value": {
"type": "NullLiteral",
"start":14,"end":18,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":18}}
}
}
]
}
}
],
"directives": []
}
}