Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c20c401

Browse files
committed
feat: ts modules
1 parent daa415c commit c20c401

24 files changed

+593
-7
lines changed

packages/scope-manager/src/ScopeManager.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
ModuleScope,
1515
Scope,
1616
SwitchScope,
17+
TSModuleScope,
1718
TypeScope,
1819
WithScope,
1920
} from './scope';
@@ -228,6 +229,11 @@ class ScopeManager {
228229
return this.nestScope(new SwitchScope(this, this.currentScope, node));
229230
}
230231

232+
public nestTSModuleScope(node: TSModuleScope['block']): Scope {
233+
assert(this.currentScope);
234+
return this.nestScope(new TSModuleScope(this, this.currentScope, node));
235+
}
236+
231237
public nestTypeScope(node: TypeScope['block']): Scope {
232238
assert(this.currentScope);
233239
return this.nestScope(new TypeScope(this, this.currentScope, node));

packages/scope-manager/src/definition/Definition.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { FunctionNameDefinition } from './FunctionNameDefinition';
44
import { ImplicitGlobalVariableDefinition } from './ImplicitGlobalVariableDefinition';
55
import { ImportBindingDefinition } from './ImportBindingDefinition';
66
import { ParameterDefinition } from './ParameterDefinition';
7+
import { TSModuleNameDefinition } from './TSModuleNameDefinition';
78
import { TypeDefinition } from './TypeDefinition';
89
import { VariableDefinition } from './VariableDefinition';
910

@@ -14,6 +15,7 @@ type Definition =
1415
| ImplicitGlobalVariableDefinition
1516
| ImportBindingDefinition
1617
| ParameterDefinition
18+
| TSModuleNameDefinition
1719
| TypeDefinition
1820
| VariableDefinition;
1921

packages/scope-manager/src/definition/DefinitionType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ enum DefinitionType {
66
ImplicitGlobalVariable = 'ImplicitGlobalVariable',
77
ImportBinding = 'ImportBinding',
88
Parameter = 'Parameter',
9+
TSModuleName = 'TSModuleName',
910
Type = 'Type',
1011
Variable = 'Variable',
1112
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { TSESTree } from '@typescript-eslint/experimental-utils';
2+
import { DefinitionType } from './DefinitionType';
3+
import { DefinitionBase } from './DefinitionBase';
4+
5+
class TSModuleNameDefinition extends DefinitionBase<
6+
DefinitionType.TSModuleName,
7+
TSESTree.TSModuleDeclaration,
8+
null
9+
> {
10+
constructor(name: TSESTree.Identifier, node: TSModuleNameDefinition['node']) {
11+
super(DefinitionType.TSModuleName, name, node, null);
12+
}
13+
14+
public readonly isTypeDefinition = true;
15+
public readonly isVariableDefinition = true;
16+
}
17+
18+
export { TSModuleNameDefinition };

packages/scope-manager/src/definition/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ export * from './FunctionNameDefinition';
66
export * from './ImplicitGlobalVariableDefinition';
77
export * from './ImportBindingDefinition';
88
export * from './ParameterDefinition';
9+
export * from './TSModuleNameDefinition';
910
export * from './TypeDefinition';
1011
export * from './VariableDefinition';

packages/scope-manager/src/referencer/Referencer.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
FunctionNameDefinition,
1515
ImportBindingDefinition,
1616
ParameterDefinition,
17+
TSModuleNameDefinition,
1718
VariableDefinition,
1819
} from '../definition';
1920
import { Scope } from '../scope';
@@ -100,6 +101,8 @@ class Referencer extends Visitor {
100101
this.scopeManager.nestClassScope(node);
101102

102103
if (node.id) {
104+
// define the class name again inside the new scope
105+
// references to the class should not resolve directly to the parent class
103106
this.currentScope().defineIdentifier(
104107
node.id,
105108
new ClassNameDefinition(node.id, node),
@@ -579,6 +582,30 @@ class Referencer extends Visitor {
579582
this.visitType(node);
580583
}
581584

585+
protected TSModuleDeclaration(node: TSESTree.TSModuleDeclaration): void {
586+
if (node.id.type === AST_NODE_TYPES.Identifier) {
587+
this.currentScope().defineIdentifier(
588+
node.id,
589+
new TSModuleNameDefinition(node.id, node),
590+
);
591+
}
592+
593+
this.scopeManager.nestTSModuleScope(node);
594+
595+
if (node.id.type === AST_NODE_TYPES.Identifier) {
596+
// define the module name again inside the new module scope
597+
// references to the module should not resolve directly to the module
598+
this.currentScope().defineIdentifier(
599+
node.id,
600+
new TSModuleNameDefinition(node.id, node),
601+
);
602+
}
603+
604+
this.visit(node.body);
605+
606+
this.close(node);
607+
}
608+
582609
protected TSTypeAliasDeclaration(
583610
node: TSESTree.TSTypeAliasDeclaration,
584611
): void {

packages/scope-manager/src/referencer/TypeVisitor.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ class TypeVisitor extends Visitor {
114114
.currentScope()
115115
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
116116

117-
// type parameters cannot be referenced from outside their current scope
118117
if (node.typeParameters) {
118+
// type parameters cannot be referenced from outside their current scope
119119
this.referencer.scopeManager.nestTypeScope(node);
120120
this.visit(node.typeParameters);
121121
}
@@ -130,6 +130,7 @@ class TypeVisitor extends Visitor {
130130
}
131131

132132
protected TSMappedType(node: TSESTree.TSMappedType): void {
133+
// mapped types key can only be referenced within their return value
133134
this.referencer.scopeManager.nestMappedTypeScope(node);
134135
this.visitChildren(node);
135136
this.referencer.close(node);
@@ -157,8 +158,8 @@ class TypeVisitor extends Visitor {
157158
.currentScope()
158159
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
159160

160-
// type parameters cannot be referenced from outside their current scope
161161
if (node.typeParameters) {
162+
// type parameters cannot be referenced from outside their current scope
162163
this.referencer.scopeManager.nestTypeScope(node);
163164
this.visit(node.typeParameters);
164165
}

packages/scope-manager/src/scope/Scope.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { GlobalScope } from './GlobalScope';
1010
import { MappedTypeScope } from './MappedTypeScope';
1111
import { ModuleScope } from './ModuleScope';
1212
import { SwitchScope } from './SwitchScope';
13+
import { TSModuleScope } from './TSModuleScope';
1314
import { TypeScope } from './TypeScope';
1415
import { WithScope } from './WithScope';
1516

@@ -26,6 +27,7 @@ type Scope =
2627
| MappedTypeScope
2728
| ModuleScope
2829
| SwitchScope
30+
| TSModuleScope
2931
| TypeScope
3032
| WithScope;
3133

packages/scope-manager/src/scope/ScopeBase.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,12 @@ function isStrictScope(
3939

4040
if (
4141
scope.type === ScopeType.class ||
42-
scope.type === ScopeType.module ||
43-
scope.type === ScopeType.type ||
4442
scope.type === ScopeType.conditionalType ||
45-
scope.type === ScopeType.functionType
43+
scope.type === ScopeType.functionType ||
44+
scope.type === ScopeType.mappedType ||
45+
scope.type === ScopeType.module ||
46+
scope.type === ScopeType.tsModule ||
47+
scope.type === ScopeType.type
4648
) {
4749
return true;
4850
}
@@ -127,6 +129,7 @@ function registerScope(scopeManager: ScopeManager, scope: Scope): void {
127129
function shouldBeStaticallyClosed(def: Definition): boolean {
128130
return (
129131
def.type === DefinitionType.Type ||
132+
def.type === DefinitionType.TSModuleName ||
130133
def.type === DefinitionType.ClassName ||
131134
(def.type === DefinitionType.Variable &&
132135
def.parent?.type === AST_NODE_TYPES.VariableDeclaration &&

packages/scope-manager/src/scope/ScopeType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum ScopeType {
1111
mappedType = 'mappedType',
1212
module = 'module',
1313
switch = 'switch',
14+
tsModule = 'tsModule',
1415
type = 'type',
1516
with = 'with',
1617
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { TSESTree } from '@typescript-eslint/experimental-utils';
2+
import { Scope } from './Scope';
3+
import { ScopeBase } from './ScopeBase';
4+
import { ScopeType } from './ScopeType';
5+
import { ScopeManager } from '../ScopeManager';
6+
7+
class TSModuleScope extends ScopeBase<
8+
ScopeType.tsModule,
9+
TSESTree.TSModuleDeclaration,
10+
Scope
11+
> {
12+
constructor(
13+
scopeManager: ScopeManager,
14+
upperScope: TSModuleScope['upper'],
15+
block: TSModuleScope['block'],
16+
) {
17+
super(scopeManager, ScopeType.tsModule, upperScope, block, false);
18+
}
19+
}
20+
21+
export { TSModuleScope };

packages/scope-manager/src/scope/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ export * from './ModuleScope';
1212
export * from './Scope';
1313
export * from './ScopeType';
1414
export * from './SwitchScope';
15+
export * from './TSModuleScope';
1516
export * from './TypeScope';
1617
export * from './WithScope';

packages/scope-manager/tests/fixtures.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function nestDescribe(
5959

6060
const match = FOUR_SLASH.exec(line);
6161
if (!match) {
62-
continue;
62+
throw new Error(`Four-slash did not match expected format: ${line}`);
6363
}
6464
const [, key, value] = match;
6565
if (!ALLOWED_OPTIONS.has(key)) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Foo {
2+
export const x = 1;
3+
}
4+
5+
Foo.x;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`ts-module external-ref 1`] = `
4+
ScopeManager {
5+
variables: Array [
6+
Variable$1 {
7+
defs: Array [
8+
TSModuleNameDefinition$1 {
9+
name: Identifier<"Foo">,
10+
node: TSModuleDeclaration$1,
11+
},
12+
],
13+
name: "Foo",
14+
references: Array [
15+
Reference$2 {
16+
identifier: Identifier<"Foo">,
17+
isTypeReference: false,
18+
resolved: Variable$1,
19+
},
20+
],
21+
isValueVariable: true,
22+
isTypeVariable: true,
23+
},
24+
Variable$2 {
25+
defs: Array [
26+
TSModuleNameDefinition$2 {
27+
name: Identifier<"Foo">,
28+
node: TSModuleDeclaration$1,
29+
},
30+
],
31+
name: "Foo",
32+
references: Array [],
33+
isValueVariable: true,
34+
isTypeVariable: true,
35+
},
36+
Variable$3 {
37+
defs: Array [
38+
VariableDefinition$3 {
39+
name: Identifier<"x">,
40+
node: VariableDeclarator$2,
41+
},
42+
],
43+
name: "x",
44+
references: Array [
45+
Reference$1 {
46+
identifier: Identifier<"x">,
47+
init: true,
48+
isTypeReference: false,
49+
resolved: Variable$3,
50+
writeExpr: Literal$3,
51+
},
52+
],
53+
isValueVariable: true,
54+
isTypeVariable: false,
55+
},
56+
],
57+
scopes: Array [
58+
GlobalScope$1 {
59+
block: Program$4,
60+
isStrict: false,
61+
references: Array [
62+
Reference$2,
63+
],
64+
set: Map {
65+
"Foo" => Variable$1,
66+
},
67+
type: "global",
68+
upper: null,
69+
variables: Array [
70+
Variable$1,
71+
],
72+
},
73+
TSModuleScope$2 {
74+
block: TSModuleDeclaration$1,
75+
isStrict: true,
76+
references: Array [
77+
Reference$1,
78+
],
79+
set: Map {
80+
"Foo" => Variable$2,
81+
"x" => Variable$3,
82+
},
83+
type: "tsModule",
84+
upper: GlobalScope$1,
85+
variables: Array [
86+
Variable$2,
87+
Variable$3,
88+
],
89+
},
90+
],
91+
}
92+
`;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//// @sourceType = module
2+
3+
declare module 'foo' {
4+
import { bar } from 'mod';
5+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`ts-module import 1`] = `
4+
ScopeManager {
5+
variables: Array [
6+
Variable$1 {
7+
defs: Array [
8+
ImportBindingDefinition$1 {
9+
name: Identifier<"bar">,
10+
node: ImportSpecifier$1,
11+
},
12+
],
13+
name: "bar",
14+
references: Array [],
15+
isValueVariable: true,
16+
isTypeVariable: true,
17+
},
18+
],
19+
scopes: Array [
20+
GlobalScope$1 {
21+
block: Program$2,
22+
isStrict: false,
23+
references: Array [],
24+
set: Map {},
25+
type: "global",
26+
upper: null,
27+
variables: Array [],
28+
},
29+
ModuleScope$2 {
30+
block: Program$2,
31+
isStrict: true,
32+
references: Array [],
33+
set: Map {},
34+
type: "module",
35+
upper: GlobalScope$1,
36+
variables: Array [],
37+
},
38+
TSModuleScope$3 {
39+
block: TSModuleDeclaration$3,
40+
isStrict: true,
41+
references: Array [],
42+
set: Map {
43+
"bar" => Variable$1,
44+
},
45+
type: "tsModule",
46+
upper: ModuleScope$2,
47+
variables: Array [
48+
Variable$1,
49+
],
50+
},
51+
],
52+
}
53+
`;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Foo {
2+
export const x = 1;
3+
Foo.x;
4+
}
5+
6+
const unresolved = x;
7+
Foo.x;

0 commit comments

Comments
 (0)