Skip to content

Commit f3537c6

Browse files
authored
Merge pull request microsoft#557 from Microsoft/pgonzal/ae-trimming-3
(API Extractor) Refactoring setup for nested trimming
2 parents 0ed3018 + 93b9ea8 commit f3537c6

10 files changed

Lines changed: 566 additions & 310 deletions

File tree

apps/api-extractor/src/generators/packageTypings/Entry.ts

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,51 @@ export interface IEntryParameters {
1818
}
1919

2020
/**
21-
* An "Entry" is a type definition that we encounter while traversing the
22-
* references from the package entry point. This data structure helps filter,
23-
* sort, and rename the entries that end up in the output package typings file.
21+
* Indicates how this Entry will be processed when emitting the *.d.ts file.
2422
*/
25-
export class Entry {
23+
export const enum EntryRole {
2624
/**
27-
* The original name of the symbol, as exported from the module (i.e. source file)
28-
* containing the original TypeScript definition.
25+
* The item will be a top-level definition in the emitted *.d.ts file.
2926
*/
30-
public readonly localName: string;
27+
EmittedDefinition = 'EmittedDefinition',
3128

3229
/**
33-
* If this entry is a top-level export of the package that we are analyzing, then its
34-
* name is stored here. In this case, the uniqueName must be the same as packageExportName.
35-
* @remarks
36-
* Since Entry objects are collected via a depth first search, we may encounter it
37-
* before we realize that it is a package export; the packageExportName property is not
38-
* accurate until the collection phase has completed.
30+
* The item will be emitted as an import statement. It is declared in
31+
* a dependency package.
3932
*/
40-
public packageExportName: string | undefined;
33+
EmittedImport = 'EmittedImport',
4134

4235
/**
43-
* The localName, possibly renamed to ensure that all the top-level exports have unique names.
36+
* The item is a nested part of its Entry.parent. Its role will be determined
37+
* by the root parent.
4438
*/
45-
public get uniqueName(): string | undefined {
46-
return this._uniqueName;
47-
}
39+
Child = 'Child'
40+
}
4841

49-
public set uniqueName(value: string | undefined) {
50-
this._uniqueName = value;
51-
this._sortKey = undefined; // invalidate the cached value
52-
}
42+
/**
43+
* An "Entry" represents an API item such as a class member, interface, or namespace.
44+
*
45+
* @remarks
46+
* We only model items that the PackageTypingsGenerator could potentially trim, e.g.
47+
* function parameters and literal types are not represented. It is a semantic unit
48+
* (i.e. ts.Symbol not ts.Node), so a single Entry may emit multiple definitions.
49+
* For nested API items (e.g. a member inside a class inside a namespace), the parent
50+
* chain is always populated, but children are only added on demand.
51+
*
52+
* During analysis, "Entry" objects have three possible roles, represented by the
53+
* EntryRole enum.
54+
*/
55+
export class Entry {
56+
// ------------------------------------------------------------------------
57+
// IMMUTABLE STATE
58+
59+
public readonly role: EntryRole;
60+
61+
/**
62+
* The original name of the symbol, as exported from the module (i.e. source file)
63+
* containing the original TypeScript definition.
64+
*/
65+
public readonly localName: string;
5366

5467
/**
5568
* The compiler symbol where this type was defined, after following any aliases.
@@ -86,13 +99,56 @@ export class Entry {
8699
*/
87100
public readonly releaseTag: ReleaseTag;
88101

102+
// ------------------------------------------------------------------------
103+
// MUTABLE STATE
104+
89105
/**
90-
* If true, this entry should be emitted using the "export" keyword instead of the "declare" keyword.
106+
* If this entry is a top-level export of the package that we are analyzing, then its
107+
* name is stored here. In this case, the uniqueName must be the same as packageExportName.
108+
* @remarks
109+
* Since Entry objects are collected via a depth first search, we may encounter it
110+
* before we realize that it is a package export; the packageExportName property is not
111+
* accurate until the collection phase has completed.
91112
*/
92-
public exported: boolean = false;
113+
public get packageExportName(): string | undefined {
114+
return this._packageExportName;
115+
}
116+
117+
public set packageExportName(value: string | undefined) {
118+
this._role = EntryRole.EmittedDefinition;
119+
this._packageExportName = value;
120+
}
121+
122+
/**
123+
* Indicates that the item must be emitted as a definition in the *.d.ts file but
124+
* without an "export" keyword. If so, then:
125+
* - The API file will warn the developer that they referenced this type but forgot
126+
* to export it
127+
* - The uniqueName may get renamed to avoid conflicts with the explicit exports
128+
*
129+
* NOTE: During analysis, the packageExportName can be assigned after the constructor
130+
* is called. If this happens, the forgottenExport state will change.
131+
*/
132+
public get forgottenExport(): boolean {
133+
return this.role === EntryRole.EmittedDefinition && !this.packageExportName;
134+
}
135+
136+
/**
137+
* The localName, possibly renamed to ensure that all the top-level exports have unique names.
138+
*/
139+
public get uniqueName(): string | undefined {
140+
return this._uniqueName;
141+
}
142+
143+
public set uniqueName(value: string | undefined) {
144+
this._uniqueName = value;
145+
this._sortKey = undefined; // invalidate the cached value
146+
}
93147

94148
private _uniqueName: string | undefined = undefined;
95149
private _sortKey: string|undefined = undefined;
150+
private _packageExportName: string | undefined;
151+
private _role: EntryRole;
96152

97153
public constructor(parameters: IEntryParameters) {
98154
this.localName = parameters.localName;
@@ -101,6 +157,12 @@ export class Entry {
101157
this.importPackageExportName = parameters.importPackageExportName;
102158
this.importPackageKey = parameters.importPackageKey;
103159
this.releaseTag = parameters.releaseTag;
160+
161+
if (this.importPackagePath) {
162+
this.role = EntryRole.EmittedImport;
163+
} else {
164+
this.role = EntryRole.EmittedDefinition;
165+
}
104166
}
105167

106168
public getSortKey(): string {

0 commit comments

Comments
 (0)