1/* 2 * Copyright (c) 2023 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 16const path = require('path'); 17 18const ApiStatusCode = { 19 DELETE: 0, 20 DELETE_DTS: 1, 21 DELETE_CLASS: 2, 22 NEW_API: 3, 23 VERSION_CHNAGES: 4, 24 DEPRECATED_CHNAGES: 5, 25 NEW_ERRORCODE: 6, 26 ERRORCODE_CHANGES: 7, 27 SYSCAP_CHANGES: 8, 28 SYSTEM_API_CHNAGES: 9, 29 PERMISSION_DELETE: 10, 30 PERMISSION_NEW: 11, 31 PERMISSION_CHANGES: 12, 32 MODEL_CHNAGES: 13, 33 TYPE_CHNAGES: 14, 34 CLASS_CHANGES: 15, 35 FUNCTION_CHANGES: 16, 36 CHANGELOG: 17, 37 DTS_CHANGED: 18, 38 FORM_CHANGED: 19, 39 CROSSPLATFORM_CHANGED: 20, 40 NEW_DTS: 21, 41 NEW_CLASS: 22, 42 HOSTORICAL_JSDOC_CHANGE: 23 43}; 44 45const StatusMessages = []; 46StatusMessages[ApiStatusCode.DELETE] = '删除'; 47StatusMessages[ApiStatusCode.DELETE_DTS] = 'd.ts删除'; 48StatusMessages[ApiStatusCode.NEW_DTS] = 'd.ts新增'; 49StatusMessages[ApiStatusCode.DELETE_CLASS] = '类型删除'; 50StatusMessages[ApiStatusCode.NEW_CLASS] = '类型新增'; 51StatusMessages[ApiStatusCode.NEW_API] = '新增'; 52StatusMessages[ApiStatusCode.VERSION_CHNAGES] = '起始版本有变化'; 53StatusMessages[ApiStatusCode.DEPRECATED_CHNAGES] = '废弃版本有变化'; 54StatusMessages[ApiStatusCode.NEW_ERRORCODE] = '新增(错误码)'; 55StatusMessages[ApiStatusCode.ERRORCODE_CHANGES] = '错误码有变化'; 56StatusMessages[ApiStatusCode.SYSCAP_CHANGES] = 'SysCap有变化'; 57StatusMessages[ApiStatusCode.SYSTEM_API_CHNAGES] = '访问级别有变化'; 58StatusMessages[ApiStatusCode.PERMISSION_DELETE] = '删除(权限)'; 59StatusMessages[ApiStatusCode.PERMISSION_NEW] = '新增(权限)'; 60StatusMessages[ApiStatusCode.PERMISSION_CHANGES] = '权限有变化'; 61StatusMessages[ApiStatusCode.MODEL_CHNAGES] = 'model有变化'; 62StatusMessages[ApiStatusCode.TYPE_CHNAGES] = 'type有变化'; 63StatusMessages[ApiStatusCode.CLASS_CHANGES] = '类型有变化'; 64StatusMessages[ApiStatusCode.FUNCTION_CHANGES] = '函数有变化'; 65StatusMessages[ApiStatusCode.CHANGELOG] = 'changelog'; 66StatusMessages[ApiStatusCode.DTS_CHANGED] = 'd.ts有变化'; 67StatusMessages[ApiStatusCode.FORM_CHANGED] = '卡片应用支持性有变化'; 68StatusMessages[ApiStatusCode.CROSSPLATFORM_CHANGED] = '跨平台能力有变化'; 69StatusMessages[ApiStatusCode.HOSTORICAL_JSDOC_CHANGE] = '历史jsdoc有变化'; 70 71function reportDeletedApi(api, syscap) { 72 return wrapApiDiffInfo(api, ApiStatusCode.DELETE, '', '', '', syscap); 73} 74 75function reportDeletedClass(api, syscap) { 76 const reporterData = new ReporterData(api); 77 reporterData.setStatusCode(ApiStatusCode.DELETE_CLASS) 78 .setStatusMessage(StatusMessages[ApiStatusCode.DELETE_CLASS] + `(${api.getApiType().name})`) 79 .setOldMessage('') 80 .setNewMessage('') 81 .setSyscap(syscap); 82 return reporterData; 83} 84 85function reportDeletedPackage(packageName, dtsName) { 86 const reporterData = new ReporterData(undefined); 87 reporterData.setStatusCode(ApiStatusCode.DELETE_DTS) 88 .setPackageName(packageName) 89 .setOldMessage('d.ts声明文件已删除') 90 .setNewMessage('') 91 .setDtsName(path.basename(dtsName)) 92 .setDtsPath(dtsName); 93 return reporterData; 94} 95 96function reportNewPackage(packageName, dtsName, syscap) { 97 const reporterData = new ReporterData(undefined); 98 reporterData.setStatusCode(ApiStatusCode.NEW_DTS) 99 .setPackageName(packageName) 100 .setOldMessage('') 101 .setNewMessage('新增d.ts声明文件') 102 .setDtsName(path.basename(dtsName)) 103 .setDtsPath(dtsName) 104 .setSyscap(syscap); 105 return reporterData; 106} 107 108function reportNewApi(api, syscap) { 109 return wrapApiDiffInfo(api, ApiStatusCode.NEW_API, '', '', '', syscap); 110} 111 112function reportApiChanges(apiChanges) { 113 return wrapApiDiffInfo(apiChanges.api, apiChanges.statusCode, 114 `${apiChanges.oldMessage}`, `${apiChanges.newMessage}`, `${apiChanges.hint}`, `${apiChanges.syscap}`); 115} 116 117function wrapApiDiffInfo(api, statusCode, oldMessage, newMessage, hint, syscap) { 118 const reporterData = new ReporterData(api); 119 reporterData.setStatusCode(statusCode) 120 .setOldMessage(oldMessage) 121 .setNewMessage(newMessage) 122 .setHint(hint) 123 .setSyscap(syscap); 124 return reporterData; 125} 126 127function addNodeInfo(diffItem, changeInfo) { 128 diffItem.oldNode = changeInfo.oldNode; 129 diffItem.newNode = changeInfo.newNode; 130 return diffItem; 131} 132 133exports.StatusCode = ApiStatusCode; 134exports.StatusMessages = StatusMessages; 135 136class ReporterData { 137 constructor(apiDigestInfo) { 138 if (apiDigestInfo) { 139 this.packageName = apiDigestInfo.getPackageName(); 140 this.className = apiDigestInfo.getClassName(); 141 this.rawText = apiDigestInfo.getRawText(); 142 this.dtsName = path.basename(apiDigestInfo.getPath()); 143 this.dtsPath = apiDigestInfo.getPath(); 144 } else { 145 this.packageName = ''; 146 this.className = ''; 147 this.rawText = ''; 148 this.dtsName = ''; 149 this.dtsPath = ''; 150 } 151 this.hint = ''; 152 this.changelogs = new Set(); 153 } 154 155 setDtsPath(dtsPath) { 156 this.dtsPath = dtsPath; 157 return this; 158 } 159 160 161 setPackageName(packageName) { 162 this.packageName = packageName; 163 return this; 164 } 165 166 setDtsName(dtsName) { 167 this.dtsName = path.basename(dtsName); 168 return this; 169 } 170 171 setClassName(className) { 172 this.className = className; 173 return this; 174 } 175 176 setStatusCode(statusCode) { 177 this.statusCode = statusCode; 178 this.status = StatusMessages[statusCode]; 179 return this; 180 } 181 182 setStatusMessage(msg) { 183 this.status = msg; 184 return this; 185 } 186 187 setOldMessage(oldMessage) { 188 this.oldMessage = oldMessage; 189 return this; 190 } 191 192 setNewMessage(newMessage) { 193 this.newMessage = newMessage; 194 return this; 195 } 196 197 setHint(hint) { 198 this.hint = hint; 199 return this; 200 } 201 202 setSyscap(syscap) { 203 if (!syscap) { 204 this.syscap = ''; 205 return this; 206 } 207 this.syscap = syscap.split('.')[1]; 208 return this; 209 } 210} 211 212class DiffReporter { 213 constructor() { 214 this.diffs = new Map(); 215 this.diffInfos = []; 216 } 217 218 addDeletedApi(api, syscap) { 219 this.setMap(reportDeletedApi(api, syscap)); 220 } 221 222 addDeletedPackage(packageName, dtsName) { 223 this.setMap(reportDeletedPackage(packageName, dtsName)); 224 } 225 226 addNewPackage(packageName, dtsName, syscap) { 227 this.setMap(reportNewPackage(packageName, dtsName, syscap)); 228 } 229 230 addNewApi(api, syscap) { 231 this.setMap(reportNewApi(api, syscap)); 232 } 233 234 addChangedApi(apiChanges) { 235 let reportItem; 236 if (apiChanges.statusCode === ApiStatusCode.DELETE_CLASS) { 237 reportItem = reportDeletedClass(apiChanges.api, apiChanges.syscap); 238 } else { 239 reportItem = reportApiChanges(apiChanges); 240 } 241 this.setMap(reportItem); 242 } 243 244 addDiffInfo(apiChanges) { 245 const reportItem = reportApiChanges(apiChanges); 246 this.diffInfos.push(addNodeInfo(reportItem, apiChanges)); 247 } 248 249 setMap(api) { 250 const key = `${api.dtsPath}#${this.formatApiText(api.rawText)}`; 251 if (this.diffs.get(key)) { 252 this.diffs.get(key).push(api); 253 } else { 254 this.diffs.set(key, [api]); 255 } 256 } 257 258 getResults() { 259 return this.diffs; 260 } 261 262 getDiffInfos() { 263 return this.diffInfos; 264 } 265 266 formatApiText(apiText) { 267 return apiText.replace(/\r|\n|\s+|\,|\;/g, ''); 268 } 269} 270 271exports.DiffReporter = DiffReporter;