1/* 2 * Copyright (c) 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 { ImportInfo } from '../../core/model/ArkImport'; 17import { ArkMetadataKind, CommentsMetadata } from '../../core/model/ArkMetadata'; 18import { BasePrinter, Dump } from './BasePrinter'; 19 20export class ImportPrinter extends BasePrinter { 21 infos: ImportInfo[]; 22 23 public constructor(infos: ImportInfo[], indent: string = '') { 24 super(indent); 25 this.infos = infos; 26 } 27 28 public getLine(): number { 29 return this.infos[0].getOriginTsPosition().getLineNo(); 30 } 31 32 public dump(): string { 33 const commentsMetadata = this.infos[0].getMetadata(ArkMetadataKind.LEADING_COMMENTS); 34 if (commentsMetadata instanceof CommentsMetadata) { 35 this.printComments(commentsMetadata); 36 } 37 let clauseNames: string[] = []; 38 let namedImports: string[] = []; 39 40 for (const info of this.infos) { 41 if (info.getImportType() === 'Identifier') { 42 // sample: import fs from 'fs' 43 clauseNames.push(info.getImportClauseName()); 44 } else if (info.getImportType() === 'NamedImports') { 45 // sample: import {xxx} from './yyy' 46 if (info.getNameBeforeAs()) { 47 namedImports.push(`${info.getNameBeforeAs()} as ${info.getImportClauseName()}`); 48 } else { 49 namedImports.push(info.getImportClauseName()); 50 } 51 } else if (info.getImportType() === 'NamespaceImport') { 52 // sample: import * as ts from 'ohos-typescript' 53 clauseNames.push(`* as ${info.getImportClauseName()}`); 54 } else if (info.getImportType() === 'EqualsImport') { 55 // sample: import mmmm = require('./xxx') 56 this.printer.writeIndent().writeLine(`import ${info.getImportClauseName()} = require('${info.getFrom() as string}');`); 57 } else { 58 // sample: import '../xxx' 59 this.printer.writeIndent().writeLine(`import '${info.getFrom() as string}';`); 60 } 61 } 62 63 if (namedImports.length > 0) { 64 clauseNames.push(`{${namedImports.join(', ')}}`); 65 } 66 67 this.printer.writeIndent().writeLine(`import ${clauseNames.join(', ')} from '${this.infos[0].getFrom() as string}';`); 68 69 return this.printer.toString(); 70 } 71} 72 73function mergeImportInfos(infos: ImportInfo[]): Map<string, ImportInfo[]> { 74 let map = new Map<string, ImportInfo[]>(); 75 76 for (let info of infos) { 77 let key = `${info.getOriginTsPosition().getLineNo()}-${info.getFrom()}`; 78 let merge = map.get(key) || []; 79 merge.push(info); 80 map.set(key, merge); 81 } 82 83 return map; 84} 85 86export function printImports(imports: ImportInfo[], indent: string): Dump[] { 87 let mergeImports = mergeImportInfos(imports); 88 let items: Dump[] = []; 89 90 for (const [_, importInfos] of mergeImports) { 91 items.push(new ImportPrinter(importInfos, indent)); 92 } 93 return items; 94} 95