Skip to content

Commit 2e9656a

Browse files
authored
[api-extractor] (fix) Fix module resolution for some type import declarations (#5288)
* Add ability for api-extractor-scenarios to customize the extractor compiler options * Add api-extractor-scenarios "bundlerModuleResolution" scenario * [api-extractor] Fix ExportAnalyzer unable to resolve type import declaration with LiteralTypeNode argument * rush change --------- Co-authored-by: Leon Schiffler <[email protected]>
1 parent e49dd82 commit 2e9656a

File tree

10 files changed

+280
-3
lines changed

10 files changed

+280
-3
lines changed

apps/api-extractor/src/analyzer/ExportAnalyzer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,12 @@ export class ExportAnalyzer {
264264
importOrExportDeclaration: ts.ImportDeclaration | ts.ExportDeclaration | ts.ImportTypeNode,
265265
moduleSpecifier: string
266266
): boolean {
267-
const specifier: ts.TypeNode | ts.Expression | undefined = ts.isImportTypeNode(importOrExportDeclaration)
267+
let specifier: ts.TypeNode | ts.Expression | undefined = ts.isImportTypeNode(importOrExportDeclaration)
268268
? importOrExportDeclaration.argument
269269
: importOrExportDeclaration.moduleSpecifier;
270+
if (specifier && ts.isLiteralTypeNode(specifier)) {
271+
specifier = specifier.literal;
272+
}
270273
const mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined =
271274
specifier && ts.isStringLiteralLike(specifier)
272275
? TypeScriptInternals.getModeForUsageLocation(
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
{
2+
"metadata": {
3+
"toolPackage": "@microsoft/api-extractor",
4+
"toolVersion": "[test mode]",
5+
"schemaVersion": 1011,
6+
"oldestForwardsCompatibleVersion": 1001,
7+
"tsdocConfig": {
8+
"$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
9+
"noStandardTags": true,
10+
"tagDefinitions": [
11+
{
12+
"tagName": "@alpha",
13+
"syntaxKind": "modifier"
14+
},
15+
{
16+
"tagName": "@beta",
17+
"syntaxKind": "modifier"
18+
},
19+
{
20+
"tagName": "@defaultValue",
21+
"syntaxKind": "block"
22+
},
23+
{
24+
"tagName": "@decorator",
25+
"syntaxKind": "block",
26+
"allowMultiple": true
27+
},
28+
{
29+
"tagName": "@deprecated",
30+
"syntaxKind": "block"
31+
},
32+
{
33+
"tagName": "@eventProperty",
34+
"syntaxKind": "modifier"
35+
},
36+
{
37+
"tagName": "@example",
38+
"syntaxKind": "block",
39+
"allowMultiple": true
40+
},
41+
{
42+
"tagName": "@experimental",
43+
"syntaxKind": "modifier"
44+
},
45+
{
46+
"tagName": "@inheritDoc",
47+
"syntaxKind": "inline"
48+
},
49+
{
50+
"tagName": "@internal",
51+
"syntaxKind": "modifier"
52+
},
53+
{
54+
"tagName": "@label",
55+
"syntaxKind": "inline"
56+
},
57+
{
58+
"tagName": "@link",
59+
"syntaxKind": "inline",
60+
"allowMultiple": true
61+
},
62+
{
63+
"tagName": "@override",
64+
"syntaxKind": "modifier"
65+
},
66+
{
67+
"tagName": "@packageDocumentation",
68+
"syntaxKind": "modifier"
69+
},
70+
{
71+
"tagName": "@param",
72+
"syntaxKind": "block",
73+
"allowMultiple": true
74+
},
75+
{
76+
"tagName": "@privateRemarks",
77+
"syntaxKind": "block"
78+
},
79+
{
80+
"tagName": "@public",
81+
"syntaxKind": "modifier"
82+
},
83+
{
84+
"tagName": "@readonly",
85+
"syntaxKind": "modifier"
86+
},
87+
{
88+
"tagName": "@remarks",
89+
"syntaxKind": "block"
90+
},
91+
{
92+
"tagName": "@returns",
93+
"syntaxKind": "block"
94+
},
95+
{
96+
"tagName": "@sealed",
97+
"syntaxKind": "modifier"
98+
},
99+
{
100+
"tagName": "@see",
101+
"syntaxKind": "block"
102+
},
103+
{
104+
"tagName": "@throws",
105+
"syntaxKind": "block",
106+
"allowMultiple": true
107+
},
108+
{
109+
"tagName": "@typeParam",
110+
"syntaxKind": "block",
111+
"allowMultiple": true
112+
},
113+
{
114+
"tagName": "@virtual",
115+
"syntaxKind": "modifier"
116+
},
117+
{
118+
"tagName": "@betaDocumentation",
119+
"syntaxKind": "modifier"
120+
},
121+
{
122+
"tagName": "@internalRemarks",
123+
"syntaxKind": "block"
124+
},
125+
{
126+
"tagName": "@preapproved",
127+
"syntaxKind": "modifier"
128+
}
129+
],
130+
"supportForTags": {
131+
"@alpha": true,
132+
"@beta": true,
133+
"@defaultValue": true,
134+
"@decorator": true,
135+
"@deprecated": true,
136+
"@eventProperty": true,
137+
"@example": true,
138+
"@experimental": true,
139+
"@inheritDoc": true,
140+
"@internal": true,
141+
"@label": true,
142+
"@link": true,
143+
"@override": true,
144+
"@packageDocumentation": true,
145+
"@param": true,
146+
"@privateRemarks": true,
147+
"@public": true,
148+
"@readonly": true,
149+
"@remarks": true,
150+
"@returns": true,
151+
"@sealed": true,
152+
"@see": true,
153+
"@throws": true,
154+
"@typeParam": true,
155+
"@virtual": true,
156+
"@betaDocumentation": true,
157+
"@internalRemarks": true,
158+
"@preapproved": true
159+
},
160+
"reportUnsupportedHtmlElements": false
161+
}
162+
},
163+
"kind": "Package",
164+
"canonicalReference": "api-extractor-scenarios!",
165+
"docComment": "",
166+
"name": "api-extractor-scenarios",
167+
"preserveMemberOrder": false,
168+
"members": [
169+
{
170+
"kind": "EntryPoint",
171+
"canonicalReference": "api-extractor-scenarios!",
172+
"name": "",
173+
"preserveMemberOrder": false,
174+
"members": [
175+
{
176+
"kind": "Variable",
177+
"canonicalReference": "api-extractor-scenarios!reexport:var",
178+
"docComment": "/**\n * @public\n */\n",
179+
"excerptTokens": [
180+
{
181+
"kind": "Content",
182+
"text": "reexport: "
183+
},
184+
{
185+
"kind": "Content",
186+
"text": "import(\"./other\")."
187+
},
188+
{
189+
"kind": "Reference",
190+
"text": "Foo",
191+
"canonicalReference": "api-extractor-scenarios!~Foo:class"
192+
}
193+
],
194+
"fileUrlPath": "src/bundlerModuleResolution/index.ts",
195+
"isReadonly": true,
196+
"releaseTag": "Public",
197+
"name": "reexport",
198+
"variableTypeTokenRange": {
199+
"startIndex": 1,
200+
"endIndex": 3
201+
}
202+
}
203+
]
204+
}
205+
]
206+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## API Report File for "api-extractor-scenarios"
2+
3+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4+
5+
```ts
6+
7+
// Warning: (ae-forgotten-export) The symbol "Foo" needs to be exported by the entry point index.d.ts
8+
//
9+
// @public (undocumented)
10+
export const reexport: Foo;
11+
12+
// (No @packageDocumentation comment for this package)
13+
14+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
declare class Foo {
2+
}
3+
4+
/**
5+
* @public
6+
*/
7+
export declare const reexport: Foo;
8+
9+
export { }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compiler": {
3+
"tsconfigFilePath": "<projectFolder>/src/bundlerModuleResolution/config/tsconfig.json"
4+
}
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "../../../tsconfig.json",
3+
"compilerOptions": {
4+
"module": "esnext",
5+
"moduleResolution": "bundler"
6+
}
7+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { foo } from './other';
2+
3+
/**
4+
* @public
5+
*/
6+
export const reexport = foo;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export class Foo {}
2+
3+
export const foo = new Foo();

build-tests/run-scenarios-helpers/src/index.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export async function runScenariosAsync(
3030
{ libFolderPath, additionalApiExtractorConfig, afterApiExtractorAsync }: IRunScenariosOptions
3131
): Promise<void> {
3232
const entryPoints: string[] = [];
33+
const scenariosWithCustomCompilerOptions: string[] = [];
3334

3435
const scenarioFolderNames: string[] = [];
3536
const folderItems: FolderItem[] = await FileSystem.readFolderItemsAsync(libFolderPath);
@@ -56,6 +57,10 @@ export async function runScenariosAsync(
5657
}
5758
}
5859

60+
if (apiExtractorJsonOverrides && 'compiler' in apiExtractorJsonOverrides) {
61+
scenariosWithCustomCompilerOptions.push(scenarioFolderName);
62+
}
63+
5964
const apiExtractorJson: {} = {
6065
$schema: 'https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json',
6166

@@ -93,18 +98,27 @@ export async function runScenariosAsync(
9398
{ concurrency: 10 }
9499
);
95100

96-
let compilerState: CompilerState | undefined = undefined;
101+
let baseCompilerState: CompilerState | undefined = undefined;
97102
for (const scenarioFolderName of scenarioFolderNames) {
98103
logger.terminal.writeLine(`Scenario: ${scenarioFolderName}`);
99104

100105
// Run API Extractor programmatically
101106
const apiExtractorJsonPath: string = `${buildFolderPath}/temp/configs/api-extractor-${scenarioFolderName}.json`;
102107
const extractorConfig: ExtractorConfig = ExtractorConfig.loadFileAndPrepare(apiExtractorJsonPath);
103108

104-
if (!compilerState) {
109+
let compilerState: CompilerState;
110+
if (scenariosWithCustomCompilerOptions.includes(scenarioFolderName)) {
111+
logger.terminal.writeLine(`Using custom compiler state (${scenarioFolderName})`);
105112
compilerState = CompilerState.create(extractorConfig, {
106113
additionalEntryPoints: entryPoints
107114
});
115+
} else {
116+
if (!baseCompilerState) {
117+
baseCompilerState = CompilerState.create(extractorConfig, {
118+
additionalEntryPoints: entryPoints
119+
});
120+
}
121+
compilerState = baseCompilerState;
108122
}
109123

110124
const extractorResult: ExtractorResult = Extractor.invoke(extractorConfig, {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/api-extractor",
5+
"comment": "Fixes a bug in ExtractorAnalyzer._isExternalModulePath where type import declarations were not resolved.",
6+
"type": "patch"
7+
}
8+
],
9+
"packageName": "@microsoft/api-extractor"
10+
}

0 commit comments

Comments
 (0)