Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed Sep 2, 2022
1 parent f4de8d9 commit 0c73e9b
Show file tree
Hide file tree
Showing 18 changed files with 2,152 additions and 21 deletions.
7 changes: 1 addition & 6 deletions packages/babel-parser/src/parser/statement.ts
Expand Up @@ -17,7 +17,6 @@ import {
BIND_LEXICAL,
BIND_VAR,
BIND_FUNCTION,
BIND_KIND_TYPE,
SCOPE_CLASS,
SCOPE_FUNCTION,
SCOPE_OTHER,
Expand Down Expand Up @@ -2904,11 +2903,7 @@ export default abstract class StatementParser extends ExpressionParser {
specifier.local = cloneIdentifier(imported);
}
}
return this.finishImportSpecifier(
specifier,
"ImportSpecifier",
isInTypeOnlyImport ? BIND_KIND_TYPE : undefined,
);
return this.finishImportSpecifier(specifier, "ImportSpecifier");
}

// This is used in flow and typescript plugin
Expand Down
36 changes: 29 additions & 7 deletions packages/babel-parser/src/plugins/typescript/index.ts
Expand Up @@ -19,16 +19,18 @@ import type Parser from "../../parser";
import {
type BindingTypes,
SCOPE_TS_MODULE,
SCOPE_OTHER,
SCOPE_TS_TOP_LEVEL,
BIND_TS_ENUM,
BIND_TS_CONST_ENUM,
BIND_TS_TYPE,
BIND_TS_INTERFACE,
BIND_TS_AMBIENT,
BIND_TS_NAMESPACE,
BIND_TS_TYPE_IMPORT,
BIND_CLASS,
BIND_LEXICAL,
BIND_NONE,
BIND_FLAGS_TS_IMPORT,
} from "../../util/scopeflags";
import TypeScriptScopeHandler from "./scope";
import * as charCodes from "charcodes";
Expand Down Expand Up @@ -1859,7 +1861,7 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>

tsParseModuleBlock(): N.TsModuleBlock {
const node = this.startNode<N.TsModuleBlock>();
this.scope.enter(SCOPE_OTHER);
this.scope.enter(SCOPE_TS_TOP_LEVEL);

this.expect(tt.braceL);
// Inside of a module block is considered "top-level", meaning it can have imports and exports.
Expand Down Expand Up @@ -3961,11 +3963,31 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
return this.finishNode<N.ImportSpecifier>(specifier, "ImportSpecifier");
}
specifier.importKind = "value";
return super.parseImportSpecifier(

if (this.eatContextual(tt._as)) {
specifier.local = this.parseIdentifier();
} else {
const { imported } = specifier;
if (importedIsString) {
throw this.raise(Errors.ImportBindingIsString, {
at: specifier,
importName: (imported as N.StringLiteral).value,
});
}
this.checkReservedWord(
(imported as N.Identifier).name,
specifier.loc.start,
true,
true,
);
if (!specifier.local) {
specifier.local = cloneIdentifier(imported);
}
}
return this.finishImportSpecifier(
specifier,
importedIsString,
isInTypeOnlyImport,
isMaybeTypeOnly,
"ImportSpecifier",
isInTypeOnlyImport ? BIND_TS_TYPE_IMPORT : BIND_FLAGS_TS_IMPORT,
);
}

Expand Down Expand Up @@ -4063,7 +4085,7 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
if (isImport) {
this.checkIdentifier(
node[rightOfAsKey],
hasTypeSpecifier ? BIND_TS_TYPE : BIND_LEXICAL,
hasTypeSpecifier ? BIND_TS_TYPE_IMPORT : BIND_FLAGS_TS_IMPORT,
);
}
}
Expand Down
49 changes: 48 additions & 1 deletion packages/babel-parser/src/plugins/typescript/scope.ts
Expand Up @@ -9,8 +9,12 @@ import {
BIND_FLAGS_CLASS,
type ScopeFlags,
type BindingTypes,
BIND_FLAGS_TS_IMPORT,
SCOPE_TS_MODULE,
SCOPE_TS_TOP_LEVEL,
} from "../../util/scopeflags";
import * as N from "../../types";
import { Errors } from "../../parse-error";

class TypeScriptScope extends Scope {
types: Set<string> = new Set();
Expand All @@ -35,11 +39,53 @@ class TypeScriptScope extends Scope {
// explanation of how typescript handles scope.

export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope> {
importsStack: Set<string>[] = [];

createScope(flags: ScopeFlags): TypeScriptScope {
this.importsStack.push(new Set()); // SCOPE_TS_TOP_LEVEL should be kept

return new TypeScriptScope(flags);
}

enter(flags: number): void {
if (flags == SCOPE_TS_MODULE || flags == SCOPE_TS_TOP_LEVEL) {
this.importsStack.push(new Set());
}

super.enter(flags);
}

exit(): ScopeFlags {
const flags = super.exit();

if (flags == SCOPE_TS_MODULE || flags == SCOPE_TS_TOP_LEVEL) {
this.importsStack.pop();
}

return flags;
}

hasImport(name: string, allowShadow?: boolean) {
const len = this.importsStack.length;
if (!this.importsStack[len - 1].has(name)) {
return !allowShadow && len > 2 && this.importsStack[0].has(name);
}

return true;
}

declareName(name: string, bindingType: BindingTypes, loc: Position) {
if (bindingType & BIND_FLAGS_TS_IMPORT) {
if (this.hasImport(name, true)) {
this.parser.raise(Errors.VarRedeclaration, {
at: loc,
identifierName: name,
});
}
this.importsStack[this.importsStack.length - 1].add(name);
return;
}

const scope = this.currentScope();
if (bindingType & BIND_FLAGS_TS_EXPORT_ONLY) {
this.maybeExportDefined(scope, name);
Expand Down Expand Up @@ -98,7 +144,8 @@ export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope
const { name } = id;
if (
!topLevelScope.types.has(name) &&
!topLevelScope.exportOnlyBindings.has(name)
!topLevelScope.exportOnlyBindings.has(name) &&
!this.hasImport(name)
) {
super.checkLocalExport(id);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/babel-parser/src/util/scope.ts
Expand Up @@ -93,8 +93,9 @@ export default class ScopeHandler<IScope extends Scope = Scope> {
this.scopeStack.push(this.createScope(flags));
}

exit() {
this.scopeStack.pop();
exit(): ScopeFlags {
const scope = this.scopeStack.pop();
return scope.flags;
}

// The spec says:
Expand Down
11 changes: 7 additions & 4 deletions packages/babel-parser/src/util/scopeflags.ts
Expand Up @@ -10,7 +10,8 @@ export const SCOPE_OTHER = 0b000000000,
SCOPE_CLASS = 0b001000000,
SCOPE_STATIC_BLOCK = 0b010000000,
SCOPE_TS_MODULE = 0b100000000,
SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_TS_MODULE;
SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_TS_MODULE,
SCOPE_TS_TOP_LEVEL = 0b1000000000;

export type ScopeFlags =
| typeof SCOPE_OTHER
Expand Down Expand Up @@ -40,7 +41,8 @@ export const BIND_KIND_VALUE = 0b000000_0000_01,
BIND_FLAGS_TS_ENUM = 0b000100_0000_00,
BIND_FLAGS_TS_CONST_ENUM = 0b001000_0000_00,
BIND_FLAGS_TS_EXPORT_ONLY = 0b010000_0000_00,
BIND_FLAGS_FLOW_DECLARE_FN = 0b100000_0000_00;
BIND_FLAGS_FLOW_DECLARE_FN = 0b100000_0000_00,
BIND_FLAGS_TS_IMPORT = 0b1_000000_0000_00;

// These flags are meant to be _only_ used by Scope consumers
// prettier-ignore
Expand All @@ -58,8 +60,9 @@ export const BIND_CLASS = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_
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 = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY,
BIND_TS_CONST_ENUM = BIND_TS_ENUM | BIND_FLAGS_TS_CONST_ENUM ,
BIND_TS_NAMESPACE = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY,
BIND_TS_TYPE_IMPORT= 0 | BIND_KIND_TYPE | 0 | BIND_FLAGS_TS_IMPORT,

BIND_FLOW_DECLARE_FN = BIND_FLAGS_FLOW_DECLARE_FN;

Expand Down
@@ -0,0 +1,7 @@
import React, { Context } from 'react';
import { a } from 'react';
import { a as b } from 'react';

let Context: Context<{}> = React.createContext({});
let a: a = 1;
let b: b = 1;

0 comments on commit 0c73e9b

Please sign in to comment.