Skip to content

Commit 4a8519f

Browse files
committed
Update API
1 parent 08701ac commit 4a8519f

File tree

3 files changed

+49
-31
lines changed

3 files changed

+49
-31
lines changed

src/compiler/checker.ts

+21-23
Original file line numberDiff line numberDiff line change
@@ -5161,6 +5161,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
51615161
interface ExportCollisionTracker {
51625162
specifierText: string;
51635163
exportsWithDuplicate?: ExportDeclaration[];
5164+
isTypeOnly?: boolean;
51645165
}
51655166

51665167
type ExportCollisionTrackerTable = UnderscoreEscapedMap<ExportCollisionTracker>;
@@ -5169,7 +5170,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
51695170
* Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument
51705171
* Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables
51715172
*/
5172-
function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) {
5173+
function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration, isTypeOnly?: boolean) {
51735174
if (!source) return;
51745175
source.forEach((sourceSymbol, id) => {
51755176
if (id === InternalSymbolName.Default) return;
@@ -5179,17 +5180,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
51795180
target.set(id, sourceSymbol);
51805181
if (lookupTable && exportNode) {
51815182
lookupTable.set(id, {
5182-
specifierText: getTextOfNode(exportNode.moduleSpecifier!)
5183+
specifierText: getTextOfNode(exportNode.moduleSpecifier!),
5184+
isTypeOnly,
51835185
});
51845186
}
51855187
}
5186-
else if (lookupTable && exportNode && targetSymbol && resolveSymbol(targetSymbol) !== resolveSymbol(sourceSymbol)) {
5188+
else if (lookupTable && exportNode && targetSymbol) {
51875189
const collisionTracker = lookupTable.get(id)!;
5188-
if (!collisionTracker.exportsWithDuplicate) {
5189-
collisionTracker.exportsWithDuplicate = [exportNode];
5190-
}
5191-
else {
5192-
collisionTracker.exportsWithDuplicate.push(exportNode);
5190+
collisionTracker.isTypeOnly = collisionTracker.isTypeOnly && isTypeOnly;
5191+
if (resolveSymbol(targetSymbol) !== resolveSymbol(sourceSymbol)) {
5192+
if (!collisionTracker.exportsWithDuplicate) {
5193+
collisionTracker.exportsWithDuplicate = [exportNode];
5194+
}
5195+
else {
5196+
collisionTracker.exportsWithDuplicate.push(exportNode);
5197+
}
51935198
}
51945199
}
51955200
});
@@ -5198,30 +5203,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
51985203
function getExportsOfModuleWorker(moduleSymbol: Symbol) {
51995204
const visitedSymbols: Symbol[] = [];
52005205
let typeOnlyExportStarMap: UnderscoreEscapedMap<ExportDeclaration & { readonly isTypeOnly: true }> | undefined;
5201-
const nonTypeOnlyNames = new Set<__String>();
52025206

52035207
// A module defined by an 'export=' consists of one export that needs to be resolved
52045208
moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
5205-
const exports = visit(moduleSymbol) || emptySymbols;
5206-
5207-
if (typeOnlyExportStarMap) {
5208-
nonTypeOnlyNames.forEach(name => typeOnlyExportStarMap!.delete(name));
5209-
}
52105209

52115210
return {
5212-
exports,
5211+
exports: visit(moduleSymbol) || emptySymbols,
52135212
typeOnlyExportStarMap,
52145213
};
52155214

52165215
// The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
52175216
// module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
52185217
function visit(symbol: Symbol | undefined, exportStar?: ExportDeclaration, isTypeOnly?: boolean): SymbolTable | undefined {
5219-
if (!isTypeOnly && symbol?.exports) {
5220-
// Add non-type-only names before checking if we've visited this module,
5221-
// because we might have visited it via an 'export type *', and visiting
5222-
// again with 'export *' will override the type-onlyness of its exports.
5223-
symbol.exports.forEach((_, name) => nonTypeOnlyNames.add(name));
5224-
}
52255218
if (!(symbol && symbol.exports && pushIfUnique(visitedSymbols, symbol))) {
52265219
return;
52275220
}
@@ -5235,16 +5228,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
52355228
if (exportStars.declarations) {
52365229
for (const node of exportStars.declarations) {
52375230
const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!);
5238-
const exportedSymbols = visit(resolvedModule, node as ExportDeclaration, isTypeOnly || (node as ExportDeclaration).isTypeOnly);
5231+
const nestedExportsAreTypeOnly = isTypeOnly || (node as ExportDeclaration).isTypeOnly;
5232+
const exportedSymbols = visit(resolvedModule, node as ExportDeclaration, nestedExportsAreTypeOnly);
52395233
extendExportSymbols(
52405234
nestedSymbols,
52415235
exportedSymbols,
52425236
lookupTable,
5243-
node as ExportDeclaration
5237+
node as ExportDeclaration,
5238+
nestedExportsAreTypeOnly,
52445239
);
52455240
}
52465241
}
52475242
lookupTable.forEach(({ exportsWithDuplicate }, id) => {
5243+
if (typeOnlyExportStarMap && !isTypeOnly && exportsWithDuplicate?.length) {
5244+
typeOnlyExportStarMap.delete(id);
5245+
}
52485246
// It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself
52495247
if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || symbols.has(id)) {
52505248
return;

tests/baselines/reference/api/tsserverlibrary.d.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -5713,8 +5713,8 @@ declare namespace ts {
57135713
readonly name: Identifier;
57145714
}
57155715
type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier;
5716-
type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier;
5717-
type TypeOnlyAliasDeclaration = ImportClause & {
5716+
type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport;
5717+
type TypeOnlyImportDeclaration = ImportClause & {
57185718
readonly isTypeOnly: true;
57195719
readonly name: Identifier;
57205720
} | ImportEqualsDeclaration & {
@@ -5731,15 +5731,23 @@ declare namespace ts {
57315731
readonly isTypeOnly: true;
57325732
};
57335733
};
5734-
}) | ExportSpecifier & ({
5734+
});
5735+
type TypeOnlyExportDeclaration = ExportSpecifier & ({
57355736
readonly isTypeOnly: true;
57365737
} | {
57375738
readonly parent: NamedExports & {
57385739
readonly parent: ExportDeclaration & {
57395740
readonly isTypeOnly: true;
57405741
};
57415742
};
5742-
});
5743+
}) | ExportDeclaration & {
5744+
readonly isTypeOnly: true;
5745+
} | NamespaceExport & {
5746+
readonly parent: ExportDeclaration & {
5747+
readonly isTypeOnly: true;
5748+
};
5749+
};
5750+
type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration;
57435751
/**
57445752
* This is either an `export =` or an `export default` declaration.
57455753
* Unless `isExportEquals` is set, this node was parsed as an `export default`.
@@ -8732,6 +8740,8 @@ declare namespace ts {
87328740
function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken;
87338741
function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail;
87348742
function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier;
8743+
function isTypeOnlyImportDeclaration(node: Node): node is TypeOnlyImportDeclaration;
8744+
function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportDeclaration;
87358745
function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration;
87368746
function isAssertionKey(node: Node): node is AssertionKey;
87378747
function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken;

tests/baselines/reference/api/typescript.d.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -1778,8 +1778,8 @@ declare namespace ts {
17781778
readonly name: Identifier;
17791779
}
17801780
type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier;
1781-
type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier;
1782-
type TypeOnlyAliasDeclaration = ImportClause & {
1781+
type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport;
1782+
type TypeOnlyImportDeclaration = ImportClause & {
17831783
readonly isTypeOnly: true;
17841784
readonly name: Identifier;
17851785
} | ImportEqualsDeclaration & {
@@ -1796,15 +1796,23 @@ declare namespace ts {
17961796
readonly isTypeOnly: true;
17971797
};
17981798
};
1799-
}) | ExportSpecifier & ({
1799+
});
1800+
type TypeOnlyExportDeclaration = ExportSpecifier & ({
18001801
readonly isTypeOnly: true;
18011802
} | {
18021803
readonly parent: NamedExports & {
18031804
readonly parent: ExportDeclaration & {
18041805
readonly isTypeOnly: true;
18051806
};
18061807
};
1807-
});
1808+
}) | ExportDeclaration & {
1809+
readonly isTypeOnly: true;
1810+
} | NamespaceExport & {
1811+
readonly parent: ExportDeclaration & {
1812+
readonly isTypeOnly: true;
1813+
};
1814+
};
1815+
type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration;
18081816
/**
18091817
* This is either an `export =` or an `export default` declaration.
18101818
* Unless `isExportEquals` is set, this node was parsed as an `export default`.
@@ -4797,6 +4805,8 @@ declare namespace ts {
47974805
function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken;
47984806
function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail;
47994807
function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier;
4808+
function isTypeOnlyImportDeclaration(node: Node): node is TypeOnlyImportDeclaration;
4809+
function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportDeclaration;
48004810
function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration;
48014811
function isAssertionKey(node: Node): node is AssertionKey;
48024812
function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken;

0 commit comments

Comments
 (0)