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 type { SourceFile } from 'typescript'; 17import { SyntaxKind } from 'typescript'; 18import { firstCharacterToUppercase } from '../common/commonUtils'; 19import type { ClassEntity } from '../declaration-node/classDeclaration'; 20import { generateCommonMethod } from './generateCommonMethod'; 21import { getWarnConsole } from './generateCommonUtil'; 22import { generatePropertyDeclaration } from './generatePropertyDeclaration'; 23import { generateStaticFunction } from './generateStaticFunction'; 24 25/** 26 * generate class 27 * @param rootName 28 * @param classEntity 29 * @param isSystem 30 * @param globalName 31 * @param filename 32 * @param sourceFile 33 * @param isInnerMockFunction 34 * @returns 35 */ 36export function generateClassDeclaration(rootName: string, classEntity: ClassEntity, isSystem: boolean, globalName: string, 37 filename: string, sourceFile: SourceFile, isInnerMockFunction: boolean, mockApi: string): string { 38 if (isSystem) { 39 return ''; 40 } 41 42 const className = firstCharacterToUppercase(classEntity.className); 43 let classBody = ''; 44 if ((classEntity.exportModifiers.includes(SyntaxKind.ExportKeyword) || 45 classEntity.exportModifiers.includes(SyntaxKind.DeclareKeyword)) && 46 !isInnerMockFunction) { 47 classBody += `export const ${className} = class ${className} `; 48 } else { 49 classBody += `const ${className} = class ${className} `; 50 } 51 52 const heritageClausesData = handleClassEntityHeritageClauses(rootName, classEntity); 53 const isExtend = heritageClausesData.isExtend; 54 classBody += heritageClausesData.classBody; 55 56 if (!isSystem) { 57 classBody += '{'; 58 if (classEntity.classConstructor.length > 1) { 59 classBody += 'constructor(...arg) { '; 60 } else { 61 classBody += 'constructor() { '; 62 } 63 if (isExtend) { 64 classBody += 'super();\n'; 65 } 66 classBody += sourceFile.fileName.endsWith('PermissionRequestResult.d.ts') ? '' : getWarnConsole(className, 'constructor'); 67 } 68 if (classEntity.classProperty.length > 0) { 69 classEntity.classProperty.forEach(value => { 70 classBody += generatePropertyDeclaration(className, value, sourceFile) + '\n'; 71 }); 72 } 73 74 if (classEntity.classMethod.size > 0) { 75 classEntity.classMethod.forEach(value => { 76 classBody += generateCommonMethod(className, value, sourceFile, mockApi); 77 }); 78 } 79 80 classBody += '}\n};'; 81 if ( 82 (classEntity.exportModifiers.includes(SyntaxKind.ExportKeyword) || 83 classEntity.exportModifiers.includes(SyntaxKind.DeclareKeyword)) && 84 !isInnerMockFunction 85 ) { 86 classBody += ` 87 if (!global.${className}) { 88 global.${className} = ${className};\n 89 } 90 `; 91 } 92 if (!filename.startsWith('system_')) { 93 if (classEntity.staticMethods.length > 0) { 94 let staticMethodBody = ''; 95 classEntity.staticMethods.forEach(value => { 96 staticMethodBody += generateStaticFunction(value, false, sourceFile, mockApi) + '\n'; 97 }); 98 classBody += staticMethodBody; 99 } 100 } 101 if (classEntity.exportModifiers.includes(SyntaxKind.DefaultKeyword)) { 102 classBody += `\nexport default ${className};`; 103 } 104 return classBody; 105} 106 107/** 108 * generate class 109 * @param rootName 110 * @param classEntity 111 * @returns 112 */ 113function handleClassEntityHeritageClauses(rootName: string, classEntity: ClassEntity): { isExtend: boolean, classBody: string } { 114 let isExtend = false; 115 let classBody = ''; 116 if (classEntity.heritageClauses.length > 0) { 117 classEntity.heritageClauses.forEach(value => { 118 if (value.clauseToken === 'extends') { 119 isExtend = true; 120 classBody += `${value.clauseToken} `; 121 value.types.forEach((val, index) => { 122 const extendClassName = val.split('<')[0]; 123 const moduleName = firstCharacterToUppercase(rootName); 124 if (val.startsWith('Array<')) { 125 val = 'Array'; 126 } else { 127 if (classEntity.exportModifiers.includes(SyntaxKind.ExportKeyword) && rootName !== '') { 128 val = `mock${moduleName}().${val}`; 129 } 130 } 131 if (index !== value.types.length - 1) { 132 classBody += `${extendClassName},`; 133 } else { 134 classBody += val === 'uri.URI' ? 'mockUri().URI' : `${extendClassName}`; 135 } 136 }); 137 } 138 }); 139 } 140 return { 141 isExtend, 142 classBody 143 }; 144} 145