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 16import { GEN_ABC_PLUGIN_NAME } from './common/ark_define'; 17import { 18 ErrorCode, 19 SubsystemCode, 20 ES2ABC_ERROR_MAPPING 21} from './error_code'; 22 23export class CommonLogger { 24 private static instance: CommonLogger; 25 private logger: Object; 26 private hvigorConsoleLoggerMap: { [key in SubsystemCode]?: Object }; 27 throwArkTsCompilerError: Object; 28 29 private constructor(rollupObject: Object) { 30 this.logger = rollupObject.share.getLogger(GEN_ABC_PLUGIN_NAME); 31 this.throwArkTsCompilerError = rollupObject.share.throwArkTsCompilerError; 32 this.hvigorConsoleLoggerMap = this.initializeHvigorConsoleLoggers(rollupObject); 33 } 34 35 private initializeHvigorConsoleLoggers(rollupObject: Object): { [key in SubsystemCode]?: Object } { 36 const loggerMap: { [key in SubsystemCode]?: Object } = {}; 37 if (typeof rollupObject.share.getHvigorConsoleLogger === 'function') { 38 loggerMap[SubsystemCode.ETS2BUNDLE] = rollupObject.share.getHvigorConsoleLogger(SubsystemCode.ETS2BUNDLE); 39 loggerMap[SubsystemCode.ABC2PROGRAM] = rollupObject.share.getHvigorConsoleLogger(SubsystemCode.ABC2PROGRAM); 40 loggerMap[SubsystemCode.ES2ABC] = rollupObject.share.getHvigorConsoleLogger(SubsystemCode.ES2ABC); 41 } 42 return loggerMap; 43 } 44 45 static getInstance(rollupObject: Object): CommonLogger { 46 if (!CommonLogger.instance) { 47 CommonLogger.instance = new CommonLogger(rollupObject); 48 } 49 return CommonLogger.instance; 50 } 51 52 static destroyInstance(): void { 53 CommonLogger.instance = undefined; 54 } 55 56 info(...args: string[]): void { 57 this.logger.info(...args); 58 } 59 60 debug(...args: string[]): void { 61 this.logger.debug(...args); 62 } 63 64 warn(...args: string[]): void { 65 this.logger.warn(...args); 66 } 67 68 error(...args: string[]): void { 69 this.logger.error(...args); 70 } 71 72 printError(error: LogData | string): void { 73 if (typeof error === 'string') { 74 this.logger.error(error); 75 return; 76 } 77 const hvigorConsoleLogger = this.getLoggerFromErrorCode(error.code); 78 if (hvigorConsoleLogger) { 79 hvigorConsoleLogger.printError(error); 80 } else { 81 this.logger.error(error.toString()); 82 } 83 } 84 85 printErrorAndExit(error: LogData | string): void { 86 if (typeof error === 'string') { 87 this.throwArkTsCompilerError(error); 88 return; 89 } 90 const hvigorConsoleLogger = this.getLoggerFromErrorCode(error.code); 91 if (hvigorConsoleLogger) { 92 hvigorConsoleLogger.printErrorAndExit(error); 93 } else { 94 this.throwArkTsCompilerError(error.toString()); 95 } 96 } 97 98 private isValidErrorCode(errorCode: string): boolean { 99 return /^\d{8}$/.test(errorCode); 100 } 101 102 private getLoggerFromErrorCode(errorCode: string): Object | undefined { 103 if (!this.isValidErrorCode(errorCode)) { 104 return undefined; 105 } 106 const subsystemCode = errorCode.slice(0, 3); 107 return this.hvigorConsoleLoggerMap[subsystemCode]; 108 } 109} 110 111export class LogDataFactory { 112 113 static newInstance( 114 code: ErrorCode, 115 description: string, 116 cause: string = '', 117 position: string = '', 118 solutions: string[] = [] 119 ): LogData { 120 const data: LogData = new LogData(code, description, cause, position, solutions); 121 return data; 122 } 123 124 /** 125 * Parses an es2abc error string and returns a LogData instance. 126 * @param error The es2abc error string to parse. 127 * @returns A LogData instance or undefined if no matching error is found. 128 */ 129 static newInstanceFromEs2AbcError(error: string): LogData | undefined { 130 for (const prefix in ES2ABC_ERROR_MAPPING) { 131 if (error.startsWith(prefix)) { 132 const { code, description, solutions } = ES2ABC_ERROR_MAPPING[prefix]; 133 const cause = error.replace(prefix, ''); 134 return LogDataFactory.newInstance(code, description, cause, '', solutions); 135 } 136 } 137 return undefined; 138 } 139} 140 141export class LogData { 142 143 code: string; 144 description: string; 145 cause: string; 146 position: string; 147 solutions: string[]; 148 149 constructor( 150 code: ErrorCode, 151 description: string, 152 cause: string = '', 153 position: string = '', 154 solutions: string[] = [ArkTSInternalErrorSolution] 155 ) { 156 this.code = code; 157 this.description = description; 158 this.cause = cause; 159 this.position = position; 160 this.solutions = solutions; 161 } 162 163 toString(): string { 164 let errorString = `ERROR Code: ${this.code} ${this.description}\n`; 165 166 if (this.cause || this.position) { 167 errorString += `Error Message: ${this.cause}`; 168 if (this.position) { 169 errorString += ` ${this.position}`; 170 } 171 errorString += '\n\n'; 172 } 173 174 if (this.solutions.length > 0 && this.solutions[0] !== '') { 175 errorString += `* Try the following: \n${this.solutions.map(str => ` > ${str}`).join('\n')}\n`; 176 } 177 178 return errorString; 179 } 180}