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 fs from 'fs'; 17import path from 'path'; 18import { 19 ScriptTarget, 20 SyntaxKind, 21 createSourceFile 22} from 'typescript'; 23import type { SourceFile } from 'typescript'; 24import { 25 collectAllLegalImports, 26 dtsFileList, 27 firstCharacterToUppercase, 28 getAllFileNameList, 29 getApiInputPath 30} from '../common/commonUtils'; 31import type { ImportElementEntity } from '../declaration-node/importAndExportDeclaration'; 32import { getDefaultExportClassDeclaration } from '../declaration-node/sourceFileElementsAssemply'; 33import type { SourceFileEntity } from '../declaration-node/sourceFileElementsAssemply'; 34import { generateClassDeclaration } from './generateClassDeclaration'; 35import { generateEnumDeclaration } from './generateEnumDeclaration'; 36import { addToIndexArray } from './generateIndex'; 37 38import { generateInterfaceDeclaration } from './generateInterfaceDeclaration'; 39import { generateModuleDeclaration } from './generateModuleDeclaration'; 40import { generateStaticFunction } from './generateStaticFunction'; 41import { addToSystemIndexArray } from './generateSystemIndex'; 42import { generateTypeAliasDeclaration } from './generateTypeAlias'; 43import { generateCommonFunction } from './generateCommonFunction'; 44import { 45 needToAddBrace, 46 hasExportDefaultKeyword, 47 MockFunctionElementEntity, 48 ReturnDataParams, 49 needAddExtraClass 50} from './generateCommonUtil'; 51 52/** 53 * generate mock file string 54 * @param rootName absolute path to the mock file to be generated 55 * @param sourceFileEntity all node information in the file 56 * @param sourceFile file Text Information 57 * @param fileName file name 58 * @returns file mock text 59 */ 60export function generateSourceFileElements( 61 rootName: string, 62 sourceFileEntity: SourceFileEntity, 63 sourceFile: SourceFile, 64 fileName: string 65): string { 66 let mockApi = ''; 67 let mockFunctionElements: Array<MockFunctionElementEntity> = []; 68 const dependsSourceFileList = collectReferenceFiles(sourceFile); 69 const heritageClausesArray = getCurrentApiHeritageArray(sourceFileEntity, sourceFile); 70 const extraImport = []; 71 72 mockApi += importDeclarationsGenerate(sourceFileEntity, sourceFile, fileName, heritageClausesArray, dependsSourceFileList); 73 const enumDeclarationsData = enumDeclarationsGenerate(sourceFileEntity, mockFunctionElements); 74 mockApi += enumDeclarationsData.mockData; 75 mockFunctionElements = enumDeclarationsData.mockFunctionElements; 76 77 const typeAliasDeclarationsData = typeAliasDeclarationsGenerate(sourceFileEntity, mockFunctionElements, sourceFile, extraImport, mockApi); 78 mockApi += typeAliasDeclarationsData.mockData; 79 mockFunctionElements = typeAliasDeclarationsData.mockFunctionElements; 80 81 const interfaceDeclarationsData = interfaceDeclarationsGenerate(sourceFileEntity, mockFunctionElements, sourceFile, extraImport, mockApi); 82 mockApi += interfaceDeclarationsData.mockData; 83 mockFunctionElements = interfaceDeclarationsData.mockFunctionElements; 84 85 const classDeclarationsData = classDeclarationsGenerate(sourceFileEntity, mockFunctionElements, sourceFile, mockApi, fileName); 86 mockApi += classDeclarationsData.mockData; 87 mockFunctionElements = classDeclarationsData.mockFunctionElements; 88 89 mockApi += moduleDeclarationsGenerate(sourceFileEntity, sourceFile, mockApi, fileName, extraImport); 90 91 mockApi += functionDeclarationsGenerate(sourceFileEntity, sourceFile, mockApi); 92 93 mockApi += otherDeclarationsGenerate(rootName, sourceFileEntity, mockFunctionElements, sourceFile, mockApi, fileName).mockData; 94 95 mockApi += handleExportDeclarations(sourceFileEntity); 96 97 mockApi = extraImport.join('') + mockApi; 98 99 mockApi = addExportDefaultExpression(mockApi); 100 101 return mockApi; 102} 103 104/** 105 * get import declarations generate 106 * @param sourceFileEntity all node information in the file 107 * @param sourceFile file Text Information 108 * @param fileName file name 109 * @param heritageClausesArray heritage elements array data 110 * @param dependsSourceFileList reference Files data 111 * @returns string 112 */ 113function importDeclarationsGenerate( 114 sourceFileEntity: SourceFileEntity, 115 sourceFile: SourceFile, 116 fileName: string, 117 heritageClausesArray: string[], 118 dependsSourceFileList: SourceFile[] 119): string { 120 let mockData = ''; 121 if (needAddExtraClass.includes(`${fileName}.d.ts`)) { 122 mockData += 'import { CommonMethod } from \'./common\';\n'; 123 } 124 if (sourceFileEntity.importDeclarations.length > 0) { 125 sourceFileEntity.importDeclarations.forEach(value => { 126 if ( 127 sourceFile.fileName.endsWith('@ohos.arkui.UIContext.d.ts') && 128 ['\'DatePickerDialogParam\'', '\'TimePickerDialogParam\'', '\'textPickerDialogParam\''].includes(value.importPath) 129 ) { 130 mockData += ''; 131 } else { 132 mockData += generateImportDeclaration(value, fileName, heritageClausesArray, sourceFile.fileName, dependsSourceFileList); 133 } 134 }); 135 } 136 return mockData; 137} 138 139/** 140 * get enum declarations generate 141 * @param sourceFileEntity all node information in the file 142 * @param mockFunctionElements all function element entity 143 * @returns ReturnDataParams 144 */ 145function enumDeclarationsGenerate( 146 sourceFileEntity: SourceFileEntity, 147 mockFunctionElements: Array<MockFunctionElementEntity> 148): ReturnDataParams { 149 const data: ReturnDataParams = { 150 mockData: '', 151 mockFunctionElements: mockFunctionElements 152 }; 153 if (sourceFileEntity.enumDeclarations.length > 0) { 154 sourceFileEntity.enumDeclarations.forEach(value => { 155 data.mockData += generateEnumDeclaration('', value) + '\n'; 156 data.mockFunctionElements.push({ elementName: value.enumName, type: 'enum' }); 157 }); 158 } 159 return data; 160} 161 162/** 163 * get typeAlias declarations generate 164 * @param sourceFileEntity all node information in the file 165 * @param mockFunctionElements all function element entity 166 * @param sourceFile file Text Information 167 * @param extraImport extra import data 168 * @param mockApi file mock text 169 * @returns ReturnDataParams 170 */ 171function typeAliasDeclarationsGenerate( 172 sourceFileEntity: SourceFileEntity, 173 mockFunctionElements: Array<MockFunctionElementEntity>, 174 sourceFile: SourceFile, 175 extraImport: string[], 176 mockApi: string 177): ReturnDataParams { 178 const data: ReturnDataParams = { 179 mockData: '', 180 mockFunctionElements: mockFunctionElements 181 }; 182 if (sourceFileEntity.typeAliasDeclarations.length > 0) { 183 sourceFileEntity.typeAliasDeclarations.forEach(value => { 184 data.mockData += generateTypeAliasDeclaration(value, false, sourceFile, extraImport, mockApi) + '\n'; 185 data.mockFunctionElements.push({ elementName: value.typeAliasName, type: 'typeAlias' }); 186 }); 187 } 188 return data; 189} 190 191/** 192 * get interface declarations generate 193 * @param sourceFileEntity all node information in the file 194 * @param mockFunctionElements all function element entity 195 * @param sourceFile file Text Information 196 * @param extraImport extra import data 197 * @param mockApi file mock text 198 * @returns ReturnDataParams 199 */ 200function interfaceDeclarationsGenerate( 201 sourceFileEntity: SourceFileEntity, 202 mockFunctionElements: Array<MockFunctionElementEntity>, 203 sourceFile: SourceFile, 204 extraImport: string[], 205 mockApi: string 206): ReturnDataParams { 207 const data: ReturnDataParams = { 208 mockData: '', 209 mockFunctionElements: mockFunctionElements 210 }; 211 if (sourceFileEntity.interfaceDeclarations.length > 0) { 212 sourceFileEntity.interfaceDeclarations.forEach(value => { 213 data.mockData += generateInterfaceDeclaration( 214 value, sourceFile, true, mockApi, sourceFileEntity.interfaceDeclarations, 215 sourceFileEntity.importDeclarations, extraImport 216 ) + '\n'; 217 data.mockFunctionElements.push({ elementName: value.interfaceName, type: 'interface' }); 218 }); 219 } 220 return data; 221} 222 223/** 224 * get class declarations generate 225 * @param sourceFileEntity all node information in the file 226 * @param mockFunctionElements all function element entity 227 * @param sourceFile file Text Information 228 * @param mockApi file mock text 229 * @param fileName file name 230 * @returns ReturnDataParams 231 */ 232function classDeclarationsGenerate( 233 sourceFileEntity: SourceFileEntity, 234 mockFunctionElements: Array<MockFunctionElementEntity>, 235 sourceFile: SourceFile, 236 mockApi: string, 237 fileName: string 238): ReturnDataParams { 239 const data: ReturnDataParams = { 240 mockData: '', 241 mockFunctionElements: mockFunctionElements 242 }; 243 if (sourceFileEntity.classDeclarations.length > 0) { 244 sourceFileEntity.classDeclarations.forEach(value => { 245 if (!fileName.startsWith('system_') && !value.exportModifiers.includes(SyntaxKind.DefaultKeyword)) { 246 data.mockData += generateClassDeclaration('', value, false, '', fileName, sourceFile, false, mockApi) + '\n'; 247 data.mockFunctionElements.push({ elementName: value.className, type: 'class' }); 248 } 249 }); 250 } 251 return data; 252} 253 254/** 255 * get module declarations generate 256 * @param sourceFileEntity all node information in the file 257 * @param sourceFile file Text Information 258 * @param mockApi file mock text 259 * @param fileName file name 260 * @param extraImport extra import data 261 * @returns string 262 */ 263function moduleDeclarationsGenerate( 264 sourceFileEntity: SourceFileEntity, 265 sourceFile: SourceFile, 266 mockApi: string, 267 fileName: string, 268 extraImport: string[] 269): string { 270 let mockData = ''; 271 if (sourceFileEntity.moduleDeclarations.length > 0) { 272 sourceFileEntity.moduleDeclarations.forEach(value => { 273 mockData += generateModuleDeclaration(value, sourceFile, fileName, mockApi, extraImport, sourceFileEntity.importDeclarations) + '\n'; 274 }); 275 } 276 return mockData; 277} 278 279/** 280 * get function declarations generate 281 * @param sourceFileEntity all node information in the file 282 * @param sourceFile file Text Information 283 * @param mockApi file mock text 284 * @returns string 285 */ 286function functionDeclarationsGenerate( 287 sourceFileEntity: SourceFileEntity, 288 sourceFile: SourceFile, 289 mockApi: string 290): string { 291 let mockData = ''; 292 if (sourceFileEntity.functionDeclarations.size > 0) { 293 Array.from(sourceFileEntity.functionDeclarations.keys()).forEach(key => { 294 mockData += generateCommonFunction(key, sourceFileEntity.functionDeclarations.get(key), sourceFile, mockApi, true) + '\n'; 295 }); 296 } 297 return mockData; 298} 299 300/** 301 * get other declarations generate 302 * @param rootName absolute path to the mock file to be generated 303 * @param sourceFileEntity all node information in the file 304 * @param mockFunctionElements all function element entity 305 * @param sourceFile file Text Information 306 * @param mockApi file mock text 307 * @param fileName file name 308 * @returns ReturnDataParams 309 */ 310function otherDeclarationsGenerate( 311 rootName: string, 312 sourceFileEntity: SourceFileEntity, 313 mockFunctionElements: Array<MockFunctionElementEntity>, 314 sourceFile: SourceFile, 315 mockApi: string, 316 fileName: string 317): ReturnDataParams { 318 const data: ReturnDataParams = { 319 mockData: '', 320 mockFunctionElements: [] 321 }; 322 if ( 323 sourceFileEntity.moduleDeclarations.length === 0 && 324 (fileName.startsWith('ohos_') || fileName.startsWith('system_') || fileName.startsWith('webgl')) 325 ) { 326 const moduleDeclarationsData = handleModuleDeclarationsNotExist(rootName, fileName, sourceFile, mockApi, mockFunctionElements); 327 data.mockData = moduleDeclarationsData.mockData; 328 data.mockFunctionElements = moduleDeclarationsData.mockFunctionElements; 329 } else { 330 const defaultExportClass = getDefaultExportClassDeclaration(sourceFile); 331 if (defaultExportClass.length > 0) { 332 const mockNameArr = fileName.split('_'); 333 const mockName = mockNameArr[mockNameArr.length - 1]; 334 defaultExportClass.forEach(value => { 335 data.mockData += generateClassDeclaration(rootName, value, false, mockName, '', sourceFile, false, mockApi) + '\n'; 336 }); 337 } 338 } 339 return data; 340} 341 342/** 343 * handle Export Declarations 344 * @param sourceFileEntity all node information in the file 345 * @returns export text info 346 */ 347function handleExportDeclarations(sourceFileEntity: SourceFileEntity): string { 348 let mockApi = ''; 349 if (sourceFileEntity.exportDeclarations.length > 0) { 350 sourceFileEntity.exportDeclarations.forEach(value => { 351 if (value.includes('export type {')) { 352 return; 353 } 354 if (!value.includes('export {')) { 355 mockApi += `${value}\n`; 356 } 357 }); 358 } 359 return mockApi; 360} 361 362/** 363 * add extra export default expression 364 * @param mockApi file mock text 365 * @returns export text info 366 */ 367function addExportDefaultExpression(mockApi: string): string { 368 const paramIndex = 2; 369 const reg = /export\sconst\s.*\s=/g; 370 const regDefault = /export\sdefault\s/g; 371 const regFunc = /export\sfunction\s/g; 372 const results = mockApi.match(reg); 373 const resultDefaults = mockApi.match(regDefault); 374 const resultFuncs = mockApi.match(regFunc); 375 if (results && results.length === 1 && !resultDefaults && !resultFuncs) { 376 const arr = results[0].split(' '); 377 const moduleName = arr[arr.length - paramIndex]; 378 mockApi += `\nexport default ${moduleName};`; 379 } 380 return mockApi; 381} 382 383/** 384 * generate import definition 385 * @param importEntity import entity data 386 * @param sourceFileName file name 387 * @param heritageClausesArray heritage elements array data 388 * @param currentFilePath current file path 389 * @param dependsSourceFileList reference Files data 390 * @returns string 391 */ 392export function generateImportDeclaration( 393 importEntity: ImportElementEntity, 394 sourceFileName: string, 395 heritageClausesArray: string[], 396 currentFilePath: string, 397 dependsSourceFileList: SourceFile[] 398): string { 399 const importDeclaration = referenctImport2ModuleImport(importEntity, currentFilePath, dependsSourceFileList); 400 if (importDeclaration) { 401 return importDeclaration; 402 } 403 404 const importPathSplit = importEntity.importPath.split('/'); 405 406 let importPath = importPathSplit.slice(0, -1).join('/') + '/'; 407 importPath += getImportPathName(importPathSplit); 408 409 let importElements = generateImportElements(importEntity, heritageClausesArray); 410 if (importElements === '{ mockWantAgent }' && importPath.includes('ohos_app_ability_wantAgent')) { 411 importElements = '{ mockWantAgent as mockAbilityWantAgent }'; 412 } 413 const testPath = importPath.replace(/"/g, '').replace(/'/g, '').split('/'); 414 if (!getAllFileNameList().has(testPath[testPath.length - 1]) && testPath[testPath.length - 1] !== 'ohos_application_want') { 415 return ''; 416 } 417 418 let tmpImportPath = importPath.replace(/'/g, '').replace(/"/g, ''); 419 if (!tmpImportPath.startsWith('./') && !tmpImportPath.startsWith('../')) { 420 importPath = `'./${tmpImportPath}'`; 421 } 422 if (sourceFileName === 'tagSession' && tmpImportPath === './basic' || sourceFileName === 'notificationContent' && 423 tmpImportPath === './ohos_multimedia_image') { 424 importPath = `'.${importPath.replace(/'/g, '')}'`; 425 } 426 427 if (sourceFileName === 'AbilityContext' && tmpImportPath === '../ohos_application_Ability' || 428 sourceFileName === 'Context' && tmpImportPath === './ApplicationContext') { 429 return ''; 430 } 431 if (!importElements.includes('{') && !importElements.includes('}') && needToAddBrace.includes(importElements)) { 432 importElements = `{ ${importElements} }`; 433 } 434 collectAllLegalImports(importElements); 435 return `import ${importElements} from ${importPath}\n`; 436} 437 438/** 439 * handle module declarations does it exist 440 * @param rootName absolute path to the mock file to be generated 441 * @param fileName file name 442 * @param sourceFile file Text Information 443 * @param mockApi file mock text 444 * @param mockFunctionElements all function element entity 445 * @returns ReturnDataParams 446 */ 447function handleModuleDeclarationsNotExist( 448 rootName: string, fileName: string, sourceFile: SourceFile, mockApi: string, mockFunctionElements: Array<MockFunctionElementEntity> 449): ReturnDataParams { 450 const data: ReturnDataParams = { 451 mockData: '', 452 mockFunctionElements: mockFunctionElements 453 }; 454 const mockNameArr = fileName.split('_'); 455 const mockName = mockNameArr[mockNameArr.length - 1]; 456 const defaultExportClass = getDefaultExportClassDeclaration(sourceFile); 457 defaultExportClass.forEach(value => { 458 data.mockData += generateClassDeclaration(rootName, value, false, mockName, '', sourceFile, false, mockApi) + '\n'; 459 data.mockFunctionElements.push({ elementName: value.className, type: 'class' }); 460 }); 461 data.mockData += `export function mock${firstCharacterToUppercase(mockName)}() {\n`; 462 if (fileName.startsWith('system_')) { 463 addToSystemIndexArray({ 464 filename: fileName, 465 mockFunctionName: `mock${firstCharacterToUppercase(mockName)}` 466 }); 467 data.mockData += `global.systemplugin.${mockName} = {`; 468 const defaultClass = getDefaultExportClassDeclaration(sourceFile); 469 let staticMethodBody = ''; 470 defaultClass.forEach(value => { 471 value.staticMethods.forEach(val => { 472 staticMethodBody += generateStaticFunction(val, true, sourceFile, mockApi); 473 }); 474 }); 475 data.mockData += staticMethodBody; 476 data.mockData += '}'; 477 } else { 478 if (!fileName.startsWith('webgl')) { 479 addToIndexArray({ fileName: fileName, mockFunctionName: `mock${firstCharacterToUppercase(mockName)}` }); 480 } 481 } 482 data.mockData += `\nconst mockModule${firstCharacterToUppercase(mockName)} = {`; 483 data.mockFunctionElements.forEach(val => { 484 data.mockData += `${val.elementName}: ${val.elementName},`; 485 }); 486 data.mockData += '}\n'; 487 const isHaveExportDefault = hasExportDefaultKeyword(mockName, sourceFile); 488 const mockNameUppercase = firstCharacterToUppercase(mockName); 489 data.mockData += 490 isHaveExportDefault ? `return mockModule${mockNameUppercase}\n` : `return mockModule${mockNameUppercase}.${mockNameUppercase}\n`; 491 data.mockData += '}'; 492 return data; 493} 494 495/** 496 * adapter default export 497 * @param importName 498 * @returns boolean 499 */ 500function checIsDefaultExportClass(importName: string): boolean { 501 const defaultExportClass = ['Context', 'BaseContext', 'ExtensionContext', 'ApplicationContext', 502 'ExtensionAbility', 'Ability', 'UIExtensionAbility', 'UIExtensionContext']; 503 return defaultExportClass.includes(importName); 504} 505 506/** 507 * get heritage elements 508 * @param sourceFileEntity all node information in the file 509 * @param sourceFile file Text Information 510 * @returns string[] 511 */ 512function getCurrentApiHeritageArray(sourceFileEntity: SourceFileEntity, sourceFile: SourceFile): string[] { 513 const heritageClausesArray = []; 514 const defaultClassArray = getDefaultExportClassDeclaration(sourceFile); 515 sourceFileEntity.classDeclarations.forEach(value => { 516 value.heritageClauses.forEach(val => { 517 val.types.forEach(v => { 518 heritageClausesArray.push(v); 519 }); 520 }); 521 }); 522 defaultClassArray.forEach(value => { 523 value.heritageClauses.forEach(val => { 524 val.types.forEach(v => { 525 heritageClausesArray.push(v); 526 }); 527 }); 528 }); 529 return heritageClausesArray; 530} 531 532/** 533 * collect reference Files 534 * @param sourceFile file Text Information 535 * @returns SourceFile[] 536 */ 537function collectReferenceFiles(sourceFile: SourceFile): SourceFile[] { 538 const referenceElementTemplate = /\/\/\/\s*<reference\s+path="[^'"\[\]]+/g; 539 const referenceFiles: SourceFile[] = []; 540 const text = sourceFile.text; 541 const referenceElement = text.match(referenceElementTemplate); 542 543 referenceElement && referenceElement.forEach(element => { 544 const referenceRelatePath = element.split(/path=["']/g)[1]; 545 const realReferenceFilePath = contentRelatePath2RealRelatePath(sourceFile.fileName, referenceRelatePath); 546 if (!realReferenceFilePath) { 547 return; 548 } 549 550 if (!fs.existsSync(realReferenceFilePath)) { 551 console.error(`Can not resolve file: ${realReferenceFilePath}`); 552 return; 553 } 554 const code = fs.readFileSync(realReferenceFilePath); 555 referenceFiles.push(createSourceFile(realReferenceFilePath, code.toString(), ScriptTarget.Latest)); 556 !dtsFileList.includes(realReferenceFilePath) && dtsFileList.push(realReferenceFilePath); 557 }); 558 return referenceFiles; 559} 560 561/** 562 * content relatePath to real relatePath 563 * @param currentFilePath file name 564 * @param contentReferenceRelatePath reference relate Path 565 * @returns string 566 */ 567function contentRelatePath2RealRelatePath(currentFilePath: string, contentReferenceRelatePath: string): string { 568 const conmponentSourceFileTemplate = /component\/[^'"\/]+\.d\.ts/; 569 const currentFolderSourceFileTemplate = /\.\/[^\/]+\.d\.ts/; 570 const baseFileNameTemplate = /[^\/]+\.d\.ts/; 571 572 let realReferenceFilePath: string; 573 if (conmponentSourceFileTemplate.test(contentReferenceRelatePath)) { 574 const newRelateReferencePath = contentReferenceRelatePath.match(conmponentSourceFileTemplate)[0]; 575 const referenceFileName = path.basename(newRelateReferencePath); 576 realReferenceFilePath = path.join(getApiInputPath(), '@internal', 'component', 'ets', referenceFileName); 577 } else if (currentFolderSourceFileTemplate.test(contentReferenceRelatePath)) { 578 const referenceFileName = path.basename(contentReferenceRelatePath); 579 realReferenceFilePath = currentFilePath.replace(baseFileNameTemplate, referenceFileName).replace(/\//g, path.sep); 580 } else { 581 console.error(`Can not find reference ${contentReferenceRelatePath} from ${currentFilePath}`); 582 return ''; 583 } 584 return realReferenceFilePath; 585} 586 587/** 588 * referenct import to module import 589 * @param importEntity import entity data 590 * @param currentFilePath current file path data 591 * @param dependsSourceFileList reference Files data 592 * @returns string 593 */ 594export function referenctImport2ModuleImport( 595 importEntity: ImportElementEntity, 596 currentFilePath: string, 597 dependsSourceFileList: SourceFile[] 598): string { 599 if (dependsSourceFileList.length && !importEntity.importPath.includes('.')) { 600 for (let i = 0; i < dependsSourceFileList.length; i++) { 601 if (dependsSourceFileList[i].text.includes(`declare module ${importEntity.importPath.replace(/'/g, '"')}`)) { 602 let relatePath = path.relative(path.dirname(currentFilePath), dependsSourceFileList[i].fileName) 603 .replace(/\\/g, '/') 604 .replace(/.d.ts/g, '') 605 .replace(/.d.es/g, ''); 606 relatePath = (relatePath.startsWith('@internal/component') ? './' : '') + relatePath; 607 return `import ${importEntity.importElements} from "${relatePath}"\n`; 608 } 609 } 610 } 611 return ''; 612} 613 614/** 615 * get import pathName 616 * @param importPathSplit import path split to array data 617 * @returns string 618 */ 619function getImportPathName(importPathSplit: string[]): string { 620 let importPathName: string; 621 let fileName = importPathSplit[importPathSplit.length - 1]; 622 if (fileName.endsWith('.d.ts') || fileName.endsWith('.d.ets')) { 623 fileName = fileName.split(/\.d\.e?ts/)[0]; 624 } 625 if (fileName.includes('@')) { 626 importPathName = fileName.replace('@', '').replace(/\./g, '_'); 627 } else { 628 importPathName = fileName.replace(/\./g, '_'); 629 } 630 return importPathName; 631} 632 633/** 634 * get import pathName 635 * @param importEntity import entity data 636 * @param heritageClausesArray heritage elements array data 637 * @returns string 638 */ 639function generateImportElements(importEntity: ImportElementEntity, heritageClausesArray: string[]): string { 640 let importElements = importEntity.importElements; 641 if ( 642 !importElements.includes('{') && 643 !importElements.includes('* as') && 644 !heritageClausesArray.includes(importElements) && 645 importEntity.importPath.includes('@ohos') 646 ) { 647 const tmpArr = importEntity.importPath.split('.'); 648 const mockModuleName = firstCharacterToUppercase(tmpArr[tmpArr.length - 1].replace('"', '').replace('\'', '')); 649 if (importElements === 'observer' && importEntity.importPath.includes('@ohos.arkui.observer')) { 650 return `{ mockUiObserver as ${importElements}}`; 651 } 652 importElements = `{ mock${mockModuleName} }`; 653 } else { 654 // adapt no rules .d.ts 655 if (importElements.trim() === 'AccessibilityExtensionContext, { AccessibilityElement }') { 656 importElements = '{ AccessibilityExtensionContext, AccessibilityElement }'; 657 } else if (importElements.trim() === '{ image }') { 658 importElements = '{ mockImage as image }'; 659 } 660 } 661 return importElements; 662} 663