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