17c804472Sopenharmony_ci/* 27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 47c804472Sopenharmony_ci * you may not use this file except in compliance with the License. 57c804472Sopenharmony_ci * You may obtain a copy of the License at 67c804472Sopenharmony_ci * 77c804472Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 87c804472Sopenharmony_ci * 97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 127c804472Sopenharmony_ci * See the License for the specific language governing permissions and 137c804472Sopenharmony_ci * limitations under the License. 147c804472Sopenharmony_ci */ 157c804472Sopenharmony_ci 167c804472Sopenharmony_ciimport path from 'path'; 177c804472Sopenharmony_ciimport type { SourceFile } from 'typescript'; 187c804472Sopenharmony_ciimport { SyntaxKind } from 'typescript'; 197c804472Sopenharmony_ciimport { firstCharacterToUppercase } from '../common/commonUtils'; 207c804472Sopenharmony_ciimport type { ClassEntity } from '../declaration-node/classDeclaration'; 217c804472Sopenharmony_ciimport { generateCommonMethod } from './generateCommonMethod'; 227c804472Sopenharmony_ciimport { getWarnConsole } from './generateCommonUtil'; 237c804472Sopenharmony_ciimport { generatePropertyDeclaration } from './generatePropertyDeclaration'; 247c804472Sopenharmony_ciimport { generateStaticFunction } from './generateStaticFunction'; 257c804472Sopenharmony_ciimport { ImportElementEntity } from '../declaration-node/importAndExportDeclaration'; 267c804472Sopenharmony_ciimport { HeritageClauseEntity } from '../declaration-node/heritageClauseDeclaration'; 277c804472Sopenharmony_ci 287c804472Sopenharmony_ciinterface AssemblyClassParams { 297c804472Sopenharmony_ci isSystem: boolean; 307c804472Sopenharmony_ci classEntity: ClassEntity; 317c804472Sopenharmony_ci classBody: string; 327c804472Sopenharmony_ci sourceFile: SourceFile; 337c804472Sopenharmony_ci mockApi: string; 347c804472Sopenharmony_ci isInnerMockFunction: boolean; 357c804472Sopenharmony_ci filename: string; 367c804472Sopenharmony_ci isExtend: boolean; 377c804472Sopenharmony_ci className: string; 387c804472Sopenharmony_ci extraImport?: string[]; 397c804472Sopenharmony_ci importDeclarations?: ImportElementEntity[]; 407c804472Sopenharmony_ci} 417c804472Sopenharmony_ci 427c804472Sopenharmony_ci/** 437c804472Sopenharmony_ci * generate class 447c804472Sopenharmony_ci * @param rootName 457c804472Sopenharmony_ci * @param classEntity 467c804472Sopenharmony_ci * @param isSystem 477c804472Sopenharmony_ci * @param globalName 487c804472Sopenharmony_ci * @param filename 497c804472Sopenharmony_ci * @param sourceFile 507c804472Sopenharmony_ci * @param isInnerMockFunction 517c804472Sopenharmony_ci * @returns 527c804472Sopenharmony_ci */ 537c804472Sopenharmony_ciexport function generateClassDeclaration( 547c804472Sopenharmony_ci rootName: string, 557c804472Sopenharmony_ci classEntity: ClassEntity, 567c804472Sopenharmony_ci isSystem: boolean, 577c804472Sopenharmony_ci globalName: string, 587c804472Sopenharmony_ci filename: string, 597c804472Sopenharmony_ci sourceFile: SourceFile, 607c804472Sopenharmony_ci isInnerMockFunction: boolean, 617c804472Sopenharmony_ci mockApi: string, 627c804472Sopenharmony_ci extraImport?: string[], 637c804472Sopenharmony_ci importDeclarations?: ImportElementEntity[] 647c804472Sopenharmony_ci): string { 657c804472Sopenharmony_ci if (isSystem) { 667c804472Sopenharmony_ci return ''; 677c804472Sopenharmony_ci } 687c804472Sopenharmony_ci 697c804472Sopenharmony_ci const className = firstCharacterToUppercase(classEntity.className); 707c804472Sopenharmony_ci let classBody = ''; 717c804472Sopenharmony_ci if ( 727c804472Sopenharmony_ci (classEntity.exportModifiers.includes(SyntaxKind.ExportKeyword) || 737c804472Sopenharmony_ci classEntity.exportModifiers.includes(SyntaxKind.DeclareKeyword)) && 747c804472Sopenharmony_ci !isInnerMockFunction 757c804472Sopenharmony_ci ) { 767c804472Sopenharmony_ci classBody += `export const ${className} = class ${className} `; 777c804472Sopenharmony_ci } else { 787c804472Sopenharmony_ci classBody += `const ${className} = class ${className} `; 797c804472Sopenharmony_ci } 807c804472Sopenharmony_ci 817c804472Sopenharmony_ci const heritageClausesData = handleClassEntityHeritageClauses(rootName, classEntity, mockApi, sourceFile); 827c804472Sopenharmony_ci const isExtend = heritageClausesData.isExtend; 837c804472Sopenharmony_ci classBody = addCustomeClass(heritageClausesData, sourceFile, importDeclarations) + classBody; 847c804472Sopenharmony_ci classBody += heritageClausesData.classBody; 857c804472Sopenharmony_ci classBody = assemblyClassBody({ 867c804472Sopenharmony_ci isSystem, 877c804472Sopenharmony_ci classEntity, 887c804472Sopenharmony_ci classBody, 897c804472Sopenharmony_ci className, 907c804472Sopenharmony_ci isExtend, 917c804472Sopenharmony_ci sourceFile, 927c804472Sopenharmony_ci mockApi, 937c804472Sopenharmony_ci isInnerMockFunction, 947c804472Sopenharmony_ci filename, 957c804472Sopenharmony_ci extraImport, 967c804472Sopenharmony_ci importDeclarations 977c804472Sopenharmony_ci }); 987c804472Sopenharmony_ci return classBody; 997c804472Sopenharmony_ci} 1007c804472Sopenharmony_ci 1017c804472Sopenharmony_ci/** 1027c804472Sopenharmony_ci * generate some class 1037c804472Sopenharmony_ci * @param porps 1047c804472Sopenharmony_ci * @returns 1057c804472Sopenharmony_ci */ 1067c804472Sopenharmony_cifunction assemblyClassBody(porps: AssemblyClassParams): string { 1077c804472Sopenharmony_ci if (!porps.isSystem) { 1087c804472Sopenharmony_ci porps.classBody += '{'; 1097c804472Sopenharmony_ci if (porps.classEntity.classConstructor.length > 1) { 1107c804472Sopenharmony_ci porps.classBody += 'constructor(...arg) { '; 1117c804472Sopenharmony_ci } else { 1127c804472Sopenharmony_ci porps.classBody += 'constructor() { '; 1137c804472Sopenharmony_ci } 1147c804472Sopenharmony_ci if (porps.isExtend) { 1157c804472Sopenharmony_ci porps.classBody += 'super();\n'; 1167c804472Sopenharmony_ci } 1177c804472Sopenharmony_ci const warnCon = getWarnConsole(porps.className, 'constructor'); 1187c804472Sopenharmony_ci porps.classBody += porps.sourceFile.fileName.endsWith('PermissionRequestResult.d.ts') ? '' : warnCon; 1197c804472Sopenharmony_ci } 1207c804472Sopenharmony_ci if (porps.classEntity.classProperty.length > 0) { 1217c804472Sopenharmony_ci porps.classEntity.classProperty.forEach(value => { 1227c804472Sopenharmony_ci porps.classBody += 1237c804472Sopenharmony_ci generatePropertyDeclaration( 1247c804472Sopenharmony_ci porps.className, 1257c804472Sopenharmony_ci value, 1267c804472Sopenharmony_ci porps.sourceFile, 1277c804472Sopenharmony_ci porps.extraImport, 1287c804472Sopenharmony_ci porps.importDeclarations 1297c804472Sopenharmony_ci ) + '\n'; 1307c804472Sopenharmony_ci }); 1317c804472Sopenharmony_ci } 1327c804472Sopenharmony_ci 1337c804472Sopenharmony_ci if (porps.classEntity.classMethod.size > 0) { 1347c804472Sopenharmony_ci porps.classEntity.classMethod.forEach(value => { 1357c804472Sopenharmony_ci porps.classBody += generateCommonMethod(porps.className, value, porps.sourceFile, porps.mockApi); 1367c804472Sopenharmony_ci }); 1377c804472Sopenharmony_ci } 1387c804472Sopenharmony_ci 1397c804472Sopenharmony_ci porps.classBody += '}\n};'; 1407c804472Sopenharmony_ci porps.classBody = assemblyGlobal(porps); 1417c804472Sopenharmony_ci 1427c804472Sopenharmony_ci if (!porps.filename.startsWith('system_')) { 1437c804472Sopenharmony_ci if (porps.classEntity.staticMethods.length > 0) { 1447c804472Sopenharmony_ci let staticMethodBody = ''; 1457c804472Sopenharmony_ci porps.classEntity.staticMethods.forEach(value => { 1467c804472Sopenharmony_ci staticMethodBody += generateStaticFunction(value, false, porps.sourceFile, porps.mockApi) + '\n'; 1477c804472Sopenharmony_ci }); 1487c804472Sopenharmony_ci porps.classBody += staticMethodBody; 1497c804472Sopenharmony_ci } 1507c804472Sopenharmony_ci } 1517c804472Sopenharmony_ci if (porps.classEntity.exportModifiers.includes(SyntaxKind.DefaultKeyword)) { 1527c804472Sopenharmony_ci porps.classBody += `\nexport default ${porps.className};`; 1537c804472Sopenharmony_ci } 1547c804472Sopenharmony_ci return porps.classBody; 1557c804472Sopenharmony_ci} 1567c804472Sopenharmony_ci 1577c804472Sopenharmony_ci/** 1587c804472Sopenharmony_ci * generate some class 1597c804472Sopenharmony_ci * @param porps 1607c804472Sopenharmony_ci * @returns 1617c804472Sopenharmony_ci */ 1627c804472Sopenharmony_cifunction assemblyGlobal(porps: AssemblyClassParams): string { 1637c804472Sopenharmony_ci if ( 1647c804472Sopenharmony_ci (porps.classEntity.exportModifiers.includes(SyntaxKind.ExportKeyword) || 1657c804472Sopenharmony_ci porps.classEntity.exportModifiers.includes(SyntaxKind.DeclareKeyword)) && 1667c804472Sopenharmony_ci !porps.isInnerMockFunction 1677c804472Sopenharmony_ci ) { 1687c804472Sopenharmony_ci porps.classBody += ` 1697c804472Sopenharmony_ci if (!global.${porps.className}) { 1707c804472Sopenharmony_ci global.${porps.className} = ${porps.className};\n 1717c804472Sopenharmony_ci } 1727c804472Sopenharmony_ci `; 1737c804472Sopenharmony_ci } 1747c804472Sopenharmony_ci return porps.classBody; 1757c804472Sopenharmony_ci} 1767c804472Sopenharmony_ci 1777c804472Sopenharmony_ci/** 1787c804472Sopenharmony_ci * generate class 1797c804472Sopenharmony_ci * @param rootName 1807c804472Sopenharmony_ci * @param classEntity 1817c804472Sopenharmony_ci * @returns 1827c804472Sopenharmony_ci */ 1837c804472Sopenharmony_cifunction handleClassEntityHeritageClauses( 1847c804472Sopenharmony_ci rootName: string, 1857c804472Sopenharmony_ci classEntity: ClassEntity, 1867c804472Sopenharmony_ci mockApi: string, 1877c804472Sopenharmony_ci sourceFile: SourceFile 1887c804472Sopenharmony_ci): { isExtend: boolean; classBody: string } { 1897c804472Sopenharmony_ci let isExtend = false; 1907c804472Sopenharmony_ci let classBody = ''; 1917c804472Sopenharmony_ci if (classEntity.heritageClauses.length > 0) { 1927c804472Sopenharmony_ci classEntity.heritageClauses.forEach(value => { 1937c804472Sopenharmony_ci if (value.clauseToken === 'extends') { 1947c804472Sopenharmony_ci isExtend = true; 1957c804472Sopenharmony_ci classBody += `${value.clauseToken} `; 1967c804472Sopenharmony_ci classBody = generateClassEntityHeritageClauses(classEntity, value, classBody, rootName, mockApi, sourceFile); 1977c804472Sopenharmony_ci } 1987c804472Sopenharmony_ci }); 1997c804472Sopenharmony_ci } 2007c804472Sopenharmony_ci return { 2017c804472Sopenharmony_ci isExtend, 2027c804472Sopenharmony_ci classBody 2037c804472Sopenharmony_ci }; 2047c804472Sopenharmony_ci} 2057c804472Sopenharmony_ci 2067c804472Sopenharmony_ci/** 2077c804472Sopenharmony_ci * generate classEntity heritageClauses 2087c804472Sopenharmony_ci * @param classEntity 2097c804472Sopenharmony_ci * @param value 2107c804472Sopenharmony_ci * @param classBody 2117c804472Sopenharmony_ci * @param rootName 2127c804472Sopenharmony_ci * @param mockApi 2137c804472Sopenharmony_ci * @param sourceFile 2147c804472Sopenharmony_ci * @returns 2157c804472Sopenharmony_ci */ 2167c804472Sopenharmony_cifunction generateClassEntityHeritageClauses( 2177c804472Sopenharmony_ci classEntity: ClassEntity, 2187c804472Sopenharmony_ci value: HeritageClauseEntity, 2197c804472Sopenharmony_ci classBody: string, 2207c804472Sopenharmony_ci rootName: string, 2217c804472Sopenharmony_ci mockApi: string, 2227c804472Sopenharmony_ci sourceFile: SourceFile 2237c804472Sopenharmony_ci): string { 2247c804472Sopenharmony_ci value.types.forEach((val, index) => { 2257c804472Sopenharmony_ci const extendClassName = val.trim().split('<')[0]; 2267c804472Sopenharmony_ci const moduleName = firstCharacterToUppercase(rootName); 2277c804472Sopenharmony_ci if (val.startsWith('Array<')) { 2287c804472Sopenharmony_ci val = 'Array'; 2297c804472Sopenharmony_ci } else { 2307c804472Sopenharmony_ci if (classEntity.exportModifiers.includes(SyntaxKind.ExportKeyword) && rootName !== '') { 2317c804472Sopenharmony_ci val = `mock${moduleName}().${val}`; 2327c804472Sopenharmony_ci } 2337c804472Sopenharmony_ci } 2347c804472Sopenharmony_ci if (index !== value.types.length - 1) { 2357c804472Sopenharmony_ci classBody += `${extendClassName},`; 2367c804472Sopenharmony_ci } else if (val.includes('.')) { 2377c804472Sopenharmony_ci const name = val.split('.')[0]; 2387c804472Sopenharmony_ci if ( 2397c804472Sopenharmony_ci mockApi.includes(`import { mock${firstCharacterToUppercase(name)} }`) && 2407c804472Sopenharmony_ci path.basename(sourceFile.fileName).startsWith('@ohos.') 2417c804472Sopenharmony_ci ) { 2427c804472Sopenharmony_ci classBody += val.replace(name, `mock${firstCharacterToUppercase(name)}()`); 2437c804472Sopenharmony_ci } else { 2447c804472Sopenharmony_ci classBody += `${extendClassName}`; 2457c804472Sopenharmony_ci } 2467c804472Sopenharmony_ci } else { 2477c804472Sopenharmony_ci classBody += `${extendClassName}`; 2487c804472Sopenharmony_ci } 2497c804472Sopenharmony_ci }); 2507c804472Sopenharmony_ci return classBody; 2517c804472Sopenharmony_ci} 2527c804472Sopenharmony_ci 2537c804472Sopenharmony_ci/** 2547c804472Sopenharmony_ci * add custome class 2557c804472Sopenharmony_ci * @param heritageClausesData 2567c804472Sopenharmony_ci * @param sourceFile 2577c804472Sopenharmony_ci * @returns 2587c804472Sopenharmony_ci */ 2597c804472Sopenharmony_cifunction addCustomeClass( 2607c804472Sopenharmony_ci heritageClausesData: { isExtend: boolean; classBody: string }, 2617c804472Sopenharmony_ci sourceFile: SourceFile, 2627c804472Sopenharmony_ci importDeclarations?: ImportElementEntity[] 2637c804472Sopenharmony_ci): string { 2647c804472Sopenharmony_ci if (!heritageClausesData.isExtend) { 2657c804472Sopenharmony_ci return ''; 2667c804472Sopenharmony_ci } 2677c804472Sopenharmony_ci if ( 2687c804472Sopenharmony_ci !path.resolve(sourceFile.fileName).includes(path.join('@internal', 'component', 'ets')) && 2697c804472Sopenharmony_ci path.basename(sourceFile.fileName).startsWith('@ohos.') 2707c804472Sopenharmony_ci ) { 2717c804472Sopenharmony_ci return ''; 2727c804472Sopenharmony_ci } 2737c804472Sopenharmony_ci let mockClassBody = ''; 2747c804472Sopenharmony_ci if (!heritageClausesData.classBody.startsWith('extends ')) { 2757c804472Sopenharmony_ci return mockClassBody; 2767c804472Sopenharmony_ci } 2777c804472Sopenharmony_ci const classArr = heritageClausesData.classBody.split('extends'); 2787c804472Sopenharmony_ci const className = classArr[classArr.length - 1].trim(); 2797c804472Sopenharmony_ci if (className === 'extends') { 2807c804472Sopenharmony_ci return mockClassBody; 2817c804472Sopenharmony_ci } 2827c804472Sopenharmony_ci const removeNoteRegx = /\/\*[\s\S]*?\*\//g; 2837c804472Sopenharmony_ci const fileContent = sourceFile.getText().replace(removeNoteRegx, ''); 2847c804472Sopenharmony_ci let hasImportType = false; 2857c804472Sopenharmony_ci if (importDeclarations) { 2867c804472Sopenharmony_ci importDeclarations.forEach(element => { 2877c804472Sopenharmony_ci if (element.importElements.includes(className)) { 2887c804472Sopenharmony_ci hasImportType = true; 2897c804472Sopenharmony_ci } 2907c804472Sopenharmony_ci }); 2917c804472Sopenharmony_ci } 2927c804472Sopenharmony_ci const regex = new RegExp(`\\sclass\\s*${className}\\s*(<|{|extends|implements)`); 2937c804472Sopenharmony_ci const results = fileContent.match(regex); 2947c804472Sopenharmony_ci if (!results && !hasImportType) { 2957c804472Sopenharmony_ci mockClassBody = `export class ${className} {};\n`; 2967c804472Sopenharmony_ci } 2977c804472Sopenharmony_ci return mockClassBody; 2987c804472Sopenharmony_ci} 299