feat(api-extractor): support export * as ___ syntax (#10173)

* feat(api-extractor): support `export * as ___` syntax

* fix: typescript version
This commit is contained in:
Qjuh
2024-04-16 10:35:34 +02:00
committed by GitHub
parent 7baa9e4333
commit 1c5de21a29
3 changed files with 44 additions and 52 deletions

View File

@@ -197,9 +197,8 @@ export class ExportAnalyzer {
(moduleReference.moduleSpecifierSymbol.flags & ts.SymbolFlags.Alias) !== 0
) {
// Follow the import/export declaration to one hop the exported item inside the target module
let followedSymbol: ts.Symbol | undefined = TypeScriptInternals.getImmediateAliasedSymbol(
let followedSymbol: ts.Symbol | undefined = this._typeChecker.getImmediateAliasedSymbol(
moduleReference.moduleSpecifierSymbol,
this._typeChecker,
);
if (followedSymbol === undefined) {
@@ -256,7 +255,11 @@ export class ExportAnalyzer {
: importOrExportDeclaration.moduleSpecifier;
const mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined =
specifier && ts.isStringLiteralLike(specifier)
? TypeScriptInternals.getModeForUsageLocation(importOrExportDeclaration.getSourceFile(), specifier)
? ts.getModeForUsageLocation(
importOrExportDeclaration.getSourceFile(),
specifier,
this._program.getCompilerOptions(),
)
: undefined;
const resolvedModule: ts.ResolvedModuleFull | undefined = TypeScriptInternals.getResolvedModule(
@@ -392,7 +395,7 @@ export class ExportAnalyzer {
break;
}
const currentAlias: ts.Symbol = TypeScriptInternals.getImmediateAliasedSymbol(current, this._typeChecker);
const currentAlias: ts.Symbol | undefined = this._typeChecker.getImmediateAliasedSymbol(current);
// Stop if we reach the end of the chain
if (!currentAlias || currentAlias === current) {
break;
@@ -547,11 +550,13 @@ export class ExportAnalyzer {
// SemicolonToken: pre=[;]
// Issue tracking this feature: https://github.com/microsoft/rushstack/issues/2780
throw new Error(
`The "export * as ___" syntax is not supported yet; as a workaround,` +
` use "import * as ___" with a separate "export { ___ }" declaration\n` +
SourceFileLocationFormatter.formatDeclaration(declaration),
);
const namespaceExport: ts.NamespaceExport = declaration as ts.NamespaceExport;
exportName = namespaceExport.name.getText().trim();
// throw new Error(
// `The "export * as ___" syntax is not supported yet; as a workaround,` +
// ` use "import * as ___" with a separate "export { ___ }" declaration\n` +
// SourceFileLocationFormatter.formatDeclaration(declaration),
// );
} else {
throw new InternalError(
`Unimplemented export declaration kind: ${declaration.getText()}\n` +
@@ -563,6 +568,33 @@ export class ExportAnalyzer {
if (exportDeclaration.moduleSpecifier) {
const externalModulePath: string | undefined = this._tryGetExternalModulePath(exportDeclaration);
if (declaration.kind === ts.SyntaxKind.NamespaceExport) {
if (externalModulePath === undefined) {
const astModule: AstModule = this._fetchSpecifierAstModule(exportDeclaration, declarationSymbol);
let namespaceImport: AstNamespaceImport | undefined = this._astNamespaceImportByModule.get(astModule);
if (namespaceImport === undefined) {
namespaceImport = new AstNamespaceImport({
namespaceName: declarationSymbol.name,
astModule,
declaration,
symbol: declarationSymbol,
});
this._astNamespaceImportByModule.set(astModule, namespaceImport);
}
return namespaceImport;
}
// Here importSymbol=undefined because {@inheritDoc} and such are not going to work correctly for
// a package or source file.
return this._fetchAstImport(undefined, {
importKind: AstImportKind.StarImport,
exportName,
modulePath: externalModulePath,
isTypeOnly: exportDeclaration.isTypeOnly,
});
}
if (externalModulePath !== undefined) {
return this._fetchAstImport(declarationSymbol, {
importKind: AstImportKind.NamedImport,
@@ -851,9 +883,10 @@ export class ExportAnalyzer {
const moduleSpecifier: string = this._getModuleSpecifier(importOrExportDeclaration);
const mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined =
importOrExportDeclaration.moduleSpecifier && ts.isStringLiteralLike(importOrExportDeclaration.moduleSpecifier)
? TypeScriptInternals.getModeForUsageLocation(
? ts.getModeForUsageLocation(
importOrExportDeclaration.getSourceFile(),
importOrExportDeclaration.moduleSpecifier,
this._program.getCompilerOptions(),
)
: undefined;
const resolvedModule: ts.ResolvedModuleFull | undefined = TypeScriptInternals.getResolvedModule(

View File

@@ -6,7 +6,7 @@
"scripts": {
"test": "vitest run",
"build": "tsc --noEmit && tsup",
"build:docs": "tsc -p tsconfig.docs.json && downlevel-dts ./dist-docs ./dist-docs",
"build:docs": "tsc -p tsconfig.docs.json",
"lint": "prettier --check . && cross-env TIMING=1 eslint --format=pretty src __tests__",
"format": "prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src __tests__",
"fmt": "pnpm run format",
@@ -79,7 +79,6 @@
"@types/node": "16.18.60",
"@vitest/coverage-v8": "^1.3.1",
"cross-env": "^7.0.3",
"downlevel-dts": "^0.11.0",
"esbuild-plugin-version-injector": "^1.2.1",
"eslint": "^8.57.0",
"eslint-config-neon": "^0.1.59",