1/* 2 * Copyright (c) 2022 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 { SourceFile, SyntaxKind } from 'typescript'; 17import { firstCharacterToUppercase } from '../common/commonUtils'; 18import { ModuleBlockEntity } from '../declaration-node/moduleDeclaration'; 19import { 20 getDefaultExportClassDeclaration, getSourceFileFunctions, 21 getSourceFileVariableStatements 22} from '../declaration-node/sourceFileElementsAssemply'; 23import { generateClassDeclaration } from './generateClassDeclaration'; 24import { generateCommonFunction } from './generateCommonFunction'; 25import { generateEnumDeclaration } from './generateEnumDeclaration'; 26import { generateImportEqual } from './generateImportEqual'; 27import { addToIndexArray } from './generateIndex'; 28import { generateInterfaceDeclaration } from './generateInterfaceDeclaration'; 29import { generateStaticFunction } from './generateStaticFunction'; 30import { addToSystemIndexArray } from './generateSystemIndex'; 31import { generateTypeAliasDeclaration } from './generateTypeAlias'; 32import { generateVariableStatementDelcatation } from './generateVariableStatementDeclaration'; 33 34/** 35 * generate declare 36 * @param rootName 37 * @param moduleEntity 38 * @param sourceFile 39 * @param filename 40 * @returns 41 */ 42export function generateModuleDeclaration(rootName: string, moduleEntity: ModuleBlockEntity, sourceFile: SourceFile, filename: string): string { 43 const moduleName = moduleEntity.moduleName; 44 const mockNameArr = filename.split('_'); 45 const mockName = mockNameArr[mockNameArr.length - 1]; 46 let moduleBody = `export function mock${firstCharacterToUppercase(mockName)}() {\n`; 47 addToIndexArray({ fileName: filename, mockFunctionName: `mock${firstCharacterToUppercase(mockName)}` }); 48 let outBody = ''; 49 const defaultExportClass = getDefaultExportClassDeclaration(sourceFile); 50 51 if (defaultExportClass.length > 0) { 52 defaultExportClass.forEach(value => { 53 if (value.exportModifiers.includes(SyntaxKind.DefaultKeyword) && value.exportModifiers.includes(SyntaxKind.ExportKeyword)) { 54 if (filename.startsWith('system_')) { 55 const mockNameArr = filename.split('_'); 56 const mockName = mockNameArr[mockNameArr.length - 1]; 57 addToSystemIndexArray({ 58 filename: filename, 59 mockFunctionName: `mock${firstCharacterToUppercase(mockName)}` 60 }); 61 62 moduleBody += `global.systemplugin.${mockName} = {`; 63 if (value.staticMethods.length > 0) { 64 let staticMethodBody = ''; 65 value.staticMethods.forEach(val => { 66 staticMethodBody += generateStaticFunction(val, true, sourceFile) + '\n'; 67 }); 68 moduleBody += staticMethodBody; 69 } 70 moduleBody += '}'; 71 } else { 72 outBody += generateClassDeclaration('', value, false, '', filename, sourceFile, false); 73 } 74 } 75 }); 76 } 77 78 if (moduleEntity.typeAliasDeclarations.length > 0) { 79 moduleEntity.typeAliasDeclarations.forEach(value => { 80 outBody += generateTypeAliasDeclaration(value, true) + '\n'; 81 }); 82 } 83 84 if (moduleEntity.moduleImportEquaqls.length > 0) { 85 moduleEntity.moduleImportEquaqls.forEach(value => { 86 outBody += generateImportEqual(value) + '\n'; 87 }); 88 } 89 90 if (moduleEntity.classDeclarations.length > 0) { 91 moduleEntity.classDeclarations.forEach(value => { 92 if (value.exportModifiers.length > 0 && value.exportModifiers.includes(SyntaxKind.ExportKeyword)) { 93 outBody += generateClassDeclaration(moduleName, value, false, '', '', sourceFile, false) + '\n'; 94 } else { 95 moduleBody += '\t' + generateClassDeclaration(moduleName, value, false, '', '', sourceFile, true) + '\n'; 96 } 97 }); 98 } 99 100 if (moduleEntity.interfaceDeclarations.length > 0) { 101 moduleEntity.interfaceDeclarations.forEach(value => { 102 if (value.exportModifiers.length > 0) { 103 outBody += generateInterfaceDeclaration(moduleName, value, sourceFile, false, moduleEntity.interfaceDeclarations) + ';\n'; 104 } else { 105 moduleBody += '\t' + generateInterfaceDeclaration(moduleName, value, sourceFile, false, moduleEntity.interfaceDeclarations) + ';\n'; 106 } 107 }); 108 } 109 110 if (moduleEntity.enumDeclarations.length > 0) { 111 moduleEntity.enumDeclarations.forEach(value => { 112 if (value.exportModifiers.length > 0) { 113 outBody += generateEnumDeclaration(moduleName, value) + '\n'; 114 } else { 115 moduleBody += '\t' + generateEnumDeclaration(moduleName, value) + '\n'; 116 } 117 }); 118 } 119 120 if (moduleEntity.moduleDeclarations.length > 0) { 121 moduleEntity.moduleDeclarations.forEach(value => { 122 moduleBody += generateInnerModule(value, sourceFile) + '\n'; 123 }); 124 } 125 126 let functionBody = ''; 127 if (moduleEntity.functionDeclarations.size > 0) { 128 moduleEntity.functionDeclarations.forEach(value => { 129 functionBody += '\t' + generateCommonFunction(moduleName, value, sourceFile) + '\n'; 130 }); 131 } 132 133 moduleBody += '\t' + `const ${moduleName} = {`; 134 if (moduleEntity.variableStatements.length > 0) { 135 moduleEntity.variableStatements.forEach(value => { 136 value.forEach(val => { 137 moduleBody += generateVariableStatementDelcatation(val) + '\n'; 138 }); 139 }); 140 } 141 142 const sourceFileFunctions = getSourceFileFunctions(sourceFile); 143 let sourceFileFunctionBody = ''; 144 if (sourceFileFunctions.size > 0) { 145 sourceFileFunctions.forEach(value => { 146 sourceFileFunctionBody += generateCommonFunction(moduleName, value, sourceFile); 147 }); 148 } 149 150 const sourceFileVariableStatements = getSourceFileVariableStatements(sourceFile); 151 let sourceFileStatementBody = ''; 152 if (sourceFileVariableStatements.length > 0) { 153 sourceFileVariableStatements.forEach(value => { 154 value.forEach(val => { 155 sourceFileStatementBody += generateVariableStatementDelcatation(val); 156 }); 157 }); 158 } 159 160 moduleBody += sourceFileFunctionBody + '\n'; 161 moduleBody += sourceFileStatementBody + '\n'; 162 moduleBody += functionBody + '\n'; 163 164 const exports = getModuleExportElements(moduleEntity); 165 let exportString = ''; 166 exports.forEach(value => { 167 exportString += `${value.name}: ${value.name},\n`; 168 }); 169 if (exportString !== '') { 170 moduleBody += '\t' + exportString; 171 } 172 173 moduleBody += '\t};'; 174 moduleBody += `\n\treturn ${moduleName};}\n`; 175 moduleBody += outBody; 176 return moduleBody; 177} 178 179/** 180 * generate inner module 181 * @param moduleEntity 182 * @param sourceFile 183 * @returns 184 */ 185function generateInnerModule(moduleEntity: ModuleBlockEntity, sourceFile: SourceFile): string { 186 const moduleName = moduleEntity.moduleName; 187 let innerModuleBody = `const ${moduleName} = {`; 188 189 if (moduleEntity.typeAliasDeclarations.length > 0) { 190 moduleEntity.typeAliasDeclarations.forEach(value => { 191 innerModuleBody += generateTypeAliasDeclaration(value, true) + '\n'; 192 }); 193 } 194 195 if (moduleEntity.moduleImportEquaqls.length > 0) { 196 moduleEntity.moduleImportEquaqls.forEach(value => { 197 innerModuleBody += generateImportEqual(value) + '\n'; 198 }); 199 } 200 201 if (moduleEntity.interfaceDeclarations.length > 0) { 202 moduleEntity.interfaceDeclarations.forEach(value => { 203 innerModuleBody += generateInterfaceDeclaration(moduleName, value, sourceFile, false, moduleEntity.interfaceDeclarations) + '\n'; 204 }); 205 } 206 207 if (moduleEntity.enumDeclarations.length > 0) { 208 moduleEntity.enumDeclarations.forEach(value => { 209 innerModuleBody += generateEnumDeclaration(moduleName, value) + '\n'; 210 }); 211 } 212 213 let functionBody = ''; 214 if (moduleEntity.functionDeclarations.size > 0) { 215 moduleEntity.functionDeclarations.forEach(value => { 216 functionBody += generateCommonFunction(moduleName, value, sourceFile) + '\n'; 217 }); 218 } 219 220 if (moduleEntity.variableStatements.length > 0) { 221 moduleEntity.variableStatements.forEach(value => { 222 value.forEach(val => { 223 innerModuleBody += generateVariableStatementDelcatation(val) + '\n'; 224 }); 225 }); 226 } 227 innerModuleBody += functionBody + '\n'; 228 229 const exports = getModuleExportElements(moduleEntity); 230 let exportString = ''; 231 exports.forEach(value => { 232 exportString += `${value.name}: ${value.name},\n`; 233 }); 234 if (exportString !== '') { 235 innerModuleBody += '\t' + exportString; 236 } 237 innerModuleBody += '\t};'; 238 return innerModuleBody; 239} 240 241/** 242 * get all export elements 243 * @param moduleEntity 244 * @returns 245 */ 246function getModuleExportElements(moduleEntity: ModuleBlockEntity): Array<ModuleExportEntity> { 247 const exportElements: Array<ModuleExportEntity> = []; 248 if (moduleEntity.classDeclarations.length > 0) { 249 moduleEntity.classDeclarations.forEach(value => { 250 exportElements.push({ name: firstCharacterToUppercase(value.className), type: 'class' }); 251 }); 252 } 253 254 if (moduleEntity.interfaceDeclarations.length > 0) { 255 moduleEntity.interfaceDeclarations.forEach(value => { 256 exportElements.push({ name: value.interfaceName, type: 'interface' }); 257 }); 258 } 259 260 if (moduleEntity.enumDeclarations.length > 0) { 261 moduleEntity.enumDeclarations.forEach(value => { 262 exportElements.push({ name: value.enumName, type: 'enum' }); 263 }); 264 } 265 266 if (moduleEntity.moduleDeclarations.length > 0) { 267 moduleEntity.moduleDeclarations.forEach(value => { 268 exportElements.push({ name: value.moduleName, type: 'module' }); 269 }); 270 } 271 272 if (moduleEntity.typeAliasDeclarations.length > 0) { 273 moduleEntity.typeAliasDeclarations.forEach(value => { 274 exportElements.push({ name: value.typeAliasName, type: 'type' }); 275 }); 276 } 277 return exportElements; 278} 279 280interface ModuleExportEntity { 281 type: string, 282 name: string 283} 284