Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 414bc49

Browse filesBrowse files
authored
Module or import types (microsoft#22592)
* Type side of import types * Value side of import types * Accept library changes * Refined implementation, more tests * Allow resolutions to be performed late if the resolution still results in a file already in the build * Add another test case * Add some jsdoc usages * Allow nodebuilder to use import types where appropriate * Parse & check generic instantiations * use import types in nodebuilder for typeof module symbols * Wire up go to definition for import types * Accept updated type/symbol baselines now that symbols are wired in * PR feedback * Fix changes from merge * Walk back late import handling * Remove unused diagnostic * Remove unrelated changes * Use recursive function over loop * Emit type arguments * undo unrelated change * Test for and support import type nodes in bundled declaration emit
1 parent 5c44241 commit 414bc49
Copy full SHA for 414bc49

287 files changed

+3,825-1,278Lines changed: 3825 additions & 1278 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+163-25Lines changed: 163 additions & 25 deletions
Large diffs are not rendered by default.
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,18 @@
955955
"category": "Error",
956956
"code": 1338
957957
},
958+
"Module '{0}' does not refer to a value, but is used as a value here.": {
959+
"category": "Error",
960+
"code": 1339
961+
},
962+
"Module '{0}' does not refer to a type, but is used as a type here.": {
963+
"category": "Error",
964+
"code": 1340
965+
},
966+
"Type arguments cannot be used here.": {
967+
"category": "Error",
968+
"code": 1342
969+
},
958970

959971
"Duplicate identifier '{0}'.": {
960972
"category": "Error",
Collapse file

‎src/compiler/emitter.ts‎

Copy file name to clipboardExpand all lines: src/compiler/emitter.ts
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,8 @@ namespace ts {
615615
return emitMappedType(<MappedTypeNode>node);
616616
case SyntaxKind.LiteralType:
617617
return emitLiteralType(<LiteralTypeNode>node);
618+
case SyntaxKind.ImportTypeNode:
619+
return emitImportTypeNode(<ImportTypeNode>node);
618620
case SyntaxKind.JSDocAllType:
619621
write("*");
620622
return;
@@ -1327,6 +1329,22 @@ namespace ts {
13271329
emitExpression(node.literal);
13281330
}
13291331

1332+
function emitImportTypeNode(node: ImportTypeNode) {
1333+
if (node.isTypeOf) {
1334+
writeKeyword("typeof");
1335+
writeSpace();
1336+
}
1337+
writeKeyword("import");
1338+
writePunctuation("(");
1339+
emit(node.argument);
1340+
writePunctuation(")");
1341+
if (node.qualifier) {
1342+
writePunctuation(".");
1343+
emit(node.qualifier);
1344+
}
1345+
emitTypeArguments(node, node.typeArguments);
1346+
}
1347+
13301348
//
13311349
// Binding patterns
13321350
//
Collapse file

‎src/compiler/factory.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory.ts
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,24 @@ namespace ts {
809809
: node;
810810
}
811811

812+
export function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: ReadonlyArray<TypeNode>, isTypeOf?: boolean) {
813+
const node = <ImportTypeNode>createSynthesizedNode(SyntaxKind.ImportTypeNode);
814+
node.argument = argument;
815+
node.qualifier = qualifier;
816+
node.typeArguments = asNodeArray(typeArguments);
817+
node.isTypeOf = isTypeOf;
818+
return node;
819+
}
820+
821+
export function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier?: EntityName, typeArguments?: ReadonlyArray<TypeNode>, isTypeOf?: boolean) {
822+
return node.argument !== argument
823+
|| node.qualifier !== qualifier
824+
|| node.typeArguments !== typeArguments
825+
|| node.isTypeOf !== isTypeOf
826+
? updateNode(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node)
827+
: node;
828+
}
829+
812830
export function createParenthesizedType(type: TypeNode) {
813831
const node = <ParenthesizedTypeNode>createSynthesizedNode(SyntaxKind.ParenthesizedType);
814832
node.type = type;
Collapse file

‎src/compiler/parser.ts‎

Copy file name to clipboardExpand all lines: src/compiler/parser.ts
+30-1Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ namespace ts {
189189
visitNode(cbNode, (<ConditionalTypeNode>node).falseType);
190190
case SyntaxKind.InferType:
191191
return visitNode(cbNode, (<InferTypeNode>node).typeParameter);
192+
case SyntaxKind.ImportTypeNode:
193+
return visitNode(cbNode, (<ImportTypeNode>node).argument) ||
194+
visitNode(cbNode, (<ImportTypeNode>node).qualifier) ||
195+
visitNodes(cbNode, cbNodes, (<ImportTypeNode>node).typeArguments);
192196
case SyntaxKind.ParenthesizedType:
193197
case SyntaxKind.TypeOperator:
194198
return visitNode(cbNode, (<ParenthesizedTypeNode | TypeOperatorNode>node).type);
@@ -2733,6 +2737,28 @@ namespace ts {
27332737
return finishNode(node);
27342738
}
27352739

2740+
function isStartOfTypeOfImportType() {
2741+
nextToken();
2742+
return token() === SyntaxKind.ImportKeyword;
2743+
}
2744+
2745+
function parseImportType(): ImportTypeNode {
2746+
sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport;
2747+
const node = createNode(SyntaxKind.ImportTypeNode) as ImportTypeNode;
2748+
if (parseOptional(SyntaxKind.TypeOfKeyword)) {
2749+
node.isTypeOf = true;
2750+
}
2751+
parseExpected(SyntaxKind.ImportKeyword);
2752+
parseExpected(SyntaxKind.OpenParenToken);
2753+
node.argument = parseType();
2754+
parseExpected(SyntaxKind.CloseParenToken);
2755+
if (parseOptional(SyntaxKind.DotToken)) {
2756+
node.qualifier = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
2757+
}
2758+
node.typeArguments = tryParseTypeArguments();
2759+
return finishNode(node);
2760+
}
2761+
27362762
function nextTokenIsNumericLiteral() {
27372763
return nextToken() === SyntaxKind.NumericLiteral;
27382764
}
@@ -2780,13 +2806,15 @@ namespace ts {
27802806
}
27812807
}
27822808
case SyntaxKind.TypeOfKeyword:
2783-
return parseTypeQuery();
2809+
return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery();
27842810
case SyntaxKind.OpenBraceToken:
27852811
return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral();
27862812
case SyntaxKind.OpenBracketToken:
27872813
return parseTupleType();
27882814
case SyntaxKind.OpenParenToken:
27892815
return parseParenthesizedType();
2816+
case SyntaxKind.ImportKeyword:
2817+
return parseImportType();
27902818
default:
27912819
return parseTypeReference();
27922820
}
@@ -2822,6 +2850,7 @@ namespace ts {
28222850
case SyntaxKind.ExclamationToken:
28232851
case SyntaxKind.DotDotDotToken:
28242852
case SyntaxKind.InferKeyword:
2853+
case SyntaxKind.ImportKeyword:
28252854
return true;
28262855
case SyntaxKind.MinusToken:
28272856
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
Collapse file

‎src/compiler/program.ts‎

Copy file name to clipboardExpand all lines: src/compiler/program.ts
+11-1Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1686,10 +1686,20 @@ namespace ts {
16861686
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
16871687
imports = append(imports, node.arguments[0] as StringLiteralLike);
16881688
}
1689+
else if (isLiteralImportTypeNode(node)) {
1690+
imports = append(imports, node.argument.literal);
1691+
}
16891692
else {
1690-
forEachChild(node, collectDynamicImportOrRequireCalls);
1693+
collectDynamicImportOrRequireCallsForEachChild(node);
1694+
if (hasJSDocNodes(node)) {
1695+
forEach(node.jsDoc, collectDynamicImportOrRequireCallsForEachChild);
1696+
}
16911697
}
16921698
}
1699+
1700+
function collectDynamicImportOrRequireCallsForEachChild(node: Node) {
1701+
forEachChild(node, collectDynamicImportOrRequireCalls);
1702+
}
16931703
}
16941704

16951705
/** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */
Collapse file

‎src/compiler/transformers/declarations.ts‎

Copy file name to clipboardExpand all lines: src/compiler/transformers/declarations.ts
+15-3Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,9 @@ namespace ts {
450450
return setCommentRange(updated, getCommentRange(original));
451451
}
452452

453-
function rewriteModuleSpecifier<T extends Node>(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration, input: T): T | StringLiteral {
453+
function rewriteModuleSpecifier<T extends Node>(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T): T | StringLiteral {
454454
if (!input) return;
455-
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== SyntaxKind.ModuleDeclaration;
455+
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportTypeNode);
456456
if (input.kind === SyntaxKind.StringLiteral && isBundledEmit) {
457457
const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent);
458458
if (newName) {
@@ -765,6 +765,16 @@ namespace ts {
765765
case SyntaxKind.ConstructorType: {
766766
return cleanup(updateConstructorTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
767767
}
768+
case SyntaxKind.ImportTypeNode: {
769+
if (!isLiteralImportTypeNode(input)) return cleanup(input);
770+
return cleanup(updateImportTypeNode(
771+
input,
772+
updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)),
773+
input.qualifier,
774+
visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode),
775+
input.isTypeOf
776+
));
777+
}
768778
default: Debug.assertNever(input, `Attempted to process unhandled node kind: ${(ts as any).SyntaxKind[(input as any).kind]}`);
769779
}
770780
}
@@ -1264,7 +1274,8 @@ namespace ts {
12641274
| TypeReferenceNode
12651275
| ConditionalTypeNode
12661276
| FunctionTypeNode
1267-
| ConstructorTypeNode;
1277+
| ConstructorTypeNode
1278+
| ImportTypeNode;
12681279

12691280
function isProcessedComponent(node: Node): node is ProcessedComponent {
12701281
switch (node.kind) {
@@ -1285,6 +1296,7 @@ namespace ts {
12851296
case SyntaxKind.ConditionalType:
12861297
case SyntaxKind.FunctionType:
12871298
case SyntaxKind.ConstructorType:
1299+
case SyntaxKind.ImportTypeNode:
12881300
return true;
12891301
}
12901302
return false;
Collapse file

‎src/compiler/types.ts‎

Copy file name to clipboardExpand all lines: src/compiler/types.ts
+19-6Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ namespace ts {
284284
IndexedAccessType,
285285
MappedType,
286286
LiteralType,
287+
ImportTypeNode,
287288
// Binding patterns
288289
ObjectBindingPattern,
289290
ArrayBindingPattern,
@@ -445,7 +446,7 @@ namespace ts {
445446
FirstFutureReservedWord = ImplementsKeyword,
446447
LastFutureReservedWord = YieldKeyword,
447448
FirstTypeNode = TypePredicate,
448-
LastTypeNode = LiteralType,
449+
LastTypeNode = ImportTypeNode,
449450
FirstPunctuation = OpenBraceToken,
450451
LastPunctuation = CaretEqualsToken,
451452
FirstToken = Unknown,
@@ -1067,6 +1068,16 @@ namespace ts {
10671068
| SyntaxKind.NeverKeyword;
10681069
}
10691070

1071+
export interface ImportTypeNode extends NodeWithTypeArguments {
1072+
kind: SyntaxKind.ImportTypeNode;
1073+
isTypeOf?: boolean;
1074+
argument: TypeNode;
1075+
qualifier?: EntityName;
1076+
}
1077+
1078+
/* @internal */
1079+
export type LiteralImportTypeNode = ImportTypeNode & { argument: LiteralTypeNode & { literal: StringLiteral } };
1080+
10701081
export interface ThisTypeNode extends TypeNode {
10711082
kind: SyntaxKind.ThisType;
10721083
}
@@ -1081,12 +1092,15 @@ namespace ts {
10811092
kind: SyntaxKind.ConstructorType;
10821093
}
10831094

1095+
export interface NodeWithTypeArguments extends TypeNode {
1096+
typeArguments?: NodeArray<TypeNode>;
1097+
}
1098+
10841099
export type TypeReferenceType = TypeReferenceNode | ExpressionWithTypeArguments;
10851100

1086-
export interface TypeReferenceNode extends TypeNode {
1101+
export interface TypeReferenceNode extends NodeWithTypeArguments {
10871102
kind: SyntaxKind.TypeReference;
10881103
typeName: EntityName;
1089-
typeArguments?: NodeArray<TypeNode>;
10901104
}
10911105

10921106
export interface TypePredicateNode extends TypeNode {
@@ -1696,11 +1710,10 @@ namespace ts {
16961710
expression: ImportExpression;
16971711
}
16981712

1699-
export interface ExpressionWithTypeArguments extends TypeNode {
1713+
export interface ExpressionWithTypeArguments extends NodeWithTypeArguments {
17001714
kind: SyntaxKind.ExpressionWithTypeArguments;
17011715
parent?: HeritageClause;
17021716
expression: LeftHandSideExpression;
1703-
typeArguments?: NodeArray<TypeNode>;
17041717
}
17051718

17061719
export interface NewExpression extends PrimaryExpression, Declaration {
@@ -3244,7 +3257,7 @@ namespace ts {
32443257
isOptionalParameter(node: ParameterDeclaration): boolean;
32453258
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
32463259
isArgumentsLocalBinding(node: Identifier): boolean;
3247-
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile;
3260+
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): SourceFile;
32483261
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[];
32493262
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
32503263
isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean;
Collapse file

‎src/compiler/utilities.ts‎

Copy file name to clipboardExpand all lines: src/compiler/utilities.ts
+10-2Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,12 @@ namespace ts {
734734
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.ImportKeyword;
735735
}
736736

737+
export function isLiteralImportTypeNode(n: Node): n is LiteralImportTypeNode {
738+
return n.kind === SyntaxKind.ImportTypeNode &&
739+
(n as ImportTypeNode).argument.kind === SyntaxKind.LiteralType &&
740+
isStringLiteral(((n as ImportTypeNode).argument as LiteralTypeNode).literal);
741+
}
742+
737743
export function isPrologueDirective(node: Node): node is PrologueDirective {
738744
return node.kind === SyntaxKind.ExpressionStatement
739745
&& (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
@@ -1697,13 +1703,15 @@ namespace ts {
16971703
}
16981704
}
16991705

1700-
export function getExternalModuleName(node: AnyImportOrReExport): Expression {
1706+
export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode): Expression {
17011707
switch (node.kind) {
17021708
case SyntaxKind.ImportDeclaration:
17031709
case SyntaxKind.ExportDeclaration:
17041710
return node.moduleSpecifier;
17051711
case SyntaxKind.ImportEqualsDeclaration:
17061712
return node.moduleReference.kind === SyntaxKind.ExternalModuleReference ? node.moduleReference.expression : undefined;
1713+
case SyntaxKind.ImportTypeNode:
1714+
return isLiteralImportTypeNode(node) ? node.argument.literal : undefined;
17071715
default:
17081716
return Debug.assertNever(node);
17091717
}
@@ -2809,7 +2817,7 @@ namespace ts {
28092817
return file.moduleName || getExternalModuleNameFromPath(host, file.fileName);
28102818
}
28112819

2812-
export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): string {
2820+
export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string {
28132821
const file = resolver.getExternalModuleFileFromDeclaration(declaration);
28142822
if (!file || file.isDeclarationFile) {
28152823
return undefined;
Collapse file

‎src/compiler/visitor.ts‎

Copy file name to clipboardExpand all lines: src/compiler/visitor.ts
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,14 @@ namespace ts {
398398
return updateInferTypeNode(<InferTypeNode>node,
399399
visitNode((<InferTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration));
400400

401+
case SyntaxKind.ImportTypeNode:
402+
return updateImportTypeNode(<ImportTypeNode>node,
403+
visitNode((<ImportTypeNode>node).argument, visitor, isTypeNode),
404+
visitNode((<ImportTypeNode>node).qualifier, visitor, isEntityName),
405+
visitNodes((<ImportTypeNode>node).typeArguments, visitor, isTypeNode),
406+
(<ImportTypeNode>node).isTypeOf
407+
);
408+
401409
case SyntaxKind.ParenthesizedType:
402410
return updateParenthesizedType(<ParenthesizedTypeNode>node,
403411
visitNode((<ParenthesizedTypeNode>node).type, visitor, isTypeNode));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.