Skip to content

Commit

Permalink
Do not register ambient classes to the TS scope (#10352)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo authored and existentialism committed Aug 20, 2019
1 parent 11ed2e2 commit 15aa511
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 8 deletions.
4 changes: 3 additions & 1 deletion packages/babel-parser/src/parser/statement.js
Expand Up @@ -20,6 +20,7 @@ import {
SCOPE_OTHER,
SCOPE_SIMPLE_CATCH,
SCOPE_SUPER,
type BindingTypes,
} from "../util/scopeflags";

const loopLabel = { kind: "loop" },
Expand Down Expand Up @@ -1611,11 +1612,12 @@ export default class StatementParser extends ExpressionParser {
node: N.Class,
isStatement: boolean,
optionalId: ?boolean,
bindingType: BindingTypes = BIND_CLASS,
): void {
if (this.match(tt.name)) {
node.id = this.parseIdentifier();
if (isStatement) {
this.checkLVal(node.id, BIND_CLASS, undefined, "class name");
this.checkLVal(node.id, bindingType, undefined, "class name");
}
} else {
if (optionalId || !isStatement) {
Expand Down
15 changes: 12 additions & 3 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -14,8 +14,9 @@ import {
BIND_TS_CONST_ENUM,
BIND_TS_TYPE,
BIND_TS_INTERFACE,
BIND_TS_FN_TYPE,
BIND_TS_AMBIENT,
BIND_TS_NAMESPACE,
BIND_CLASS,
} from "../../util/scopeflags";
import TypeScriptScopeHandler from "./scope";

Expand Down Expand Up @@ -1278,6 +1279,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
/* declarationPosition */ true,
);
case tt._class:
// While this is also set by tsParseExpressionStatement, we need to set it
// before parsing the class declaration to now how to register it in the scope.
nany.declare = true;
return this.parseClass(
nany,
/* isStatement */ true,
Expand Down Expand Up @@ -1552,7 +1556,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>

checkFunctionStatementId(node: N.Function): void {
if (!node.body && node.id) {
this.checkLVal(node.id, BIND_TS_FN_TYPE, null, "function name");
this.checkLVal(node.id, BIND_TS_AMBIENT, null, "function name");
} else {
super.checkFunctionStatementId(...arguments);
}
Expand Down Expand Up @@ -1988,7 +1992,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return;
}

super.parseClassId(...arguments);
super.parseClassId(
node,
isStatement,
optionalId,
(node: any).declare ? BIND_TS_AMBIENT : BIND_CLASS,
);
const typeParameters = this.tsTryParseTypeParameters();
if (typeParameters) node.typeParameters = typeParameters;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/plugins/typescript/scope.js
Expand Up @@ -25,7 +25,7 @@ class TypeScriptScope extends Scope {
// classes (which are also in .lexical) and interface (which are also in .types)
classes: string[] = [];

// namespaces and bodyless-functions are too difficult to track,
// namespaces and ambient functions (or classes) are too difficult to track,
// especially without type analysis.
// We need to track them anyway, to avoid "X is not defined" errors
// when exporting them.
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-parser/src/util/scopeflags.js
Expand Up @@ -62,14 +62,14 @@ export const BIND_CLASS = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_
BIND_TS_INTERFACE = 0 | BIND_KIND_TYPE | 0 | BIND_FLAGS_CLASS ,
BIND_TS_TYPE = 0 | BIND_KIND_TYPE | 0 | 0 ,
BIND_TS_ENUM = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_TS_ENUM,
BIND_TS_FN_TYPE = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY,
BIND_TS_AMBIENT = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY,
// These bindings don't introduce anything in the scope. They are used for assignments and
// function expressions IDs.
BIND_NONE = 0 | 0 | 0 | BIND_FLAGS_NONE ,
BIND_OUTSIDE = BIND_KIND_VALUE | 0 | 0 | BIND_FLAGS_NONE ,

BIND_TS_CONST_ENUM = BIND_TS_ENUM | BIND_FLAGS_TS_CONST_ENUM,
BIND_TS_NAMESPACE = BIND_TS_FN_TYPE;
BIND_TS_NAMESPACE = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY;

export type BindingTypes =
| typeof BIND_NONE
Expand All @@ -81,5 +81,5 @@ export type BindingTypes =
| typeof BIND_TS_INTERFACE
| typeof BIND_TS_TYPE
| typeof BIND_TS_ENUM
| typeof BIND_TS_FN_TYPE
| typeof BIND_TS_AMBIENT
| typeof BIND_TS_NAMESPACE;
@@ -0,0 +1,2 @@
declare class C { }
declare function C(): void;
@@ -0,0 +1,151 @@
{
"type": "File",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 27
}
},
"program": {
"type": "Program",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 27
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"id": {
"type": "Identifier",
"start": 14,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "C"
},
"name": "C"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 16,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 19
}
},
"body": []
},
"declare": true
},
{
"type": "TSDeclareFunction",
"start": 20,
"end": 47,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 27
}
},
"id": {
"type": "Identifier",
"start": 37,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 18
},
"identifierName": "C"
},
"name": "C"
},
"generator": false,
"async": false,
"params": [],
"returnType": {
"type": "TSTypeAnnotation",
"start": 40,
"end": 46,
"loc": {
"start": {
"line": 2,
"column": 20
},
"end": {
"line": 2,
"column": 26
}
},
"typeAnnotation": {
"type": "TSVoidKeyword",
"start": 42,
"end": 46,
"loc": {
"start": {
"line": 2,
"column": 22
},
"end": {
"line": 2,
"column": 26
}
}
}
},
"declare": true
}
],
"directives": []
}
}
@@ -0,0 +1,2 @@
declare class C { }
function C() { }
@@ -0,0 +1,137 @@
{
"type": "File",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"program": {
"type": "Program",
"start": 0,
"end": 36,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 19
}
},
"declare": true,
"id": {
"type": "Identifier",
"start": 14,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 15
},
"identifierName": "C"
},
"name": "C"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 16,
"end": 19,
"loc": {
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 19
}
},
"body": []
}
},
{
"type": "FunctionDeclaration",
"start": 20,
"end": 36,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"id": {
"type": "Identifier",
"start": 29,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "C"
},
"name": "C"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 33,
"end": 36,
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 16
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
}

0 comments on commit 15aa511

Please sign in to comment.