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 fs from 'fs'; 177c804472Sopenharmony_ciimport path from 'path'; 187c804472Sopenharmony_ciimport type { SourceFile } from 'typescript'; 197c804472Sopenharmony_ciimport { SyntaxKind } from 'typescript'; 207c804472Sopenharmony_ciimport type { InterfaceEntity } from '../declaration-node/interfaceDeclaration'; 217c804472Sopenharmony_ciimport { generateCommonMethodSignature } from './generateCommonMethodSignature'; 227c804472Sopenharmony_ciimport { generateIndexSignature } from './generateIndexSignature'; 237c804472Sopenharmony_ciimport { generatePropertySignatureDeclaration } from './generatePropertySignatureDeclaration'; 247c804472Sopenharmony_ciimport { dtsFileList, getApiInputPath, hasBeenImported, specialFiles } from '../common/commonUtils'; 257c804472Sopenharmony_ciimport type { ImportElementEntity } from '../declaration-node/importAndExportDeclaration'; 267c804472Sopenharmony_ciimport type { PropertySignatureEntity } from '../declaration-node/propertySignatureDeclaration'; 277c804472Sopenharmony_ci 287c804472Sopenharmony_ci/** 297c804472Sopenharmony_ci * generate interface 307c804472Sopenharmony_ci * @param interfaceEntity 317c804472Sopenharmony_ci * @param sourceFile 327c804472Sopenharmony_ci * @param isSourceFile 337c804472Sopenharmony_ci * @returns 347c804472Sopenharmony_ci */ 357c804472Sopenharmony_ciexport function generateInterfaceDeclaration( 367c804472Sopenharmony_ci interfaceEntity: InterfaceEntity, 377c804472Sopenharmony_ci sourceFile: SourceFile, 387c804472Sopenharmony_ci isSourceFile: boolean, 397c804472Sopenharmony_ci mockApi: string, 407c804472Sopenharmony_ci currentSourceInterfaceArray: InterfaceEntity[], 417c804472Sopenharmony_ci importDeclarations?: ImportElementEntity[], 427c804472Sopenharmony_ci extraImport?: string[] 437c804472Sopenharmony_ci): string { 447c804472Sopenharmony_ci const interfaceName = interfaceEntity.interfaceName; 457c804472Sopenharmony_ci let interfaceBody = ''; 467c804472Sopenharmony_ci let interfaceElementSet = new Set<string>(); 477c804472Sopenharmony_ci if (interfaceEntity.exportModifiers.length > 0 || isSourceFile) { 487c804472Sopenharmony_ci interfaceBody += `export const ${interfaceName} = { \n`; 497c804472Sopenharmony_ci } else { 507c804472Sopenharmony_ci interfaceBody += `const ${interfaceName} = { \n`; 517c804472Sopenharmony_ci } 527c804472Sopenharmony_ci if (interfaceEntity.interfacePropertySignatures.length > 0) { 537c804472Sopenharmony_ci const isAddExtraImportReturn = isNeedAddExtraImport(interfaceEntity, interfaceBody, interfaceName, mockApi, sourceFile, 547c804472Sopenharmony_ci interfaceElementSet, extraImport, importDeclarations); 557c804472Sopenharmony_ci interfaceElementSet = isAddExtraImportReturn.interfaceElementSet; 567c804472Sopenharmony_ci interfaceBody = isAddExtraImportReturn.interfaceBody; 577c804472Sopenharmony_ci } 587c804472Sopenharmony_ci if (interfaceEntity.interfaceMethodSignature.size > 0) { 597c804472Sopenharmony_ci interfaceEntity.interfaceMethodSignature.forEach(value => { 607c804472Sopenharmony_ci interfaceBody += generateCommonMethodSignature(interfaceName, value, sourceFile, mockApi) + '\n'; 617c804472Sopenharmony_ci interfaceElementSet.add(value[0].functionName); 627c804472Sopenharmony_ci }); 637c804472Sopenharmony_ci } 647c804472Sopenharmony_ci if (extraImport.length > 0) { 657c804472Sopenharmony_ci for (let i = 0; i < extraImport.length; i++) { 667c804472Sopenharmony_ci if (mockApi.includes(extraImport[i])) { 677c804472Sopenharmony_ci extraImport.splice(i, 1); 687c804472Sopenharmony_ci } 697c804472Sopenharmony_ci } 707c804472Sopenharmony_ci } 717c804472Sopenharmony_ci if (interfaceEntity.indexSignature.length > 0) { 727c804472Sopenharmony_ci interfaceEntity.indexSignature.forEach(value => { 737c804472Sopenharmony_ci interfaceBody += generateIndexSignature(value) + '\n'; 747c804472Sopenharmony_ci interfaceElementSet.add(value.indexSignatureKey); 757c804472Sopenharmony_ci }); 767c804472Sopenharmony_ci } 777c804472Sopenharmony_ci interfaceBody = assemblyInterface(interfaceEntity, currentSourceInterfaceArray, interfaceBody, 787c804472Sopenharmony_ci sourceFile, interfaceElementSet, mockApi, interfaceName); 797c804472Sopenharmony_ci return interfaceBody; 807c804472Sopenharmony_ci} 817c804472Sopenharmony_ci 827c804472Sopenharmony_ci/** 837c804472Sopenharmony_ci * @param interfaceEntity 847c804472Sopenharmony_ci * @param interfaceBody 857c804472Sopenharmony_ci * @param interfaceName 867c804472Sopenharmony_ci * @param mockApi 877c804472Sopenharmony_ci * @param sourceFile 887c804472Sopenharmony_ci * @param interfaceElementSet 897c804472Sopenharmony_ci * @param extraImport 907c804472Sopenharmony_ci * @param importDeclarations 917c804472Sopenharmony_ci * @returns 927c804472Sopenharmony_ci */ 937c804472Sopenharmony_cifunction isNeedAddExtraImport( 947c804472Sopenharmony_ci interfaceEntity: InterfaceEntity, 957c804472Sopenharmony_ci interfaceBody: string, 967c804472Sopenharmony_ci interfaceName: string, 977c804472Sopenharmony_ci mockApi: string, 987c804472Sopenharmony_ci sourceFile: SourceFile, 997c804472Sopenharmony_ci interfaceElementSet: Set<string>, 1007c804472Sopenharmony_ci extraImport: string[], 1017c804472Sopenharmony_ci importDeclarations: ImportElementEntity[] 1027c804472Sopenharmony_ci): { interfaceBody: string; interfaceElementSet: Set<string> } { 1037c804472Sopenharmony_ci interfaceEntity.interfacePropertySignatures.forEach(value => { 1047c804472Sopenharmony_ci interfaceBody += generatePropertySignatureDeclaration(interfaceName, value, sourceFile, mockApi) + '\n'; 1057c804472Sopenharmony_ci interfaceElementSet.add(value.propertyName); 1067c804472Sopenharmony_ci if (!value.propertyTypeName.includes(' ')) { 1077c804472Sopenharmony_ci // Find out whether the value.propertyTypeName was introduced through import. 1087c804472Sopenharmony_ci const regex = new RegExp(`import[\\s\n]*?{?[\\s\n]*?${value.propertyTypeName}[,\\s\n]*?`); 1097c804472Sopenharmony_ci const results = mockApi.match(regex); 1107c804472Sopenharmony_ci if (results) { 1117c804472Sopenharmony_ci return; 1127c804472Sopenharmony_ci } 1137c804472Sopenharmony_ci let temp = false; 1147c804472Sopenharmony_ci importDeclarations.forEach(element => { 1157c804472Sopenharmony_ci // Determine whether the external variable introduced by import contains value.propertyTypeName. 1167c804472Sopenharmony_ci if ( 1177c804472Sopenharmony_ci element.importPath.startsWith('\'@ohos') && 1187c804472Sopenharmony_ci element.importElements.match(new RegExp(`[\\s\n]*${value.propertyTypeName}[,\\s\n]*`)) 1197c804472Sopenharmony_ci ) { 1207c804472Sopenharmony_ci temp = true; 1217c804472Sopenharmony_ci } 1227c804472Sopenharmony_ci }); 1237c804472Sopenharmony_ci if (temp) { 1247c804472Sopenharmony_ci return; 1257c804472Sopenharmony_ci } 1267c804472Sopenharmony_ci } 1277c804472Sopenharmony_ci addExtraImport(extraImport, importDeclarations, sourceFile, value); 1287c804472Sopenharmony_ci }); 1297c804472Sopenharmony_ci return { 1307c804472Sopenharmony_ci interfaceBody, 1317c804472Sopenharmony_ci interfaceElementSet 1327c804472Sopenharmony_ci }; 1337c804472Sopenharmony_ci} 1347c804472Sopenharmony_ci 1357c804472Sopenharmony_cifunction assemblyInterface( 1367c804472Sopenharmony_ci interfaceEntity: InterfaceEntity, 1377c804472Sopenharmony_ci currentSourceInterfaceArray: InterfaceEntity[], 1387c804472Sopenharmony_ci interfaceBody: string, 1397c804472Sopenharmony_ci sourceFile: SourceFile, 1407c804472Sopenharmony_ci interfaceElementSet: Set<string>, 1417c804472Sopenharmony_ci mockApi: string, 1427c804472Sopenharmony_ci interfaceName: string 1437c804472Sopenharmony_ci): string { 1447c804472Sopenharmony_ci if (interfaceEntity.heritageClauses.length > 0) { 1457c804472Sopenharmony_ci interfaceEntity.heritageClauses.forEach(value => { 1467c804472Sopenharmony_ci currentSourceInterfaceArray.forEach(currentInterface => { 1477c804472Sopenharmony_ci if (value.types.includes(currentInterface.interfaceName)) { 1487c804472Sopenharmony_ci interfaceBody += generateHeritageInterface(currentInterface, sourceFile, interfaceElementSet, mockApi); 1497c804472Sopenharmony_ci } 1507c804472Sopenharmony_ci }); 1517c804472Sopenharmony_ci }); 1527c804472Sopenharmony_ci } 1537c804472Sopenharmony_ci interfaceBody += '}\n'; 1547c804472Sopenharmony_ci if (interfaceEntity.exportModifiers.includes(SyntaxKind.DeclareKeyword)) { 1557c804472Sopenharmony_ci interfaceBody += ` 1567c804472Sopenharmony_ci if (!global.${interfaceName}) { 1577c804472Sopenharmony_ci global.${interfaceName} = ${interfaceName};\n 1587c804472Sopenharmony_ci } 1597c804472Sopenharmony_ci `; 1607c804472Sopenharmony_ci } 1617c804472Sopenharmony_ci return interfaceBody; 1627c804472Sopenharmony_ci} 1637c804472Sopenharmony_ci 1647c804472Sopenharmony_cifunction generateHeritageInterface( 1657c804472Sopenharmony_ci interfaceEntity: InterfaceEntity, 1667c804472Sopenharmony_ci sourceFile: SourceFile, 1677c804472Sopenharmony_ci elements: Set<string>, 1687c804472Sopenharmony_ci mockApi: string 1697c804472Sopenharmony_ci): string { 1707c804472Sopenharmony_ci const interfaceName = interfaceEntity.interfaceName; 1717c804472Sopenharmony_ci let interfaceBody = ''; 1727c804472Sopenharmony_ci if (interfaceEntity.interfacePropertySignatures.length > 0) { 1737c804472Sopenharmony_ci interfaceEntity.interfacePropertySignatures.forEach(value => { 1747c804472Sopenharmony_ci if (!elements.has(value.propertyName)) { 1757c804472Sopenharmony_ci interfaceBody += generatePropertySignatureDeclaration(interfaceName, value, sourceFile, mockApi) + '\n'; 1767c804472Sopenharmony_ci } 1777c804472Sopenharmony_ci }); 1787c804472Sopenharmony_ci } 1797c804472Sopenharmony_ci 1807c804472Sopenharmony_ci if (interfaceEntity.interfaceMethodSignature.size > 0) { 1817c804472Sopenharmony_ci interfaceEntity.interfaceMethodSignature.forEach(value => { 1827c804472Sopenharmony_ci if (!elements.has(value[0].functionName)) { 1837c804472Sopenharmony_ci interfaceBody += generateCommonMethodSignature(interfaceName, value, sourceFile, mockApi) + '\n'; 1847c804472Sopenharmony_ci } 1857c804472Sopenharmony_ci }); 1867c804472Sopenharmony_ci } 1877c804472Sopenharmony_ci 1887c804472Sopenharmony_ci if (interfaceEntity.indexSignature.length > 0) { 1897c804472Sopenharmony_ci interfaceEntity.indexSignature.forEach(value => { 1907c804472Sopenharmony_ci if (elements.has(value.indexSignatureKey)) { 1917c804472Sopenharmony_ci interfaceBody += generateIndexSignature(value) + '\n'; 1927c804472Sopenharmony_ci } 1937c804472Sopenharmony_ci }); 1947c804472Sopenharmony_ci } 1957c804472Sopenharmony_ci return interfaceBody; 1967c804472Sopenharmony_ci} 1977c804472Sopenharmony_ci 1987c804472Sopenharmony_ci/** 1997c804472Sopenharmony_ci * @param extraImport 2007c804472Sopenharmony_ci * @param importDeclarations 2017c804472Sopenharmony_ci * @param sourceFile 2027c804472Sopenharmony_ci * @param value 2037c804472Sopenharmony_ci * @returns 2047c804472Sopenharmony_ci */ 2057c804472Sopenharmony_ciexport function addExtraImport( 2067c804472Sopenharmony_ci extraImport: string[], 2077c804472Sopenharmony_ci importDeclarations: ImportElementEntity[], 2087c804472Sopenharmony_ci sourceFile: SourceFile, 2097c804472Sopenharmony_ci value: PropertySignatureEntity 2107c804472Sopenharmony_ci): void { 2117c804472Sopenharmony_ci if (extraImport && importDeclarations) { 2127c804472Sopenharmony_ci const propertyTypeName = value.propertyTypeName.split('.')[0].split('|')[0].split('&')[0].replace(/"'/g, '').trim(); 2137c804472Sopenharmony_ci if (propertyTypeName.includes('/')) { 2147c804472Sopenharmony_ci return; 2157c804472Sopenharmony_ci } 2167c804472Sopenharmony_ci if (hasBeenImported(importDeclarations, propertyTypeName)) { 2177c804472Sopenharmony_ci return; 2187c804472Sopenharmony_ci } 2197c804472Sopenharmony_ci const specialFilesList = [ 2207c804472Sopenharmony_ci ...specialFiles.map(specialFile => path.join(getApiInputPath(), ...specialFile.split('/'))) 2217c804472Sopenharmony_ci ]; 2227c804472Sopenharmony_ci if (!specialFilesList.includes(sourceFile.fileName)) { 2237c804472Sopenharmony_ci specialFilesList.unshift(sourceFile.fileName); 2247c804472Sopenharmony_ci } 2257c804472Sopenharmony_ci searchHasExtraImport(specialFilesList, propertyTypeName, sourceFile, extraImport); 2267c804472Sopenharmony_ci } 2277c804472Sopenharmony_ci} 2287c804472Sopenharmony_ci 2297c804472Sopenharmony_ci/** 2307c804472Sopenharmony_ci * @param specialFilesList 2317c804472Sopenharmony_ci * @param propertyTypeName 2327c804472Sopenharmony_ci * @param sourceFile 2337c804472Sopenharmony_ci * @param extraImport 2347c804472Sopenharmony_ci * @returns 2357c804472Sopenharmony_ci */ 2367c804472Sopenharmony_cifunction searchHasExtraImport( 2377c804472Sopenharmony_ci specialFilesList: string[], 2387c804472Sopenharmony_ci propertyTypeName: string, 2397c804472Sopenharmony_ci sourceFile: SourceFile, 2407c804472Sopenharmony_ci extraImport: string[] 2417c804472Sopenharmony_ci): void { 2427c804472Sopenharmony_ci for (let i = 0; i < specialFilesList.length; i++) { 2437c804472Sopenharmony_ci const specialFilePath = specialFilesList[i]; 2447c804472Sopenharmony_ci if (!fs.existsSync(specialFilePath)) { 2457c804472Sopenharmony_ci continue; 2467c804472Sopenharmony_ci } 2477c804472Sopenharmony_ci let specialFileContent = fs.readFileSync(specialFilePath, 'utf-8'); 2487c804472Sopenharmony_ci const removeNoteRegx = /\/\*[\s\S]*?\*\//g; 2497c804472Sopenharmony_ci specialFileContent = specialFileContent.replace(removeNoteRegx, ''); 2507c804472Sopenharmony_ci const regex = new RegExp(`\\s${propertyTypeName}\\s*(<|{|=|extends)`); 2517c804472Sopenharmony_ci const results = specialFileContent.match(regex); 2527c804472Sopenharmony_ci if (!results) { 2537c804472Sopenharmony_ci continue; 2547c804472Sopenharmony_ci } 2557c804472Sopenharmony_ci if (sourceFile.fileName === specialFilePath) { 2567c804472Sopenharmony_ci return; 2577c804472Sopenharmony_ci } 2587c804472Sopenharmony_ci let specialFileRelatePath = path.relative(path.dirname(sourceFile.fileName), path.dirname(specialFilePath)); 2597c804472Sopenharmony_ci if (!specialFileRelatePath.startsWith('./') && !specialFileRelatePath.startsWith('../')) { 2607c804472Sopenharmony_ci specialFileRelatePath = './' + specialFileRelatePath; 2617c804472Sopenharmony_ci } 2627c804472Sopenharmony_ci if (!dtsFileList.includes(specialFilePath)) { 2637c804472Sopenharmony_ci dtsFileList.push(specialFilePath); 2647c804472Sopenharmony_ci } 2657c804472Sopenharmony_ci specialFileRelatePath = specialFileRelatePath.split(path.sep).join('/'); 2667c804472Sopenharmony_ci const importStr = `import { ${propertyTypeName} } from '${specialFileRelatePath}${ 2677c804472Sopenharmony_ci specialFileRelatePath.endsWith('/') ? '' : '/' 2687c804472Sopenharmony_ci }${path.basename(specialFilePath).replace('.d.ts', '').replace('.d.ets', '')}'\n`; 2697c804472Sopenharmony_ci if (extraImport.includes(importStr)) { 2707c804472Sopenharmony_ci return; 2717c804472Sopenharmony_ci } 2727c804472Sopenharmony_ci extraImport.push(importStr); 2737c804472Sopenharmony_ci return; 2747c804472Sopenharmony_ci } 2757c804472Sopenharmony_ci if (propertyTypeName.includes('<') || propertyTypeName.includes('[')) { 2767c804472Sopenharmony_ci return; 2777c804472Sopenharmony_ci } 2787c804472Sopenharmony_ci console.log(sourceFile.fileName, 'propertyTypeName', propertyTypeName); 2797c804472Sopenharmony_ci return; 2807c804472Sopenharmony_ci} 281