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: 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 functionDeclarations.push(getFunctionDeclaration(node, sourceFile)); 91 } 92 else { 93 if (node.kind !== SyntaxKind.EndOfFileToken && !isFunctionDeclaration(node) && !isVariableStatement(node)) { 94 console.log('--------------------------- uncaught sourceFile type start -----------------------'); 95 console.log('fileName: ' + fileName); 96 console.log(node); 97 console.log('--------------------------- uncaught sourceFile type end -----------------------'); 98 } 99 } 100 }); 101 102 return { 103 importDeclarations: importDeclarations, 104 moduleDeclarations: moduleDeclarations, 105 typeAliasDeclarations: typeAliasDeclarations, 106 classDeclarations: classDeclarations, 107 interfaceDeclarations: interfaceDeclarations, 108 enumDeclarations: enumDeclarations, 109 exportAssignment: exportAssignment, 110 staticMethods: staticMethods, 111 exportDeclarations: exportDeclarations, 112 functionDeclarations: functionDeclarations, 113 }; 114} 115 116/** 117 * get default export class 118 * @param sourceFile 119 * @returns 120 */ 121export function getDefaultExportClassDeclaration(sourceFile: SourceFile): Array<ClassEntity> { 122 const defaultExportClass: Array<ClassEntity> = []; 123 sourceFile.forEachChild(node => { 124 if (isClassDeclaration(node)) { 125 defaultExportClass.push(getClassDeclaration(node, sourceFile)); 126 } 127 }); 128 return defaultExportClass; 129} 130 131/** 132 * get sourceFile const variable statement 133 * @param sourceFile 134 * @returns 135 */ 136export function getSourceFileVariableStatements(sourceFile: SourceFile): Array<Array<StatementEntity>> { 137 const variableStatements: Array<Array<StatementEntity>> = []; 138 sourceFile.forEachChild(node => { 139 if (isVariableStatement(node)) { 140 variableStatements.push(getVariableStatementDeclaration(node, sourceFile)); 141 } 142 }); 143 return variableStatements; 144} 145 146/** 147 * get sourcefile functions 148 * @param sourceFile 149 * @returns 150 */ 151export function getSourceFileFunctions(sourceFile: SourceFile): Map<string, Array<FunctionEntity>> { 152 const functionDeclarations: Map<string, Array<FunctionEntity>> = new Map<string, Array<FunctionEntity>>(); 153 sourceFile.forEachChild(node => { 154 if (isFunctionDeclaration(node)) { 155 const functionEntity = getFunctionDeclaration(node, sourceFile); 156 if (functionDeclarations.get(functionEntity.functionName) !== undefined) { 157 functionDeclarations.get(functionEntity.functionName)?.push(functionEntity); 158 } else { 159 const functionArray: Array<FunctionEntity> = []; 160 functionArray.push(functionEntity); 161 functionDeclarations.set(functionEntity.functionName, functionArray); 162 } 163 } 164 }); 165 return functionDeclarations; 166} 167 168export interface SourceFileEntity { 169 importDeclarations: Array<ImportElementEntity>, 170 moduleDeclarations: Array<ModuleBlockEntity>, 171 typeAliasDeclarations: Array<TypeAliasEntity>, 172 classDeclarations: Array<ClassEntity>, 173 interfaceDeclarations: Array<InterfaceEntity>, 174 enumDeclarations: Array<EnumEntity>, 175 exportAssignment: Array<string>, 176 staticMethods: Array<Array<StaticMethodEntity>>, 177 exportDeclarations: Array<string>, 178 functionDeclarations: Array<FunctionEntity> 179} 180