Add TS support to @babel/parser's Scope (#9766)

* [parser] Allow plugins to extend ScopeHandler

* Directly extend Scope

* Don't use new.target to get the ScopeHandler

* [parser] Add TS enum  support to the Scope

* Remove duplicated options in tests

* Fix

* Fix flow

* Rename tests

* Add tests

* Full typescript support in scope

* Remove BIND_SIMPLE_CATCH

SCOPE_SIMPLE_CATCH was used instead

* Export TS types

* Register function declarations

* Fix body-less functions and namespaces

1) Move this.scope.exit() for functions from parseFunctionBody to the callers.
    Otherwise the scope of body-less functions was never closed.
    Also, it is easier to track scope.exit() if it is near to scope.enter()
2) Register namespace ids for export

* Disallow redeclaration of enum with const enum
This commit is contained in:
Nicolò Ribaudo 2019-04-26 14:19:53 +02:00 committed by GitHub
parent 293f3c98d2
commit 30d507c915
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
108 changed files with 3974 additions and 98 deletions

View File

@ -9,7 +9,7 @@ export default class BaseParser {
// Properties set by constructor in index.js // Properties set by constructor in index.js
options: Options; options: Options;
inModule: boolean; inModule: boolean;
scope: ScopeHandler; scope: ScopeHandler<*>;
plugins: PluginsMap; plugins: PluginsMap;
filename: ?string; filename: ?string;
sawUnambiguousESM: boolean = false; sawUnambiguousESM: boolean = false;

View File

@ -1767,6 +1767,7 @@ export default class ExpressionParser extends LValParser {
this.parseFunctionParams((node: any), allowModifiers); this.parseFunctionParams((node: any), allowModifiers);
this.checkYieldAwaitInDefaultParams(); this.checkYieldAwaitInDefaultParams();
this.parseFunctionBodyAndFinish(node, type, true); this.parseFunctionBodyAndFinish(node, type, true);
this.scope.exit();
this.state.yieldPos = oldYieldPos; this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos; this.state.awaitPos = oldAwaitPos;
@ -1795,6 +1796,7 @@ export default class ExpressionParser extends LValParser {
if (params) this.setArrowFunctionParameters(node, params); if (params) this.setArrowFunctionParameters(node, params);
this.parseFunctionBody(node, true); this.parseFunctionBody(node, true);
this.scope.exit();
this.state.maybeInArrowParameters = oldMaybeInArrowParameters; this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
this.state.yieldPos = oldYieldPos; this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos; this.state.awaitPos = oldAwaitPos;
@ -1890,7 +1892,6 @@ export default class ExpressionParser extends LValParser {
node.body = this.parseBlock(true, false); node.body = this.parseBlock(true, false);
this.state.labels = oldLabels; this.state.labels = oldLabels;
} }
this.scope.exit();
this.state.inParameters = oldInParameters; this.state.inParameters = oldInParameters;
// Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'

View File

@ -20,6 +20,8 @@ export default class Parser extends StatementParser {
options = getOptions(options); options = getOptions(options);
super(options, input); super(options, input);
const ScopeHandler = this.getScopeHandler();
this.options = options; this.options = options;
this.inModule = this.options.sourceType === "module"; this.inModule = this.options.sourceType === "module";
this.scope = new ScopeHandler(this.raise.bind(this), this.inModule); this.scope = new ScopeHandler(this.raise.bind(this), this.inModule);
@ -27,6 +29,11 @@ export default class Parser extends StatementParser {
this.filename = options.sourceFilename; this.filename = options.sourceFilename;
} }
// This can be overwritten, for example, by the TypeScript plugin.
getScopeHandler(): Class<ScopeHandler<*>> {
return ScopeHandler;
}
parse(): File { parse(): File {
this.scope.enter(SCOPE_PROGRAM); this.scope.enter(SCOPE_PROGRAM);
const file = this.startNode(); const file = this.startNode();

View File

@ -16,7 +16,7 @@ import type {
import type { Pos, Position } from "../util/location"; import type { Pos, Position } from "../util/location";
import { isStrictBindReservedWord } from "../util/identifier"; import { isStrictBindReservedWord } from "../util/identifier";
import { NodeUtils } from "./node"; import { NodeUtils } from "./node";
import { type BindingTypes, BIND_NONE, BIND_OUTSIDE } from "../util/scopeflags"; import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
export default class LValParser extends NodeUtils { export default class LValParser extends NodeUtils {
// Forward-declaration: defined in expression.js // Forward-declaration: defined in expression.js
@ -325,7 +325,7 @@ export default class LValParser extends NodeUtils {
checkLVal( checkLVal(
expr: Expression, expr: Expression,
bindingType: ?BindingTypes = BIND_NONE, bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean }, checkClashes: ?{ [key: string]: boolean },
contextDescription: string, contextDescription: string,
): void { ): void {
@ -363,7 +363,7 @@ export default class LValParser extends NodeUtils {
checkClashes[key] = true; checkClashes[key] = true;
} }
} }
if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { if (!(bindingType & BIND_NONE)) {
this.scope.declareName(expr.name, bindingType, expr.start); this.scope.declareName(expr.name, bindingType, expr.start);
} }
break; break;

View File

@ -11,7 +11,7 @@ import {
import { lineBreak, skipWhiteSpace } from "../util/whitespace"; import { lineBreak, skipWhiteSpace } from "../util/whitespace";
import * as charCodes from "charcodes"; import * as charCodes from "charcodes";
import { import {
BIND_SIMPLE_CATCH, BIND_CLASS,
BIND_LEXICAL, BIND_LEXICAL,
BIND_VAR, BIND_VAR,
BIND_FUNCTION, BIND_FUNCTION,
@ -662,12 +662,7 @@ export default class StatementParser extends ExpressionParser {
clause.param = this.parseBindingAtom(); clause.param = this.parseBindingAtom();
const simple = clause.param.type === "Identifier"; const simple = clause.param.type === "Identifier";
this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0); this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0);
this.checkLVal( this.checkLVal(clause.param, BIND_LEXICAL, null, "catch clause");
clause.param,
simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL,
null,
"catch clause",
);
this.expect(tt.parenR); this.expect(tt.parenR);
} else { } else {
clause.param = null; clause.param = null;
@ -1056,22 +1051,6 @@ export default class StatementParser extends ExpressionParser {
if (isStatement) { if (isStatement) {
node.id = this.parseFunctionId(requireId); node.id = this.parseFunctionId(requireId);
if (node.id && !isHangingStatement) {
// If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see
// treatFunctionsAsVar).
this.checkLVal(
node.id,
this.state.strict || node.generator || node.async
? this.scope.treatFunctionsAsVar
? BIND_VAR
: BIND_LEXICAL
: BIND_FUNCTION,
null,
"function name",
);
}
} }
const oldInClassProperty = this.state.inClassProperty; const oldInClassProperty = this.state.inClassProperty;
@ -1099,6 +1078,15 @@ export default class StatementParser extends ExpressionParser {
); );
}); });
this.scope.exit();
if (isStatement && !isHangingStatement) {
// We need to validate this _after_ parsing the function body
// because of TypeScript body-less function declarations,
// which shouldn't be added to the scope.
this.checkFunctionStatementId(node);
}
this.state.inClassProperty = oldInClassProperty; this.state.inClassProperty = oldInClassProperty;
this.state.yieldPos = oldYieldPos; this.state.yieldPos = oldYieldPos;
this.state.awaitPos = oldAwaitPos; this.state.awaitPos = oldAwaitPos;
@ -1125,6 +1113,25 @@ export default class StatementParser extends ExpressionParser {
this.checkYieldAwaitInDefaultParams(); this.checkYieldAwaitInDefaultParams();
} }
checkFunctionStatementId(node: N.Function): void {
if (!node.id) return;
// If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see
// treatFunctionsAsVar).
this.checkLVal(
node.id,
this.state.strict || node.generator || node.async
? this.scope.treatFunctionsAsVar
? BIND_VAR
: BIND_LEXICAL
: BIND_FUNCTION,
null,
"function name",
);
}
// Parse a class declaration or literal (depending on the // Parse a class declaration or literal (depending on the
// `isStatement` parameter). // `isStatement` parameter).
@ -1612,7 +1619,7 @@ export default class StatementParser extends ExpressionParser {
if (this.match(tt.name)) { if (this.match(tt.name)) {
node.id = this.parseIdentifier(); node.id = this.parseIdentifier();
if (isStatement) { if (isStatement) {
this.checkLVal(node.id, BIND_LEXICAL, undefined, "class name"); this.checkLVal(node.id, BIND_CLASS, undefined, "class name");
} }
} else { } else {
if (optionalId || !isStatement) { if (optionalId || !isStatement) {

View File

@ -105,7 +105,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
checkLVal( checkLVal(
expr: N.Expression, expr: N.Expression,
bindingType: ?BindingTypes = BIND_NONE, bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean }, checkClashes: ?{ [key: string]: boolean },
contextDescription: string, contextDescription: string,
): void { ): void {

View File

@ -2016,7 +2016,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
checkLVal( checkLVal(
expr: N.Expression, expr: N.Expression,
bindingType: ?BindingTypes = BIND_NONE, bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean }, checkClashes: ?{ [key: string]: boolean },
contextDescription: string, contextDescription: string,
): void { ): void {

View File

@ -1,12 +1,23 @@
// @flow // @flow
import type { TokenType } from "../tokenizer/types"; import type { TokenType } from "../../tokenizer/types";
import { types as tt } from "../tokenizer/types"; import { types as tt } from "../../tokenizer/types";
import { types as ct } from "../tokenizer/context"; import { types as ct } from "../../tokenizer/context";
import * as N from "../types"; import * as N from "../../types";
import type { Pos, Position } from "../util/location"; import type { Pos, Position } from "../../util/location";
import Parser from "../parser"; import type Parser from "../../parser";
import { type BindingTypes, BIND_NONE, SCOPE_OTHER } from "../util/scopeflags"; import {
type BindingTypes,
BIND_NONE,
SCOPE_OTHER,
BIND_TS_ENUM,
BIND_TS_CONST_ENUM,
BIND_TS_TYPE,
BIND_TS_INTERFACE,
BIND_TS_FN_TYPE,
BIND_TS_NAMESPACE,
} from "../../util/scopeflags";
import TypeScriptScopeHandler from "./scope";
type TsModifier = type TsModifier =
| "readonly" | "readonly"
@ -69,6 +80,10 @@ function keywordTypeFromName(
export default (superClass: Class<Parser>): Class<Parser> => export default (superClass: Class<Parser>): Class<Parser> =>
class extends superClass { class extends superClass {
getScopeHandler(): Class<TypeScriptScopeHandler> {
return TypeScriptScopeHandler;
}
tsIsIdentifier(): boolean { tsIsIdentifier(): boolean {
// TODO: actually a bit more complex in TypeScript, but shouldn't matter. // TODO: actually a bit more complex in TypeScript, but shouldn't matter.
// See https://github.com/Microsoft/TypeScript/issues/15008 // See https://github.com/Microsoft/TypeScript/issues/15008
@ -1017,6 +1032,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.TsInterfaceDeclaration, node: N.TsInterfaceDeclaration,
): N.TsInterfaceDeclaration { ): N.TsInterfaceDeclaration {
node.id = this.parseIdentifier(); node.id = this.parseIdentifier();
this.checkLVal(
node.id,
BIND_TS_INTERFACE,
undefined,
"typescript interface declaration",
);
node.typeParameters = this.tsTryParseTypeParameters(); node.typeParameters = this.tsTryParseTypeParameters();
if (this.eat(tt._extends)) { if (this.eat(tt._extends)) {
node.extends = this.tsParseHeritageClause("extends"); node.extends = this.tsParseHeritageClause("extends");
@ -1031,6 +1052,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.TsTypeAliasDeclaration, node: N.TsTypeAliasDeclaration,
): N.TsTypeAliasDeclaration { ): N.TsTypeAliasDeclaration {
node.id = this.parseIdentifier(); node.id = this.parseIdentifier();
this.checkLVal(node.id, BIND_TS_TYPE, undefined, "typescript type alias");
node.typeParameters = this.tsTryParseTypeParameters(); node.typeParameters = this.tsTryParseTypeParameters();
node.typeAnnotation = this.tsExpectThenParseType(tt.eq); node.typeAnnotation = this.tsExpectThenParseType(tt.eq);
this.semicolon(); this.semicolon();
@ -1099,6 +1122,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
): N.TsEnumDeclaration { ): N.TsEnumDeclaration {
if (isConst) node.const = true; if (isConst) node.const = true;
node.id = this.parseIdentifier(); node.id = this.parseIdentifier();
this.checkLVal(
node.id,
isConst ? BIND_TS_CONST_ENUM : BIND_TS_ENUM,
undefined,
"typescript enum declaration",
);
this.expect(tt.braceL); this.expect(tt.braceL);
node.members = this.tsParseDelimitedList( node.members = this.tsParseDelimitedList(
"EnumMembers", "EnumMembers",
@ -1126,11 +1156,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseModuleOrNamespaceDeclaration( tsParseModuleOrNamespaceDeclaration(
node: N.TsModuleDeclaration, node: N.TsModuleDeclaration,
nested?: boolean = false,
): N.TsModuleDeclaration { ): N.TsModuleDeclaration {
node.id = this.parseIdentifier(); node.id = this.parseIdentifier();
if (!nested) {
this.checkLVal(
node.id,
BIND_TS_NAMESPACE,
null,
"module or namespace declaration",
);
}
if (this.eat(tt.dot)) { if (this.eat(tt.dot)) {
const inner = this.startNode(); const inner = this.startNode();
this.tsParseModuleOrNamespaceDeclaration(inner); this.tsParseModuleOrNamespaceDeclaration(inner, true);
node.body = inner; node.body = inner;
} else { } else {
node.body = this.tsParseModuleBlock(); node.body = this.tsParseModuleBlock();
@ -1260,7 +1301,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
switch (starttype) { switch (starttype) {
case tt._function: case tt._function:
return this.parseFunctionStatement(nany); return this.parseFunctionStatement(
nany,
/* async */ false,
/* declarationPosition */ true,
);
case tt._class: case tt._class:
return this.parseClass( return this.parseClass(
nany, nany,
@ -1531,6 +1576,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.parseFunctionBodyAndFinish(node, type, isMethod); super.parseFunctionBodyAndFinish(node, type, isMethod);
} }
checkFunctionStatementId(node: N.Function): void {
if (!node.body && node.id) {
this.checkLVal(node.id, BIND_TS_FN_TYPE, null, "function name");
} else {
super.checkFunctionStatementId(...arguments);
}
}
parseSubscript( parseSubscript(
base: N.Expression, base: N.Expression,
startPos: number, startPos: number,
@ -2214,7 +2267,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
checkLVal( checkLVal(
expr: N.Expression, expr: N.Expression,
bindingType: ?BindingTypes = BIND_NONE, bindingType: BindingTypes = BIND_NONE,
checkClashes: ?{ [key: string]: boolean }, checkClashes: ?{ [key: string]: boolean },
contextDescription: string, contextDescription: string,
): void { ): void {

View File

@ -0,0 +1,105 @@
// @flow
import ScopeHandler, { Scope } from "../../util/scope";
import {
BIND_KIND_TYPE,
BIND_FLAGS_TS_ENUM,
BIND_FLAGS_TS_CONST_ENUM,
BIND_FLAGS_TS_EXPORT_ONLY,
BIND_KIND_VALUE,
BIND_FLAGS_CLASS,
type ScopeFlags,
type BindingTypes,
} from "../../util/scopeflags";
import * as N from "../../types";
class TypeScriptScope extends Scope {
types: string[] = [];
// enums (which are also in .types)
enums: string[] = [];
// const enums (which are also in .enums and .types)
constEnums: string[] = [];
// classes (which are also in .lexical) and interface (which are also in .types)
classes: string[] = [];
// namespaces and bodyless-functions 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.
exportOnlyBindings: string[] = [];
}
// See https://github.com/babel/babel/pull/9766#discussion_r268920730 for an
// explanation of how typescript handles scope.
export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope> {
createScope(flags: ScopeFlags): TypeScriptScope {
return new TypeScriptScope(flags);
}
declareName(name: string, bindingType: BindingTypes, pos: number) {
const scope = this.currentScope();
if (bindingType & BIND_FLAGS_TS_EXPORT_ONLY) {
this.maybeExportDefined(scope, name);
scope.exportOnlyBindings.push(name);
return;
}
super.declareName(...arguments);
if (bindingType & BIND_KIND_TYPE) {
if (!(bindingType & BIND_KIND_VALUE)) {
// "Value" bindings have already been registered by the superclass.
this.checkRedeclarationInScope(scope, name, bindingType, pos);
this.maybeExportDefined(scope, name);
}
scope.types.push(name);
}
if (bindingType & BIND_FLAGS_TS_ENUM) scope.enums.push(name);
if (bindingType & BIND_FLAGS_TS_CONST_ENUM) scope.constEnums.push(name);
if (bindingType & BIND_FLAGS_CLASS) scope.classes.push(name);
}
isRedeclaredInScope(
scope: TypeScriptScope,
name: string,
bindingType: BindingTypes,
): boolean {
if (scope.enums.indexOf(name) > -1) {
if (bindingType & BIND_FLAGS_TS_ENUM) {
// Enums can be merged with other enums if they are both
// const or both non-const.
const isConst = !!(bindingType & BIND_FLAGS_TS_CONST_ENUM);
const wasConst = scope.constEnums.indexOf(name) > -1;
return isConst !== wasConst;
}
return true;
}
if (bindingType & BIND_FLAGS_CLASS && scope.classes.indexOf(name) > -1) {
if (scope.lexical.indexOf(name) > -1) {
// Classes can be merged with interfaces
return !!(bindingType & BIND_KIND_VALUE);
} else {
// Interface can be merged with other classes or interfaces
return false;
}
}
if (bindingType & BIND_KIND_TYPE && scope.types.indexOf(name) > -1) {
return true;
}
return super.isRedeclaredInScope(...arguments);
}
checkLocalExport(id: N.Identifier) {
if (
this.scopeStack[0].types.indexOf(id.name) === -1 &&
this.scopeStack[0].exportOnlyBindings.indexOf(id.name) === -1
) {
super.checkLocalExport(id);
}
}
}

View File

@ -9,17 +9,18 @@ import {
SCOPE_SUPER, SCOPE_SUPER,
SCOPE_PROGRAM, SCOPE_PROGRAM,
SCOPE_VAR, SCOPE_VAR,
BIND_SIMPLE_CATCH, SCOPE_CLASS,
BIND_LEXICAL, BIND_SCOPE_FUNCTION,
BIND_FUNCTION, BIND_SCOPE_VAR,
BIND_SCOPE_LEXICAL,
BIND_KIND_VALUE,
type ScopeFlags, type ScopeFlags,
type BindingTypes, type BindingTypes,
SCOPE_CLASS,
} from "./scopeflags"; } from "./scopeflags";
import * as N from "../types"; import * as N from "../types";
// Start an AST node, attaching a start offset. // Start an AST node, attaching a start offset.
class Scope { export class Scope {
flags: ScopeFlags; flags: ScopeFlags;
// A list of var-declared names in the current lexical scope // A list of var-declared names in the current lexical scope
var: string[] = []; var: string[] = [];
@ -37,8 +38,8 @@ type raiseFunction = (number, string) => void;
// The functions in this module keep track of declared variables in the // The functions in this module keep track of declared variables in the
// current scope in order to detect duplicate variable names. // current scope in order to detect duplicate variable names.
export default class ScopeHandler { export default class ScopeHandler<IScope: Scope = Scope> {
scopeStack: Array<Scope> = []; scopeStack: Array<IScope> = [];
raise: raiseFunction; raise: raiseFunction;
inModule: boolean; inModule: boolean;
undefinedExports: Map<string, number> = new Map(); undefinedExports: Map<string, number> = new Map();
@ -70,8 +71,14 @@ export default class ScopeHandler {
return this.treatFunctionsAsVarInScope(this.currentScope()); return this.treatFunctionsAsVarInScope(this.currentScope());
} }
createScope(flags: ScopeFlags): Scope {
return new Scope(flags);
}
// This method will be overwritten by subclasses
+createScope: (flags: ScopeFlags) => IScope;
enter(flags: ScopeFlags) { enter(flags: ScopeFlags) {
this.scopeStack.push(new Scope(flags)); this.scopeStack.push(this.createScope(flags));
} }
exit() { exit() {
@ -81,46 +88,33 @@ export default class ScopeHandler {
// The spec says: // The spec says:
// > At the top level of a function, or script, function declarations are // > At the top level of a function, or script, function declarations are
// > treated like var declarations rather than like lexical declarations. // > treated like var declarations rather than like lexical declarations.
treatFunctionsAsVarInScope(scope: Scope): boolean { treatFunctionsAsVarInScope(scope: IScope): boolean {
return !!( return !!(
scope.flags & SCOPE_FUNCTION || scope.flags & SCOPE_FUNCTION ||
(!this.inModule && scope.flags & SCOPE_PROGRAM) (!this.inModule && scope.flags & SCOPE_PROGRAM)
); );
} }
declareName(name: string, bindingType: ?BindingTypes, pos: number) { declareName(name: string, bindingType: BindingTypes, pos: number) {
let redeclared = false;
let scope = this.currentScope(); let scope = this.currentScope();
if (bindingType & BIND_SCOPE_LEXICAL || bindingType & BIND_SCOPE_FUNCTION) {
this.checkRedeclarationInScope(scope, name, bindingType, pos);
if (bindingType === BIND_LEXICAL) { if (bindingType & BIND_SCOPE_FUNCTION) {
redeclared =
scope.lexical.indexOf(name) > -1 ||
scope.functions.indexOf(name) > -1 ||
scope.var.indexOf(name) > -1;
scope.lexical.push(name);
} else if (bindingType === BIND_SIMPLE_CATCH) {
scope.lexical.push(name);
} else if (bindingType === BIND_FUNCTION) {
if (this.treatFunctionsAsVar) {
redeclared = scope.lexical.indexOf(name) > -1;
} else {
redeclared =
scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
}
scope.functions.push(name); scope.functions.push(name);
} else { } else {
scope.lexical.push(name);
}
if (bindingType & BIND_SCOPE_LEXICAL) {
this.maybeExportDefined(scope, name);
}
} else if (bindingType & BIND_SCOPE_VAR) {
for (let i = this.scopeStack.length - 1; i >= 0; --i) { for (let i = this.scopeStack.length - 1; i >= 0; --i) {
scope = this.scopeStack[i]; scope = this.scopeStack[i];
if ( this.checkRedeclarationInScope(scope, name, bindingType, pos);
(scope.lexical.indexOf(name) > -1 &&
!(scope.flags & SCOPE_SIMPLE_CATCH && scope.lexical[0] === name)) ||
(!this.treatFunctionsAsVarInScope(scope) &&
scope.functions.indexOf(name) > -1)
) {
redeclared = true;
break;
}
scope.var.push(name); scope.var.push(name);
this.maybeExportDefined(scope, name);
if (scope.flags & SCOPE_VAR) break; if (scope.flags & SCOPE_VAR) break;
} }
@ -128,11 +122,56 @@ export default class ScopeHandler {
if (this.inModule && scope.flags & SCOPE_PROGRAM) { if (this.inModule && scope.flags & SCOPE_PROGRAM) {
this.undefinedExports.delete(name); this.undefinedExports.delete(name);
} }
if (redeclared) { }
maybeExportDefined(scope: IScope, name: string) {
if (this.inModule && scope.flags & SCOPE_PROGRAM) {
this.undefinedExports.delete(name);
}
}
checkRedeclarationInScope(
scope: IScope,
name: string,
bindingType: BindingTypes,
pos: number,
) {
if (this.isRedeclaredInScope(scope, name, bindingType)) {
this.raise(pos, `Identifier '${name}' has already been declared`); this.raise(pos, `Identifier '${name}' has already been declared`);
} }
} }
isRedeclaredInScope(
scope: IScope,
name: string,
bindingType: BindingTypes,
): boolean {
if (!(bindingType & BIND_KIND_VALUE)) return false;
if (bindingType & BIND_SCOPE_LEXICAL) {
return (
scope.lexical.indexOf(name) > -1 ||
scope.functions.indexOf(name) > -1 ||
scope.var.indexOf(name) > -1
);
}
if (bindingType & BIND_SCOPE_FUNCTION) {
return (
scope.lexical.indexOf(name) > -1 ||
(!this.treatFunctionsAsVarInScope(scope) &&
scope.var.indexOf(name) > -1)
);
}
return (
(scope.lexical.indexOf(name) > -1 &&
!(scope.flags & SCOPE_SIMPLE_CATCH && scope.lexical[0] === name)) ||
(!this.treatFunctionsAsVarInScope(scope) &&
scope.functions.indexOf(name) > -1)
);
}
checkLocalExport(id: N.Identifier) { checkLocalExport(id: N.Identifier) {
if ( if (
this.scopeStack[0].lexical.indexOf(id.name) === -1 && this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
@ -146,12 +185,12 @@ export default class ScopeHandler {
} }
} }
currentScope(): Scope { currentScope(): IScope {
return this.scopeStack[this.scopeStack.length - 1]; return this.scopeStack[this.scopeStack.length - 1];
} }
// $FlowIgnore // $FlowIgnore
currentVarScope(): Scope { currentVarScope(): IScope {
for (let i = this.scopeStack.length - 1; ; i--) { for (let i = this.scopeStack.length - 1; ; i--) {
const scope = this.scopeStack[i]; const scope = this.scopeStack[i];
if (scope.flags & SCOPE_VAR) { if (scope.flags & SCOPE_VAR) {
@ -162,7 +201,7 @@ export default class ScopeHandler {
// Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
// $FlowIgnore // $FlowIgnore
currentThisScope(): Scope { currentThisScope(): IScope {
for (let i = this.scopeStack.length - 1; ; i--) { for (let i = this.scopeStack.length - 1; ; i--) {
const scope = this.scopeStack[i]; const scope = this.scopeStack[i];
if ( if (

View File

@ -35,18 +35,51 @@ export function functionFlags(isAsync: boolean, isGenerator: boolean) {
); );
} }
// Used in checkLVal and declareName to determine the type of a binding // These flags are meant to be _only_ used inside the Scope class (or subclasses).
export const BIND_NONE = 0, // Not a binding // prettier-ignore
BIND_VAR = 1, // Var-style binding export const BIND_KIND_VALUE = 0b00000_0000_01,
BIND_LEXICAL = 2, // Let- or const-style binding BIND_KIND_TYPE = 0b00000_0000_10,
BIND_FUNCTION = 3, // Function declaration // Used in checkLVal and declareName to determine the type of a binding
BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding BIND_SCOPE_VAR = 0b00000_0001_00, // Var-style binding
BIND_OUTSIDE = 5; // Special case for function names as bound inside the function BIND_SCOPE_LEXICAL = 0b00000_0010_00, // Let- or const-style binding
BIND_SCOPE_FUNCTION = 0b00000_0100_00, // Function declaration
BIND_SCOPE_OUTSIDE = 0b00000_1000_00, // Special case for function names as
// bound inside the function
// Misc flags
BIND_FLAGS_NONE = 0b00001_0000_00,
BIND_FLAGS_CLASS = 0b00010_0000_00,
BIND_FLAGS_TS_ENUM = 0b00100_0000_00,
BIND_FLAGS_TS_CONST_ENUM = 0b01000_0000_00,
BIND_FLAGS_TS_EXPORT_ONLY = 0b10000_0000_00;
// These flags are meant to be _only_ used by Scope consumers
// prettier-ignore
/* = is value? | is type? | scope | misc flags */
export const BIND_CLASS = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_CLASS ,
BIND_LEXICAL = BIND_KIND_VALUE | 0 | BIND_SCOPE_LEXICAL | 0 ,
BIND_VAR = BIND_KIND_VALUE | 0 | BIND_SCOPE_VAR | 0 ,
BIND_FUNCTION = BIND_KIND_VALUE | 0 | BIND_SCOPE_FUNCTION | 0 ,
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,
// 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;
export type BindingTypes = export type BindingTypes =
| typeof BIND_NONE | typeof BIND_NONE
| typeof BIND_OUTSIDE
| typeof BIND_VAR | typeof BIND_VAR
| typeof BIND_LEXICAL | typeof BIND_LEXICAL
| typeof BIND_CLASS
| typeof BIND_FUNCTION | typeof BIND_FUNCTION
| typeof BIND_SIMPLE_CATCH | typeof BIND_TS_INTERFACE
| typeof BIND_OUTSIDE; | typeof BIND_TS_TYPE
| typeof BIND_TS_ENUM
| typeof BIND_TS_FN_TYPE
| typeof BIND_TS_NAMESPACE;

View File

@ -2,6 +2,6 @@ type Foo = false;
type Foo2 = true; type Foo2 = true;
type Foo3 = "string"; type Foo3 = "string";
type Foo4 = 123; type Foo4 = 123;
type Foo4 = 123.4; type Foo5 = 123.4;
type Foo5 = -123; type Foo6 = -123;
type Foo5 = -123.5; type Foo7 = -123.5;

View File

@ -312,9 +312,9 @@
"line": 5, "line": 5,
"column": 9 "column": 9
}, },
"identifierName": "Foo4" "identifierName": "Foo5"
}, },
"name": "Foo4" "name": "Foo5"
}, },
"typeAnnotation": { "typeAnnotation": {
"type": "TSLiteralType", "type": "TSLiteralType",
@ -376,9 +376,9 @@
"line": 6, "line": 6,
"column": 9 "column": 9
}, },
"identifierName": "Foo5" "identifierName": "Foo6"
}, },
"name": "Foo5" "name": "Foo6"
}, },
"typeAnnotation": { "typeAnnotation": {
"type": "TSLiteralType", "type": "TSLiteralType",
@ -457,9 +457,9 @@
"line": 7, "line": 7,
"column": 9 "column": 9
}, },
"identifierName": "Foo5" "identifierName": "Foo7"
}, },
"name": "Foo5" "name": "Foo7"
}, },
"typeAnnotation": { "typeAnnotation": {
"type": "TSLiteralType", "type": "TSLiteralType",

View File

@ -0,0 +1,2 @@
{ enum Foo {} }
let Foo;

View File

@ -0,0 +1,137 @@
{
"type": "File",
"start": 0,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 8
}
},
"program": {
"type": "Program",
"start": 0,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 8
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "BlockStatement",
"start": 0,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 15
}
},
"body": [
{
"type": "TSEnumDeclaration",
"start": 2,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 2
},
"end": {
"line": 1,
"column": 13
}
},
"id": {
"type": "Identifier",
"start": 7,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "Foo"
},
"name": "Foo"
},
"members": []
}
],
"directives": []
},
{
"type": "VariableDeclaration",
"start": 16,
"end": 24,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 8
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 20,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
}
},
"id": {
"type": "Identifier",
"start": 20,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "Foo"
},
"name": "Foo"
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
declare function foo(): void;
export { foo };

View File

@ -0,0 +1,169 @@
{
"type": "File",
"start": 0,
"end": 46,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 15
}
},
"program": {
"type": "Program",
"start": 0,
"end": 46,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 15
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSDeclareFunction",
"start": 0,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 29
}
},
"id": {
"type": "Identifier",
"start": 17,
"end": 20,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 20
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"returnType": {
"type": "TSTypeAnnotation",
"start": 22,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 22
},
"end": {
"line": 1,
"column": 28
}
},
"typeAnnotation": {
"type": "TSVoidKeyword",
"start": 24,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 24
},
"end": {
"line": 1,
"column": 28
}
}
}
},
"declare": true
},
{
"type": "ExportNamedDeclaration",
"start": 31,
"end": 46,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 15
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 40,
"end": 43,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 12
}
},
"local": {
"type": "Identifier",
"start": 40,
"end": 43,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"exported": {
"type": "Identifier",
"start": 40,
"end": 43,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
export { foo };
declare function foo(): void;

View File

@ -0,0 +1,169 @@
{
"type": "File",
"start": 0,
"end": 46,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 29
}
},
"program": {
"type": "Program",
"start": 0,
"end": 46,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 29
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 15
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 12
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
},
"exported": {
"type": "Identifier",
"start": 9,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "foo"
},
"name": "foo"
}
}
],
"source": null,
"declaration": null
},
{
"type": "TSDeclareFunction",
"start": 17,
"end": 46,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 29
}
},
"id": {
"type": "Identifier",
"start": 34,
"end": 37,
"loc": {
"start": {
"line": 3,
"column": 17
},
"end": {
"line": 3,
"column": 20
},
"identifierName": "foo"
},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"returnType": {
"type": "TSTypeAnnotation",
"start": 39,
"end": 45,
"loc": {
"start": {
"line": 3,
"column": 22
},
"end": {
"line": 3,
"column": 28
}
},
"typeAnnotation": {
"type": "TSVoidKeyword",
"start": 41,
"end": 45,
"loc": {
"start": {
"line": 3,
"column": 24
},
"end": {
"line": 3,
"column": 28
}
}
}
},
"declare": true
}
],
"directives": []
}
}

View File

@ -0,0 +1,5 @@
// https://github.com/babel/babel/issues/9763
enum Test {}
export { Test as default }

View File

@ -0,0 +1,172 @@
{
"type": "File",
"start": 0,
"end": 87,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 26
}
},
"program": {
"type": "Program",
"start": 0,
"end": 87,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 5,
"column": 26
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSEnumDeclaration",
"start": 47,
"end": 59,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 52,
"end": 56,
"loc": {
"start": {
"line": 3,
"column": 5
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "Test"
},
"name": "Test"
},
"members": [],
"leadingComments": [
{
"type": "CommentLine",
"value": " https://github.com/babel/babel/issues/9763",
"start": 0,
"end": 45,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 45
}
}
}
]
},
{
"type": "ExportNamedDeclaration",
"start": 61,
"end": 87,
"loc": {
"start": {
"line": 5,
"column": 0
},
"end": {
"line": 5,
"column": 26
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 70,
"end": 85,
"loc": {
"start": {
"line": 5,
"column": 9
},
"end": {
"line": 5,
"column": 24
}
},
"local": {
"type": "Identifier",
"start": 70,
"end": 74,
"loc": {
"start": {
"line": 5,
"column": 9
},
"end": {
"line": 5,
"column": 13
},
"identifierName": "Test"
},
"name": "Test"
},
"exported": {
"type": "Identifier",
"start": 78,
"end": 85,
"loc": {
"start": {
"line": 5,
"column": 17
},
"end": {
"line": 5,
"column": 24
},
"identifierName": "default"
},
"name": "default"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
},
"comments": [
{
"type": "CommentLine",
"value": " https://github.com/babel/babel/issues/9763",
"start": 0,
"end": 45,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 45
}
}
}
]
}

View File

@ -0,0 +1,3 @@
export { Test as default }
enum Test {}

View File

@ -0,0 +1,136 @@
{
"type": "File",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"program": {
"type": "Program",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 26
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 24
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 13
},
"identifierName": "Test"
},
"name": "Test"
},
"exported": {
"type": "Identifier",
"start": 17,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 24
},
"identifierName": "default"
},
"name": "default"
}
}
],
"source": null,
"declaration": null
},
{
"type": "TSEnumDeclaration",
"start": 28,
"end": 40,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 12
}
},
"id": {
"type": "Identifier",
"start": 33,
"end": 37,
"loc": {
"start": {
"line": 3,
"column": 5
},
"end": {
"line": 3,
"column": 9
},
"identifierName": "Test"
},
"name": "Test"
},
"members": []
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
interface A {}
export { A };

View File

@ -0,0 +1,151 @@
{
"type": "File",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"program": {
"type": "Program",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "ExportNamedDeclaration",
"start": 15,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
}
},
"local": {
"type": "Identifier",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"exported": {
"type": "Identifier",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "A"
},
"name": "A"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
export { A };
interface A {}

View File

@ -0,0 +1,151 @@
{
"type": "File",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"program": {
"type": "Program",
"start": 0,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 13
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"exported": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "A"
},
"name": "A"
}
}
],
"source": null,
"declaration": null
},
{
"type": "TSInterfaceDeclaration",
"start": 14,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 26,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 14
}
},
"body": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
namespace N {}
export { N };

View File

@ -0,0 +1,151 @@
{
"type": "File",
"start": 0,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 13
}
},
"program": {
"type": "Program",
"start": 0,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 13
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSModuleDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "N"
},
"name": "N"
},
"body": {
"type": "TSModuleBlock",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "ExportNamedDeclaration",
"start": 16,
"end": 29,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 13
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 10
}
},
"local": {
"type": "Identifier",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 10
},
"identifierName": "N"
},
"name": "N"
},
"exported": {
"type": "Identifier",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 3,
"column": 9
},
"end": {
"line": 3,
"column": 10
},
"identifierName": "N"
},
"name": "N"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
type A = number;
export { A };

View File

@ -0,0 +1,150 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSTypeAliasDeclaration",
"start": 0,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 16
}
},
"id": {
"type": "Identifier",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
},
"identifierName": "A"
},
"name": "A"
},
"typeAnnotation": {
"type": "TSNumberKeyword",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
}
}
}
},
{
"type": "ExportNamedDeclaration",
"start": 17,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 13
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
}
},
"local": {
"type": "Identifier",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"exported": {
"type": "Identifier",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "A"
},
"name": "A"
}
}
],
"source": null,
"declaration": null
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
export { A };
type A = number;

View File

@ -0,0 +1,150 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExportNamedDeclaration",
"start": 0,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 13
}
},
"specifiers": [
{
"type": "ExportSpecifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
}
},
"local": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"exported": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "A"
},
"name": "A"
}
}
],
"source": null,
"declaration": null
},
{
"type": "TSTypeAliasDeclaration",
"start": 14,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 6
},
"identifierName": "A"
},
"name": "A"
},
"typeAnnotation": {
"type": "TSNumberKeyword",
"start": 23,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 15
}
}
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,4 @@
function f(): void;
function f() {}
export { f };

View File

@ -0,0 +1,2 @@
class A {}
class A {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:6)"
}

View File

@ -0,0 +1,2 @@
class A {}
enum A {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
class A {}
interface A {}

View File

@ -0,0 +1,132 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start": 0,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 10
}
},
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 7
},
"identifierName": "A"
},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 8,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 10
}
},
"body": []
}
},
{
"type": "TSInterfaceDeclaration",
"start": 11,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 21,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 23,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 14
}
},
"body": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
class A {}
type A = number;

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
const enum Foo {}
const enum Foo {}

View File

@ -0,0 +1,103 @@
{
"type": "File",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 17
}
},
"program": {
"type": "Program",
"start": 0,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 17
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSEnumDeclaration",
"start": 0,
"end": 17,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 17
}
},
"const": true,
"id": {
"type": "Identifier",
"start": 11,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 14
},
"identifierName": "Foo"
},
"name": "Foo"
},
"members": []
},
{
"type": "TSEnumDeclaration",
"start": 18,
"end": 35,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 17
}
},
"const": true,
"id": {
"type": "Identifier",
"start": 29,
"end": 32,
"loc": {
"start": {
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 14
},
"identifierName": "Foo"
},
"name": "Foo"
},
"members": []
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
const enum X {}
enum X {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'X' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
enum X {}
class X {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'X' has already been declared (2:6)"
}

View File

@ -0,0 +1,2 @@
enum X {}
const enum X {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'X' has already been declared (2:11)"
}

View File

@ -0,0 +1,2 @@
enum Foo {}
enum Foo {}

View File

@ -0,0 +1,101 @@
{
"type": "File",
"start": 0,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 11
}
},
"program": {
"type": "Program",
"start": 0,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 11
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSEnumDeclaration",
"start": 0,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 5,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 8
},
"identifierName": "Foo"
},
"name": "Foo"
},
"members": []
},
{
"type": "TSEnumDeclaration",
"start": 12,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 11
}
},
"id": {
"type": "Identifier",
"start": 17,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 8
},
"identifierName": "Foo"
},
"name": "Foo"
},
"members": []
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
enum Foo {}
function Foo() {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'Foo' has already been declared (2:9)"
}

View File

@ -0,0 +1,2 @@
enum X {}
interface X {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'X' has already been declared (2:10)"
}

View File

@ -0,0 +1,2 @@
enum Foo {}
let Foo;

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'Foo' has already been declared (2:4)"
}

View File

@ -0,0 +1,2 @@
enum X {}
type X = number;

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'X' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
enum Foo {}
let Foo;

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'Foo' has already been declared (2:4)"
}

View File

@ -0,0 +1,2 @@
function Foo() {}
enum Foo {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'Foo' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
function A() {}
interface A {}

View File

@ -0,0 +1,135 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start": 0,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 15
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 13,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 15
}
},
"body": [],
"directives": []
}
},
{
"type": "TSInterfaceDeclaration",
"start": 16,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 28,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 14
}
},
"body": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
function A() {}
type A = number;

View File

@ -0,0 +1,134 @@
{
"type": "File",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"program": {
"type": "Program",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start": 0,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 15
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 13,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 15
}
},
"body": [],
"directives": []
}
},
{
"type": "TSTypeAliasDeclaration",
"start": 16,
"end": 32,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 16
}
},
"id": {
"type": "Identifier",
"start": 21,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 6
},
"identifierName": "A"
},
"name": "A"
},
"typeAnnotation": {
"type": "TSNumberKeyword",
"start": 25,
"end": 31,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 15
}
}
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
interface A {}
class A {}

View File

@ -0,0 +1,132 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 10
}
},
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 10
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "ClassDeclaration",
"start": 15,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 10
}
},
"id": {
"type": "Identifier",
"start": 21,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 7
},
"identifierName": "A"
},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start": 23,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 8
},
"end": {
"line": 2,
"column": 10
}
},
"body": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
interface X {}
enum X {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'X' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
interface A {}
function A() {}

View File

@ -0,0 +1,135 @@
{
"type": "File",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 15
}
},
"program": {
"type": "Program",
"start": 0,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 15
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "FunctionDeclaration",
"start": 15,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 15
}
},
"id": {
"type": "Identifier",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 28,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 15
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
interface A {}
interface A {}

View File

@ -0,0 +1,131 @@
{
"type": "File",
"start": 0,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"program": {
"type": "Program",
"start": 0,
"end": 29,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "TSInterfaceDeclaration",
"start": 15,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 25,
"end": 26,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 27,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 14
}
},
"body": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
interface A {}
let A;

View File

@ -0,0 +1,134 @@
{
"type": "File",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"program": {
"type": "Program",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "VariableDeclaration",
"start": 15,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 5
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 5
},
"identifierName": "A"
},
"name": "A"
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
interface A {}
var A;

View File

@ -0,0 +1,134 @@
{
"type": "File",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"program": {
"type": "Program",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSInterfaceDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 10,
"end": 11,
"loc": {
"start": {
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 12,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 14
}
},
"body": []
}
},
{
"type": "VariableDeclaration",
"start": 15,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 5
}
},
"id": {
"type": "Identifier",
"start": 19,
"end": 20,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 5
},
"identifierName": "A"
},
"name": "A"
},
"init": null
}
],
"kind": "var"
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
let Foo;
enum Foo {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'Foo' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
let A;
interface A {}

View File

@ -0,0 +1,134 @@
{
"type": "File",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"program": {
"type": "Program",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 6
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "A"
},
"name": "A"
},
"init": null
}
],
"kind": "let"
},
{
"type": "TSInterfaceDeclaration",
"start": 7,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 14
}
},
"id": {
"type": "Identifier",
"start": 17,
"end": 18,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 11
},
"identifierName": "A"
},
"name": "A"
},
"body": {
"type": "TSInterfaceBody",
"start": 19,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 14
}
},
"body": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
type A = number;
class A {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:6)"
}

View File

@ -0,0 +1,2 @@
type A = number;
enum A {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:5)"
}

View File

@ -0,0 +1,2 @@
type A = number;
function A() {}

View File

@ -0,0 +1,134 @@
{
"type": "File",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 15
}
},
"program": {
"type": "Program",
"start": 0,
"end": 32,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 15
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSTypeAliasDeclaration",
"start": 0,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 16
}
},
"id": {
"type": "Identifier",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
},
"identifierName": "A"
},
"name": "A"
},
"typeAnnotation": {
"type": "TSNumberKeyword",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
}
}
}
},
{
"type": "FunctionDeclaration",
"start": 17,
"end": 32,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 15
}
},
"id": {
"type": "Identifier",
"start": 26,
"end": 27,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
},
"identifierName": "A"
},
"name": "A"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 30,
"end": 32,
"loc": {
"start": {
"line": 2,
"column": 13
},
"end": {
"line": 2,
"column": 15
}
},
"body": [],
"directives": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
type A = number;
interface A {}

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:10)"
}

View File

@ -0,0 +1,2 @@
type A = number;
let A;

View File

@ -0,0 +1,133 @@
{
"type": "File",
"start": 0,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"program": {
"type": "Program",
"start": 0,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSTypeAliasDeclaration",
"start": 0,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 16
}
},
"id": {
"type": "Identifier",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
},
"identifierName": "A"
},
"name": "A"
},
"typeAnnotation": {
"type": "TSNumberKeyword",
"start": 9,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 15
}
}
}
},
{
"type": "VariableDeclaration",
"start": 17,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 21,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 5
}
},
"id": {
"type": "Identifier",
"start": 21,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 4
},
"end": {
"line": 2,
"column": 5
},
"identifierName": "A"
},
"name": "A"
},
"init": null
}
],
"kind": "let"
}
],
"directives": []
}
}

View File

@ -0,0 +1,2 @@
type A = number;
type A = string;

View File

@ -0,0 +1,3 @@
{
"throws": "Identifier 'A' has already been declared (2:5)"
}

Some files were not shown because too many files have changed in this diff Show More