Skip to content

Commit 01f040c

Browse files
committed
Import converter
Converter that converts and resolves imported declarations of any kind and includes them into the docs.
1 parent b3c4294 commit 01f040c

File tree

6 files changed

+1102
-1
lines changed

6 files changed

+1102
-1
lines changed

src/lib/converter/factories/declaration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function createDeclaration(context: Context, node: ts.Node, kind: Reflect
5252
}
5353

5454
if (kind === ReflectionKind.ExternalModule) {
55-
isExported = true; // Always mark external modules as exported
55+
isExported = container.isProject(); // Always mark external modules as exported
5656
} else if (node.parent && node.parent.kind === ts.SyntaxKind.VariableDeclarationList) {
5757
const parentModifiers = ts.getCombinedModifierFlags(node.parent.parent);
5858
isExported = isExported || !!(parentModifiers & ts.ModifierFlags.Export);

src/lib/converter/nodes/import.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import * as ts from 'typescript';
2+
3+
import { Reflection, DeclarationReflection } from '../../models/index';
4+
import { createDeclaration } from '../factories/index';
5+
import { Context } from '../context';
6+
import { Component, ConverterNodeComponent } from '../components';
7+
8+
@Component({name: 'node:import'})
9+
export class ImportConverter extends ConverterNodeComponent<ts.ImportDeclaration | ts.ImportEqualsDeclaration> {
10+
/**
11+
* List of supported TypeScript syntax kinds.
12+
*/
13+
supports: ts.SyntaxKind[] = [
14+
ts.SyntaxKind.ImportDeclaration,
15+
ts.SyntaxKind.ImportEqualsDeclaration
16+
];
17+
18+
convert(context: Context, node: ts.ImportDeclaration | ts.ImportEqualsDeclaration): Reflection {
19+
// import * as foo from 'xx'
20+
// import { MyType, MyVar as ImportedVar } from 'xx'
21+
if (node.kind === ts.SyntaxKind.ImportDeclaration) {
22+
const importDeclarationNode = node as ts.ImportDeclaration;
23+
const importClause = importDeclarationNode.importClause;
24+
25+
if (importClause) {
26+
// import myType from 'default-export';
27+
if (importClause.symbol) {
28+
this.createImportedSymbolDeclarationForAlias(context, node, importClause.symbol);
29+
} else if (importClause.namedBindings) {
30+
// import { MyType, MyVar as ImportedVar } from 'xx'
31+
if (importClause.namedBindings.kind === ts.SyntaxKind.NamedImports) {
32+
const namedImports = importClause.namedBindings as ts.NamedImports;
33+
namedImports.elements.forEach(imp => {
34+
if (imp.symbol) {
35+
this.createImportedSymbolDeclarationForAlias(context, node, imp.symbol);
36+
}
37+
});
38+
// import * as foo from 'xx'
39+
} else if (importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) {
40+
const nsImport = importClause.namedBindings as ts.NamespaceImport;
41+
if (nsImport.symbol) {
42+
this.createImportedSymbolDeclarationForAlias(context, node, nsImport.symbol);
43+
}
44+
}
45+
}
46+
}
47+
// import foo = Foo;
48+
// import bar = require('bar');
49+
} else if (node.kind === ts.SyntaxKind.ImportEqualsDeclaration) {
50+
const importEqualsDeclaration = node as ts.ImportEqualsDeclaration;
51+
const moduleRef = importEqualsDeclaration.moduleReference;
52+
const type = context.checker.getTypeAtLocation(moduleRef);
53+
54+
if (type) {
55+
this.createImportedSymbolDeclaration(context, node, type.symbol, node.symbol.name);
56+
}
57+
}
58+
return context.scope;
59+
}
60+
61+
private createImportedSymbolDeclarationForAlias(context: Context, node: ts.Node, symbol: ts.Symbol): void {
62+
if (symbol && (symbol.flags & ts.SymbolFlags.Alias) === ts.SymbolFlags.Alias) {
63+
this.createImportedSymbolDeclaration(context, node, context.checker.getAliasedSymbol(symbol), symbol.name);
64+
}
65+
}
66+
67+
private createImportedSymbolDeclaration(context: Context, node: ts.Node, symbol: ts.Symbol, name: string): void {
68+
if (symbol && symbol.declarations) {
69+
const project = context.project;
70+
for (let d of symbol.declarations) {
71+
if (!d.symbol) {
72+
continue;
73+
}
74+
const id = project.symbolMapping[context.getSymbolID(d.symbol)];
75+
if (!id) {
76+
continue;
77+
}
78+
79+
const reflection = project.reflections[id];
80+
if (reflection instanceof DeclarationReflection) {
81+
const importedDeclaration = createDeclaration(context, node, reflection.kind, name);
82+
if (importedDeclaration != null) {
83+
importedDeclaration.importedFrom = reflection;
84+
}
85+
break;
86+
}
87+
}
88+
}
89+
}
90+
}

src/lib/converter/nodes/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export { ConstructorConverter } from './constructor';
66
export { EnumConverter } from './enum';
77
export { ExportConverter } from './export';
88
export { FunctionConverter } from './function';
9+
export { ImportConverter } from './import';
910
export { InterfaceConverter } from './interface';
1011
export { TypeLiteralConverter } from './literal-type';
1112
export { ObjectLiteralConverter } from './literal-object';

src/lib/models/reflections/declaration.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ export class DeclarationReflection extends ContainerReflection implements Defaul
114114
*/
115115
implementedBy: Type[];
116116

117+
/**
118+
* If this reflection is an imported reference to another reflection, this is
119+
* the original reflection this reflection points to.
120+
*/
121+
importedFrom?: DeclarationReflection;
122+
117123
/**
118124
* Contains a simplified representation of the type hierarchy suitable for being
119125
* rendered in templates.
@@ -221,6 +227,13 @@ export class DeclarationReflection extends ContainerReflection implements Defaul
221227
result.implementationOf = this.implementationOf.toObject();
222228
}
223229

230+
if (this.importedFrom) {
231+
result.importedFrom = {
232+
id: this.importedFrom.id,
233+
name: this.importedFrom.name
234+
};
235+
}
236+
224237
return result;
225238
}
226239

src/test/converter/import/import.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* This is a NamespaceImport.
3+
*/
4+
import * as vars from '../variable/variable';
5+
6+
/**
7+
* This is a NamespaceImport.
8+
*/
9+
import * as enums from '../enum/enum';
10+
11+
/**
12+
* Those are NamedImports.
13+
*/
14+
import { SimpleEnum, ModuleEnum as MyEnum } from '../enum/enum';
15+
16+
/**
17+
* This is an ImportEqualsDeclaration.
18+
*/
19+
import z = require('../enum/enum');
20+
21+
/**
22+
* This is a side-effect-only import and does not create a reflection.
23+
*/
24+
import '../enum/enum';
25+
26+
/**
27+
* This is a NamespaceImport that imports the defaults of a module.
28+
*/
29+
import def from '../export-default/export-default';
30+
31+
/**
32+
* This is a namespace that is aliased later.
33+
*/
34+
namespace Foo
35+
{
36+
/**
37+
* This is a variable of an enum type imported by a namespace import.
38+
*/
39+
let simpleEnum: enums.SimpleEnum = enums.SimpleEnum.EnumValue1;
40+
41+
/**
42+
* This is a variable of an enum type imported by a named import.
43+
*/
44+
export const se = SimpleEnum.EnumValue2;
45+
46+
/**
47+
* This is a variable of an enum type imported by a named import with a custom alias.
48+
*/
49+
let mye: MyEnum = MyEnum.EnumValue3;
50+
51+
/**
52+
* This is a variable of an enum type imported by an ImportEqualsDeclaration.
53+
*/
54+
let zMe: z.ModuleEnum = z.ModuleEnum.EnumValue2;
55+
56+
/**
57+
* This is a const that equals the default export of a module.
58+
*/
59+
const defx = def;
60+
61+
/**
62+
* This is a const that equals a type of an imported module.
63+
*/
64+
const SimpleEnumType = enums.SimpleEnum;
65+
66+
/**
67+
* This is a const that equals an exported variable of an imported module.
68+
*/
69+
const varx = vars.myLet;
70+
}
71+
72+
/**
73+
* This is an ImportEqualsDeclaration to a namespace.
74+
*/
75+
import foo = Foo;
76+
77+
/**
78+
* This is an exported ImportEqualsDeclaration to an exported member of the namespace.
79+
*/
80+
export import fooSe = Foo.se;
81+
82+
/**
83+
* This is a const to test type resolution.
84+
*/
85+
const fooxx = foo.se;

0 commit comments

Comments
 (0)