in packages/jsii/lib/transforms/deprecated-remover.ts [806:917]
private visitor<T extends ts.Node>(node: T): ts.VisitResult<T> {
if (this.isDeprecated(node)) {
// Removing deprecated members by substituting "nothing" to them
return undefined;
}
if (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) {
for (const transformation of this.transformations) {
// 👇 as any because the assignment below confuses type checker
if (transformation.targets(node as any)) {
const { node: transformedNode, syntheticImport } =
transformation.apply(node);
node = transformedNode as any;
if (syntheticImport) {
this.syntheticImports.push(syntheticImport);
}
}
}
}
// Remove named imports of `@deprecated` members from the source...
if (
ts.isImportDeclaration(node) &&
node.importClause &&
node.importClause.namedBindings &&
ts.isNamedImports(node.importClause.namedBindings)
) {
const filteredElements = node.importClause.namedBindings.elements.filter(
(element) => {
// This symbol is local (it's declaration points back to the named import)
const symbol = this.typeChecker.getSymbolAtLocation(element.name);
const exportedSymbol =
// This "resolves" the imported type, so we can get to it's declaration(s)
symbol && this.typeChecker.getDeclaredTypeOfSymbol(symbol)?.symbol;
return !exportedSymbol?.declarations.some((decl) =>
this.isDeprecated(decl),
);
},
);
if (
filteredElements.length !==
node.importClause.namedBindings.elements.length
) {
return ts.updateImportDeclaration(
node,
node.decorators,
node.modifiers,
node.importClause.name != null || filteredElements.length > 0
? ts.updateImportClause(
node.importClause,
node.importClause.name,
ts.updateNamedImports(
node.importClause.namedBindings,
filteredElements,
),
node.importClause.isTypeOnly,
)
: undefined,
node.moduleSpecifier,
) as any;
}
return node;
}
// Replace "export ... from ..." places that no longer export anything
// with an "import from ...", so side effects are preserved.
if (ts.isExportDeclaration(node) && node.moduleSpecifier) {
const symbol = this.typeChecker.getSymbolAtLocation(node.moduleSpecifier);
const moduleExports =
symbol &&
this.typeChecker
.getExportsOfModule(symbol)
?.filter(
(sym) => !sym.declarations.some((decl) => this.isDeprecated(decl)),
);
if (
(node.exportClause == null ||
ts.isNamespaceExport(node.exportClause)) &&
moduleExports?.length === 0
) {
return ts.createImportDeclaration(
undefined /* decorators */,
undefined /* modifiers */,
undefined /* importClause */,
node.moduleSpecifier,
) as any;
}
if (node.exportClause != null && moduleExports) {
const bindings = node.exportClause as ts.NamedExports;
const exportedNames = new Set(moduleExports.map((sym) => sym.name));
const filteredElements = bindings.elements?.filter((elt) =>
exportedNames.has(elt.name.text),
);
if (filteredElements?.length !== bindings.elements?.length) {
return ts.updateExportDeclaration(
node,
node.decorators,
node.modifiers,
ts.updateNamedExports(bindings, filteredElements),
node.moduleSpecifier,
node.isTypeOnly,
) as any;
}
}
}
return DeprecationRemovalTransformer.IGNORE_CHILDREN.has(node.kind)
? node
: this.visitEachChild(node);
}