diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index aed992336b99..7a1fbc80cc8d 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -1624,14 +1624,13 @@ export default (superClass: Class): Class => value: string, next: boolean, ): ?N.Declaration { + // no declaration apart from enum can be followed by a line break. switch (value) { case "abstract": if ( - this.tsCheckLineTerminatorAndMatch(tt._class, next) || - // for interface - this.tsCheckLineTerminatorAndMatch(tt.name, next) + this.tsCheckLineTerminator(next) && + (this.match(tt._class) || this.match(tt.name)) ) { - if (next) this.next(); return this.tsParseAbstractDeclaration(node); } break; @@ -1644,39 +1643,42 @@ export default (superClass: Class): Class => break; case "interface": - if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) { - if (next) this.next(); + if (this.tsCheckLineTerminator(next) && this.match(tt.name)) { return this.tsParseInterfaceDeclaration(node); } break; case "module": - if (next) this.next(); - if (this.match(tt.string)) { - return this.tsParseAmbientExternalModuleDeclaration(node); - } else if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) { - return this.tsParseModuleOrNamespaceDeclaration(node); + if (this.tsCheckLineTerminator(next)) { + if (this.match(tt.string)) { + return this.tsParseAmbientExternalModuleDeclaration(node); + } else if (this.match(tt.name)) { + return this.tsParseModuleOrNamespaceDeclaration(node); + } } break; case "namespace": - if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) { - if (next) this.next(); + if (this.tsCheckLineTerminator(next) && this.match(tt.name)) { return this.tsParseModuleOrNamespaceDeclaration(node); } break; case "type": - if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) { - if (next) this.next(); + if (this.tsCheckLineTerminator(next) && this.match(tt.name)) { return this.tsParseTypeAliasDeclaration(node); } break; } } - tsCheckLineTerminatorAndMatch(tokenType: TokenType, next: boolean) { - return (next || this.match(tokenType)) && !this.isLineTerminator(); + tsCheckLineTerminator(next: boolean) { + if (next) { + if (this.hasFollowingLineBreak()) return false; + this.next(); + return true; + } + return !this.isLineTerminator(); } tsTryParseGenericAsyncArrowFunction( diff --git a/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/input.ts b/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/input.ts new file mode 100644 index 000000000000..8c6c81cfafcc --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/input.ts @@ -0,0 +1,2 @@ +declare abstract +class A {} diff --git a/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/output.json b/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/output.json new file mode 100644 index 000000000000..04a02c759f73 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/class/declare-new-line-abstract/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":10}}, + "errors": [ + "SyntaxError: Missing semicolon (1:7)" + ], + "program": { + "type": "Program", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":10}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "Identifier", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":8,"end":16,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":16}}, + "expression": { + "type": "Identifier", + "start":8,"end":16,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":16},"identifierName":"abstract"}, + "name": "abstract" + } + }, + { + "type": "ClassDeclaration", + "start":17,"end":27,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":10}}, + "id": { + "type": "Identifier", + "start":23,"end":24,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":7},"identifierName":"A"}, + "name": "A" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":25,"end":27,"loc":{"start":{"line":2,"column":8},"end":{"line":2,"column":10}}, + "body": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/enum/declare-new-line/input.ts b/packages/babel-parser/test/fixtures/typescript/enum/declare-new-line/input.ts new file mode 100644 index 000000000000..8ce2bd56c88a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/enum/declare-new-line/input.ts @@ -0,0 +1,3 @@ +declare enum +E +{} diff --git a/packages/babel-parser/test/fixtures/typescript/enum/declare-new-line/output.json b/packages/babel-parser/test/fixtures/typescript/enum/declare-new-line/output.json new file mode 100644 index 000000000000..5ec877e931ba --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/enum/declare-new-line/output.json @@ -0,0 +1,24 @@ +{ + "type": "File", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "program": { + "type": "Program", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "TSEnumDeclaration", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "id": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":1},"identifierName":"E"}, + "name": "E" + }, + "members": [], + "declare": true + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/interface/declare-new-line/input.ts b/packages/babel-parser/test/fixtures/typescript/interface/declare-new-line/input.ts new file mode 100644 index 000000000000..2a075540d6ae --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/interface/declare-new-line/input.ts @@ -0,0 +1,3 @@ +declare interface +I +{} diff --git a/packages/babel-parser/test/fixtures/typescript/interface/declare-new-line/output.json b/packages/babel-parser/test/fixtures/typescript/interface/declare-new-line/output.json new file mode 100644 index 000000000000..5158d520298c --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/interface/declare-new-line/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "errors": [ + "SyntaxError: Missing semicolon (1:7)" + ], + "program": { + "type": "Program", + "start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "Identifier", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":8,"end":17,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":17}}, + "expression": { + "type": "Identifier", + "start":8,"end":17,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":17},"identifierName":"interface"}, + "name": "interface" + } + }, + { + "type": "ExpressionStatement", + "start":18,"end":19,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":1}}, + "expression": { + "type": "Identifier", + "start":18,"end":19,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":1},"identifierName":"I"}, + "name": "I" + } + }, + { + "type": "BlockStatement", + "start":20,"end":22,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":2}}, + "body": [], + "directives": [] + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/module-namespace/module-declare-new-line/input.ts b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-declare-new-line/input.ts new file mode 100644 index 000000000000..58c8603a5b29 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-declare-new-line/input.ts @@ -0,0 +1,8 @@ +declare +module +'foo' +{} + +declare module +'bar' +{} diff --git a/packages/babel-parser/test/fixtures/typescript/module-namespace/module-declare-new-line/output.json b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-declare-new-line/output.json new file mode 100644 index 000000000000..1ba41584fb21 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-declare-new-line/output.json @@ -0,0 +1,90 @@ +{ + "type": "File", + "start":0,"end":48,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":2}}, + "errors": [ + "SyntaxError: Missing semicolon (6:7)" + ], + "program": { + "type": "Program", + "start":0,"end":48,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "Identifier", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":8,"end":14,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":6}}, + "expression": { + "type": "Identifier", + "start":8,"end":14,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":6},"identifierName":"module"}, + "name": "module" + } + }, + { + "type": "ExpressionStatement", + "start":15,"end":20,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":5}}, + "expression": { + "type": "StringLiteral", + "start":15,"end":20,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":5}}, + "extra": { + "rawValue": "foo", + "raw": "'foo'" + }, + "value": "foo" + } + }, + { + "type": "BlockStatement", + "start":21,"end":23,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":2}}, + "body": [], + "directives": [] + }, + { + "type": "ExpressionStatement", + "start":25,"end":32,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":7}}, + "expression": { + "type": "Identifier", + "start":25,"end":32,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":33,"end":39,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":14}}, + "expression": { + "type": "Identifier", + "start":33,"end":39,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":14},"identifierName":"module"}, + "name": "module" + } + }, + { + "type": "ExpressionStatement", + "start":40,"end":45,"loc":{"start":{"line":7,"column":0},"end":{"line":7,"column":5}}, + "expression": { + "type": "StringLiteral", + "start":40,"end":45,"loc":{"start":{"line":7,"column":0},"end":{"line":7,"column":5}}, + "extra": { + "rawValue": "bar", + "raw": "'bar'" + }, + "value": "bar" + } + }, + { + "type": "BlockStatement", + "start":46,"end":48,"loc":{"start":{"line":8,"column":0},"end":{"line":8,"column":2}}, + "body": [], + "directives": [] + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/input.ts b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/input.ts index f3a399f41cb7..2d31fff550e4 100644 --- a/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/input.ts +++ b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/input.ts @@ -1,3 +1,7 @@ module Foo {} + +module +'m' +{} diff --git a/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/output.json b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/output.json index 172c4f667538..295cd5263ead 100644 --- a/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/output.json +++ b/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line/output.json @@ -1,9 +1,9 @@ { "type": "File", - "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":2}}, "program": { "type": "Program", - "start":0,"end":13,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}}, + "start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":7,"column":2}}, "sourceType": "module", "interpreter": null, "body": [ @@ -30,6 +30,34 @@ "start":11,"end":13,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":2}}, "body": [], "directives": [] + }, + { + "type": "ExpressionStatement", + "start":15,"end":21,"loc":{"start":{"line":5,"column":0},"end":{"line":5,"column":6}}, + "expression": { + "type": "Identifier", + "start":15,"end":21,"loc":{"start":{"line":5,"column":0},"end":{"line":5,"column":6},"identifierName":"module"}, + "name": "module" + } + }, + { + "type": "ExpressionStatement", + "start":22,"end":25,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":3}}, + "expression": { + "type": "StringLiteral", + "start":22,"end":25,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":3}}, + "extra": { + "rawValue": "m", + "raw": "'m'" + }, + "value": "m" + } + }, + { + "type": "BlockStatement", + "start":26,"end":28,"loc":{"start":{"line":7,"column":0},"end":{"line":7,"column":2}}, + "body": [], + "directives": [] } ], "directives": [] diff --git a/packages/babel-parser/test/fixtures/typescript/module-namespace/namespace-declare-new-line/input.ts b/packages/babel-parser/test/fixtures/typescript/module-namespace/namespace-declare-new-line/input.ts new file mode 100644 index 000000000000..865c248d4a89 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/module-namespace/namespace-declare-new-line/input.ts @@ -0,0 +1,8 @@ +declare +namespace +foofoo +{} + +declare namespace +barbar +{} diff --git a/packages/babel-parser/test/fixtures/typescript/module-namespace/namespace-declare-new-line/output.json b/packages/babel-parser/test/fixtures/typescript/module-namespace/namespace-declare-new-line/output.json new file mode 100644 index 000000000000..738b0bfc7701 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/module-namespace/namespace-declare-new-line/output.json @@ -0,0 +1,82 @@ +{ + "type": "File", + "start":0,"end":56,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":2}}, + "errors": [ + "SyntaxError: Missing semicolon (6:7)" + ], + "program": { + "type": "Program", + "start":0,"end":56,"loc":{"start":{"line":1,"column":0},"end":{"line":8,"column":2}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "Identifier", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":8,"end":17,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":9}}, + "expression": { + "type": "Identifier", + "start":8,"end":17,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":9},"identifierName":"namespace"}, + "name": "namespace" + } + }, + { + "type": "ExpressionStatement", + "start":18,"end":24,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":6}}, + "expression": { + "type": "Identifier", + "start":18,"end":24,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":6},"identifierName":"foofoo"}, + "name": "foofoo" + } + }, + { + "type": "BlockStatement", + "start":25,"end":27,"loc":{"start":{"line":4,"column":0},"end":{"line":4,"column":2}}, + "body": [], + "directives": [] + }, + { + "type": "ExpressionStatement", + "start":29,"end":36,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":7}}, + "expression": { + "type": "Identifier", + "start":29,"end":36,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":37,"end":46,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":17}}, + "expression": { + "type": "Identifier", + "start":37,"end":46,"loc":{"start":{"line":6,"column":8},"end":{"line":6,"column":17},"identifierName":"namespace"}, + "name": "namespace" + } + }, + { + "type": "ExpressionStatement", + "start":47,"end":53,"loc":{"start":{"line":7,"column":0},"end":{"line":7,"column":6}}, + "expression": { + "type": "Identifier", + "start":47,"end":53,"loc":{"start":{"line":7,"column":0},"end":{"line":7,"column":6},"identifierName":"barbar"}, + "name": "barbar" + } + }, + { + "type": "BlockStatement", + "start":54,"end":56,"loc":{"start":{"line":8,"column":0},"end":{"line":8,"column":2}}, + "body": [], + "directives": [] + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-alias/declare-new-line/input.ts b/packages/babel-parser/test/fixtures/typescript/type-alias/declare-new-line/input.ts new file mode 100644 index 000000000000..d8433232652d --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-alias/declare-new-line/input.ts @@ -0,0 +1,2 @@ +declare type +T = number diff --git a/packages/babel-parser/test/fixtures/typescript/type-alias/declare-new-line/output.json b/packages/babel-parser/test/fixtures/typescript/type-alias/declare-new-line/output.json new file mode 100644 index 000000000000..89ebf2f1f64a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-alias/declare-new-line/output.json @@ -0,0 +1,53 @@ +{ + "type": "File", + "start":0,"end":23,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":10}}, + "errors": [ + "SyntaxError: Missing semicolon (1:7)" + ], + "program": { + "type": "Program", + "start":0,"end":23,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":10}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7}}, + "expression": { + "type": "Identifier", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":7},"identifierName":"declare"}, + "name": "declare" + } + }, + { + "type": "ExpressionStatement", + "start":8,"end":12,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":12}}, + "expression": { + "type": "Identifier", + "start":8,"end":12,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":12},"identifierName":"type"}, + "name": "type" + } + }, + { + "type": "ExpressionStatement", + "start":13,"end":23,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":10}}, + "expression": { + "type": "AssignmentExpression", + "start":13,"end":23,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":10}}, + "operator": "=", + "left": { + "type": "Identifier", + "start":13,"end":14,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":1},"identifierName":"T"}, + "name": "T" + }, + "right": { + "type": "Identifier", + "start":17,"end":23,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":10},"identifierName":"number"}, + "name": "number" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file