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 16import { 17 ApiInfo, 18 ApiType, 19 BasicApiInfo, 20 ConstantInfo, 21 EnumValueInfo, 22 MethodInfo, 23 ParamInfo, 24 EnumInfo, 25 PropertyInfo, 26 TypeAliasInfo, 27 ClassInfo, 28} from '../../typedef/parser/ApiInfoDefination'; 29import { Comment } from '../../typedef/parser/Comment'; 30import { 31 ApiDiffType, 32 ApiStatusCode, 33 ApiNodeDiffProcessor, 34 ApiSceneDiffProcessor, 35 ApiScenesDiffProcessor, 36 BasicDiffInfo, 37 DiffTypeInfo, 38 diffMap, 39 incompatibleApiDiffTypes, 40 JsDocDiffProcessor, 41} from '../../typedef/diff/ApiInfoDiff'; 42import { StringUtils } from '../../utils/StringUtils'; 43import { CharMapType, CompareReturnObjType, PermissionsProcessorHelper, RangeChange } from './PermissionsProcessor'; 44import { DecoratorInfo } from '../../typedef/parser/Decorator'; 45import { ApiStatisticsHelper } from '../statistics/Statistics'; 46import { FunctionUtils } from '../../utils/FunctionUtils'; 47import { CommonFunctions } from '../../utils/checkUtils'; 48import { NumberConstant } from '../../utils/Constant'; 49 50export namespace DiffProcessorHelper { 51 /** 52 * 权限编码进行逻辑运算的转义规则 53 */ 54 export const permissionsCharMap: CharMapType = new Map([ 55 ['and', { splitchar: 'and', transferchar: '&' }], 56 ['or', { splitchar: 'or', transferchar: '|' }], 57 ]); 58 59 /** 60 * type进行逻辑运算的转义规则 61 */ 62 export const typeCharMap: CharMapType = new Map([ 63 ['and', { splitchar: '&', transferchar: '&' }], 64 ['or', { splitchar: '|', transferchar: '|' }], 65 ]); 66 67 /** 68 * 处理api节点jsdoc中的diff信息工具 69 * 70 */ 71 export class JsDocDiffHelper { 72 static diffJsDocInfo(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 73 const oldJsDocInfo: Comment.JsDocInfo | undefined = oldApiInfo.getLastJsDocInfo(); 74 const newJsDocInfo: Comment.JsDocInfo | undefined = newApiInfo.getLastJsDocInfo(); 75 JsDocDiffHelper.diffSinceVersion(oldApiInfo, newApiInfo, diffInfos); 76 for (let i = 0; i < jsDocDiffProcessors.length; i++) { 77 const jsDocDiffProcessor: JsDocDiffProcessor | undefined = jsDocDiffProcessors[i]; 78 const diffType: DiffTypeInfo | undefined = jsDocDiffProcessor(oldJsDocInfo, newJsDocInfo); 79 if (!diffType) { 80 continue; 81 } 82 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffType); 83 diffInfos.push(diffInfo); 84 } 85 } 86 87 static getFirstSinceVersion(jsDocInfos: Comment.JsDocInfo[]): string { 88 let sinceVersion: string = ''; 89 for (let i = 0; i < jsDocInfos.length; i++) { 90 const jsDocInfo: Comment.JsDocInfo = jsDocInfos[i]; 91 if (jsDocInfo.getSince() !== '-1') { 92 sinceVersion = jsDocInfo.getSince(); 93 return sinceVersion; 94 } 95 } 96 return sinceVersion; 97 } 98 99 static diffSinceVersion(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 100 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 101 const oldJsDocInfos: Comment.JsDocInfo[] = oldApiInfo.getJsDocInfos(); 102 const newJsDocInfos: Comment.JsDocInfo[] = newApiInfo.getJsDocInfos(); 103 const sinceVersionOfOld: string = JsDocDiffHelper.getFirstSinceVersion(oldJsDocInfos); 104 const sinceVersionOfNew: string = JsDocDiffHelper.getFirstSinceVersion(newJsDocInfos); 105 diffTypeInfo 106 .setStatusCode(ApiStatusCode.VERSION_CHNAGES) 107 .setOldMessage(sinceVersionOfOld) 108 .setNewMessage(sinceVersionOfNew); 109 if (sinceVersionOfOld === sinceVersionOfNew) { 110 return; 111 } 112 if (sinceVersionOfOld === '-1') { 113 diffTypeInfo.setDiffType(ApiDiffType.SINCE_VERSION_NA_TO_HAVE); 114 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 115 diffInfos.push(diffInfo); 116 return; 117 } 118 if (sinceVersionOfNew === '-1') { 119 diffTypeInfo.setDiffType(ApiDiffType.SINCE_VERSION_HAVE_TO_NA); 120 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 121 diffInfos.push(diffInfo); 122 return; 123 } 124 diffTypeInfo.setDiffType(ApiDiffType.SINCE_VERSION_A_TO_B); 125 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 126 diffInfos.push(diffInfo); 127 } 128 129 static diffIsSystemApi( 130 oldJsDocInfo: Comment.JsDocInfo | undefined, 131 newJsDocInfo: Comment.JsDocInfo | undefined 132 ): DiffTypeInfo | undefined { 133 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 134 const isSystemApiOfOld: boolean = oldJsDocInfo ? oldJsDocInfo.getIsSystemApi() : false; 135 const isSystemApiOfNew: boolean = newJsDocInfo ? newJsDocInfo.getIsSystemApi() : false; 136 diffTypeInfo 137 .setStatusCode(ApiStatusCode.SYSTEM_API_CHNAGES) 138 .setOldMessage(StringUtils.transformBooleanToTag(isSystemApiOfOld, Comment.JsDocTag.SYSTEM_API)) 139 .setNewMessage(StringUtils.transformBooleanToTag(isSystemApiOfNew, Comment.JsDocTag.SYSTEM_API)); 140 if (isSystemApiOfNew === isSystemApiOfOld) { 141 return undefined; 142 } 143 if (isSystemApiOfNew) { 144 return diffTypeInfo.setDiffType(ApiDiffType.PUBLIC_TO_SYSTEM); 145 } 146 return diffTypeInfo.setDiffType(ApiDiffType.SYSTEM_TO_PUBLIC); 147 } 148 149 static diffModelLimitation( 150 oldJsDocInfo: Comment.JsDocInfo | undefined, 151 newJsDocInfo: Comment.JsDocInfo | undefined 152 ): DiffTypeInfo | undefined { 153 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 154 const modelLimitationDiffMap: Map<string, ApiDiffType> = new Map([ 155 ['_stagemodelonly', ApiDiffType.NA_TO_STAGE], 156 ['stagemodelonly_', ApiDiffType.STAGE_TO_NA], 157 ['_famodelonly', ApiDiffType.NA_TO_FA], 158 ['famodelonly_', ApiDiffType.FA_TO_NA], 159 ['famodelonly_stagemodelonly', ApiDiffType.FA_TO_STAGE], 160 ['stagemodelonly_famodelonly', ApiDiffType.STAGE_TO_FA], 161 ]); 162 const modelLimitationOfOld: string = oldJsDocInfo ? oldJsDocInfo.getModelLimitation() : ''; 163 const modelLimitationOfNew: string = newJsDocInfo ? newJsDocInfo.getModelLimitation() : ''; 164 if (modelLimitationOfNew === modelLimitationOfOld) { 165 return undefined; 166 } 167 const diffMsg: string = `${modelLimitationOfOld.toLowerCase()}_${modelLimitationOfNew.toLowerCase()}`; 168 const diffType: ApiDiffType = modelLimitationDiffMap.get(diffMsg) as ApiDiffType; 169 diffTypeInfo 170 .setStatusCode(ApiStatusCode.MODEL_CHNAGES) 171 .setDiffType(diffType) 172 .setOldMessage(modelLimitationOfOld) 173 .setNewMessage(modelLimitationOfNew); 174 return diffTypeInfo; 175 } 176 177 static diffIsForm( 178 oldJsDocInfo: Comment.JsDocInfo | undefined, 179 newJsDocInfo: Comment.JsDocInfo | undefined 180 ): DiffTypeInfo | undefined { 181 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 182 const isCardOfOld: boolean = oldJsDocInfo ? oldJsDocInfo.getIsForm() : false; 183 const isCardOfNew: boolean = newJsDocInfo ? newJsDocInfo.getIsForm() : false; 184 diffTypeInfo 185 .setStatusCode(ApiStatusCode.FORM_CHANGED) 186 .setOldMessage(StringUtils.transformBooleanToTag(isCardOfOld, Comment.JsDocTag.FORM)) 187 .setNewMessage(StringUtils.transformBooleanToTag(isCardOfNew, Comment.JsDocTag.FORM)); 188 if (isCardOfNew === isCardOfOld) { 189 return undefined; 190 } 191 if (isCardOfNew) { 192 return diffTypeInfo.setDiffType(ApiDiffType.NA_TO_CARD); 193 } 194 return diffTypeInfo.setDiffType(ApiDiffType.CARD_TO_NA); 195 } 196 197 static diffIsCrossPlatForm( 198 oldJsDocInfo: Comment.JsDocInfo | undefined, 199 newJsDocInfo: Comment.JsDocInfo | undefined 200 ): DiffTypeInfo | undefined { 201 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 202 const isCrossPlatFormOfOld: boolean = oldJsDocInfo ? oldJsDocInfo.getIsCrossPlatForm() : false; 203 const isCrossPlatFormOfNew: boolean = newJsDocInfo ? newJsDocInfo.getIsCrossPlatForm() : false; 204 diffTypeInfo 205 .setStatusCode(ApiStatusCode.CROSSPLATFORM_CHANGED) 206 .setOldMessage(StringUtils.transformBooleanToTag(isCrossPlatFormOfOld, Comment.JsDocTag.CROSS_PLAT_FORM)) 207 .setNewMessage(StringUtils.transformBooleanToTag(isCrossPlatFormOfNew, Comment.JsDocTag.CROSS_PLAT_FORM)); 208 if (isCrossPlatFormOfNew === isCrossPlatFormOfOld) { 209 return undefined; 210 } 211 if (isCrossPlatFormOfNew) { 212 return diffTypeInfo.setDiffType(ApiDiffType.NA_TO_CROSS_PLATFORM); 213 } 214 return diffTypeInfo.setDiffType(ApiDiffType.CROSS_PLATFORM_TO_NA); 215 } 216 217 static diffPermissions( 218 oldJsDocInfo: Comment.JsDocInfo | undefined, 219 newJsDocInfo: Comment.JsDocInfo | undefined 220 ): DiffTypeInfo | undefined { 221 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 222 const permissionsOfOld: string = oldJsDocInfo ? oldJsDocInfo.getPermission() : ''; 223 const permissionsOfNew: string = newJsDocInfo ? newJsDocInfo.getPermission() : ''; 224 diffTypeInfo 225 .setStatusCode(ApiStatusCode.PERMISSION_CHANGES) 226 .setOldMessage(permissionsOfOld) 227 .setNewMessage(permissionsOfNew); 228 if (permissionsOfOld === permissionsOfNew) { 229 return undefined; 230 } 231 if (permissionsOfOld === '') { 232 return diffTypeInfo.setStatusCode(ApiStatusCode.PERMISSION_NEW).setDiffType(ApiDiffType.PERMISSION_NA_TO_HAVE); 233 } 234 if (permissionsOfNew === '') { 235 return diffTypeInfo 236 .setStatusCode(ApiStatusCode.PERMISSION_DELETE) 237 .setDiffType(ApiDiffType.PERMISSION_HAVE_TO_NA); 238 } 239 const permiss: PermissionsProcessorHelper = new PermissionsProcessorHelper(permissionsCharMap); 240 const compareVal: CompareReturnObjType = permiss.comparePermissions(permissionsOfOld, permissionsOfNew); 241 if (compareVal.range === RangeChange.DOWN) { 242 return diffTypeInfo.setDiffType(ApiDiffType.PERMISSION_RANGE_SMALLER); 243 } 244 if (compareVal.range === RangeChange.UP) { 245 return diffTypeInfo.setDiffType(ApiDiffType.PERMISSION_RANGE_BIGGER); 246 } 247 return diffTypeInfo.setDiffType(ApiDiffType.PERMISSION_RANGE_CHANGE); 248 } 249 250 static diffErrorCodes( 251 oldJsDocInfo: Comment.JsDocInfo | undefined, 252 newJsDocInfo: Comment.JsDocInfo | undefined 253 ): DiffTypeInfo | undefined { 254 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 255 const errorCodesOfOld: number[] = oldJsDocInfo ? oldJsDocInfo.getErrorCode().sort() : []; 256 const errorCodesOfNew: number[] = newJsDocInfo ? newJsDocInfo.getErrorCode().sort() : []; 257 const errorCodesStringOfOld: string = errorCodesOfOld.toString(); 258 const errorCodesStringOfNew: string = errorCodesOfNew.toString(); 259 diffTypeInfo 260 .setStatusCode(ApiStatusCode.ERRORCODE_CHANGES) 261 .setOldMessage(errorCodesStringOfOld) 262 .setNewMessage(errorCodesStringOfNew); 263 if (errorCodesStringOfNew === errorCodesStringOfOld) { 264 return undefined; 265 } 266 if (StringUtils.hasSubstring(errorCodesStringOfNew, errorCodesStringOfOld)) { 267 return diffTypeInfo.setStatusCode(ApiStatusCode.NEW_ERRORCODE).setDiffType(ApiDiffType.ERROR_CODE_ADD); 268 } 269 if (StringUtils.hasSubstring(errorCodesStringOfOld, errorCodesStringOfNew)) { 270 return diffTypeInfo.setDiffType(ApiDiffType.ERROR_CODE_REDUCE); 271 } 272 return diffTypeInfo.setDiffType(ApiDiffType.ERROR_CODE_CHANGE); 273 } 274 275 static diffSyscap( 276 oldJsDocInfo: Comment.JsDocInfo | undefined, 277 newJsDocInfo: Comment.JsDocInfo | undefined 278 ): DiffTypeInfo | undefined { 279 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 280 const syscapOfOld: string = oldJsDocInfo ? oldJsDocInfo.getSyscap() : ''; 281 const syscapOfNew: string = newJsDocInfo ? newJsDocInfo.getSyscap() : ''; 282 diffTypeInfo.setStatusCode(ApiStatusCode.SYSCAP_CHANGES).setOldMessage(syscapOfOld).setNewMessage(syscapOfNew); 283 if (syscapOfNew === syscapOfOld) { 284 return undefined; 285 } 286 if (syscapOfOld === '') { 287 return diffTypeInfo.setDiffType(ApiDiffType.SYSCAP_NA_TO_HAVE); 288 } 289 if (syscapOfNew === '') { 290 return diffTypeInfo.setDiffType(ApiDiffType.SYSCAP_HAVE_TO_NA); 291 } 292 return diffTypeInfo.setDiffType(ApiDiffType.SYSCAP_A_TO_B); 293 } 294 295 static diffDeprecated( 296 oldJsDocInfo: Comment.JsDocInfo | undefined, 297 newJsDocInfo: Comment.JsDocInfo | undefined 298 ): DiffTypeInfo | undefined { 299 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 300 const deprecatedVersionOfOld: string = oldJsDocInfo ? oldJsDocInfo.getDeprecatedVersion() : '-1'; 301 const deprecatedVersionOfNew: string = newJsDocInfo ? newJsDocInfo.getDeprecatedVersion() : '-1'; 302 diffTypeInfo 303 .setStatusCode(ApiStatusCode.DEPRECATED_CHNAGES) 304 .setOldMessage(deprecatedVersionOfOld.toString()) 305 .setNewMessage(deprecatedVersionOfNew.toString()); 306 if (deprecatedVersionOfNew === deprecatedVersionOfOld) { 307 return undefined; 308 } 309 if (deprecatedVersionOfOld === '-1') { 310 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_NA_TO_HAVE); 311 } 312 if (deprecatedVersionOfNew === '-1') { 313 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_HAVE_TO_NA); 314 } 315 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_A_TO_B); 316 } 317 } 318 319 /** 320 * 比较API的装饰器信息 321 */ 322 export class ApiDecoratorsDiffHelper { 323 /** 324 * 新旧版本API一致的情况下,比较装饰器 325 * 326 * @param {ApiInfo} oldApiInfo 327 * @param {ApiInfo} newApiInfo 328 * @param {BasicDiffInfo[]} diffInfos 329 * @returns 330 */ 331 static diffDecorator(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 332 const oldDecoratorsMap: Map<string, string[] | undefined> = ApiDecoratorsDiffHelper.setDecoratorsMap( 333 oldApiInfo.getDecorators() 334 ); 335 const newDecoratorsMap: Map<string, string[] | undefined> = ApiDecoratorsDiffHelper.setDecoratorsMap( 336 newApiInfo.getDecorators() 337 ); 338 if (newDecoratorsMap.size === 0) { 339 for (const key of oldDecoratorsMap.keys()) { 340 ApiDecoratorsDiffHelper.addDeleteDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 341 } 342 return; 343 } 344 345 if (oldDecoratorsMap.size === 0) { 346 for (const key of newDecoratorsMap.keys()) { 347 ApiDecoratorsDiffHelper.addNewDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 348 newDecoratorsMap.delete(key); 349 } 350 return; 351 } 352 ApiDecoratorsDiffHelper.diffDecoratorInfo(oldDecoratorsMap, newDecoratorsMap, oldApiInfo, newApiInfo, diffInfos); 353 } 354 355 static diffDecoratorInfo( 356 oldDecoratorsMap: Map<string, string[] | undefined>, 357 newDecoratorsMap: Map<string, string[] | undefined>, 358 oldApiInfo: ApiInfo, 359 newApiInfo: ApiInfo, 360 diffInfos: BasicDiffInfo[] 361 ): void { 362 const sameDecoratorSet: Set<string> = new Set(); 363 for (const key of oldDecoratorsMap.keys()) { 364 const newDecoratorArguments: string[] | undefined = newDecoratorsMap.get(key); 365 const oldDecoratorArguments: string[] | undefined = oldDecoratorsMap.get(key); 366 //新版本没有这个装饰器 367 if (!newDecoratorArguments) { 368 ApiDecoratorsDiffHelper.addDeleteDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 369 sameDecoratorSet.add(key); 370 continue; 371 } 372 373 // 新旧版本装饰器参数一样 374 if (oldDecoratorArguments && newDecoratorArguments.join() === oldDecoratorArguments.join()) { 375 newDecoratorsMap.delete(key); 376 sameDecoratorSet.add(key); 377 continue; 378 } 379 } 380 // 新版中剩下的装饰器为新增 381 for (const key of newDecoratorsMap.keys()) { 382 ApiDecoratorsDiffHelper.addNewDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 383 } 384 385 for (const key of oldDecoratorsMap.keys()) { 386 if (sameDecoratorSet.has(key)) { 387 continue; 388 } 389 ApiDecoratorsDiffHelper.addDeleteDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 390 } 391 } 392 393 static setDecoratorsMap(decorators: DecoratorInfo[] | undefined): Map<string, string[] | undefined> { 394 const decoratorsMap: Map<string, string[]> = new Map(); 395 if (!decorators) { 396 return decoratorsMap; 397 } 398 399 decorators.forEach((decoratorInfo: DecoratorInfo) => { 400 const expressionArguments: string[] | undefined = decoratorInfo.getExpressionArguments(); 401 decoratorsMap.set(decoratorInfo.getExpression(), expressionArguments === undefined ? [] : expressionArguments); 402 }); 403 return decoratorsMap; 404 } 405 406 static addDeleteDecoratorsInfo( 407 decoratorName: string, 408 oldApiInfo: ApiInfo, 409 newApiInfo: ApiInfo, 410 diffInfos: BasicDiffInfo[] 411 ): void { 412 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 413 diffTypeInfo 414 .setStatusCode(ApiStatusCode.DELETE_DECORATOR) 415 .setDiffType(ApiDiffType.DELETE_DECORATOR) 416 .setOldMessage(decoratorName) 417 .setNewMessage(''); 418 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 419 diffInfos.push(diffInfo); 420 } 421 422 static addNewDecoratorsInfo( 423 decoratorName: string, 424 oldApiInfo: ApiInfo, 425 newApiInfo: ApiInfo, 426 diffInfos: BasicDiffInfo[] 427 ): void { 428 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 429 diffTypeInfo 430 .setStatusCode(ApiStatusCode.NEW_DECORATOR) 431 .setDiffType(ApiDiffType.NEW_DECORATOR) 432 .setOldMessage('') 433 .setNewMessage(decoratorName); 434 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 435 diffInfos.push(diffInfo); 436 } 437 } 438 439 export class ApiCheckHelper { 440 /** 441 * 比较两个API的历史版本jsdoc 442 * 443 * @param {ApiInfo} oldApiInfo 444 * @param {ApiInfo} newApiInfo 445 * @param {BasicDiffInfo[]} diffInfos 446 */ 447 static diffHistoricalJsDoc(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 448 const currentVersion: string = CommonFunctions.getCheckApiVersion().toString(); 449 const oldJsDocTextArr: Array<string> = oldApiInfo.getJsDocText().split('*/'); 450 const newJsDocTextArr: Array<string> = newApiInfo.getJsDocText().split('*/'); 451 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 452 if (oldApiInfo.getCurrentVersion() === currentVersion) { 453 oldJsDocTextArr.splice(NumberConstant.DELETE_CURRENT_JS_DOC); 454 } else { 455 oldJsDocTextArr.splice(-1); 456 } 457 458 if (newApiInfo.getCurrentVersion() === currentVersion) { 459 newJsDocTextArr.splice(NumberConstant.DELETE_CURRENT_JS_DOC); 460 } else { 461 newJsDocTextArr.splice(-1); 462 } 463 464 if (oldJsDocTextArr.length !== newJsDocTextArr.length) { 465 diffTypeInfo.setDiffType(ApiDiffType.HISTORICAL_JSDOC_CHANGE); 466 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 467 diffInfos.push(diffInfo); 468 return; 469 } 470 for (let i = 0; i < oldJsDocTextArr.length; i++) { 471 if (oldJsDocTextArr[i].replace(/\r\n/g, '') !== newJsDocTextArr[i].replace(/\r\n/g, '')) { 472 diffTypeInfo.setDiffType(ApiDiffType.HISTORICAL_JSDOC_CHANGE); 473 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 474 diffInfos.push(diffInfo); 475 } 476 } 477 } 478 479 static diffHistoricalAPI(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 480 const currentVersion: string = CommonFunctions.getCheckApiVersion().toString(); 481 const oldApiDefinedText: string = oldApiInfo.getDefinedText(); 482 const newApiDefinedText: string = newApiInfo.getDefinedText(); 483 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 484 if (oldApiDefinedText !== newApiDefinedText && newApiInfo.getCurrentVersion() !== currentVersion) { 485 diffTypeInfo.setDiffType(ApiDiffType.HISTORICAL_API_CHANGE); 486 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 487 diffInfos.push(diffInfo); 488 } 489 } 490 } 491 492 /** 493 * 处理api节点的diff信息工具 494 * 495 */ 496 export class ApiNodeDiffHelper { 497 /** 498 * 根据节点类型处理节点的diff信息,处理的主流程 499 * 500 * @param {ApiInfo} oldApiInfo 旧版本的节点信息 501 * @param {ApiInfo} newApiInfo 新版本的节点信息 502 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 503 * @return {void} 504 */ 505 static diffNodeInfo(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[], isCheck?: boolean): void { 506 if (isCheck) { 507 ApiCheckHelper.diffHistoricalJsDoc(oldApiInfo, newApiInfo, diffInfos); 508 ApiCheckHelper.diffHistoricalAPI(oldApiInfo, newApiInfo, diffInfos); 509 } 510 const apiType: string = newApiInfo.getApiType(); 511 if (oldApiInfo.getApiType() !== apiType) { 512 return; 513 } 514 const apiNodeDiff: ApiNodeDiffProcessor | undefined = apiNodeDiffMethod.get(apiType); 515 if (!apiNodeDiff) { 516 return; 517 } 518 apiNodeDiff(oldApiInfo, newApiInfo, diffInfos); 519 } 520 521 /** 522 * 处理type类型 523 * 524 * @static 525 * @param {string} oldType 旧版本的type字符串 526 * @param {string} newType 新版本的type字符串 527 * @return { ApiDiffType | undefined} type范围的变化情况 528 * @memberof ApiNodeDiffHelper 529 */ 530 static diffBaseType(oldType: string, newType: string): DiffTypeInfo | undefined { 531 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 532 if (oldType === newType) { 533 return undefined; 534 } 535 diffTypeInfo.setStatusCode(ApiStatusCode.TYPE_CHNAGES).setOldMessage(oldType).setNewMessage(newType); 536 if (oldType === '') { 537 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE); 538 } 539 if (newType === '') { 540 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE); 541 } 542 const permiss: PermissionsProcessorHelper = new PermissionsProcessorHelper(typeCharMap); 543 const compareVal: CompareReturnObjType = permiss.comparePermissions(oldType, newType); 544 if (compareVal.range === RangeChange.DOWN) { 545 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_SMALLER); 546 } 547 if (compareVal.range === RangeChange.UP) { 548 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_BIGGER); 549 } 550 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE); 551 } 552 553 /** 554 * 处理方法节点,获取对应diff信息 555 * 556 * @param {ApiInfo} oldApiInfo 旧版本的方法节点信息 557 * @param {ApiInfo} newApiInfo 新版本的方法节点信息 558 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 559 */ 560 static diffMethod(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 561 methodDiffProcessors.forEach((methodDiffProcessor: ApiScenesDiffProcessor) => { 562 const diffTypeInfo: DiffTypeInfo[] | DiffTypeInfo | undefined = methodDiffProcessor( 563 oldApiInfo as MethodInfo, 564 newApiInfo as MethodInfo 565 ); 566 if (!diffTypeInfo) { 567 return; 568 } 569 if (diffTypeInfo instanceof Array) { 570 diffTypeInfo.forEach((info: DiffTypeInfo) => { 571 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 572 oldApiInfo, 573 newApiInfo, 574 info.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 575 ); 576 diffInfos.push(diffInfo); 577 }); 578 } else { 579 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 580 oldApiInfo, 581 newApiInfo, 582 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 583 ); 584 diffInfos.push(diffInfo); 585 } 586 }); 587 } 588 589 /** 590 * 处理方法节点的返回值 591 * 592 * @param {MethodInfo} oldApiInfo 旧版本的方法节点信息 593 * @param {MethodInfo} newApiInfo 新版本的方法节点信息 594 * @return {*} {(ApiDiffType | undefined)} 方法节点的返回值的变化情况 595 */ 596 static diffMethodReturnType(oldApiInfo: MethodInfo, newApiInfo: MethodInfo): DiffTypeInfo | undefined { 597 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 598 const olaMethodType: string[] = oldApiInfo.getReturnValue(); 599 const newMethodType: string[] = newApiInfo.getReturnValue(); 600 const olaMethodTypeStr = olaMethodType.toString().replace(/\r|\n|\s+|'|"/g, ''); 601 const newMethodTypeStr = newMethodType.toString().replace(/\r|\n|\s+|'|"/g, ''); 602 if (olaMethodTypeStr === newMethodTypeStr) { 603 return undefined; 604 } 605 diffTypeInfo.setOldMessage(olaMethodTypeStr).setNewMessage(newMethodTypeStr); 606 if (StringUtils.hasSubstring(newMethodTypeStr, olaMethodTypeStr)) { 607 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_ADD); 608 } 609 if (StringUtils.hasSubstring(olaMethodTypeStr, newMethodTypeStr)) { 610 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_REDUCE); 611 } 612 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_CHANGE); 613 } 614 615 /** 616 * 处理方法节点的参数,获取对应diff信息 617 * 618 * @param {MethodInfo} oldApiInfo 旧版本的方法节点信息 619 * @param {MethodInfo} newApiInfo 新版本的方法节点信息 620 * @return {*} {ApiDiffType[]} 返回各个参数的变化情况 621 */ 622 static diffMethodParams(oldApiInfo: MethodInfo, newApiInfo: MethodInfo): DiffTypeInfo[] { 623 const diffTypeInfos: DiffTypeInfo[] = []; 624 const diffTypes: ApiDiffType[] = []; 625 const oldMethodParams: ParamInfo[] = oldApiInfo.getParams(); 626 const newMethodParams: ParamInfo[] = newApiInfo.getParams(); 627 const diffProcessors: ((oldApiInfo: ParamInfo, newApiInfo: ParamInfo) => ApiDiffType | undefined)[] = [ 628 ApiNodeDiffHelper.diffMethodParamName, 629 ApiNodeDiffHelper.diffMethodParamType, 630 ApiNodeDiffHelper.diffMethodParamRequired, 631 ]; 632 const maxLen: number = Math.max(oldMethodParams.length, newMethodParams.length); 633 // 遍历方法参数列表 634 for (let i = 0; i < maxLen; i++) { 635 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 636 if (i >= oldMethodParams.length) { 637 const newElement: ParamInfo = newMethodParams[i]; 638 const oldParamISRequired: boolean = newElement.getIsRequired(); 639 diffTypeInfo 640 .setDiffType( 641 oldParamISRequired ? ApiDiffType.FUNCTION_PARAM_REQUIRED_ADD : ApiDiffType.FUNCTION_PARAM_UNREQUIRED_ADD 642 ) 643 .setNewMessage(newElement.getDefinedText()); 644 diffTypeInfos.push(diffTypeInfo); 645 continue; 646 } 647 if (i >= newMethodParams.length) { 648 const oldElement: ParamInfo = oldMethodParams[i]; 649 diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_PARAM_REDUCE).setOldMessage(oldElement.getDefinedText()); 650 diffTypeInfos.push(diffTypeInfo); 651 continue; 652 } 653 const oldElement: ParamInfo = oldMethodParams[i]; 654 const newElement: ParamInfo = newMethodParams[i]; 655 diffTypeInfo.setOldMessage(oldElement.getDefinedText()).setNewMessage(newElement.getDefinedText()); 656 for (let j = 0; j < diffProcessors.length; j++) { 657 const apiSceneDiffProcessor = diffProcessors[j]; 658 const diffType: ApiDiffType | undefined = apiSceneDiffProcessor(oldElement, newElement); 659 if (!diffType) { 660 continue; 661 } 662 diffTypeInfos.push(diffTypeInfo.setDiffType(diffType)); 663 } 664 } 665 return diffTypeInfos; 666 } 667 668 /** 669 * 处理方法节点的参数名称 670 * 671 * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息 672 * @param {ParamInfo} newApiInfo 新版本的参数节点信息 673 * @return {*} {(ApiDiffType | undefined)} 方法节点的参数名称的变化情况 674 */ 675 static diffMethodParamName(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined { 676 const oldParamName: string = oldApiInfo.getApiName(); 677 const newParamName: string = newApiInfo.getApiName(); 678 if (oldParamName === newParamName) { 679 return undefined; 680 } 681 return ApiDiffType.FUNCTION_PARAM_NAME_CHANGE; 682 } 683 684 /** 685 * 处理方法节点的参数类型 686 * 687 * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息 688 * @param {ParamInfo} newApiInfo 新版本的参数节点信息 689 * @return {*} {(ApiDiffType | undefined)} 方法节点的参数类型的变化情况 690 */ 691 static diffMethodParamType(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined { 692 const oldParamType: string[] = oldApiInfo.getType(); 693 const newParamType: string[] = newApiInfo.getType(); 694 const oldParamTypeStr: string = oldParamType.toString().replace(/\r|\n|\s+|'|"/g, ''); 695 const newParamTypeStr: string = newParamType.toString().replace(/\r|\n|\s+|'|"/g, ''); 696 if (oldParamTypeStr === newParamTypeStr) { 697 return undefined; 698 } 699 if (StringUtils.hasSubstring(newParamTypeStr, oldParamTypeStr)) { 700 return ApiDiffType.FUNCTION_PARAM_TYPE_ADD; 701 } 702 if (StringUtils.hasSubstring(oldParamTypeStr, newParamTypeStr)) { 703 return ApiDiffType.FUNCTION_PARAM_TYPE_REDUCE; 704 } 705 return ApiDiffType.FUNCTION_PARAM_TYPE_CHANGE; 706 } 707 708 /** 709 * 处理方法节点的参数必选 710 * 711 * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息 712 * @param {ParamInfo} newApiInfo 新版本的参数节点信息 713 * @return {*} {(ApiDiffType | undefined)} 方法节点的必选参数的变化情况 714 */ 715 static diffMethodParamRequired(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined { 716 const oldParamISRequired: boolean = oldApiInfo.getIsRequired(); 717 const newParamISRequired: boolean = newApiInfo.getIsRequired(); 718 if (oldParamISRequired === newParamISRequired) { 719 return undefined; 720 } 721 return newParamISRequired ? ApiDiffType.FUNCTION_PARAM_TO_REQUIRED : ApiDiffType.FUNCTION_PARAM_TO_UNREQUIRED; 722 } 723 724 /** 725 * 处理class节点,获取对应diff信息 726 * 727 * @param {ApiInfo} oldApiInfo 旧版本的class节点信息 728 * @param {ApiInfo} newApiInfo 新版本的class节点信息 729 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 730 * @return {*} {void} 731 */ 732 static diffClass(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 733 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 734 const olaClassName: string = oldApiInfo.getApiName(); 735 const newClassName: string = newApiInfo.getApiName(); 736 if (olaClassName === newClassName) { 737 return; 738 } 739 diffTypeInfo 740 .setStatusCode(ApiStatusCode.CLASS_CHANGES) 741 .setDiffType(ApiDiffType.API_NAME_CHANGE) 742 .setOldMessage(olaClassName) 743 .setNewMessage(newClassName); 744 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 745 diffInfos.push(diffInfo); 746 } 747 748 /** 749 * 处理interface节点,获取对应diff信息 750 * 751 * @param {ApiInfo} oldApiInfo 旧版本的interface节点信息 752 * @param {ApiInfo} newApiInfo 新版本的interface节点信息 753 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 754 * @return {*} {void} 755 */ 756 static diffInterface(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 757 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 758 const olaClassName: string = oldApiInfo.getApiName(); 759 const newClassName: string = newApiInfo.getApiName(); 760 if (olaClassName === newClassName) { 761 return; 762 } 763 diffTypeInfo 764 .setStatusCode(ApiStatusCode.CLASS_CHANGES) 765 .setDiffType(ApiDiffType.API_NAME_CHANGE) 766 .setOldMessage(olaClassName) 767 .setNewMessage(newClassName); 768 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 769 diffInfos.push(diffInfo); 770 } 771 772 /** 773 * 处理namespace节点,获取对应diff信息 774 * 775 * @param {ApiInfo} oldApiInfo 旧版本的namespace节点信息 776 * @param {ApiInfo} newApiInfo 新版本的namespace节点信息 777 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 778 * @return {*} {void} 779 */ 780 static diffNamespace(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 781 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 782 const olaClassName: string = oldApiInfo.getApiName(); 783 const newClassName: string = newApiInfo.getApiName(); 784 if (olaClassName === newClassName) { 785 return; 786 } 787 diffTypeInfo 788 .setStatusCode(ApiStatusCode.CLASS_CHANGES) 789 .setDiffType(ApiDiffType.API_NAME_CHANGE) 790 .setOldMessage(olaClassName) 791 .setNewMessage(newClassName); 792 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 793 diffInfos.push(diffInfo); 794 } 795 796 /** 797 * 处理属性节点,获取对应diff信息 798 * 799 * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息 800 * @param {ApiInfo} newApiInfo 新版本的属性节点信息 801 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 802 * @return {*} {void} 803 */ 804 static diffProperty(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 805 propertyDiffProcessors.forEach((propertyDiffProcessor: ApiSceneDiffProcessor) => { 806 const diffType: DiffTypeInfo | undefined = propertyDiffProcessor(oldApiInfo, newApiInfo); 807 if (!diffType) { 808 return; 809 } 810 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 811 oldApiInfo, 812 newApiInfo, 813 diffType.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 814 ); 815 diffInfos.push(diffInfo); 816 }); 817 } 818 819 /** 820 * 处理属性节点的类型 821 * 822 * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息 823 * @param {ApiInfo} newApiInfo 新版本的属性节点信息 824 * @return {*} {(ApiDiffType | undefined)} 属性节点的类型的变化情况 825 */ 826 static diffPropertyType(oldApiInfo: PropertyInfo, newApiInfo: PropertyInfo): DiffTypeInfo | undefined { 827 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 828 const olaPropertyType: string[] = oldApiInfo.getType(); 829 const newPropertyType: string[] = newApiInfo.getType(); 830 const oldPropertyIsReadOnly: boolean = oldApiInfo.getIsReadOnly(); 831 const newPropertyIsReadOnly: boolean = newApiInfo.getIsReadOnly(); 832 const olaPropertyTypeStr = olaPropertyType.toString(); 833 const newPropertyTypeStr = newPropertyType.toString(); 834 if (olaPropertyTypeStr === newPropertyTypeStr) { 835 return undefined; 836 } 837 diffTypeInfo.setOldMessage(olaPropertyTypeStr).setNewMessage(newPropertyTypeStr); 838 if (StringUtils.hasSubstring(newPropertyTypeStr, olaPropertyTypeStr)) { 839 return diffTypeInfo.setDiffType( 840 newPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_ADD : ApiDiffType.PROPERTY_WRITABLE_ADD 841 ); 842 } 843 if (StringUtils.hasSubstring(olaPropertyTypeStr, newPropertyTypeStr)) { 844 return diffTypeInfo.setDiffType( 845 oldPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_REDUCE : ApiDiffType.PROPERTY_WRITABLE_REDUCE 846 ); 847 } 848 return diffTypeInfo.setDiffType(ApiDiffType.PROPERTY_TYPE_CHANGE); 849 } 850 851 /** 852 * 处理属性节点的必选属性 853 * 854 * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息 855 * @param {ApiInfo} newApiInfo 新版本的属性节点信息 856 * @return {*} {(ApiDiffType | undefined)} 属性节点的必选属性的变化情况 857 */ 858 static diffPropertyRequired(oldApiInfo: PropertyInfo, newApiInfo: PropertyInfo): DiffTypeInfo | undefined { 859 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 860 const oldPropertyName: string = oldApiInfo.getApiName(); 861 const newPropertyName: string = newApiInfo.getApiName(); 862 const oldPropertyIsReadOnly: boolean = oldApiInfo.getIsReadOnly(); 863 //???只读属性是否会变为可写属性 864 const propertyRequiredDiffMap: Map<string, ApiDiffType> = new Map([ 865 //old是否必选_new是否必选_old是否只读 866 ['_true_false_true', ApiDiffType.PROPERTY_READONLY_TO_UNREQUIRED], 867 ['_false_true_true', ApiDiffType.PROPERTY_READONLY_TO_REQUIRED], 868 ['_true_false_false', ApiDiffType.PROPERTY_WRITABLE_TO_UNREQUIRED], 869 ['_false_true_false', ApiDiffType.PROPERTY_WRITABLE_TO_REQUIRED], 870 ]); 871 const oldPropertyISRequired: boolean = oldApiInfo.getIsRequired(); 872 const newPropertyISRequired: boolean = newApiInfo.getIsRequired(); 873 874 if (oldPropertyName === newPropertyName && oldPropertyISRequired === newPropertyISRequired) { 875 return undefined; 876 } 877 diffTypeInfo.setOldMessage(oldApiInfo.getDefinedText()).setNewMessage(newApiInfo.getDefinedText()); 878 const paramRequiredStr: string = `_${!!oldPropertyISRequired}_${!!newPropertyISRequired}_${!!oldPropertyIsReadOnly}`; 879 const paramRequiredType: ApiDiffType = propertyRequiredDiffMap.get(paramRequiredStr) as ApiDiffType; 880 return diffTypeInfo.setDiffType(paramRequiredType); 881 } 882 883 /** 884 * 处理常量节点,获取对应diff信息 885 * 886 * @param {ApiInfo} oldApiInfo 旧版本的常量节点信息 887 * @param {ApiInfo} newApiInfo 新版本的常量节点信息 888 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 889 */ 890 static diffConstant(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 891 constantDiffProcessors.forEach((constantDiffProcessor: ApiSceneDiffProcessor) => { 892 const diffTypeInfo: DiffTypeInfo | undefined = constantDiffProcessor(oldApiInfo, newApiInfo); 893 if (!diffTypeInfo) { 894 return; 895 } 896 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 897 oldApiInfo, 898 newApiInfo, 899 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 900 ); 901 diffInfos.push(diffInfo); 902 }); 903 } 904 905 /** 906 * 处理常量节点的值 907 * 908 * @param {ConstantInfo} oldApiInfo 旧版本的常量节点信息 909 * @param {ConstantInfo} newApiInfo 新版本的常量节点信息 910 * @return {*} {(ApiDiffType | undefined)} 常量节点的值的变化情况 911 */ 912 static diffConstantValue(oldApiInfo: ConstantInfo, newApiInfo: ConstantInfo): DiffTypeInfo | undefined { 913 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 914 const olaConstantValue: string = oldApiInfo.getValue(); 915 const newConstantValue: string = newApiInfo.getValue(); 916 if (olaConstantValue === newConstantValue) { 917 return undefined; 918 } 919 diffTypeInfo.setOldMessage(olaConstantValue).setNewMessage(newConstantValue); 920 return diffTypeInfo.setDiffType(ApiDiffType.CONSTANT_VALUE_CHANGE); 921 } 922 923 /** 924 * 处理自定义类型节点,过去对应diff信息 925 * 926 * @param {ApiInfo} oldApiInfo 旧版本的自定义类型节点信息 927 * @param {ApiInfo} newApiInfo 新版本的自定义类型节点信息 928 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 929 */ 930 static diffTypeAlias(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 931 typeAliasDiffProcessors.forEach((typeAliasDiffProcessor: ApiSceneDiffProcessor) => { 932 const diffTypeInfo: DiffTypeInfo | undefined = typeAliasDiffProcessor(oldApiInfo, newApiInfo); 933 if (!diffTypeInfo) { 934 return; 935 } 936 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 937 diffInfos.push(diffInfo); 938 }); 939 } 940 941 /** 942 * 处理自定义类型节点的类型 943 * 944 * @param {TypeAliasInfo} oldApiInfo 旧版本的自定义类型节点信息 945 * @param {TypeAliasInfo} newApiInfo 新版本的自定义类型节点信息 946 * @return {*} {(ApiDiffType | undefined)} 自定义类型节点的类型的变化情况 947 */ 948 static diffTypeAliasType(oldApiInfo: TypeAliasInfo, newApiInfo: TypeAliasInfo): DiffTypeInfo | undefined { 949 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 950 const olaTypeAliasType: string[] = oldApiInfo.getType(); 951 const newTypeAliasType: string[] = newApiInfo.getType(); 952 const olaTypeAliasTypeStr: string = olaTypeAliasType.toString(); 953 const newTypeAliasTypeStr: string = newTypeAliasType.toString(); 954 if (olaTypeAliasTypeStr === newTypeAliasTypeStr) { 955 return undefined; 956 } 957 diffTypeInfo.setOldMessage(olaTypeAliasTypeStr).setNewMessage(newTypeAliasTypeStr); 958 if (StringUtils.hasSubstring(newTypeAliasTypeStr, olaTypeAliasTypeStr)) { 959 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_ADD); 960 } 961 if (StringUtils.hasSubstring(olaTypeAliasTypeStr, newTypeAliasTypeStr)) { 962 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_REDUCE); 963 } 964 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_CHANGE); 965 } 966 967 /** 968 * 处理枚举值节点,获取对应diff信息 969 * 970 * @param {ApiInfo} oldApiInfo 旧版本的枚举值节点信息 971 * @param {ApiInfo} newApiInfo 新版本的枚举值节点信息 972 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 973 */ 974 static diffEnum(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 975 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 976 const oldEnumName: string = oldApiInfo.getApiName(); 977 const newEnumName: string = newApiInfo.getApiName(); 978 if (oldEnumName === newEnumName) { 979 return; 980 } 981 diffTypeInfo.setDiffType(ApiDiffType.API_NAME_CHANGE).setOldMessage(oldEnumName).setNewMessage(newEnumName); 982 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 983 oldApiInfo, 984 newApiInfo, 985 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 986 ); 987 diffInfos.push(diffInfo); 988 } 989 990 /** 991 * 处理枚举值节点的每个元素,获取对应diff信息 992 * 993 * @param {EnumValueInfo} oldApiInfo 旧版本的枚举值节点元素信息 994 * @param {EnumValueInfo} newApiInfo 新版本的枚举值节点元素信息 995 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 996 */ 997 static diffEnumMember(oldApiInfo: EnumValueInfo, newApiInfo: EnumValueInfo, diffInfos: BasicDiffInfo[]): void { 998 enumDiffProcessors.forEach((enumDiffProcessor: ApiSceneDiffProcessor) => { 999 const diffTypeInfo: DiffTypeInfo | undefined = enumDiffProcessor(oldApiInfo, newApiInfo); 1000 if (!diffTypeInfo) { 1001 return; 1002 } 1003 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 1004 oldApiInfo, 1005 newApiInfo, 1006 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 1007 ); 1008 diffInfos.push(diffInfo); 1009 }); 1010 } 1011 1012 /** 1013 * 处理枚举值节点的每个元素的值 1014 * 1015 * @param {EnumValueInfo} oldApiInfo 旧版本的枚举值节点元素信息 1016 * @param {EnumValueInfo} newApiInfo 新版本的枚举值节点元素信息 1017 * @return {*} {(ApiDiffType | undefined)} 枚举值节点的每个元素的值的变化情况 1018 */ 1019 static diffEnumMemberValue(oldApiInfo: EnumValueInfo, newApiInfo: EnumValueInfo): DiffTypeInfo | undefined { 1020 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1021 const olaEnumMemberValue: string = oldApiInfo.getValue(); 1022 const newEnumMemberValue: string = newApiInfo.getValue(); 1023 if (olaEnumMemberValue === newEnumMemberValue) { 1024 return undefined; 1025 } 1026 diffTypeInfo.setOldMessage(olaEnumMemberValue).setNewMessage(newEnumMemberValue); 1027 return diffTypeInfo.setDiffType(ApiDiffType.ENUM_MEMBER_VALUE_CHANGE); 1028 } 1029 1030 /** 1031 * 处理通用类型节点的apiName 1032 * 1033 * @param {ApiInfo} oldApiInfo 旧版本的节点信息 1034 * @param {ApiInfo} newApiInfo 新版本的节点信息 1035 * @return {*} {(ApiDiffType | undefined)} apiName的变化情况 1036 */ 1037 static diffApiName(oldApiInfo: ApiInfo, newApiInfo: ApiInfo): DiffTypeInfo | undefined { 1038 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1039 const olaConstantName: string = oldApiInfo.getApiName(); 1040 const newConstantName: string = newApiInfo.getApiName(); 1041 if (olaConstantName === newConstantName) { 1042 return undefined; 1043 } 1044 diffTypeInfo.setOldMessage(olaConstantName).setNewMessage(newConstantName); 1045 return diffTypeInfo.setDiffType(ApiDiffType.API_NAME_CHANGE); 1046 } 1047 } 1048 1049 /** 1050 * 根据节点信息和type生成需要的diff对象 1051 * 1052 * @param {(BasicApiInfo | undefined)} [oldApiInfo=undefined] 旧版本节点信息,默认undefined 1053 * @param {(BasicApiInfo | undefined)} [newApiInfo=undefined] 新版本节点信息,默认undefined 1054 * @param {ApiDiffType} diffType diff的节点类型 1055 * @return {*} {BasicDiffInfo} 生成的diff对象 1056 */ 1057 export function wrapDiffInfo( 1058 oldApiInfo: BasicApiInfo | undefined = undefined, 1059 newApiInfo: BasicApiInfo | undefined = undefined, 1060 diffTypeInfo: DiffTypeInfo 1061 ): BasicDiffInfo { 1062 const diffInfo: BasicDiffInfo = new BasicDiffInfo(); 1063 const diffType: ApiDiffType = diffTypeInfo.getDiffType(); 1064 if (oldApiInfo) { 1065 processOldApiDiff(oldApiInfo, diffInfo); 1066 } 1067 if (newApiInfo) { 1068 processNewApiDiff(newApiInfo, diffInfo); 1069 } 1070 diffInfo 1071 .setDiffType(diffType) 1072 .setDiffMessage(diffMap.get(diffType) as string) 1073 .setIsCompatible(!incompatibleApiDiffTypes.has(diffType)) 1074 .setStatusCode(diffTypeInfo.getStatusCode()) 1075 .setOldDescription(diffTypeInfo.getOldMessage()) 1076 .setNewDescription(diffTypeInfo.getNewMessage()); 1077 return diffInfo; 1078 } 1079 1080 /** 1081 * 添加旧版本的基础信息 1082 * 1083 * @param {BasicApiInfo} oldApiInfo 旧版本的节点信息 1084 * @param {BasicDiffInfo} diffInfo 需要填充的diff对象 1085 */ 1086 function processOldApiDiff(oldApiInfo: BasicApiInfo, diffInfo: BasicDiffInfo): void { 1087 diffInfo 1088 .setOldApiDefinedText(oldApiInfo.getDefinedText()) 1089 .setApiType(oldApiInfo.getApiType()) 1090 .setOldApiName(oldApiInfo.getApiName()) 1091 .setOldDtsName(oldApiInfo.getFilePath()) 1092 .setOldHierarchicalRelations(oldApiInfo.getHierarchicalRelations()) 1093 .setOldPos(oldApiInfo.getPos()) 1094 .setOldSyscapField(oldApiInfo.getSyscap()); 1095 } 1096 1097 /** 1098 * 添加新版本的基础信息 1099 * 1100 * @param {BasicApiInfo} newApiInfo 新版本的节点信息 1101 * @param {BasicDiffInfo} diffInfo 需要填充的diff对象 1102 */ 1103 function processNewApiDiff(newApiInfo: BasicApiInfo, diffInfo: BasicDiffInfo): void { 1104 diffInfo 1105 .setNewApiDefinedText(newApiInfo.getDefinedText()) 1106 .setApiType(newApiInfo.getApiType()) 1107 .setNewApiName(newApiInfo.getApiName()) 1108 .setNewDtsName(newApiInfo.getFilePath()) 1109 .setNewHierarchicalRelations(newApiInfo.getHierarchicalRelations()) 1110 .setNewPos(newApiInfo.getPos()) 1111 .setNewSyscapField(newApiInfo.getSyscap()); 1112 } 1113 /** 1114 * api节点类型对应的处理方法,获取diff信息 1115 */ 1116 export const apiNodeDiffMethod: Map<string, ApiNodeDiffProcessor> = new Map([ 1117 [ApiType.PROPERTY, ApiNodeDiffHelper.diffProperty], 1118 [ApiType.CLASS, ApiNodeDiffHelper.diffClass], 1119 [ApiType.INTERFACE, ApiNodeDiffHelper.diffInterface], 1120 [ApiType.NAMESPACE, ApiNodeDiffHelper.diffNamespace], 1121 [ApiType.METHOD, ApiNodeDiffHelper.diffMethod], 1122 [ApiType.CONSTANT, ApiNodeDiffHelper.diffConstant], 1123 [ApiType.ENUM, ApiNodeDiffHelper.diffEnum], 1124 [ApiType.ENUM_VALUE, ApiNodeDiffHelper.diffEnumMember], 1125 [ApiType.TYPE_ALIAS, DiffProcessorHelper.ApiNodeDiffHelper.diffTypeAlias], 1126 ]); 1127 1128 /** 1129 * api节点jsdoc需要处理的数据,获取diff信息 1130 */ 1131 export const jsDocDiffProcessors: JsDocDiffProcessor[] = [ 1132 JsDocDiffHelper.diffSyscap, 1133 JsDocDiffHelper.diffDeprecated, 1134 JsDocDiffHelper.diffPermissions, 1135 JsDocDiffHelper.diffErrorCodes, 1136 JsDocDiffHelper.diffIsForm, 1137 JsDocDiffHelper.diffIsCrossPlatForm, 1138 JsDocDiffHelper.diffModelLimitation, 1139 JsDocDiffHelper.diffIsSystemApi, 1140 ]; 1141 1142 /** 1143 * 枚举值节点需要处理的数据 1144 */ 1145 export const enumDiffProcessors: ApiSceneDiffProcessor[] = [ 1146 ApiNodeDiffHelper.diffApiName, 1147 ApiNodeDiffHelper.diffEnumMemberValue, 1148 ]; 1149 1150 /** 1151 * 自定义类型节点需要处理的数据 1152 */ 1153 export const typeAliasDiffProcessors: ApiSceneDiffProcessor[] = [ 1154 ApiNodeDiffHelper.diffApiName, 1155 ApiNodeDiffHelper.diffTypeAliasType, 1156 ]; 1157 1158 /** 1159 * 常量节点需要处理的数据 1160 */ 1161 export const constantDiffProcessors: ApiSceneDiffProcessor[] = [ 1162 ApiNodeDiffHelper.diffApiName, 1163 ApiNodeDiffHelper.diffConstantValue, 1164 ]; 1165 1166 /** 1167 * 属性节点需要处理的数据 1168 */ 1169 export const propertyDiffProcessors: ApiSceneDiffProcessor[] = [ 1170 ApiNodeDiffHelper.diffApiName, 1171 ApiNodeDiffHelper.diffPropertyType, 1172 ApiNodeDiffHelper.diffPropertyRequired, 1173 ]; 1174 1175 /** 1176 * 属性节点需要处理的数据 1177 */ 1178 export const methodDiffProcessors: ApiScenesDiffProcessor[] = [ 1179 ApiNodeDiffHelper.diffApiName, 1180 ApiNodeDiffHelper.diffMethodReturnType, 1181 ApiNodeDiffHelper.diffMethodParams, 1182 ]; 1183} 1184