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 { 16 requireTypescriptModule, tagsArrayOfOrder, commentNodeWhiteList, parseJsDoc, ErrorType, ErrorLevel, FileType, 17 inheritArr, ErrorValueInfo, createErrorInfo, isAscending } = require('../utils'); 18const { addAPICheckErrorLogs } = require('../compile_info'); 19const rules = require('../../code_style_rule.json'); 20const whiteLists = require('../../config/jsdocCheckWhiteList.json'); 21const ts = requireTypescriptModule(); 22 23/** 24 * 判断标签是否为官方标签 25 */ 26function isOfficialTag(tagName) { 27 return tagsArrayOfOrder.indexOf(tagName) === -1; 28} 29 30/** 31 * 对form标签的顺序做兼容处理 32 */ 33function formOrderCheck(tags, tagIndex, firstIndex, secondIndex) { 34 const frontFirstIndex = tagIndex - 1 > -1 ? tagsArrayOfOrder.indexOf(tags[tagIndex - 1].tag) : 0; 35 const formNeighborArr = [frontFirstIndex, firstIndex]; 36 const newTagIndex = tagsArrayOfOrder.lastIndexOf(tags[tagIndex].tag); 37 const newFormNeighborArr = [frontFirstIndex, newTagIndex]; 38 if (secondIndex > -1) { 39 formNeighborArr.push(secondIndex); 40 newFormNeighborArr.push(secondIndex); 41 } 42 if (!isAscending(formNeighborArr) && !isAscending(newFormNeighborArr)) { 43 return false; 44 } 45 return true; 46} 47 48 49 50/** 51 * 判断标签排列是否为升序 52 */ 53function isAscendingOrder(tags) { 54 let checkResult = true; 55 for (let tagIndex = 0; tagIndex < tags.length; tagIndex++) { 56 if (tagIndex + 1 < tags.length) { 57 // 获取前后两个tag下标 58 const firstIndex = tagsArrayOfOrder.indexOf(tags[tagIndex].tag); 59 const secondIndex = tagsArrayOfOrder.indexOf(tags[tagIndex + 1].tag); 60 // 判断标签是否为官方标签 61 const firstTag = isOfficialTag(tags[tagIndex].tag); 62 // 非自定义标签在前或数组降序时报错 63 if (tags[tagIndex].tag !== 'form' && tags[tagIndex + 1].tag !== 'form' && 64 ((firstTag && secondIndex > -1) || (firstIndex > secondIndex && secondIndex > -1))) { 65 checkResult = false; 66 break; 67 } else if (tags[tagIndex].tag === 'form') { 68 checkResult = formOrderCheck(tags, tagIndex, firstIndex, secondIndex); 69 } 70 } 71 }; 72 return checkResult; 73} 74 75// check jsdoc order 76function checkApiOrder(comments) { 77 const checkOrderRusult = []; 78 comments.forEach(docInfo => { 79 if (isAscendingOrder(docInfo.tags)) { 80 checkOrderRusult.push({ 81 checkResult: true, 82 errorInfo: '', 83 }); 84 } else { 85 const errorInfo = ErrorValueInfo.ERROR_ORDER; 86 checkOrderRusult.push({ 87 checkResult: false, 88 errorInfo: errorInfo, 89 }); 90 } 91 }); 92 return checkOrderRusult; 93} 94exports.checkApiOrder = checkApiOrder; 95 96function checkAPITagName(tag, node, sourcefile, fileName, JSDocIndec) { 97 const APITagNameResult = { 98 checkResult: true, 99 errorInfo: '', 100 }; 101 const tagName = tag.tag; 102 const docTags = [...rules.decorators.customDoc, ...rules.decorators.jsDoc]; 103 const decoratorRuleSet = new Set(docTags); 104 if (!decoratorRuleSet.has(tagName) && commentNodeWhiteList.includes(node.kind)) { 105 APITagNameResult.checkResult = false; 106 APITagNameResult.errorInfo = createErrorInfo(ErrorValueInfo.ERROR_LABELNAME, [tagName]); 107 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.WRONG_SCENE, APITagNameResult.errorInfo, 108 FileType.JSDOC, ErrorLevel.MIDDLE); 109 } 110 return APITagNameResult; 111} 112exports.checkAPITagName = checkAPITagName; 113 114function checkParentInheritTag(node, inheritTag, inheritResult, JSocIndex) { 115 const parentTagArr = []; 116 if (ts.isSourceFile(node.parent)) { 117 return inheritResult; 118 } 119 if (!ts.isModuleBlock(node.parent)) { 120 const comments = parseJsDoc(node.parent); 121 if (comments.length > 0 && Array.isArray(comments[comments.length - 1].tags)) { 122 comments[comments.length - 1].tags.forEach(tag => { 123 parentTagArr.push(tag.tag); 124 }); 125 if (parentTagArr.includes(inheritTag)) { 126 inheritResult.checkResult = false; 127 inheritResult.errorInfo += createErrorInfo(ErrorValueInfo.ERROR_INFO_INHERIT, [inheritTag]); 128 } else { 129 checkParentInheritTag(node.parent, inheritTag, inheritResult, JSocIndex); 130 } 131 } 132 } else if (ts.isModuleBlock(node.parent)) { 133 checkParentInheritTag(node.parent, inheritTag, inheritResult, JSocIndex); 134 } 135 136 return inheritResult; 137} 138 139function checkInheritTag(comment, node, sourcefile, fileName, JSocIndex) { 140 const inheritResult = { 141 checkResult: true, 142 errorInfo: '', 143 }; 144 const tagArr = []; 145 if (commentNodeWhiteList.includes(node.kind)) { 146 comment.tags.forEach(tag => { 147 tagArr.push(tag.tag); 148 }); 149 inheritArr.forEach((inheritTag, index) => { 150 if (!tagArr.includes(inheritTag)) { 151 checkParentInheritTag(node, inheritArr[index], inheritResult, JSocIndex); 152 } 153 }); 154 if (!inheritResult.checkResult) { 155 addAPICheckErrorLogs(node, sourcefile, fileName, ErrorType.WRONG_SCENE, inheritResult.errorInfo, FileType.API, 156 ErrorLevel.MIDDLE); 157 } 158 } 159 return inheritResult; 160} 161exports.checkInheritTag = checkInheritTag; 162