1/* 2 * Copyright (c) 2023 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 { 17 isClassDeclaration, isEnumDeclaration, isExportAssignment, isExportDeclaration, isFunctionDeclaration, 18 isImportDeclaration, isInterfaceDeclaration, isModuleDeclaration, isTypeAliasDeclaration, isVariableStatement, 19 SyntaxKind 20} from 'typescript'; 21import type { SourceFile } from 'typescript'; 22import { getClassDeclaration } from './classDeclaration'; 23import type { ClassEntity } from './classDeclaration'; 24import { getEnumDeclaration } from './enumDeclaration'; 25import type { EnumEntity } from './enumDeclaration'; 26import { getFunctionDeclaration } from './functionDeclaration'; 27import type { FunctionEntity } from './functionDeclaration'; 28import { getExportAssignment, getImportDeclaration } from './importAndExportDeclaration'; 29import type { ImportElementEntity } from './importAndExportDeclaration'; 30import { getInterfaceDeclaration } from './interfaceDeclaration'; 31import type { InterfaceEntity } from './interfaceDeclaration'; 32import type { StaticMethodEntity } from './methodDeclaration'; 33import { getModuleDeclaration } from './moduleDeclaration'; 34import type { ModuleBlockEntity } from './moduleDeclaration'; 35import { getTypeAliasDeclaration } from './typeAliasDeclaration'; 36import type { TypeAliasEntity } from './typeAliasDeclaration'; 37import { getVariableStatementDeclaration } from './variableStatementResolve'; 38import type { StatementEntity } from './variableStatementResolve'; 39 40/** 41 * assembly all sourceFile node info 42 * @param sourceFile 43 * @param fileName 44 * @returns 45 */ 46export function getSourceFileAssembly(sourceFile: SourceFile, fileName: string): SourceFileEntity { 47 const importDeclarations: Array<ImportElementEntity> = []; 48 const moduleDeclarations: Array<ModuleBlockEntity> = []; 49 const typeAliasDeclarations: Array<TypeAliasEntity> = []; 50 const classDeclarations: Array<ClassEntity> = []; 51 const interfaceDeclarations: Array<InterfaceEntity> = []; 52 const enumDeclarations: Array<EnumEntity> = []; 53 let exportAssignment: Array<string> = []; 54 const staticMethods: Array<Array<StaticMethodEntity>> = []; 55 const exportDeclarations: Array<string> = []; 56 const functionDeclarations: Map<string, Array<FunctionEntity>> = new Map<string, Array<FunctionEntity>>(); 57 58 sourceFile.forEachChild(node => { 59 if (isImportDeclaration(node)) { 60 importDeclarations.push(getImportDeclaration(node, sourceFile)); 61 } else if (isModuleDeclaration(node)) { 62 moduleDeclarations.push(getModuleDeclaration(node, sourceFile, fileName)); 63 } else if (isTypeAliasDeclaration(node)) { 64 typeAliasDeclarations.push(getTypeAliasDeclaration(node, sourceFile)); 65 } else if (isClassDeclaration(node)) { 66 let isDefaultExportClass = false; 67 if (node.modifiers !== undefined) { 68 node.modifiers.forEach(value => { 69 if (value.kind === SyntaxKind.DefaultKeyword) { 70 isDefaultExportClass = true; 71 } 72 }); 73 } 74 if (isDefaultExportClass) { 75 const classDeclarationEntity = getClassDeclaration(node, sourceFile); 76 classDeclarations.push(classDeclarationEntity); 77 if (classDeclarationEntity.staticMethods.length > 0) { 78 staticMethods.push(classDeclarationEntity.staticMethods); 79 } 80 } 81 } else if (isInterfaceDeclaration(node)) { 82 interfaceDeclarations.push(getInterfaceDeclaration(node, sourceFile)); 83 } else if (isExportAssignment(node)) { 84 exportAssignment = getExportAssignment(node, sourceFile); 85 } else if (isEnumDeclaration(node)) { 86 enumDeclarations.push(getEnumDeclaration(node, sourceFile)); 87 } else if (isExportDeclaration(node)) { 88 exportDeclarations.push(sourceFile.text.substring(node.pos, node.end).trimStart().trimEnd()); 89 } else if (isFunctionDeclaration(node)) { 90 const functionEntity = getFunctionDeclaration(node, sourceFile); 91 if (functionDeclarations.get(functionEntity.functionName) !== undefined) { 92 functionDeclarations.get(functionEntity.functionName)?.push(functionEntity); 93 } else { 94 const functionArray: Array<FunctionEntity> = []; 95 functionArray.push(functionEntity); 96 functionDeclarations.set(functionEntity.functionName, functionArray); 97 } 98 } else { 99 if (node.kind !== SyntaxKind.EndOfFileToken && !isFunctionDeclaration(node) && !isVariableStatement(node)) { 100 console.log('--------------------------- uncaught sourceFile type start -----------------------'); 101 console.log('fileName: ' + fileName); 102 console.log(node); 103 console.log('--------------------------- uncaught sourceFile type end -----------------------'); 104 } 105 } 106 }); 107 108 return { 109 importDeclarations: importDeclarations, 110 moduleDeclarations: moduleDeclarations, 111 typeAliasDeclarations: typeAliasDeclarations, 112 classDeclarations: classDeclarations, 113 interfaceDeclarations: interfaceDeclarations, 114 enumDeclarations: enumDeclarations, 115 exportAssignment: exportAssignment, 116 staticMethods: staticMethods, 117 exportDeclarations: exportDeclarations, 118 functionDeclarations: functionDeclarations, 119 }; 120} 121 122/** 123 * get default export class 124 * @param sourceFile 125 * @returns 126 */ 127export function getDefaultExportClassDeclaration(sourceFile: SourceFile): Array<ClassEntity> { 128 const defaultExportClass: Array<ClassEntity> = []; 129 sourceFile.forEachChild(node => { 130 if (isClassDeclaration(node)) { 131 defaultExportClass.push(getClassDeclaration(node, sourceFile)); 132 } 133 }); 134 return defaultExportClass; 135} 136 137/** 138 * get sourceFile const variable statement 139 * @param sourceFile 140 * @returns 141 */ 142export function getSourceFileVariableStatements(sourceFile: SourceFile): Array<Array<StatementEntity>> { 143 const variableStatements: Array<Array<StatementEntity>> = []; 144 sourceFile.forEachChild(node => { 145 if (isVariableStatement(node)) { 146 variableStatements.push(getVariableStatementDeclaration(node, sourceFile)); 147 } 148 }); 149 return variableStatements; 150} 151 152/** 153 * get sourcefile functions 154 * @param sourceFile 155 * @returns 156 */ 157export function getSourceFileFunctions(sourceFile: SourceFile): Map<string, Array<FunctionEntity>> { 158 const functionDeclarations: Map<string, Array<FunctionEntity>> = new Map<string, Array<FunctionEntity>>(); 159 sourceFile.forEachChild(node => { 160 if (isFunctionDeclaration(node)) { 161 const functionEntity = getFunctionDeclaration(node, sourceFile); 162 if (functionDeclarations.get(functionEntity.functionName) !== undefined) { 163 functionDeclarations.get(functionEntity.functionName)?.push(functionEntity); 164 } else { 165 const functionArray: Array<FunctionEntity> = []; 166 functionArray.push(functionEntity); 167 functionDeclarations.set(functionEntity.functionName, functionArray); 168 } 169 } 170 }); 171 return functionDeclarations; 172} 173 174export interface SourceFileEntity { 175 importDeclarations: Array<ImportElementEntity>, 176 moduleDeclarations: Array<ModuleBlockEntity>, 177 typeAliasDeclarations: Array<TypeAliasEntity>, 178 classDeclarations: Array<ClassEntity>, 179 interfaceDeclarations: Array<InterfaceEntity>, 180 enumDeclarations: Array<EnumEntity>, 181 exportAssignment: Array<string>, 182 staticMethods: Array<Array<StaticMethodEntity>>, 183 exportDeclarations: Array<string>, 184 functionDeclarations: Map<string, Array<FunctionEntity>> 185} 186