1/* 2 * Copyright (c) 2021-2022 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 */ 15const path = require('path'); 16const fs = require('fs'); 17const result = require('../check_result.json'); 18const { apiCheckArr, getApiInfo, ErrorLevel, ApiCheckResult, apiCheckInfoArr, requireTypescriptModule } = require('../src/utils'); 19const ts = requireTypescriptModule(); 20 21/** 22 * 23 * @param {ts.Node} node current node 24 * @param {ts.Sourcefile} sourcefile root node 25 * @param {String} fileName full file name 26 * @param {String} errorType enum object:ErrorType 27 * @param {String} errorInfo error infomation 28 * @param {String} type jsdoc | api 29 * @param {Enum} level enum object:ErrorLevel 30 */ 31function addAPICheckErrorLogs(node, sourcefile, fileName, errorType, errorInfo, type, level) { 32 const checkFailFileNameSet = new Set(result.apiFiles); 33 if (!checkFailFileNameSet.has(fileName)) { 34 result.apiFiles.push(fileName); 35 } 36 const posOfNode = sourcefile.getLineAndCharacterOfPosition(node.getStart()); 37 const baseFileName = fileName.substring(fileName.indexOf('api'), fileName.length); 38 const errorMessage = `API check error of [${errorType.description}]: ${errorInfo}`; 39 const needMask = checkMarkError(node, errorMessage, baseFileName); 40 if (needMask) { 41 return; 42 } 43 if (level === ErrorLevel.HIGH || level === ErrorLevel.MIDDLE) { 44 ApiCheckResult.formatCheckResult = false; 45 } 46 47 apiCheckArr.push({ 48 errorType: errorType.description, 49 fileName: `${baseFileName}(line: ${posOfNode.line + 1}, col: ${posOfNode.character + 1})`, 50 type, 51 errorInfo, 52 version: getApiInfo(node).version, 53 basename: path.basename(fileName).replace(/\.d\.ts/g, ''), 54 level, 55 apiName: node.symbol ? node.symbol.escapedName : '', 56 apiFullText: node.getFullText(), 57 }); 58 59 apiCheckInfoArr.push({ 60 id: errorType.id, 61 level, 62 location: `${baseFileName}(line: ${posOfNode.line + 1}, col: ${posOfNode.character + 1})`, 63 filePath: baseFileName, 64 message: errorMessage, 65 }); 66} 67exports.addAPICheckErrorLogs = addAPICheckErrorLogs; 68 69function checkMarkError(node, errorMessage, baseFileName) { 70 let needMasking = false; 71 let apiName = ''; 72 if (node.name?.text) { 73 apiName = node.name.text; 74 } else if (node.escapedText) { 75 apiName = node.escapedText; 76 } 77 const apiText = node.getText().replace(/\r|\n|(\r\n)|\s/g, ''); 78 const apiKindName = Object.keys(ts.SyntaxKind).find(k => ts.SyntaxKind[k] === node?.kind); 79 const apiParentKind = [apiKindName]; 80 getParentkind(node, apiParentKind); 81 82 // unicode->json 83 const maskInfos = parseUnicodeConfig(); 84 if (maskInfos === '') { 85 return needMasking; 86 } 87 maskInfos.maskInformations.forEach(maskInfo => { 88 if (maskInfo.kind === apiKindName && 89 maskInfo.name === apiName && 90 maskInfo.hierarchicalRelationship === JSON.stringify(apiParentKind) && 91 maskInfo.text.replace(/\s/g, '') === apiText && 92 maskInfo.errorMassage === errorMessage && 93 JSON.stringify(maskInfo.fileName) === JSON.stringify(baseFileName.split(path.sep).join('\\'))) { 94 needMasking = true; 95 } 96 }); 97 return needMasking; 98} 99 100function getParentkind(node, parentkindArr) { 101 if (ts.isSourceFile(node)) { 102 return; 103 } 104 if (ts.isSourceFile(node.parent)) { 105 parentkindArr.push(Object.keys(ts.SyntaxKind).find(k => ts.SyntaxKind[k] === node.parent.kind)); 106 return; 107 } 108 if (!ts.isModuleBlock(node.parent)) { 109 parentkindArr.push(Object.keys(ts.SyntaxKind).find(k => ts.SyntaxKind[k] === node.parent.kind)); 110 getParentkind(node.parent, parentkindArr); 111 } else if (ts.isModuleBlock(node.parent)) { 112 getParentkind(node.parent, parentkindArr); 113 } 114} 115exports.getParentkind = getParentkind; 116 117function parseUnicodeConfig() { 118 let maskInfos = ''; 119 if (!fs.existsSync(path.resolve(__dirname, '../config/errorMaskWhiteList.txt'))) { 120 return maskInfos; 121 } 122 const maskInformations = fs.readFileSync(path.resolve(__dirname, '../config/errorMaskWhiteList.txt'), 'utf-8'); 123 let maskInfoString = ''; 124 if (maskInformations && maskInformations.indexOf('\\u') === -1) { 125 return JSON.parse(maskInfoString); 126 } 127 let valArr = maskInformations.split('\\u'); 128 for (let j = 0; j < valArr.length; j++) { 129 if (valArr[j] === '') { 130 continue; 131 } 132 maskInfoString += String.fromCharCode(parseInt(valArr[j], 16)); 133 } 134 maskInfos = JSON.parse(maskInfoString); 135 return maskInfos; 136} 137 138function string2unicode() { 139 const str = fs.readFileSync('../test/errorlist.json', 'utf-8'); 140 let ret = ''; 141 let ustr = ''; 142 143 for (let i = 0; i < str.length; i++) { 144 let code = str.charCodeAt(i); 145 let code16 = code.toString(16); 146 if (code < 0xf) { 147 ustr = '\\u' + '000' + code16; 148 } else if (code < 0xff) { 149 ustr = '\\u' + '00' + code16; 150 } else if (code < 0xfff) { 151 ustr = '\\u' + '0' + code16; 152 } else { 153 ustr = '\\u' + code16; 154 } 155 ret += ustr; 156 } 157 fs.writeFileSync('errorlist.txt', ret); 158 return ret; 159}