1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import * as ts from "typescript"; 17 18export function exportAllTransformer(): ts.TransformerFactory<ts.SourceFile> { 19 return (context) => { 20 return (sourceFile) => { 21 const exportModifier = ts.factory.createModifier(ts.SyntaxKind.ExportKeyword); 22 23 const visitor = (node: ts.Node): ts.Node => { 24 if (isTopLevelExportable(node)) { 25 const modifiers = ts.getModifiers(node as ts.HasModifiers) || []; 26 if (!hasExportModifier(modifiers)) { 27 const newNode = updateNodeWithExport(node, modifiers, exportModifier); 28 return newNode || node; 29 } 30 } 31 return ts.visitEachChild(node, visitor, context); 32 }; 33 34 return ts.visitNode(sourceFile, visitor); 35 }; 36 }; 37} 38 39function isTopLevelExportable(node: ts.Node): boolean { 40 return ts.isFunctionDeclaration(node) || 41 ts.isClassDeclaration(node) || 42 ts.isVariableStatement(node) || 43 ts.isInterfaceDeclaration(node) || 44 ts.isTypeAliasDeclaration(node) || 45 ts.isEnumDeclaration(node) || 46 ts.isModuleDeclaration(node); 47} 48 49function hasExportModifier(modifiers: readonly ts.Modifier[]): boolean { 50 return modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword); 51} 52 53function hasDeclareModifier(modifiers: readonly ts.Modifier[]): boolean { 54 return modifiers.some(m => m.kind === ts.SyntaxKind.DeclareKeyword); 55} 56 57function handleClassModifiers(existingModifiers: readonly ts.Modifier[]): ts.Modifier[] { 58 const newModifiers = [...existingModifiers] 59 if (!hasDeclareModifier(existingModifiers)) { 60 newModifiers.unshift(ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)); 61 } 62 if (!hasExportModifier(existingModifiers)) { 63 newModifiers.unshift(ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)); 64 } 65 return newModifiers; 66} 67 68function updateNodeWithExport( 69 node: ts.Node, 70 existingModifiers: readonly ts.Modifier[], 71 exportModifier: ts.Modifier 72): ts.Node { 73 const newModifiers = [exportModifier, ...existingModifiers]; 74 75 switch (node.kind) { 76 case ts.SyntaxKind.VariableStatement: 77 return ts.factory.updateVariableStatement( 78 node as ts.VariableStatement, 79 newModifiers, 80 (node as ts.VariableStatement).declarationList 81 ); 82 83 case ts.SyntaxKind.FunctionDeclaration: 84 const func = node as ts.FunctionDeclaration; 85 return ts.factory.updateFunctionDeclaration( 86 func, 87 newModifiers, 88 func.asteriskToken, 89 func.name, 90 func.typeParameters, 91 func.parameters, 92 func.type, 93 func.body 94 ); 95 96 case ts.SyntaxKind.ClassDeclaration: 97 const cls = node as ts.ClassDeclaration; 98 return ts.factory.updateClassDeclaration( 99 cls, 100 handleClassModifiers(existingModifiers), 101 cls.name, 102 cls.typeParameters, 103 cls.heritageClauses, 104 cls.members 105 ); 106 107 case ts.SyntaxKind.InterfaceDeclaration: 108 const intf = node as ts.InterfaceDeclaration; 109 return ts.factory.updateInterfaceDeclaration( 110 intf, 111 newModifiers, 112 intf.name, 113 intf.typeParameters, 114 intf.heritageClauses, 115 intf.members 116 ); 117 118 case ts.SyntaxKind.TypeAliasDeclaration: 119 const type = node as ts.TypeAliasDeclaration; 120 return ts.factory.updateTypeAliasDeclaration( 121 type, 122 newModifiers.filter(m => m.kind !== ts.SyntaxKind.DeclareKeyword), 123 type.name, 124 type.typeParameters, 125 type.type 126 ); 127 128 case ts.SyntaxKind.EnumDeclaration: 129 const enm = node as ts.EnumDeclaration; 130 return ts.factory.updateEnumDeclaration( 131 enm, 132 newModifiers, 133 enm.name, 134 enm.members 135 ); 136 137 case ts.SyntaxKind.ModuleDeclaration: 138 const mod = node as ts.ModuleDeclaration; 139 return ts.factory.updateModuleDeclaration( 140 mod, 141 newModifiers, 142 mod.name, 143 mod.body 144 ); 145 146 default: 147 return node; 148 } 149}