1/* 2 * Copyright (c) 2024-2025 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 { Constant } from '../../core/base/Constant'; 17import { 18 ArkInstanceInvokeExpr, 19 ArkNewArrayExpr, 20 ArkNewExpr, 21 ArkStaticInvokeExpr, 22 NormalBinaryOperator 23} from '../../core/base/Expr'; 24import { Local } from '../../core/base/Local'; 25import { 26 ArkArrayRef, 27 ArkInstanceFieldRef, 28 ArkParameterRef, 29 ArkStaticFieldRef, 30 ClosureFieldRef 31} from '../../core/base/Ref'; 32import { 33 ArkAliasTypeDefineStmt, 34 ArkAssignStmt, 35 ArkIfStmt, 36 ArkInvokeStmt, 37 ArkReturnStmt, 38 ArkReturnVoidStmt, 39 ArkThrowStmt, 40 Stmt 41} from '../../core/base/Stmt'; 42import { AliasType, ClassType, Type } from '../../core/base/Type'; 43import { Value } from '../../core/base/Value'; 44import { BasicBlock } from '../../core/graph/BasicBlock'; 45import Logger, { LOG_MODULE_TYPE } from '../../utils/logger'; 46import { ArkCodeBuffer } from '../ArkStream'; 47import { StmtReader } from './SourceBody'; 48import { SourceTransformer, TransformerContext } from './SourceTransformer'; 49import { CLASS_CATEGORY_COMPONENT, PrinterUtils } from '../base/PrinterUtils'; 50import { ValueUtil } from '../../core/common/ValueUtil'; 51import { ArkClass, ClassCategory } from '../../core/model/ArkClass'; 52import { modifiers2stringArray } from '../../core/model/ArkBaseModel'; 53import { ArkMetadataKind, CommentsMetadata } from '../../core/model/ArkMetadata'; 54import { ImportInfo } from '../../core/model/ArkImport'; 55import { ArkMethod } from '../../core/model/ArkMethod'; 56import { Dump } from '../base/BasePrinter'; 57 58const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'SourceStmt'); 59const IGNOR_TYPES = new Set<string>(['any', 'Map', 'Set']); 60 61export interface StmtPrinterContext extends TransformerContext { 62 getStmtReader(): StmtReader; 63 64 setTempCode(temp: string, code: string): void; 65 66 hasTempVisit(temp: string): boolean; 67 68 setTempVisit(temp: string): void; 69 70 setSkipStmt(stmt: Stmt): void; 71 72 getLocals(): Map<string, Local>; 73 74 defineLocal(local: Local): void; 75 76 isLocalDefined(local: Local): boolean; 77 78 isInDefaultMethod(): boolean; 79} 80 81export abstract class SourceStmt implements Dump { 82 original: Stmt; 83 context: StmtPrinterContext; 84 line: number; 85 text: string = ''; 86 transformer: SourceTransformer; 87 88 constructor(context: StmtPrinterContext, original: Stmt) { 89 this.original = original; 90 this.context = context; 91 this.line = original.getOriginPositionInfo().getLineNo(); 92 this.transformer = new SourceTransformer(context); 93 } 94 95 public getLine(): number { 96 return this.line; 97 } 98 99 public setLine(line: number): void { 100 this.line = line; 101 } 102 103 public dump(): string { 104 this.beforeDump(); 105 let code = this.dumpTs(); 106 this.afterDump(); 107 return code; 108 } 109 110 protected beforeDump(): void {} 111 112 protected afterDump(): void {} 113 114 protected dumpTs(): string { 115 let content: string[] = []; 116 const commentsMetadata = this.original.getMetadata(ArkMetadataKind.LEADING_COMMENTS); 117 if (commentsMetadata instanceof CommentsMetadata) { 118 const comments = commentsMetadata.getComments(); 119 comments.forEach(comment => { 120 content.push(`${this.printer.getIndent()}${comment.content}\n`); 121 }); 122 } 123 if (this.text.length > 0) { 124 content.push(`${this.printer.getIndent()}${this.text}\n`); 125 } 126 return content.join(''); 127 } 128 129 protected get printer(): ArkCodeBuffer { 130 return this.context.getPrinter(); 131 } 132 133 public toString(): string { 134 return this.text; 135 } 136 137 protected setText(text: string): void { 138 this.text = text; 139 } 140 141 protected getIntent(): string { 142 return this.context.getPrinter().getIndent(); 143 } 144 145 public abstract transfer2ts(): void; 146 147 protected isLocalTempValue(value: Value): boolean { 148 if (!(value instanceof Local)) { 149 return false; 150 } 151 152 return PrinterUtils.isTemp(value.getName()); 153 } 154} 155 156enum AssignStmtDumpType { 157 NORMAL, 158 TEMP_REPLACE, 159 COMPONENT_CREATE, 160} 161 162export class SourceAssignStmt extends SourceStmt { 163 private leftOp: Value = ValueUtil.getUndefinedConst(); 164 private rightOp: Value = ValueUtil.getUndefinedConst(); 165 private leftCode: string = ''; 166 private rightCode: string = ''; 167 private dumpType?: AssignStmtDumpType; 168 private leftTypeCode: string; 169 170 constructor(context: StmtPrinterContext, original: ArkAssignStmt) { 171 super(context, original); 172 this.leftTypeCode = ''; 173 } 174 175 public transfer2ts(): void { 176 this.leftOp = (this.original as ArkAssignStmt).getLeftOp(); 177 this.rightOp = (this.original as ArkAssignStmt).getRightOp(); 178 179 if ( 180 (this.leftOp instanceof Local && this.leftOp.getName() === 'this') || 181 (this.rightOp instanceof Constant && this.rightOp.getValue() === 'undefined') || 182 this.rightOp instanceof ArkParameterRef || 183 this.rightOp instanceof ClosureFieldRef 184 ) { 185 this.setText(''); 186 this.dumpType = AssignStmtDumpType.NORMAL; 187 return; 188 } 189 190 this.leftCode = this.transformer.valueToString(this.leftOp, true); 191 192 if (this.leftOp instanceof Local && this.rightOp instanceof ArkNewExpr) { 193 this.transferRightNewExpr(); 194 } else if (this.leftOp instanceof Local && this.rightOp instanceof ArkNewArrayExpr) { 195 this.transferRightNewArrayExpr(); 196 } else if (this.rightOp instanceof ArkStaticInvokeExpr && PrinterUtils.isComponentCreate(this.rightOp)) { 197 this.transferRightComponentCreate(); 198 } else if (this.rightOp instanceof ArkInstanceInvokeExpr && PrinterUtils.isComponentAttributeInvoke(this.rightOp)) { 199 this.transferRightComponentAttribute(); 200 } else { 201 this.rightCode = this.transformer.valueToString(this.rightOp); 202 } 203 204 if (this.isLocalTempValue(this.leftOp)) { 205 this.context.setTempCode((this.leftOp as Local).getName(), this.rightCode); 206 } 207 208 if ((this.leftOp instanceof ArkInstanceFieldRef && this.leftOp.getBase().getName() === 'this') || this.leftOp instanceof ArkStaticFieldRef) { 209 this.context.setTempCode(this.leftOp.getFieldName(), this.rightCode); 210 } 211 212 if (this.dumpType === undefined) { 213 this.setText(`${this.leftCode} = ${this.rightCode}`); 214 this.dumpType = AssignStmtDumpType.TEMP_REPLACE; 215 } 216 217 let leftOpType = this.leftOp.getType(); 218 if (leftOpType instanceof ClassType) { 219 let name = leftOpType.getClassSignature().getClassName(); 220 if (PrinterUtils.isAnonymousClass(name)) { 221 this.leftTypeCode = 'any'; 222 } else { 223 this.leftTypeCode = name; 224 } 225 } else { 226 this.leftTypeCode = this.transformer.typeToString(leftOpType); 227 } 228 if (IGNOR_TYPES.has(this.leftTypeCode)) { 229 this.leftTypeCode = ''; 230 } 231 } 232 233 protected beforeDump(): void { 234 if (this.dumpType !== AssignStmtDumpType.TEMP_REPLACE) { 235 return; 236 } 237 238 if (this.context.hasTempVisit(this.leftCode)) { 239 this.setText(''); 240 return; 241 } else if (PrinterUtils.isTemp(this.leftCode)) { 242 this.setText(`${this.rightCode};`); 243 return; 244 } 245 if (this.leftOp instanceof Local && this.context.getLocals().has(this.leftOp.getName()) && !this.isLocalTempValue(this.leftOp)) { 246 if (this.context.isLocalDefined(this.leftOp)) { 247 this.setText(`${this.leftCode} = ${this.rightCode};`); 248 return; 249 } 250 let flag = this.leftOp.getConstFlag() ? 'const' : 'let'; 251 if (this.context.getArkFile().getExportInfoBy(this.leftCode) && this.context.isInDefaultMethod()) { 252 this.setText(`export ${flag} ${this.leftCode} = ${this.rightCode};`); 253 } else { 254 if (this.leftTypeCode.length > 0) { 255 this.setText(`${flag} ${this.leftCode}: ${this.leftTypeCode} = ${this.rightCode};`); 256 } else { 257 this.setText(`${flag} ${this.leftCode} = ${this.rightCode};`); 258 } 259 } 260 this.context.defineLocal(this.leftOp); 261 } else { 262 this.setText(`${this.leftCode} = ${this.rightCode};`); 263 } 264 } 265 266 protected afterDump(): void { 267 if (this.dumpType === AssignStmtDumpType.COMPONENT_CREATE) { 268 this.printer.incIndent(); 269 } 270 } 271 272 private getClassOriginType(type: Type): number | undefined { 273 if (!(type instanceof ClassType)) { 274 return undefined; 275 } 276 277 let signature = type.getClassSignature(); 278 let cls = this.context.getClass(signature); 279 if (!cls) { 280 return undefined; 281 } 282 return PrinterUtils.getOriginType(cls); 283 } 284 285 /** 286 * temp1 = new Person 287 * temp1.constructor(10) 288 */ 289 private transferRightNewExpr(): void { 290 let originType = this.getClassOriginType(this.rightOp.getType()); 291 if (this.context.getStmtReader().hasNext()) { 292 let stmt = this.context.getStmtReader().next(); 293 let rollback = true; 294 if (stmt instanceof ArkInvokeStmt && (stmt.getInvokeExpr() as ArkInstanceInvokeExpr)) { 295 let instanceInvokeExpr = stmt.getInvokeExpr() as ArkInstanceInvokeExpr; 296 if ( 297 'constructor' === instanceInvokeExpr.getMethodSignature().getMethodSubSignature().getMethodName() && 298 instanceInvokeExpr.getBase().getName() === (this.leftOp as Local).getName() 299 ) { 300 this.handleConstructorInvoke(instanceInvokeExpr, originType); 301 return; 302 } 303 } 304 if (rollback) { 305 this.context.getStmtReader().rollback(); 306 } 307 } 308 309 if (originType === CLASS_CATEGORY_COMPONENT) { 310 this.rightCode = `${this.transformer.typeToString(this.rightOp.getType())}()`; 311 } else if (originType === ClassCategory.TYPE_LITERAL || originType === ClassCategory.OBJECT) { 312 this.rightCode = `${this.transformer.typeToString(this.rightOp.getType())}`; 313 } else { 314 this.rightCode = `new ${this.transformer.typeToString(this.rightOp.getType())}()`; 315 } 316 } 317 318 private handleConstructorInvoke(instanceInvokeExpr: ArkInstanceInvokeExpr, originType?: number): void { 319 let args: string[] = []; 320 instanceInvokeExpr.getArgs().forEach(v => { 321 args.push(this.transformer.valueToString(v)); 322 }); 323 324 if (originType === CLASS_CATEGORY_COMPONENT) { 325 this.rightCode = `${this.transformer.typeToString(this.rightOp.getType())}(${args.join(', ')})`; 326 } else if (originType === ClassCategory.TYPE_LITERAL || originType === ClassCategory.OBJECT) { 327 this.rightCode = `${this.transformer.literalObjectToString(this.rightOp.getType() as ClassType)}`; 328 } else { 329 this.rightCode = `new ${this.transformer.typeToString(this.rightOp.getType())}(${args.join(', ')})`; 330 } 331 } 332 333 /** 334 * $temp0 = newarray[4] 335 * $temp0[0] = 1 336 * $temp0[1] = 2 337 * $temp0[2] = 3 338 */ 339 private transferRightNewArrayExpr(): void { 340 let arrayExpr = new SourceNewArrayExpr(this.rightOp as ArkNewArrayExpr); 341 let localName = (this.leftOp as Local).getName(); 342 while (this.context.getStmtReader().hasNext()) { 343 let stmt = this.context.getStmtReader().next(); 344 if (stmt instanceof ArkAssignStmt) { 345 let left = stmt.getLeftOp(); 346 if (left instanceof ArkArrayRef && left.getBase().getName() === localName) { 347 arrayExpr.addInitValue(this.transformer.valueToString(stmt.getRightOp())); 348 } else { 349 this.context.getStmtReader().rollback(); 350 break; 351 } 352 } else { 353 this.context.getStmtReader().rollback(); 354 break; 355 } 356 } 357 this.rightCode = arrayExpr.toString(); 358 } 359 360 private transferRightComponentCreate(): void { 361 this.rightCode = this.transformer.valueToString(this.rightOp); 362 if (this.context.getStmtReader().hasNext()) { 363 let stmt = this.context.getStmtReader().next(); 364 if (stmt instanceof ArkInvokeStmt) { 365 let expr = stmt.getInvokeExpr(); 366 if (expr instanceof ArkStaticInvokeExpr && PrinterUtils.isComponentPop(expr)) { 367 this.setText(`${this.rightCode}`); 368 this.dumpType = AssignStmtDumpType.NORMAL; 369 return; 370 } 371 } 372 373 this.context.getStmtReader().rollback(); 374 } 375 this.setText(`${this.rightCode} {`); 376 this.dumpType = AssignStmtDumpType.COMPONENT_CREATE; 377 } 378 379 private transferRightComponentAttribute(): void { 380 this.rightCode = this.transformer.valueToString(this.rightOp); 381 this.setText(`${this.rightCode}`); 382 this.dumpType = AssignStmtDumpType.NORMAL; 383 } 384} 385 386export class SourceInvokeStmt extends SourceStmt { 387 constructor(context: StmtPrinterContext, original: ArkInvokeStmt) { 388 super(context, original); 389 } 390 391 public transfer2ts(): void { 392 let invokeExpr = this.original.getInvokeExpr(); 393 let code = ''; 394 let isAttr = false; 395 if (invokeExpr instanceof ArkStaticInvokeExpr) { 396 if (PrinterUtils.isComponentPop(invokeExpr)) { 397 code = '}'; 398 isAttr = true; 399 } else { 400 code = this.transformer.staticInvokeExprToString(invokeExpr); 401 isAttr = PrinterUtils.isComponentIfElseInvoke(invokeExpr); 402 } 403 } else if (invokeExpr instanceof ArkInstanceInvokeExpr) { 404 isAttr = PrinterUtils.isComponentAttributeInvoke(invokeExpr); 405 code = this.transformer.instanceInvokeExprToString(invokeExpr, isAttr); 406 } 407 408 if (code.length > 0 && !isAttr) { 409 this.setText(`${code};`); 410 } else { 411 this.setText(`${code}`); 412 } 413 } 414 415 protected beforeDump(): void { 416 let invokeExpr = this.original.getInvokeExpr(); 417 if ( 418 (invokeExpr instanceof ArkStaticInvokeExpr && PrinterUtils.isComponentPop(invokeExpr)) || 419 (invokeExpr instanceof ArkStaticInvokeExpr && PrinterUtils.isComponentIfElseInvoke(invokeExpr)) 420 ) { 421 this.printer.decIndent(); 422 return; 423 } 424 } 425 426 protected afterDump(): void { 427 let invokeExpr = this.original.getInvokeExpr(); 428 if (invokeExpr instanceof ArkStaticInvokeExpr && PrinterUtils.isComponentIfElseInvoke(invokeExpr)) { 429 this.printer.incIndent(); 430 return; 431 } 432 } 433} 434 435export class SourceIfStmt extends SourceStmt { 436 constructor(context: StmtPrinterContext, original: ArkIfStmt) { 437 super(context, original); 438 } 439 440 public transfer2ts(): void { 441 let code: string; 442 let expr = (this.original as ArkIfStmt).getConditionExpr(); 443 code = `if (${this.transformer.valueToString(expr.getOp1())}`; 444 code += ` ${expr.getOperator()} `; 445 code += `${this.transformer.valueToString(expr.getOp2())}) {`; 446 this.setText(code); 447 } 448 449 protected afterDump(): void { 450 this.printer.incIndent(); 451 } 452} 453 454export class SourceWhileStmt extends SourceStmt { 455 block: BasicBlock; 456 457 constructor(context: StmtPrinterContext, original: ArkIfStmt, block: BasicBlock) { 458 super(context, original); 459 this.block = block; 460 } 461 462 protected afterDump(): void { 463 this.printer.incIndent(); 464 } 465 466 /** 467 * $temp2 = $temp1.next() 468 * $temp3 = $temp2.done() 469 * if $temp3 === true 470 * $temp4 = $temp2.value 471 * $temp5 = <> cast 472 * @returns 473 */ 474 private forOf2ts(): boolean { 475 let expr = (this.original as ArkIfStmt).getConditionExpr(); 476 let temp3 = expr.getOp1(); 477 let op2 = expr.getOp2(); 478 let firstStmt = this.context.getStmtReader().first(); 479 if (!(firstStmt instanceof ArkAssignStmt)) { 480 return false; 481 } 482 483 if (!(this.isLocalTempValue(temp3) && op2 instanceof Constant && (op2 as Constant).getValue() === 'true')) { 484 return false; 485 } 486 487 let stmt = (temp3 as Local).getDeclaringStmt(); 488 if (!(stmt instanceof ArkAssignStmt)) { 489 return false; 490 } 491 492 let done = stmt.getRightOp(); 493 if (!(done instanceof ArkInstanceFieldRef)) { 494 return false; 495 } 496 497 if (done.getFieldSignature().toString() !== '@ES2015/BuiltinClass: IteratorResult.done') { 498 return false; 499 } 500 501 let temp2 = done.getBase(); 502 if (!(temp2 instanceof Local)) { 503 return false; 504 } 505 506 stmt = temp2.getDeclaringStmt(); 507 if (!(stmt instanceof ArkAssignStmt)) { 508 return false; 509 } 510 511 let next = stmt.getRightOp(); 512 if (!(next instanceof ArkInstanceInvokeExpr)) { 513 return false; 514 } 515 516 if (next.getMethodSignature().getMethodSubSignature().getMethodName() !== 'next') { 517 return false; 518 } 519 520 let temp1 = next.getBase(); 521 if (!(temp1 instanceof Local)) { 522 return false; 523 } 524 525 stmt = temp1.getDeclaringStmt(); 526 if (!(stmt instanceof ArkAssignStmt)) { 527 return false; 528 } 529 530 let iterator = stmt.getRightOp(); 531 if (!(iterator instanceof ArkInstanceInvokeExpr)) { 532 return false; 533 } 534 535 if (iterator.getMethodSignature().getMethodSubSignature().getMethodName() !== 'Symbol.iterator') { 536 return false; 537 } 538 539 let successors = this.block.getSuccessors(); 540 if (successors.length !== 2) { 541 return false; 542 } 543 544 let stmts = successors[0].getStmts(); 545 if (stmts.length < 2) { 546 return false; 547 } 548 549 stmt = stmts[1]; 550 if (!(stmt instanceof ArkAssignStmt)) { 551 return false; 552 } 553 554 this.context.setSkipStmt(stmts[0]); 555 this.context.setSkipStmt(stmts[1]); 556 557 while (this.context.getStmtReader().hasNext()) { 558 this.context.getStmtReader().next(); 559 } 560 561 let v = stmt.getLeftOp() as Local; 562 let valueName = v.getName(); 563 if (!this.isLocalTempValue(v)) { 564 this.setText(`for (let ${valueName} of ${this.transformer.valueToString(iterator.getBase())}) {`); 565 this.context.setTempVisit((temp1 as Local).getName()); 566 this.context.setTempVisit((temp3 as Local).getName()); 567 return true; 568 } 569 570 // iterate map 'for (let [key, value] of map)' 571 let stmtReader = new StmtReader(stmts); 572 stmtReader.next(); 573 stmtReader.next(); 574 575 let arrayValueNames = []; 576 while (stmtReader.hasNext()) { 577 stmt = stmtReader.next(); 578 if (!(stmt instanceof ArkAssignStmt)) { 579 break; 580 } 581 let ref = stmt.getRightOp(); 582 if (!(ref instanceof ArkArrayRef)) { 583 break; 584 } 585 if (ref.getBase().getName() !== valueName) { 586 break; 587 } 588 let name = (stmt.getLeftOp() as Local).getName(); 589 arrayValueNames.push(name); 590 this.context.setTempVisit(name); 591 } 592 593 this.setText(`for (let [${arrayValueNames.join(', ')}] of ${this.transformer.valueToString(iterator.getBase())}) {`); 594 this.context.setTempVisit((temp3 as Local).getName()); 595 596 return true; 597 } 598 599 public transfer2ts(): void { 600 if (this.forOf2ts()) { 601 return; 602 } 603 let code: string; 604 let expr = (this.original as ArkIfStmt).getConditionExpr(); 605 code = `while (${this.valueToString(expr.getOp1())}`; 606 code += ` ${expr.getOperator().trim()} `; 607 code += `${this.valueToString(expr.getOp2())}) {`; 608 this.setText(code); 609 } 610 611 protected valueToString(value: Value): string { 612 if (!(value instanceof Local)) { 613 return this.transformer.valueToString(value); 614 } 615 616 for (const stmt of this.block.getStmts()) { 617 if (!(stmt instanceof ArkAssignStmt)) { 618 continue; 619 } 620 if (PrinterUtils.isDeIncrementStmt(stmt, NormalBinaryOperator.Addition) && (stmt.getLeftOp() as Local).getName() === value.getName()) { 621 this.context.setSkipStmt(stmt); 622 return `${value.getName()}++`; 623 } 624 625 if (PrinterUtils.isDeIncrementStmt(stmt, NormalBinaryOperator.Subtraction) && (stmt.getLeftOp() as Local).getName() === value.getName()) { 626 this.context.setSkipStmt(stmt); 627 return `${value.getName()}--`; 628 } 629 } 630 631 return this.transformer.valueToString(value); 632 } 633} 634 635export class SourceForStmt extends SourceWhileStmt { 636 incBlock: BasicBlock; 637 638 constructor(context: StmtPrinterContext, original: ArkIfStmt, block: BasicBlock, incBlock: BasicBlock) { 639 super(context, original, block); 640 this.incBlock = incBlock; 641 } 642 643 public transfer2ts(): void { 644 let code: string; 645 let expr = (this.original as ArkIfStmt).getConditionExpr(); 646 code = `for (; ${this.transformer.valueToString(expr.getOp1())}`; 647 code += ` ${expr.getOperator().trim()} `; 648 code += `${this.transformer.valueToString(expr.getOp2())}; `; 649 650 let stmtReader = new StmtReader(this.incBlock.getStmts()); 651 while (stmtReader.hasNext()) { 652 let sourceStmt = stmt2SourceStmt(this.context, stmtReader.next()); 653 sourceStmt.transfer2ts(); 654 code += sourceStmt.toString(); 655 if (stmtReader.hasNext()) { 656 code += ', '; 657 } 658 } 659 code += `) {`; 660 this.setText(code); 661 } 662} 663 664export class SourceDoStmt extends SourceStmt { 665 constructor(context: StmtPrinterContext, stmt: Stmt) { 666 super(context, stmt); 667 } 668 669 public transfer2ts(): void { 670 this.setText('do {'); 671 } 672 673 protected afterDump(): void { 674 this.printer.incIndent(); 675 } 676} 677 678export class SourceDoWhileStmt extends SourceWhileStmt { 679 constructor(context: StmtPrinterContext, stmt: ArkIfStmt, block: BasicBlock) { 680 super(context, stmt, block); 681 } 682 683 public transfer2ts(): void { 684 let code: string; 685 let expr = (this.original as ArkIfStmt).getConditionExpr(); 686 code = `} while (${this.valueToString(expr.getOp1())}`; 687 code += ` ${expr.getOperator().trim()} `; 688 code += `${this.valueToString(expr.getOp2())})`; 689 this.setText(code); 690 } 691 692 protected beforeDump(): void { 693 this.printer.decIndent(); 694 } 695 696 protected afterDump(): void {} 697} 698 699export class SourceElseStmt extends SourceStmt { 700 constructor(context: StmtPrinterContext, original: Stmt) { 701 super(context, original); 702 } 703 704 public transfer2ts(): void { 705 this.setText('} else {'); 706 } 707 708 protected beforeDump(): void { 709 this.printer.decIndent(); 710 } 711 712 protected afterDump(): void { 713 this.printer.incIndent(); 714 } 715} 716 717export class SourceContinueStmt extends SourceStmt { 718 constructor(context: StmtPrinterContext, original: Stmt) { 719 super(context, original); 720 } 721 722 // trans 2 break or continue 723 public transfer2ts(): void { 724 this.setText('continue;'); 725 } 726} 727 728export class SourceBreakStmt extends SourceStmt { 729 constructor(context: StmtPrinterContext, original: Stmt) { 730 super(context, original); 731 } 732 733 // trans 2 break or continue 734 public transfer2ts(): void { 735 this.setText('break;'); 736 } 737} 738 739export class SourceReturnStmt extends SourceStmt { 740 constructor(context: StmtPrinterContext, original: ArkReturnStmt) { 741 super(context, original); 742 } 743 744 public transfer2ts(): void { 745 this.setText(`return ${this.transformer.valueToString((this.original as ArkReturnStmt).getOp())};`); 746 } 747} 748 749export class SourceReturnVoidStmt extends SourceStmt { 750 constructor(context: StmtPrinterContext, original: ArkReturnVoidStmt) { 751 super(context, original); 752 } 753 754 public transfer2ts(): void { 755 if (this.original.getOriginPositionInfo().getLineNo() <= 0) { 756 this.setText(''); 757 } else { 758 this.setText('return;'); 759 } 760 } 761} 762 763export class SourceCompoundEndStmt extends SourceStmt { 764 constructor(context: StmtPrinterContext, stmt: Stmt, text: string) { 765 super(context, stmt); 766 this.setText(text); 767 } 768 769 public transfer2ts(): void {} 770 771 protected beforeDump(): void { 772 this.printer.decIndent(); 773 } 774} 775 776export class SourceCommonStmt extends SourceStmt { 777 constructor(context: StmtPrinterContext, stmt: Stmt) { 778 super(context, stmt); 779 } 780 781 public transfer2ts(): void { 782 this.setText(this.original.toString()); 783 } 784} 785 786export class SourceThrowStmt extends SourceStmt { 787 constructor(context: StmtPrinterContext, original: ArkThrowStmt) { 788 super(context, original); 789 } 790 791 public transfer2ts(): void { 792 this.setText(`throw ${this.transformer.valueToString((this.original as ArkThrowStmt).getOp())};`); 793 } 794} 795 796export class SourceTypeAliasStmt extends SourceStmt { 797 aliasType: AliasType; 798 constructor(context: StmtPrinterContext, original: Stmt, aliasType: AliasType) { 799 super(context, original); 800 this.aliasType = aliasType; 801 } 802 803 public transfer2ts(): void { 804 let modifiersArray: string[] = modifiers2stringArray(this.aliasType.getModifiers()); 805 let modifier = modifiersArray.length > 0 ? `${modifiersArray.join(' ')} ` : ''; 806 807 const expr = (this.original as ArkAliasTypeDefineStmt).getAliasTypeExpr(); 808 let typeOf = expr.getTransferWithTypeOf() ? 'typeof ' : ''; 809 let realGenericTypes = expr.getRealGenericTypes() ? `<${expr.getRealGenericTypes()!.join(', ')}>` : ''; 810 let genericTypes = this.aliasType.getGenericTypes() ? `<${this.transformer.typeArrayToString(this.aliasType.getGenericTypes()!)}>` : ''; 811 812 let typeObject = expr.getOriginalObject(); 813 if (typeObject instanceof Type) { 814 if (typeObject instanceof AliasType) { 815 this.setText(`${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${typeObject.getName()}${realGenericTypes};`); 816 } else { 817 this.setText( 818 `${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${this.transformer.typeToString(typeObject)}${realGenericTypes};` 819 ); 820 } 821 return; 822 } 823 if (typeObject instanceof ImportInfo) { 824 let exprStr = `import('${typeObject.getFrom()}')`; 825 if (typeObject.getImportClauseName() !== '') { 826 exprStr = `${exprStr}.${typeObject.getImportClauseName()}`; 827 } 828 this.setText(`${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${exprStr}${realGenericTypes};`); 829 return; 830 } 831 if (typeObject instanceof Local) { 832 this.setText( 833 `${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${this.transformer.valueToString(typeObject)}${realGenericTypes};` 834 ); 835 return; 836 } 837 if (typeObject instanceof ArkClass) { 838 let classTS = this.generateClassTS(typeObject); 839 this.setText(`${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${classTS}${realGenericTypes};`); 840 return; 841 } 842 if (typeObject instanceof ArkMethod) { 843 this.setText(`${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${typeObject.getName()}${realGenericTypes};`); 844 return; 845 } 846 this.setText(`${modifier}type ${this.aliasType.getName()}${genericTypes} = ${typeOf}${typeObject.getName()}${realGenericTypes};`); 847 } 848 849 private generateClassTS(arkClass: ArkClass): string { 850 let res = ''; 851 let classType = new ClassType(arkClass.getSignature()); 852 if (arkClass.getCategory() === ClassCategory.TYPE_LITERAL || arkClass.getCategory() === ClassCategory.OBJECT) { 853 res = this.transformer.literalObjectToString(classType); 854 } else { 855 res = this.transformer.typeToString(classType); 856 } 857 return res; 858 } 859} 860 861export class SourceTryStmt extends SourceStmt { 862 constructor(context: StmtPrinterContext, stmt: Stmt) { 863 super(context, stmt); 864 } 865 866 public transfer2ts(): void { 867 this.setText('try {'); 868 } 869 870 protected afterDump(): void { 871 this.printer.incIndent(); 872 } 873} 874 875export class SourceCatchStmt extends SourceStmt { 876 block: BasicBlock | undefined; 877 constructor(context: StmtPrinterContext, stmt: Stmt, block?: BasicBlock) { 878 super(context, stmt); 879 this.block = block; 880 } 881 882 public transfer2ts(): void { 883 if (this.block) { 884 let stmt = this.block!.getStmts()[0]; 885 if (stmt instanceof ArkAssignStmt) { 886 if (stmt.getLeftOp() instanceof Local) { 887 let name = (stmt.getLeftOp() as Local).getName(); 888 this.setText(`} catch (${name}) {`); 889 this.context.setSkipStmt(stmt); 890 return; 891 } 892 } 893 } 894 this.setText('} catch (e) {'); 895 } 896 897 protected beforeDump(): void { 898 this.printer.decIndent(); 899 } 900 901 protected afterDump(): void { 902 this.printer.incIndent(); 903 } 904} 905 906export class SourceFinallyStmt extends SourceStmt { 907 constructor(context: StmtPrinterContext, stmt: Stmt) { 908 super(context, stmt); 909 } 910 911 public transfer2ts(): void { 912 this.setText('} finally {'); 913 } 914 915 protected beforeDump(): void { 916 this.printer.decIndent(); 917 } 918 919 protected afterDump(): void { 920 this.printer.incIndent(); 921 } 922} 923 924export class SourceNewArrayExpr { 925 expr: ArkNewArrayExpr; 926 values: string[]; 927 928 constructor(expr: ArkNewArrayExpr) { 929 this.expr = expr; 930 this.values = []; 931 } 932 933 public addInitValue(value: string): void { 934 this.values.push(value); 935 } 936 937 public toString(): string { 938 return `[${this.values.join(', ')}]`; 939 } 940} 941 942export function stmt2SourceStmt(context: StmtPrinterContext, stmt: Stmt): SourceStmt { 943 if (stmt instanceof ArkAssignStmt) { 944 return new SourceAssignStmt(context, stmt); 945 } 946 if (stmt instanceof ArkInvokeStmt) { 947 return new SourceInvokeStmt(context, stmt); 948 } 949 if (stmt instanceof ArkReturnVoidStmt) { 950 return new SourceReturnVoidStmt(context, stmt); 951 } 952 if (stmt instanceof ArkReturnStmt) { 953 return new SourceReturnStmt(context, stmt); 954 } 955 if (stmt instanceof ArkThrowStmt) { 956 return new SourceThrowStmt(context, stmt); 957 } 958 if (stmt instanceof ArkAliasTypeDefineStmt) { 959 return new SourceTypeAliasStmt(context, stmt, stmt.getAliasType()); 960 } 961 logger.info(`stmt2SourceStmt ${stmt.constructor} not support.`); 962 return new SourceCommonStmt(context, stmt); 963} 964