diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index fb6e8363a333..f9d401fd5307 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -9,6 +9,7 @@ import type Parser from "../../parser"; import { type BindingTypes, BIND_NONE, + SCOPE_MODULE_DECLARATION, SCOPE_OTHER, BIND_TS_ENUM, BIND_TS_CONST_ENUM, @@ -1163,7 +1164,9 @@ export default (superClass: Class): Class => this.tsParseModuleOrNamespaceDeclaration(inner, true); node.body = inner; } else { + this.scope.enter(SCOPE_MODULE_DECLARATION); node.body = this.tsParseModuleBlock(); + this.scope.exit(); } return this.finishNode(node, "TSModuleDeclaration"); } @@ -1179,9 +1182,10 @@ export default (superClass: Class): Class => } else { this.unexpected(); } - if (this.match(tt.braceL)) { + this.scope.enter(SCOPE_MODULE_DECLARATION); node.body = this.tsParseModuleBlock(); + this.scope.exit(); } else { this.semicolon(); } @@ -1329,10 +1333,12 @@ export default (superClass: Class): Class => // `global { }` (with no `declare`) may appear inside an ambient module declaration. // Would like to use tsParseAmbientExternalModuleDeclaration here, but already ran past "global". if (this.match(tt.braceL)) { + this.scope.enter(SCOPE_MODULE_DECLARATION); const mod: N.TsModuleDeclaration = node; mod.global = true; mod.id = expr; mod.body = this.tsParseModuleBlock(); + this.scope.exit(); return this.finishNode(mod, "TSModuleDeclaration"); } break; diff --git a/packages/babel-parser/src/util/scopeflags.js b/packages/babel-parser/src/util/scopeflags.js index 8c9697b3a416..befd2fb89d04 100644 --- a/packages/babel-parser/src/util/scopeflags.js +++ b/packages/babel-parser/src/util/scopeflags.js @@ -2,17 +2,18 @@ // Each scope gets a bitset that may contain these flags // prettier-ignore -export const SCOPE_OTHER = 0b000000000, - SCOPE_PROGRAM = 0b000000001, - SCOPE_FUNCTION = 0b000000010, - SCOPE_ASYNC = 0b000000100, - SCOPE_GENERATOR = 0b000001000, - SCOPE_ARROW = 0b000010000, - SCOPE_SIMPLE_CATCH = 0b000100000, - SCOPE_SUPER = 0b001000000, - SCOPE_DIRECT_SUPER = 0b010000000, - SCOPE_CLASS = 0b100000000, - SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION; +export const SCOPE_OTHER = 0b0000000000, + SCOPE_PROGRAM = 0b0000000001, + SCOPE_FUNCTION = 0b0000000010, + SCOPE_ASYNC = 0b0000000100, + SCOPE_GENERATOR = 0b0000001000, + SCOPE_ARROW = 0b0000010000, + SCOPE_SIMPLE_CATCH = 0b0000100000, + SCOPE_SUPER = 0b0001000000, + SCOPE_DIRECT_SUPER = 0b0010000000, + SCOPE_CLASS = 0b0100000000, + SCOPE_MODULE_DECLARATION = 0b1000000000, + SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_MODULE_DECLARATION; export type ScopeFlags = | typeof SCOPE_OTHER diff --git a/packages/babel-parser/test/fixtures/typescript/scope/module-declaration-var/input.js b/packages/babel-parser/test/fixtures/typescript/scope/module-declaration-var/input.js new file mode 100644 index 000000000000..23f863c31ba0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/scope/module-declaration-var/input.js @@ -0,0 +1,5 @@ +declare class foo { +} +declare module 'bar' { + export var foo: any; // Identifier 'foo' has already been declared +} diff --git a/packages/babel-parser/test/fixtures/typescript/scope/module-declaration-var/output.json b/packages/babel-parser/test/fixtures/typescript/scope/module-declaration-var/output.json new file mode 100644 index 000000000000..7ef989970fe9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/scope/module-declaration-var/output.json @@ -0,0 +1,272 @@ +{ + "type": "File", + "start": 0, + "end": 115, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 115, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 14, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 17 + }, + "identifierName": "foo" + }, + "name": "foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 18, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 2, + "column": 1 + } + }, + "body": [] + }, + "declare": true + }, + { + "type": "TSModuleDeclaration", + "start": 22, + "end": 115, + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "StringLiteral", + "start": 37, + "end": 42, + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 20 + } + }, + "extra": { + "rawValue": "bar", + "raw": "'bar'" + }, + "value": "bar" + }, + "body": { + "type": "TSModuleBlock", + "start": 43, + "end": 115, + "loc": { + "start": { + "line": 3, + "column": 21 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "body": [ + { + "type": "ExportNamedDeclaration", + "start": 47, + "end": 67, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 22 + } + }, + "specifiers": [], + "source": null, + "declaration": { + "type": "VariableDeclaration", + "start": 54, + "end": 67, + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 4, + "column": 22 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 58, + "end": 66, + "loc": { + "start": { + "line": 4, + "column": 13 + }, + "end": { + "line": 4, + "column": 21 + } + }, + "id": { + "type": "Identifier", + "start": 58, + "end": 66, + "loc": { + "start": { + "line": 4, + "column": 13 + }, + "end": { + "line": 4, + "column": 21 + }, + "identifierName": "foo" + }, + "name": "foo", + "typeAnnotation": { + "type": "TSTypeAnnotation", + "start": 61, + "end": 66, + "loc": { + "start": { + "line": 4, + "column": 16 + }, + "end": { + "line": 4, + "column": 21 + } + }, + "typeAnnotation": { + "type": "TSAnyKeyword", + "start": 63, + "end": 66, + "loc": { + "start": { + "line": 4, + "column": 18 + }, + "end": { + "line": 4, + "column": 21 + } + } + } + } + }, + "init": null + } + ], + "kind": "var" + }, + "trailingComments": [ + { + "type": "CommentLine", + "value": " Identifier 'foo' has already been declared", + "start": 68, + "end": 113, + "loc": { + "start": { + "line": 4, + "column": 23 + }, + "end": { + "line": 4, + "column": 68 + } + } + } + ] + } + ] + }, + "declare": true + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentLine", + "value": " Identifier 'foo' has already been declared", + "start": 68, + "end": 113, + "loc": { + "start": { + "line": 4, + "column": 23 + }, + "end": { + "line": 4, + "column": 68 + } + } + } + ] +} \ No newline at end of file