1/* 2 * Copyright (c) 2024 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 16export enum TimePhase { 17 START = 'start', 18 GET_PROGRAM = 'getProgram(not ArkTSLinter)', 19 GET_REVERSE_STRICT_BUILDER_PROGRAM = 'getReverseStrictBuilderProgram', 20 UPDATE_ERROR_FILE = 'updateErrorFile', 21 INIT = 'init', 22 STRICT_PROGRAM_GET_SEMANTIC_DIAGNOSTICS = 'strictProgramGetSemanticDiagnostics', 23 STRICT_PROGRAM_GET_SYNTACTIC_DIAGNOSTICS = 'strictProgramGetSyntacticDiagnostics', 24 NON_STRICT_PROGRAM_GET_SEMANTIC_DIAGNOSTICS = 'nonStrictProgramGetSemanticDiagnostics', 25 NON_STRICT_PROGRAM_GET_SYNTACTIC_DIAGNOSTICS = 'nonStrictProgramGetSyntacticDiagnostics', 26 GET_TSC_DIAGNOSTICS = 'getTscDiagnostics', 27 EMIT_BUILD_INFO = 'emitBuildInfo', 28 LINT = 'lint' 29} 30 31const MILLISECOND_TO_SECOND = 1000.0; 32 33export class ArkTSLinterTimePrinter { 34 private static instance?: ArkTSLinterTimePrinter; 35 private arkTSTimePrintSwitch: boolean; 36 private readonly timeMap = new Map<string, number>(); 37 38 private constructor(ArkTSTimePrintSwitch: boolean = false) { 39 this.arkTSTimePrintSwitch = ArkTSTimePrintSwitch; 40 } 41 42 static getInstance(): ArkTSLinterTimePrinter { 43 if (!ArkTSLinterTimePrinter.instance) { 44 ArkTSLinterTimePrinter.instance = new ArkTSLinterTimePrinter(); 45 } 46 return ArkTSLinterTimePrinter.instance; 47 } 48 49 static destroyInstance(): void { 50 ArkTSLinterTimePrinter.instance = undefined; 51 } 52 53 setArkTSTimePrintSwitch(arkTSTimePrintSwitch: boolean): void { 54 this.arkTSTimePrintSwitch = arkTSTimePrintSwitch; 55 } 56 57 appendTime(key: string): void { 58 if (this.arkTSTimePrintSwitch) { 59 this.timeMap.set(key, Date.now()); 60 } 61 } 62 63 // eslint-disable-next-line class-methods-use-this 64 private formatMapAsTable(map: Map<string, number>): string { 65 if (!map.has(TimePhase.START)) { 66 return 'ArkTSLinterTimePrinter: START phase is not exist!'; 67 } 68 let maxKeyLength = 0; 69 let lastVal = 0; 70 let sum = 0; 71 const printMap = new Map(map); 72 printMap.forEach((value, key) => { 73 maxKeyLength = Math.max(maxKeyLength, key.toString().length); 74 if (key !== TimePhase.START) { 75 const relativeVal = value - lastVal; 76 if (key !== TimePhase.GET_PROGRAM) { 77 sum += relativeVal; 78 } 79 printMap.set(key, relativeVal / MILLISECOND_TO_SECOND); 80 } 81 lastVal = value; 82 }); 83 printMap.set('total', sum / MILLISECOND_TO_SECOND); 84 85 let table = ''; 86 printMap.forEach((value, key) => { 87 if (key !== TimePhase.START) { 88 const paddedKey = key.toString().padEnd(maxKeyLength, ' '); 89 table += `${paddedKey} | ${value.toString()}\n`; 90 } 91 }); 92 const header = `${'Phase'.padEnd(maxKeyLength, ' ')} | Time(seconds)\n`; 93 const FIXLENGTH = ('Phase' + 'Time').length; 94 const separator = '-'.repeat(maxKeyLength + FIXLENGTH) + '\n'; 95 return `${header}${separator}${table}`; 96 } 97 98 printTimes(): void { 99 if (this.arkTSTimePrintSwitch) { 100 const formattedMap = this.formatMapAsTable(this.timeMap); 101 console.log(formattedMap); 102 } 103 } 104} 105