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 PropertyInfo, 25 TypeAliasInfo, 26 InterfaceInfo, 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 parentApiTypeSet, 42} from '../../typedef/diff/ApiInfoDiff'; 43import { StringUtils } from '../../utils/StringUtils'; 44import { CharMapType, CompareReturnObjType, PermissionsProcessorHelper, RangeChange } from './PermissionsProcessor'; 45import { DecoratorInfo } from '../../typedef/parser/Decorator'; 46import { CommonFunctions } from '../../utils/checkUtils'; 47import { NumberConstant } from '../../utils/Constant'; 48import ts from 'typescript'; 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( 73 oldApiInfo: ApiInfo, 74 newApiInfo: ApiInfo, 75 diffInfos: BasicDiffInfo[], 76 isAllDeprecated?: boolean, 77 isAllSheet?: boolean 78 ): void { 79 const oldJsDocInfo: Comment.JsDocInfo | undefined = oldApiInfo.getLastJsDocInfo(); 80 const newJsDocInfo: Comment.JsDocInfo | undefined = newApiInfo.getLastJsDocInfo(); 81 JsDocDiffHelper.diffSinceVersion(oldApiInfo, newApiInfo, diffInfos); 82 const allDiffTypeInfo: DiffTypeInfo[] | undefined = JsDocDiffHelper.diffErrorCodes(oldJsDocInfo, newJsDocInfo); 83 allDiffTypeInfo?.forEach((diffType: DiffTypeInfo) => { 84 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffType); 85 diffInfos.push(diffInfo); 86 }); 87 for (let i = 0; i < jsDocDiffProcessors.length; i++) { 88 const jsDocDiffProcessor: JsDocDiffProcessor | undefined = jsDocDiffProcessors[i]; 89 const diffType: DiffTypeInfo | undefined = jsDocDiffProcessor( 90 oldJsDocInfo, 91 newJsDocInfo, 92 isAllDeprecated, 93 isAllSheet 94 ); 95 if (!diffType) { 96 continue; 97 } 98 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffType); 99 diffInfos.push(diffInfo); 100 } 101 } 102 103 static getFirstSinceVersion(jsDocInfos: Comment.JsDocInfo[]): string { 104 let sinceVersion: string = ''; 105 for (let i = 0; i < jsDocInfos.length; i++) { 106 const jsDocInfo: Comment.JsDocInfo = jsDocInfos[i]; 107 if (jsDocInfo.getSince() !== '-1') { 108 sinceVersion = jsDocInfo.getSince(); 109 return sinceVersion; 110 } 111 } 112 return sinceVersion; 113 } 114 115 static diffSinceVersion(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 116 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 117 const oldFirstJsDocInfo: Comment.JsDocInfo | undefined = oldApiInfo.getJsDocInfos()[0]; 118 const newFirstJsDocInfo: Comment.JsDocInfo | undefined = newApiInfo.getJsDocInfos()[0]; 119 const sinceVersionOfOld: string = oldFirstJsDocInfo ? oldFirstJsDocInfo.getSince() : '-1'; 120 const sinceVersionOfNew: string = newFirstJsDocInfo ? newFirstJsDocInfo.getSince() : '-1'; 121 diffTypeInfo 122 .setStatusCode(ApiStatusCode.VERSION_CHNAGES) 123 .setOldMessage(sinceVersionOfOld) 124 .setNewMessage(sinceVersionOfNew); 125 if (sinceVersionOfOld === sinceVersionOfNew) { 126 return; 127 } 128 if (sinceVersionOfOld === '-1') { 129 diffTypeInfo.setDiffType(ApiDiffType.SINCE_VERSION_NA_TO_HAVE); 130 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 131 diffInfos.push(diffInfo); 132 return; 133 } 134 if (sinceVersionOfNew === '-1') { 135 diffTypeInfo.setDiffType(ApiDiffType.SINCE_VERSION_HAVE_TO_NA); 136 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 137 diffInfos.push(diffInfo); 138 return; 139 } 140 diffTypeInfo.setDiffType(ApiDiffType.SINCE_VERSION_A_TO_B); 141 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 142 diffInfos.push(diffInfo); 143 } 144 145 static diffIsSystemApi( 146 oldJsDocInfo: Comment.JsDocInfo | undefined, 147 newJsDocInfo: Comment.JsDocInfo | undefined 148 ): DiffTypeInfo | undefined { 149 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 150 const isSystemApiOfOld: boolean = oldJsDocInfo ? oldJsDocInfo.getIsSystemApi() : false; 151 const isSystemApiOfNew: boolean = newJsDocInfo ? newJsDocInfo.getIsSystemApi() : false; 152 diffTypeInfo 153 .setStatusCode(ApiStatusCode.SYSTEM_API_CHNAGES) 154 .setOldMessage(StringUtils.transformBooleanToTag(isSystemApiOfOld, Comment.JsDocTag.SYSTEM_API)) 155 .setNewMessage(StringUtils.transformBooleanToTag(isSystemApiOfNew, Comment.JsDocTag.SYSTEM_API)); 156 if (isSystemApiOfNew === isSystemApiOfOld) { 157 return undefined; 158 } 159 if (isSystemApiOfNew) { 160 return diffTypeInfo.setDiffType(ApiDiffType.PUBLIC_TO_SYSTEM); 161 } 162 return diffTypeInfo.setDiffType(ApiDiffType.SYSTEM_TO_PUBLIC); 163 } 164 165 static diffModelLimitation( 166 oldJsDocInfo: Comment.JsDocInfo | undefined, 167 newJsDocInfo: Comment.JsDocInfo | undefined 168 ): DiffTypeInfo | undefined { 169 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 170 const modelLimitationDiffMap: Map<string, ApiDiffType> = new Map([ 171 ['_stagemodelonly', ApiDiffType.NA_TO_STAGE], 172 ['stagemodelonly_', ApiDiffType.STAGE_TO_NA], 173 ['_famodelonly', ApiDiffType.NA_TO_FA], 174 ['famodelonly_', ApiDiffType.FA_TO_NA], 175 ['famodelonly_stagemodelonly', ApiDiffType.FA_TO_STAGE], 176 ['stagemodelonly_famodelonly', ApiDiffType.STAGE_TO_FA], 177 ]); 178 const modelLimitationOfOld: string = oldJsDocInfo ? oldJsDocInfo.getModelLimitation().toLowerCase() : ''; 179 const modelLimitationOfNew: string = newJsDocInfo ? newJsDocInfo.getModelLimitation().toLowerCase() : ''; 180 if (modelLimitationOfNew === modelLimitationOfOld) { 181 return undefined; 182 } 183 const diffMsg: string = `${modelLimitationOfOld.toLowerCase()}_${modelLimitationOfNew.toLowerCase()}`; 184 const diffType: ApiDiffType = modelLimitationDiffMap.get(diffMsg) as ApiDiffType; 185 diffTypeInfo 186 .setStatusCode(ApiStatusCode.MODEL_CHNAGES) 187 .setDiffType(diffType) 188 .setOldMessage(modelLimitationOfOld) 189 .setNewMessage(modelLimitationOfNew); 190 return diffTypeInfo; 191 } 192 193 static diffIsForm( 194 oldJsDocInfo: Comment.JsDocInfo | undefined, 195 newJsDocInfo: Comment.JsDocInfo | undefined 196 ): DiffTypeInfo | undefined { 197 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 198 const isCardOfOld: boolean = oldJsDocInfo ? oldJsDocInfo.getIsForm() : false; 199 const isCardOfNew: boolean = newJsDocInfo ? newJsDocInfo.getIsForm() : false; 200 diffTypeInfo 201 .setStatusCode(ApiStatusCode.FORM_CHANGED) 202 .setOldMessage(StringUtils.transformBooleanToTag(isCardOfOld, Comment.JsDocTag.FORM)) 203 .setNewMessage(StringUtils.transformBooleanToTag(isCardOfNew, Comment.JsDocTag.FORM)); 204 if (isCardOfNew === isCardOfOld) { 205 return undefined; 206 } 207 if (isCardOfNew) { 208 return diffTypeInfo.setDiffType(ApiDiffType.NA_TO_CARD); 209 } 210 return diffTypeInfo.setDiffType(ApiDiffType.CARD_TO_NA); 211 } 212 213 static diffIsCrossPlatForm( 214 oldJsDocInfo: Comment.JsDocInfo | undefined, 215 newJsDocInfo: Comment.JsDocInfo | undefined 216 ): DiffTypeInfo | undefined { 217 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 218 const isCrossPlatFormOfOld: boolean = oldJsDocInfo ? oldJsDocInfo.getIsCrossPlatForm() : false; 219 const isCrossPlatFormOfNew: boolean = newJsDocInfo ? newJsDocInfo.getIsCrossPlatForm() : false; 220 diffTypeInfo 221 .setStatusCode(ApiStatusCode.CROSSPLATFORM_CHANGED) 222 .setOldMessage(StringUtils.transformBooleanToTag(isCrossPlatFormOfOld, Comment.JsDocTag.CROSS_PLAT_FORM)) 223 .setNewMessage(StringUtils.transformBooleanToTag(isCrossPlatFormOfNew, Comment.JsDocTag.CROSS_PLAT_FORM)); 224 if (isCrossPlatFormOfNew === isCrossPlatFormOfOld) { 225 return undefined; 226 } 227 if (isCrossPlatFormOfNew) { 228 return diffTypeInfo.setDiffType(ApiDiffType.NA_TO_CROSS_PLATFORM); 229 } 230 return diffTypeInfo.setDiffType(ApiDiffType.CROSS_PLATFORM_TO_NA); 231 } 232 233 static diffAtomicService( 234 oldJsDocInfo: Comment.JsDocInfo | undefined, 235 newJsDocInfo: Comment.JsDocInfo | undefined 236 ): DiffTypeInfo | undefined { 237 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 238 const isAtomicServiceOfOld: boolean | undefined = oldJsDocInfo ? oldJsDocInfo.getIsAtomicService() : false; 239 const isAtomicServiceOfNew: boolean | undefined = newJsDocInfo ? newJsDocInfo.getIsAtomicService() : false; 240 diffTypeInfo 241 .setStatusCode(ApiStatusCode.ATOMICSERVICE_CHANGE) 242 .setOldMessage(StringUtils.transformBooleanToTag(isAtomicServiceOfOld, Comment.JsDocTag.ATOMIC_SERVICE)) 243 .setNewMessage(StringUtils.transformBooleanToTag(isAtomicServiceOfNew, Comment.JsDocTag.ATOMIC_SERVICE)); 244 if (isAtomicServiceOfOld === isAtomicServiceOfNew) { 245 return undefined; 246 } 247 if (isAtomicServiceOfNew) { 248 return diffTypeInfo.setDiffType(ApiDiffType.ATOMIC_SERVICE_NA_TO_HAVE); 249 } 250 return diffTypeInfo.setDiffType(ApiDiffType.ATOMIC_SERVICE_HAVE_TO_NA); 251 } 252 253 static diffPermissions( 254 oldJsDocInfo: Comment.JsDocInfo | undefined, 255 newJsDocInfo: Comment.JsDocInfo | undefined 256 ): DiffTypeInfo | undefined { 257 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 258 const permissionsOfOld: string = oldJsDocInfo ? oldJsDocInfo.getPermission() : ''; 259 const permissionsOfNew: string = newJsDocInfo ? newJsDocInfo.getPermission() : ''; 260 diffTypeInfo 261 .setStatusCode(ApiStatusCode.PERMISSION_CHANGES) 262 .setOldMessage(permissionsOfOld) 263 .setNewMessage(permissionsOfNew); 264 if (permissionsOfOld === permissionsOfNew) { 265 return undefined; 266 } 267 if (permissionsOfOld === '') { 268 return diffTypeInfo.setStatusCode(ApiStatusCode.PERMISSION_NEW).setDiffType(ApiDiffType.PERMISSION_NA_TO_HAVE); 269 } 270 if (permissionsOfNew === '') { 271 return diffTypeInfo 272 .setStatusCode(ApiStatusCode.PERMISSION_DELETE) 273 .setDiffType(ApiDiffType.PERMISSION_HAVE_TO_NA); 274 } 275 const permiss: PermissionsProcessorHelper = new PermissionsProcessorHelper(permissionsCharMap); 276 const compareVal: CompareReturnObjType = permiss.comparePermissions(permissionsOfOld, permissionsOfNew); 277 if (compareVal.range === RangeChange.DOWN) { 278 return diffTypeInfo.setDiffType(ApiDiffType.PERMISSION_RANGE_SMALLER); 279 } 280 if (compareVal.range === RangeChange.UP) { 281 return diffTypeInfo.setDiffType(ApiDiffType.PERMISSION_RANGE_BIGGER); 282 } 283 return diffTypeInfo.setDiffType(ApiDiffType.PERMISSION_RANGE_CHANGE); 284 } 285 286 static diffErrorCodes( 287 oldJsDocInfo: Comment.JsDocInfo | undefined, 288 newJsDocInfo: Comment.JsDocInfo | undefined 289 ): DiffTypeInfo[] | undefined { 290 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 291 const errorCodesOfOld: number[] = oldJsDocInfo ? oldJsDocInfo.getErrorCode().sort() : []; 292 const errorCodesOfNew: number[] = newJsDocInfo ? newJsDocInfo.getErrorCode().sort() : []; 293 const errorCodeSetOfOld: Set<number> = new Set(errorCodesOfOld); 294 const errorCodeSetOfNew: Set<number> = new Set(errorCodesOfNew); 295 const allErrorCodes: Set<number> = new Set(errorCodesOfNew.concat(errorCodesOfOld)); 296 const errorCodesStringOfOld: string = errorCodesOfOld.toString(); 297 const errorCodesStringOfNew: string = errorCodesOfNew.toString(); 298 const allDiffTypeInfo: DiffTypeInfo[] = []; 299 diffTypeInfo 300 .setStatusCode(ApiStatusCode.ERRORCODE_CHANGES) 301 .setOldMessage(errorCodesStringOfOld) 302 .setNewMessage(errorCodesStringOfNew); 303 if (errorCodesStringOfNew === errorCodesStringOfOld) { 304 return undefined; 305 } 306 if (errorCodesOfOld.length === 0 && errorCodesOfNew.length !== 0) { 307 allDiffTypeInfo.push( 308 diffTypeInfo.setStatusCode(ApiStatusCode.NEW_ERRORCODE).setDiffType(ApiDiffType.ERROR_CODE_NA_TO_HAVE) 309 ); 310 return allDiffTypeInfo; 311 } 312 const oldChangeErrorCodes: number[] = []; 313 const newChangeErrorCodes: number[] = []; 314 allErrorCodes.forEach((errorCode: number) => { 315 if (!errorCodeSetOfOld.has(errorCode)) { 316 oldChangeErrorCodes.push(errorCode); 317 } 318 if (!errorCodeSetOfNew.has(errorCode)) { 319 newChangeErrorCodes.push(errorCode); 320 } 321 }); 322 if (oldChangeErrorCodes.length !== 0) { 323 const oldDiffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 324 oldDiffTypeInfo 325 .setOldMessage('NA') 326 .setNewMessage(oldChangeErrorCodes.join()) 327 .setStatusCode(ApiStatusCode.NEW_ERRORCODE) 328 .setDiffType(ApiDiffType.ERROR_CODE_ADD); 329 allDiffTypeInfo.push(oldDiffTypeInfo); 330 } 331 if (newChangeErrorCodes.length !== 0) { 332 const newDiffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 333 newDiffTypeInfo 334 .setOldMessage(newChangeErrorCodes.join()) 335 .setNewMessage('NA') 336 .setStatusCode(ApiStatusCode.ERRORCODE_DELETE) 337 .setDiffType(ApiDiffType.ERROR_CODE_REDUCE); 338 allDiffTypeInfo.push(newDiffTypeInfo); 339 } 340 return allDiffTypeInfo; 341 } 342 343 static diffSyscap( 344 oldJsDocInfo: Comment.JsDocInfo | undefined, 345 newJsDocInfo: Comment.JsDocInfo | undefined 346 ): DiffTypeInfo | undefined { 347 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 348 const syscapOfOld: string = oldJsDocInfo ? oldJsDocInfo.getSyscap() : ''; 349 const syscapOfNew: string = newJsDocInfo ? newJsDocInfo.getSyscap() : ''; 350 diffTypeInfo.setStatusCode(ApiStatusCode.SYSCAP_CHANGES).setOldMessage(syscapOfOld).setNewMessage(syscapOfNew); 351 if (syscapOfNew === syscapOfOld) { 352 return undefined; 353 } 354 if (syscapOfOld === '') { 355 return diffTypeInfo.setDiffType(ApiDiffType.SYSCAP_NA_TO_HAVE); 356 } 357 if (syscapOfNew === '') { 358 return diffTypeInfo.setDiffType(ApiDiffType.SYSCAP_HAVE_TO_NA); 359 } 360 return diffTypeInfo.setDiffType(ApiDiffType.SYSCAP_A_TO_B); 361 } 362 363 static diffDeprecated( 364 oldJsDocInfo: Comment.JsDocInfo | undefined, 365 newJsDocInfo: Comment.JsDocInfo | undefined, 366 isAllDeprecated?: boolean, 367 isAllSheet?: boolean 368 ): DiffTypeInfo | undefined { 369 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 370 const deprecatedVersionOfOld: string = oldJsDocInfo ? oldJsDocInfo.getDeprecatedVersion() : '-1'; 371 const deprecatedVersionOfNew: string = newJsDocInfo ? newJsDocInfo.getDeprecatedVersion() : '-1'; 372 diffTypeInfo 373 .setStatusCode(ApiStatusCode.DEPRECATED_CHNAGES) 374 .setOldMessage(deprecatedVersionOfOld.toString()) 375 .setNewMessage(deprecatedVersionOfNew.toString()); 376 if (deprecatedVersionOfNew === deprecatedVersionOfOld) { 377 return undefined; 378 } 379 if (isAllSheet) { 380 if (deprecatedVersionOfOld === '-1' && !isAllDeprecated) { 381 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_NOT_All); 382 } 383 if (deprecatedVersionOfOld === '-1' && isAllDeprecated) { 384 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_NA_TO_HAVE); 385 } 386 } else { 387 if (deprecatedVersionOfOld === '-1') { 388 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_NA_TO_HAVE); 389 } 390 if (deprecatedVersionOfNew === '-1') { 391 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_HAVE_TO_NA); 392 } 393 } 394 395 if (deprecatedVersionOfNew === '-1') { 396 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_HAVE_TO_NA); 397 } 398 399 return diffTypeInfo.setDiffType(ApiDiffType.DEPRECATED_A_TO_B); 400 } 401 } 402 403 /** 404 * 比较API的装饰器信息 405 */ 406 export class ApiDecoratorsDiffHelper { 407 /** 408 * 新旧版本API一致的情况下,比较装饰器 409 * 410 * @param {ApiInfo} oldApiInfo 411 * @param {ApiInfo} newApiInfo 412 * @param {BasicDiffInfo[]} diffInfos 413 * @returns 414 */ 415 static diffDecorator(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 416 const oldDecoratorsMap: Map<string, string[] | undefined> = ApiDecoratorsDiffHelper.setDecoratorsMap( 417 oldApiInfo.getDecorators() 418 ); 419 const newDecoratorsMap: Map<string, string[] | undefined> = ApiDecoratorsDiffHelper.setDecoratorsMap( 420 newApiInfo.getDecorators() 421 ); 422 if (newDecoratorsMap.size === 0) { 423 for (const key of oldDecoratorsMap.keys()) { 424 ApiDecoratorsDiffHelper.addDeleteDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 425 } 426 return; 427 } 428 429 if (oldDecoratorsMap.size === 0) { 430 for (const key of newDecoratorsMap.keys()) { 431 ApiDecoratorsDiffHelper.addNewDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 432 newDecoratorsMap.delete(key); 433 } 434 return; 435 } 436 ApiDecoratorsDiffHelper.diffDecoratorInfo(oldDecoratorsMap, newDecoratorsMap, oldApiInfo, newApiInfo, diffInfos); 437 } 438 439 static diffDecoratorInfo( 440 oldDecoratorsMap: Map<string, string[] | undefined>, 441 newDecoratorsMap: Map<string, string[] | undefined>, 442 oldApiInfo: ApiInfo, 443 newApiInfo: ApiInfo, 444 diffInfos: BasicDiffInfo[] 445 ): void { 446 const sameDecoratorSet: Set<string> = new Set(); 447 for (const key of oldDecoratorsMap.keys()) { 448 const newDecoratorArguments: string[] | undefined = newDecoratorsMap.get(key); 449 const oldDecoratorArguments: string[] | undefined = oldDecoratorsMap.get(key); 450 //新版本没有这个装饰器 451 if (!newDecoratorArguments) { 452 ApiDecoratorsDiffHelper.addDeleteDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 453 sameDecoratorSet.add(key); 454 continue; 455 } 456 457 // 新旧版本装饰器参数一样 458 if (oldDecoratorArguments && newDecoratorArguments.join() === oldDecoratorArguments.join()) { 459 newDecoratorsMap.delete(key); 460 sameDecoratorSet.add(key); 461 continue; 462 } 463 } 464 // 新版中剩下的装饰器为新增 465 for (const key of newDecoratorsMap.keys()) { 466 ApiDecoratorsDiffHelper.addNewDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 467 } 468 469 for (const key of oldDecoratorsMap.keys()) { 470 if (sameDecoratorSet.has(key)) { 471 continue; 472 } 473 ApiDecoratorsDiffHelper.addDeleteDecoratorsInfo(key, oldApiInfo, newApiInfo, diffInfos); 474 } 475 } 476 477 static setDecoratorsMap(decorators: DecoratorInfo[] | undefined): Map<string, string[] | undefined> { 478 const decoratorsMap: Map<string, string[]> = new Map(); 479 if (!decorators) { 480 return decoratorsMap; 481 } 482 483 decorators.forEach((decoratorInfo: DecoratorInfo) => { 484 const expressionArguments: string[] | undefined = decoratorInfo.getExpressionArguments(); 485 decoratorsMap.set(decoratorInfo.getExpression(), expressionArguments === undefined ? [] : expressionArguments); 486 }); 487 return decoratorsMap; 488 } 489 490 static addDeleteDecoratorsInfo( 491 decoratorName: string, 492 oldApiInfo: ApiInfo, 493 newApiInfo: ApiInfo, 494 diffInfos: BasicDiffInfo[] 495 ): void { 496 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 497 diffTypeInfo 498 .setStatusCode(ApiStatusCode.DELETE_DECORATOR) 499 .setDiffType(ApiDiffType.DELETE_DECORATOR) 500 .setOldMessage(decoratorName) 501 .setNewMessage(''); 502 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 503 diffInfos.push(diffInfo); 504 } 505 506 static addNewDecoratorsInfo( 507 decoratorName: string, 508 oldApiInfo: ApiInfo, 509 newApiInfo: ApiInfo, 510 diffInfos: BasicDiffInfo[] 511 ): void { 512 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 513 diffTypeInfo 514 .setStatusCode(ApiStatusCode.NEW_DECORATOR) 515 .setDiffType(ApiDiffType.NEW_DECORATOR) 516 .setOldMessage('') 517 .setNewMessage(decoratorName); 518 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 519 diffInfos.push(diffInfo); 520 } 521 } 522 523 export class ApiCheckHelper { 524 /** 525 * 比较两个API的历史版本jsdoc 526 * 527 * @param {ApiInfo} oldApiInfo 528 * @param {ApiInfo} newApiInfo 529 * @param {BasicDiffInfo[]} diffInfos 530 */ 531 static diffHistoricalJsDoc(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 532 const currentVersion: string = CommonFunctions.getCheckApiVersion().toString(); 533 const oldJsDocTextArr: Array<string> = oldApiInfo.getJsDocText().split('*/'); 534 const newJsDocTextArr: Array<string> = newApiInfo.getJsDocText().split('*/'); 535 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 536 537 if (oldApiInfo.getCurrentVersion() === currentVersion) { 538 oldJsDocTextArr.splice(NumberConstant.DELETE_CURRENT_JS_DOC); 539 } else { 540 oldJsDocTextArr.splice(-1); 541 } 542 543 if (newApiInfo.getCurrentVersion() === currentVersion) { 544 newJsDocTextArr.splice(NumberConstant.DELETE_CURRENT_JS_DOC); 545 } else { 546 newJsDocTextArr.splice(-1); 547 } 548 549 if (oldJsDocTextArr.length !== newJsDocTextArr.length) { 550 diffTypeInfo.setDiffType(ApiDiffType.HISTORICAL_JSDOC_CHANGE); 551 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 552 diffInfos.push(diffInfo); 553 return; 554 } 555 for (let i = 0; i < oldJsDocTextArr.length; i++) { 556 if (oldJsDocTextArr[i].replace(/\r\n|\n|\s+/g, '') !== newJsDocTextArr[i].replace(/\r\n|\n|\s+/g, '')) { 557 diffTypeInfo.setDiffType(ApiDiffType.HISTORICAL_JSDOC_CHANGE); 558 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 559 diffInfos.push(diffInfo); 560 } 561 } 562 } 563 564 static diffHistoricalAPI(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 565 const currentVersion: string = CommonFunctions.getCheckApiVersion().toString(); 566 const oldApiDefinedText: string = oldApiInfo.getDefinedText(); 567 const newApiDefinedText: string = newApiInfo.getDefinedText(); 568 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 569 if (oldApiDefinedText !== newApiDefinedText && newApiInfo.getCurrentVersion() !== currentVersion) { 570 diffTypeInfo.setDiffType(ApiDiffType.HISTORICAL_API_CHANGE); 571 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 572 diffInfos.push(diffInfo); 573 } 574 } 575 } 576 577 /** 578 * 处理api节点的diff信息工具 579 * 580 */ 581 export class ApiNodeDiffHelper { 582 /** 583 * 根据节点类型处理节点的diff信息,处理的主流程 584 * 585 * @param {ApiInfo} oldApiInfo 旧版本的节点信息 586 * @param {ApiInfo} newApiInfo 新版本的节点信息 587 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 588 * @return {void} 589 */ 590 static diffNodeInfo(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[], isCheck?: boolean): void { 591 if (isCheck) { 592 ApiCheckHelper.diffHistoricalJsDoc(oldApiInfo, newApiInfo, diffInfos); 593 ApiCheckHelper.diffHistoricalAPI(oldApiInfo, newApiInfo, diffInfos); 594 } 595 const oldApiType: string = oldApiInfo.getApiType(); 596 const newApiType: string = newApiInfo.getApiType(); 597 if ( 598 `${oldApiType}_${newApiType}` === `${ApiType.CONSTANT}_${ApiType.PROPERTY}` || 599 `${oldApiType}_${newApiType}` === `${ApiType.PROPERTY}_${ApiType.CONSTANT}` 600 ) { 601 ApiNodeDiffHelper.diffConstant(oldApiInfo as ApiInfo, newApiInfo as ApiInfo, diffInfos); 602 } 603 if (oldApiInfo.getApiType() !== newApiType) { 604 return; 605 } 606 const apiNodeDiff: ApiNodeDiffProcessor | undefined = apiNodeDiffMethod.get(newApiType); 607 if (!apiNodeDiff) { 608 return; 609 } 610 apiNodeDiff(oldApiInfo, newApiInfo, diffInfos); 611 } 612 613 /** 614 * 处理type类型 615 * 616 * @static 617 * @param {string} oldType 旧版本的type字符串 618 * @param {string} newType 新版本的type字符串 619 * @return { ApiDiffType | undefined} type范围的变化情况 620 * @memberof ApiNodeDiffHelper 621 */ 622 static diffBaseType(oldType: string, newType: string): DiffTypeInfo | undefined { 623 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 624 if (oldType === newType) { 625 return undefined; 626 } 627 diffTypeInfo.setStatusCode(ApiStatusCode.TYPE_CHNAGES).setOldMessage(oldType).setNewMessage(newType); 628 if (oldType === '') { 629 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE); 630 } 631 if (newType === '') { 632 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE); 633 } 634 const permiss: PermissionsProcessorHelper = new PermissionsProcessorHelper(typeCharMap); 635 const compareVal: CompareReturnObjType = permiss.comparePermissions(oldType, newType); 636 if (compareVal.range === RangeChange.DOWN) { 637 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_SMALLER); 638 } 639 if (compareVal.range === RangeChange.UP) { 640 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_BIGGER); 641 } 642 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE); 643 } 644 645 /** 646 * 处理方法节点,获取对应diff信息 647 * 648 * @param {ApiInfo} oldApiInfo 旧版本的方法节点信息 649 * @param {ApiInfo} newApiInfo 新版本的方法节点信息 650 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 651 */ 652 static diffMethod(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 653 methodDiffProcessors.forEach((methodDiffProcessor: ApiScenesDiffProcessor) => { 654 const diffTypeInfo: DiffTypeInfo[] | DiffTypeInfo | undefined = methodDiffProcessor( 655 oldApiInfo as MethodInfo, 656 newApiInfo as MethodInfo 657 ); 658 if (!diffTypeInfo) { 659 return; 660 } 661 if (diffTypeInfo instanceof Array) { 662 diffTypeInfo.forEach((info: DiffTypeInfo) => { 663 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 664 oldApiInfo, 665 newApiInfo, 666 info.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 667 ); 668 diffInfos.push(diffInfo); 669 }); 670 } else { 671 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 672 oldApiInfo, 673 newApiInfo, 674 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 675 ); 676 diffInfos.push(diffInfo); 677 } 678 }); 679 } 680 static diffTypeAliasReturnType(oldApiInfo: TypeAliasInfo, newApiInfo: TypeAliasInfo): DiffTypeInfo | undefined { 681 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 682 const oldReturnType: string[] = oldApiInfo.getReturnType(); 683 const newReturnType: string[] = newApiInfo.getReturnType(); 684 const olaMethodTypeStr = oldReturnType.toString().replace(/\r|\n|\s+|'|"/g, ''); 685 const newMethodTypeStr = newReturnType.toString().replace(/\r|\n|\s+|'|"/g, ''); 686 if (olaMethodTypeStr === newMethodTypeStr) { 687 return undefined; 688 } 689 diffTypeInfo.setOldMessage(olaMethodTypeStr).setNewMessage(newMethodTypeStr); 690 if (checkParentContainChild(newReturnType, oldReturnType)) { 691 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_FUNCTION_RETURN_TYPE_ADD); 692 } 693 if (checkParentContainChild(oldReturnType, newReturnType)) { 694 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_FUNCTION_RETURN_TYPE_REDUCE); 695 } 696 // 旧版本不包含新版本,新版本也不含旧版本,就定义为返回值变更 697 return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_FUNCTION_RETURN_TYPE_CHANGE); 698 } 699 /** 700 * 处理方法节点的返回值 701 * 702 * @param {MethodInfo} oldApiInfo 旧版本的方法节点信息 703 * @param {MethodInfo} newApiInfo 新版本的方法节点信息 704 * @return {*} {(ApiDiffType | undefined)} 方法节点的返回值的变化情况 705 */ 706 static diffMethodReturnType( 707 oldApiInfo: MethodInfo, 708 newApiInfo: MethodInfo | TypeAliasInfo 709 ): DiffTypeInfo | undefined { 710 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 711 const oldReturnType: string[] = oldApiInfo.getReturnValue(); 712 const newReturnType: string[] = 713 newApiInfo.getApiType() === ApiType.TYPE_ALIAS 714 ? (newApiInfo as TypeAliasInfo).getReturnType() 715 : (newApiInfo as MethodInfo).getReturnValue(); 716 const oldMethodTypeStr = oldReturnType.toString().replace(/\r|\n|\s+|'|"|>/g, ''); 717 const newMethodTypeStr = newReturnType.toString().replace(/\r|\n|\s+|'|"|>/g, ''); 718 if (oldMethodTypeStr === newMethodTypeStr) { 719 return undefined; 720 } 721 diffTypeInfo.setOldMessage(oldReturnType.toString()).setNewMessage(newReturnType.toString()); 722 if (checkParentContainChild(newReturnType, oldReturnType)) { 723 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_ADD); 724 } 725 if (StringUtils.hasSubstring(newMethodTypeStr, oldMethodTypeStr)) { 726 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_ADD); 727 } 728 if (checkParentContainChild(oldReturnType, newReturnType)) { 729 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_REDUCE); 730 } 731 if (StringUtils.hasSubstring(oldMethodTypeStr, newMethodTypeStr)) { 732 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_REDUCE); 733 } 734 // 旧版本不包含新版本,新版本也不含旧版本,就定义为返回值变更 735 return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_CHANGE); 736 } 737 738 /** 739 * 740 * @param isTypeAlias 是否为自定义节点类型 741 * @returns {*} {DiffMethodType} 当前节点类型对应的修改类型 742 */ 743 static getDiffMethodTypes(isTypeAlias: boolean): DiffMethodType & DiffTypeChangeType { 744 if (isTypeAlias) { 745 return { 746 POS_CHANGE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_POS_CHAHGE, 747 ADD_OPTIONAL_PARAM: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_UNREQUIRED_ADD, 748 ADD_REQUIRED_PARAM: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_REQUIRED_ADD, 749 REDUCE_PARAM: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_REDUCE, 750 PARAM_TYPE_CHANGE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TYPE_CHANGE, 751 PARAM_TYPE_ADD: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TYPE_ADD, 752 PARAM_TYPE_REDUCE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TYPE_REDUCE, 753 PARAM_TO_UNREQUIRED: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TO_UNREQUIRED, 754 PARAM_TO_REQUIRED: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TO_REQUIRED, 755 PARAM_CHANGE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_CHANGE, 756 }; 757 } else { 758 return { 759 POS_CHANGE: ApiDiffType.FUNCTION_PARAM_POS_CHANGE, 760 ADD_OPTIONAL_PARAM: ApiDiffType.FUNCTION_PARAM_UNREQUIRED_ADD, 761 ADD_REQUIRED_PARAM: ApiDiffType.FUNCTION_PARAM_REQUIRED_ADD, 762 REDUCE_PARAM: ApiDiffType.FUNCTION_PARAM_REDUCE, 763 PARAM_TYPE_CHANGE: ApiDiffType.FUNCTION_PARAM_TYPE_CHANGE, 764 PARAM_TYPE_ADD: ApiDiffType.FUNCTION_PARAM_TYPE_ADD, 765 PARAM_TYPE_REDUCE: ApiDiffType.FUNCTION_PARAM_TYPE_REDUCE, 766 PARAM_TO_UNREQUIRED: ApiDiffType.FUNCTION_PARAM_TO_UNREQUIRED, 767 PARAM_TO_REQUIRED: ApiDiffType.FUNCTION_PARAM_TO_REQUIRED, 768 PARAM_CHANGE: ApiDiffType.FUNCTION_PARAM_CHANGE, 769 }; 770 } 771 } 772 /** 773 * 处理方法节点的参数,获取对应diff信息 774 * 775 * @param {MethodInfo} oldApiInfo 旧版本的方法节点信息 776 * @param {MethodInfo} newApiInfo 新版本的方法节点信息 777 * @return {*} {ApiDiffType[]} 返回各个参数的变化情况 778 */ 779 static diffMethodParams( 780 oldApiInfo: MethodInfo | TypeAliasInfo, 781 newApiInfo: MethodInfo | TypeAliasInfo 782 ): DiffTypeInfo[] { 783 const diffTypeInfos: DiffTypeInfo[] = []; 784 const isTypeAlias: boolean = oldApiInfo.getApiType() === 'TypeAlias'; 785 const oldMethodParams: ParamInfo[] = 786 oldApiInfo.getApiType() === ApiType.TYPE_ALIAS 787 ? (oldApiInfo as TypeAliasInfo).getParamInfos() 788 : (oldApiInfo as MethodInfo).getParams(); 789 const newMethodParams: ParamInfo[] = 790 newApiInfo.getApiType() === ApiType.TYPE_ALIAS 791 ? (newApiInfo as TypeAliasInfo).getParamInfos() 792 : (newApiInfo as MethodInfo).getParams(); 793 const diffMethodType: DiffMethodType & DiffTypeChangeType = ApiNodeDiffHelper.getDiffMethodTypes(isTypeAlias); 794 795 ApiNodeDiffHelper.diffParamsPosition(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 796 ApiNodeDiffHelper.diffNewOptionalParam(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 797 ApiNodeDiffHelper.diffNewRequiredParam(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 798 ApiNodeDiffHelper.diffReducedParam(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 799 ApiNodeDiffHelper.diffParamTypeChange(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 800 ApiNodeDiffHelper.diffParamChange(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 801 ApiNodeDiffHelper.diffMethodParamChange(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType); 802 return diffTypeInfos; 803 } 804 /** 805 * 方法参数名变化,且不属于新增、减少的情况,归纳为方法参数变化, 806 * 807 * @param {ParamInfo[]} oldMethodParams 函数旧参数节点信息 808 * @param {ParamInfo[]} newMethodParams 函数新参数节点信息 809 * @param diffTypeInfos 处理好的结果信息 810 */ 811 static diffMethodParamChange( 812 oldMethodParams: ParamInfo[], 813 newMethodParams: ParamInfo[], 814 diffTypeInfos: DiffTypeInfo[], 815 diffMethodType: DiffMethodType 816 ): void { 817 const oldParamLen: number = oldMethodParams.length; 818 const newParamLen: number = newMethodParams.length; 819 // 1.新旧版本参数一个不存在即不符合,直接返回 820 if (!oldParamLen || !newParamLen) { 821 return; 822 } 823 // 2. 判断新旧版本参数名称相同的参数的个数和新旧版本的参数是否相同,相同即为新增或者减少参数 824 // 2.1 循环得到所有的参数名称 825 const oldParamNames: string[] = []; 826 const newParamNames: string[] = []; 827 for (let i: number = 0; i < Math.max(oldParamLen, newParamLen); i++) { 828 const newCur: ParamInfo = newMethodParams[i]; 829 const oldCur: ParamInfo = oldMethodParams[i]; 830 newCur && newParamNames.push(newCur.getApiName()); 831 oldCur && oldParamNames.push(oldCur.getApiName()); 832 } 833 // 2.2 找出旧版本不同的参数名称 834 const oldDiffParams: ParamInfo[] = oldMethodParams.filter( 835 (oldParam: ParamInfo) => !newParamNames.includes(oldParam.getApiName()) 836 ); 837 // 2.3 得到参数相同的个数 838 const sameParamsLength: number = oldParamLen - oldDiffParams.length; 839 // 2.4 判断新旧版本参数名称相同的参数的个数和新旧版本的参数是否相同,相同即为新增或者减少参数 840 if (sameParamsLength === oldParamLen || sameParamsLength === newParamLen) { 841 return; 842 } 843 844 let oldDiffInfos: ParamInfo[] = oldMethodParams; 845 let newDiffInfos: ParamInfo[] = newMethodParams; 846 // 3.将新旧版本参数信息中前面检查出来的信息去掉 847 diffTypeInfos.forEach((diffInfo: DiffTypeInfo) => { 848 // 循环已经得到的结果信息,找到新旧版本里不在已经得到的结果信息里面的参数信息 849 oldDiffInfos = oldDiffInfos.filter( 850 (oldDiffInfo: ParamInfo) => diffInfo.getOldMessage() !== oldDiffInfo.getDefinedText() 851 ); 852 newDiffInfos = newDiffInfos.filter( 853 (newDiffInfo: ParamInfo) => diffInfo.getNewMessage() !== newDiffInfo.getDefinedText() 854 ); 855 }); 856 // 4.剩下的部分就是发生变化的部分,生成返回信息 857 const oldNamesStr: string = stitchMethodParameters(oldDiffInfos); 858 const newNamesStr: string = stitchMethodParameters(newDiffInfos); 859 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 860 diffTypeInfo.setDiffType(diffMethodType.PARAM_CHANGE).setOldMessage(oldNamesStr).setNewMessage(newNamesStr); 861 diffTypeInfos.push(diffTypeInfo); 862 } 863 /** 864 * 比较函数位置发生变化 865 * 866 * @param {ParamInfo[]} oldMethodParams 函数旧参数节点信息 867 * @param {ParamInfo[]} newMethodParams 函数新参数节点信息 868 * @param diffTypeInfos 869 */ 870 static diffParamsPosition( 871 oldMethodParams: ParamInfo[], 872 newMethodParams: ParamInfo[], 873 diffTypeInfos: DiffTypeInfo[], 874 diffMethodType: DiffMethodType 875 ): void { 876 const oldParamLen: number = oldMethodParams.length; 877 const newParamLen: number = newMethodParams.length; 878 // 1.如果旧版本的参数长度不大于1,或者两者长度不一致,直接返回 879 if (oldParamLen <= 1 || oldParamLen !== newParamLen) { 880 return; 881 } 882 // 2.判断两个版本的相同位置的参数名称是否一致,相同直接返回 883 const isSamePosition: boolean = checkIsSameOfSamePosition(newMethodParams, oldMethodParams); 884 if (isSamePosition) { 885 return; 886 } 887 // 3.如果旧版本的参数不完全包含新版本的参数或者两个版本的参数是否完全一致,一个不符合直接返回 888 const isContain: boolean = checkIsContain(oldMethodParams, newMethodParams); 889 if (!isContain) { 890 return; 891 } 892 // 4.上述情况都不符合,处理返回信息 893 const oldNamesStr: string = stitchMethodParameters(oldMethodParams); 894 const newNamesStr: string = stitchMethodParameters(newMethodParams); 895 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 896 diffTypeInfo.setDiffType(diffMethodType.POS_CHANGE).setOldMessage(oldNamesStr).setNewMessage(newNamesStr); 897 diffTypeInfos.push(diffTypeInfo); 898 } 899 900 /** 901 * 函数新增可选参数 902 * 903 * @param oldMethodParams 904 * @param newMethodParams 905 * @param diffTypeInfos 906 */ 907 static diffNewOptionalParam( 908 oldMethodParams: ParamInfo[], 909 newMethodParams: ParamInfo[], 910 diffTypeInfos: DiffTypeInfo[], 911 diffMethodType: DiffMethodType 912 ): void { 913 const oldParamLen: number = oldMethodParams.length; 914 const newParamLen: number = newMethodParams.length; 915 // 1.如果新版本参数为空或者旧版本参数长度大于或者等于新版本参数长度,直接返回 916 if (newParamLen === 0 || oldParamLen >= newParamLen) { 917 return; 918 } 919 // 2.新版本参数需要完全包含旧版本,如果不包含,直接返回 920 const isContain: boolean = checkIsContain(newMethodParams, oldMethodParams); 921 if (!isContain) { 922 return; 923 } 924 // 3.是否存在新增的可选参数 925 const oldParamNames: string[] = oldMethodParams.map((oldParam: ParamInfo) => oldParam.getApiName()); 926 const addParams: ParamInfo[] = newMethodParams.filter((newParam: ParamInfo) => { 927 const curParamName: string = newParam.getApiName(); 928 return !oldParamNames.includes(curParamName) && !newParam.getIsRequired(); 929 }); 930 // 4.新版本新增的参数是否存在参数是可选类型,不存在直接返回 931 if (!addParams.length) { 932 return; 933 } 934 // 5.存在新增的参数是可选参数,处理返回信息 935 const addParamNamesStr: string = stitchMethodParameters(addParams); 936 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 937 diffTypeInfo.setOldMessage('').setDiffType(diffMethodType.ADD_OPTIONAL_PARAM).setNewMessage(addParamNamesStr); 938 diffTypeInfos.push(diffTypeInfo); 939 } 940 941 /** 942 * 函数新增必选参数 943 * 944 * @param oldMethodParams 945 * @param newMethodParams 946 * @param diffTypeInfos 947 */ 948 static diffNewRequiredParam( 949 oldMethodParams: ParamInfo[], 950 newMethodParams: ParamInfo[], 951 diffTypeInfos: DiffTypeInfo[], 952 diffMethodType: DiffMethodType 953 ): void { 954 const oldParamLen: number = oldMethodParams.length; 955 const newParamLen: number = newMethodParams.length; 956 // 1.如果新版本参数为空或者旧版本参数长度大于或者等于新版本参数长度,直接返回 957 if (newParamLen === 0 || oldParamLen >= newParamLen) { 958 return; 959 } 960 // 2.新版本参数需要完全包含旧版本,如果不包含,直接返回 961 const isContain: boolean = checkIsContain(newMethodParams, oldMethodParams); 962 if (!isContain) { 963 return; 964 } 965 // 3.是否存在新增的必选参数 966 const oldParamNames: string[] = oldMethodParams.map((oldParam: ParamInfo) => oldParam.getApiName()); 967 const addParams: ParamInfo[] = newMethodParams.filter((newParam: ParamInfo) => { 968 const curParamName: string = newParam.getApiName(); 969 return !oldParamNames.includes(curParamName) && newParam.getIsRequired(); 970 }); 971 // 4.新版本新增的参数是否存在参数是必选类型,不存在直接返回 972 if (!addParams.length) { 973 return; 974 } 975 // 5.存在新增的参数是可选参数,处理返回信息 976 const addParamNamesStr: string = stitchMethodParameters(addParams); 977 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 978 diffTypeInfo.setDiffType(diffMethodType.ADD_REQUIRED_PARAM).setOldMessage('').setNewMessage(addParamNamesStr); 979 diffTypeInfos.push(diffTypeInfo); 980 } 981 982 /** 983 * 函数删除参数 984 * 985 * @param oldMethodParams 986 * @param newMethodParams 987 * @param diffTypeInfos 988 */ 989 static diffReducedParam( 990 oldMethodParams: ParamInfo[], 991 newMethodParams: ParamInfo[], 992 diffTypeInfos: DiffTypeInfo[], 993 diffMethodType: DiffMethodType 994 ): void { 995 const oldParamLen: number = oldMethodParams.length; 996 const newParamLen: number = newMethodParams.length; 997 // 1.旧版本参数为空或者新版本参数长度大于或者等于旧版本参数长度,直接返回 998 if (oldParamLen === 0 || newParamLen >= oldParamLen) { 999 return; 1000 } 1001 // 2.如果旧版本的参数不包含新版本的参数,直接返回 1002 const isContain: boolean = checkIsContain(oldMethodParams, newMethodParams); 1003 if (newParamLen > 0 && !isContain) { 1004 return; 1005 } 1006 // 3.参数减少,处理返回信息 1007 const newParamNames: string[] = newMethodParams.map((newParam: ParamInfo) => newParam.getApiName()); 1008 const reduceParams: ParamInfo[] = oldMethodParams.filter( 1009 (oldParam: ParamInfo) => !newParamNames.includes(oldParam.getApiName()) 1010 ); 1011 const reduceNamesStr: string = stitchMethodParameters(reduceParams); 1012 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1013 diffTypeInfo.setDiffType(diffMethodType.REDUCE_PARAM).setOldMessage(reduceNamesStr).setNewMessage(''); 1014 diffTypeInfos.push(diffTypeInfo); 1015 } 1016 /** 1017 * 比较参数必选/可选的变更,(可选->必选,必选->可选) 1018 * 1019 * @param oldMethodParams 1020 * @param newMethodParams 1021 * @param diffTypeInfos 1022 */ 1023 static diffParamChange( 1024 oldMethodParams: ParamInfo[], 1025 newMethodParams: ParamInfo[], 1026 diffTypeInfos: DiffTypeInfo[], 1027 diffMethodType: DiffMethodType 1028 ): void { 1029 // 1.新旧版本的参数长度应大于0 1030 const oldParamLen: number = oldMethodParams.length; 1031 const newParamLen: number = newMethodParams.length; 1032 if (!oldParamLen || !newParamLen) { 1033 return; 1034 } 1035 // 2.找到参数名称一致和参数类型一致的参数进行比较,不存在直接返回 1036 const sameParamInfos: ParamInfo[] = oldMethodParams.filter((oldParam: ParamInfo) => { 1037 const oldParamName: string = oldParam.getApiName(); 1038 return newMethodParams.find((newParam: ParamInfo) => newParam.getApiName() === oldParamName); 1039 }); 1040 if (!sameParamInfos.length) { 1041 return; 1042 } 1043 // 3.比较参数名和类型一致是否发生了可选/必选的变化,参数类型不需要计较 1044 sameParamInfos.forEach((sameInfo: ParamInfo, idx: number) => { 1045 const curOldParamName: string = sameInfo.getApiName(); 1046 const curNewParam: ParamInfo = newMethodParams.find( 1047 (newParam: ParamInfo) => newParam.getApiName() === curOldParamName 1048 )!; 1049 if (curNewParam.getIsRequired() !== sameInfo.getIsRequired()) { 1050 // 参数发生了可选/必选的变化,处理返回信息 1051 const oldMessage = sameInfo.getDefinedText(); 1052 const newMessage = curNewParam.getDefinedText(); 1053 const changeType: number = sameInfo.getIsRequired() 1054 ? diffMethodType.PARAM_TO_UNREQUIRED 1055 : diffMethodType.PARAM_TO_REQUIRED; 1056 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1057 diffTypeInfo.setDiffType(changeType).setOldMessage(oldMessage).setNewMessage(newMessage); 1058 diffTypeInfos.push(diffTypeInfo); 1059 } 1060 }); 1061 } 1062 1063 /** 1064 * 比较参数类型的变更,(参数类型范围扩大/参数类型范围缩小/参数类型变更) 1065 * 1066 * @param oldMethodParams 1067 * @param newMethodParams 1068 * @param diffTypeInfos 1069 */ 1070 static diffParamTypeChange( 1071 oldMethodParams: ParamInfo[], 1072 newMethodParams: ParamInfo[], 1073 diffTypeInfos: DiffTypeInfo[], 1074 diffMethodType: DiffMethodType & DiffTypeChangeType 1075 ): void { 1076 //1.判断新旧版本参数长度大于0 1077 const oldParamLen: number = oldMethodParams.length; 1078 const newParamLen: number = newMethodParams.length; 1079 if (!oldParamLen || !newParamLen) { 1080 return; 1081 } 1082 const newParamName: string[] = newMethodParams.map((newParam: ParamInfo) => newParam.getApiName()); 1083 // 2.需要新旧版本存在参数名称一致的,不存在直接返回 1084 const sameParamInfo: ParamInfo[] = oldMethodParams.filter((oldParam: ParamInfo) => 1085 newParamName.includes(oldParam.getApiName()) 1086 ); 1087 if (!sameParamInfo.length) { 1088 return; 1089 } 1090 // 3.寻找参数名称相同的情况下的参数类型变化的 1091 sameParamInfo.forEach((curSame: ParamInfo, idx: number) => { 1092 const oldParamTypes: string[] = curSame.getType(); 1093 const curNewParam: ParamInfo = newMethodParams.find( 1094 (newParam: ParamInfo) => newParam.getApiName() === curSame.getApiName() 1095 )!; 1096 const newParamTypes: string[] = curNewParam.getType(); 1097 // 处理参数类型不一样的,生成返回信息 1098 if ( 1099 oldParamTypes.toString().replace(/\r|\n|\s+|'|"|,|;/g, '') === 1100 newParamTypes.toString().replace(/\r|\n|\s+|'|"|,|;/g, '') 1101 ) { 1102 return; 1103 } 1104 1105 // 根据参数的差异来获取对应的statusCode 1106 let diffType: ApiDiffType = ApiNodeDiffHelper.getParamDiffType(curSame, curNewParam, diffMethodType); 1107 const oldMessage: string = curSame.getDefinedText(); 1108 const newMessage: string = curNewParam.getDefinedText(); 1109 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1110 diffTypeInfo.setDiffType(diffType).setOldMessage(oldMessage).setNewMessage(newMessage); 1111 diffTypeInfos.push(diffTypeInfo); 1112 }); 1113 } 1114 1115 /** 1116 * 匿名对象整改后,获得参数类型变更类型 1117 * 1118 * @param oldParamInfo 1119 * @param newParamInfo 1120 * @returns 1121 */ 1122 static getParamDiffType( 1123 oldParamInfo: ParamInfo, 1124 newParamInfo: ParamInfo, 1125 diffMethodType: DiffMethodType & DiffTypeChangeType 1126 ): ApiDiffType { 1127 const oldParamTypes: string[] = oldParamInfo.getType(); 1128 const newParamTypes: string[] = newParamInfo.getType(); 1129 // 根据参数的差异来获取对应的statusCode 1130 let diffType: ApiDiffType = diffChangeType(oldParamTypes, newParamTypes, diffMethodType); 1131 //匿名对象整改 1132 if ( 1133 oldParamInfo.getParamType() === ts.SyntaxKind.TypeLiteral && 1134 newParamInfo.getParamType() === ts.SyntaxKind.TypeReference 1135 ) { 1136 const oldApiInfos: ApiInfo[] = oldParamInfo.getObjLocations(); 1137 const newApiInfo: ApiInfo = newParamInfo.getTypeLocations()[0]; 1138 diffType = !ApiNodeDiffHelper.judgeIsCompatible(oldApiInfos, newApiInfo) 1139 ? ApiDiffType.PARAM_TYPE_CHANGE_IN_COMPATIABLE 1140 : ApiDiffType.PARAM_TYPE_CHANGE_COMPATIABLE; 1141 } else if ( 1142 oldParamInfo.getParamType() === ts.SyntaxKind.FunctionType && 1143 newParamInfo.getParamType() === ts.SyntaxKind.TypeReference 1144 ) { 1145 diffType = !ApiNodeDiffHelper.diffFunctionTypeNode(oldParamInfo, newParamInfo) 1146 ? ApiDiffType.PARAM_TYPE_CHANGE_IN_COMPATIABLE 1147 : ApiDiffType.PARAM_TYPE_CHANGE_COMPATIABLE; 1148 } 1149 return diffType; 1150 } 1151 1152 /** 1153 * 匿名函数整改后进行对比 1154 * 1155 * @param oldParamInfo 1156 * @param newParamInfo 1157 * @returns 1158 */ 1159 static diffFunctionTypeNode(oldParamInfo: ParamInfo, newParamInfo: ParamInfo): boolean { 1160 const oldApiInfo: MethodInfo | undefined = oldParamInfo.getMethodApiInfo(); 1161 const newApiInfo: TypeAliasInfo = (newParamInfo.getTypeLocations()[0]) as TypeAliasInfo; 1162 const diffTypes: DiffTypeInfo[] = []; 1163 if (!oldApiInfo || !newApiInfo) { 1164 return false; 1165 } 1166 1167 if (newApiInfo.getApiType() !== ApiType.TYPE_ALIAS) { 1168 return false; 1169 } 1170 diffTypes.push(...ApiNodeDiffHelper.diffMethodParams(oldApiInfo, newApiInfo)); 1171 const diffTypeInfo: DiffTypeInfo | undefined = ApiNodeDiffHelper.diffMethodReturnType(oldApiInfo, newApiInfo); 1172 if (diffTypeInfo) { 1173 diffTypes.push(diffTypeInfo); 1174 } 1175 let isCompatible: boolean = true; 1176 diffTypes.forEach((diffType: DiffTypeInfo) => { 1177 if (incompatibleApiDiffTypes.has(diffType.getDiffType())) { 1178 isCompatible = false; 1179 } 1180 }); 1181 return isCompatible; 1182 } 1183 1184 /** 1185 * 匿名对象整改后进行比较 1186 * 1187 * @param oldApiInfos 1188 * @param newApiInfos 1189 * @returns 1190 */ 1191 static diffTypeLiteral(oldApiInfos: ApiInfo[], newApiInfos: BasicApiInfo[]): BasicDiffInfo[] { 1192 const oldApiInfoMap: Map<string, ApiInfo> = ApiNodeDiffHelper.setmethodInfoMap(oldApiInfos); 1193 const newApiInfoMap: Map<string, ApiInfo> = ApiNodeDiffHelper.setmethodInfoMap(newApiInfos); 1194 const diffInfos: BasicDiffInfo[] = []; 1195 oldApiInfoMap.forEach((oldApiInfo: ApiInfo, key: string) => { 1196 const newApiInfo: ApiInfo | undefined = newApiInfoMap.get(key); 1197 if (!newApiInfo) { 1198 diffInfos.push( 1199 DiffProcessorHelper.wrapDiffInfo( 1200 oldApiInfo, 1201 undefined, 1202 new DiffTypeInfo(ApiStatusCode.DELETE, ApiDiffType.REDUCE, oldApiInfo.getDefinedText()) 1203 ) 1204 ); 1205 return; 1206 } 1207 JsDocDiffHelper.diffJsDocInfo(oldApiInfo, newApiInfo, diffInfos); 1208 ApiDecoratorsDiffHelper.diffDecorator(oldApiInfo, newApiInfo, diffInfos); 1209 ApiNodeDiffHelper.diffNodeInfo(oldApiInfo, newApiInfo, diffInfos); 1210 newApiInfoMap.delete(key); 1211 }); 1212 newApiInfoMap.forEach((newApiInfo: ApiInfo) => { 1213 diffInfos.push( 1214 DiffProcessorHelper.wrapDiffInfo( 1215 undefined, 1216 newApiInfo, 1217 new DiffTypeInfo(ApiStatusCode.NEW_API, ApiDiffType.ADD, undefined, newApiInfo.getDefinedText()) 1218 ) 1219 ); 1220 }); 1221 return diffInfos; 1222 } 1223 1224 static judgeIsCompatible(oldApiInfos: ApiInfo[], newApiInfo: ApiInfo): boolean { 1225 if (!newApiInfo) { 1226 return false; 1227 } 1228 1229 let newApiInfos: BasicApiInfo[] | PropertyInfo[] = []; 1230 if (newApiInfo.getApiType() === ApiType.TYPE_ALIAS) { 1231 newApiInfos = (newApiInfo as TypeAliasInfo).getTypeLiteralApiInfos(); 1232 } else if (newApiInfo.getApiType() === ApiType.INTERFACE) { 1233 newApiInfos = (newApiInfo as InterfaceInfo).getChildApis(); 1234 } else if (newApiInfo.getApiType() === ApiType.CLASS) { 1235 newApiInfos = (newApiInfo as ClassInfo).getChildApis(); 1236 } 1237 1238 const diffInfos: BasicDiffInfo[] = ApiNodeDiffHelper.diffTypeLiteral(oldApiInfos, newApiInfos); 1239 let isCompatible: boolean = true; 1240 diffInfos.forEach((diffInfo: BasicDiffInfo) => { 1241 if (!diffInfo.getIsCompatible()) { 1242 isCompatible = false; 1243 } 1244 }); 1245 return isCompatible; 1246 } 1247 1248 static setmethodInfoMap(apiInfos:BasicApiInfo[]): Map<string, ApiInfo> { 1249 const methodInfoMap: Map<string, ApiInfo> = new Map(); 1250 apiInfos.forEach((apiInfo: BasicApiInfo) => { 1251 methodInfoMap.set(apiInfo.getApiName(), apiInfo as ApiInfo); 1252 }); 1253 return methodInfoMap; 1254 } 1255 1256 /** 1257 * 处理方法节点的参数名称 1258 * 1259 * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息 1260 * @param {ParamInfo} newApiInfo 新版本的参数节点信息 1261 * @return {*} {(ApiDiffType | undefined)} 方法节点的参数名称的变化情况 1262 */ 1263 static diffMethodParamName(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined { 1264 const oldParamName: string = oldApiInfo.getApiName(); 1265 const newParamName: string = newApiInfo.getApiName(); 1266 if (oldParamName === newParamName) { 1267 return undefined; 1268 } 1269 return ApiDiffType.FUNCTION_PARAM_NAME_CHANGE; 1270 } 1271 1272 /** 1273 * 处理方法节点的参数类型 1274 * 1275 * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息 1276 * @param {ParamInfo} newApiInfo 新版本的参数节点信息 1277 * @return {*} {(ApiDiffType | undefined)} 方法节点的参数类型的变化情况 1278 */ 1279 static diffMethodParamType(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined { 1280 const oldParamType: string[] = oldApiInfo.getType(); 1281 const newParamType: string[] = newApiInfo.getType(); 1282 const oldParamTypeStr: string = oldParamType 1283 .toString() 1284 .replace(/\r|\n|\s+|'|"/g, '') 1285 .replace(/\|/g, '\\|'); 1286 const newParamTypeStr: string = newParamType 1287 .toString() 1288 .replace(/\r|\n|\s+|'|"/g, '') 1289 .replace(/\|/g, `\\|`); 1290 if (oldParamTypeStr === newParamTypeStr) { 1291 return undefined; 1292 } 1293 if (StringUtils.hasSubstring(newParamTypeStr, oldParamTypeStr)) { 1294 return ApiDiffType.FUNCTION_PARAM_TYPE_ADD; 1295 } 1296 if (StringUtils.hasSubstring(oldParamTypeStr, newParamTypeStr)) { 1297 return ApiDiffType.FUNCTION_PARAM_TYPE_REDUCE; 1298 } 1299 return ApiDiffType.FUNCTION_PARAM_TYPE_CHANGE; 1300 } 1301 1302 /** 1303 * 处理方法节点的参数必选 1304 * 1305 * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息 1306 * @param {ParamInfo} newApiInfo 新版本的参数节点信息 1307 * @return {*} {(ApiDiffType | undefined)} 方法节点的必选参数的变化情况 1308 */ 1309 static diffMethodParamRequired(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined { 1310 const oldParamISRequired: boolean = oldApiInfo.getIsRequired(); 1311 const newParamISRequired: boolean = newApiInfo.getIsRequired(); 1312 if (oldParamISRequired === newParamISRequired) { 1313 return undefined; 1314 } 1315 return newParamISRequired ? ApiDiffType.FUNCTION_PARAM_TO_REQUIRED : ApiDiffType.FUNCTION_PARAM_TO_UNREQUIRED; 1316 } 1317 1318 /** 1319 * 处理class节点,获取对应diff信息 1320 * 1321 * @param {ApiInfo} oldApiInfo 旧版本的class节点信息 1322 * @param {ApiInfo} newApiInfo 新版本的class节点信息 1323 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1324 * @return {*} {void} 1325 */ 1326 static diffClass(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1327 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1328 const olaClassName: string = oldApiInfo.getApiName(); 1329 const newClassName: string = newApiInfo.getApiName(); 1330 if (olaClassName === newClassName) { 1331 return; 1332 } 1333 diffTypeInfo 1334 .setStatusCode(ApiStatusCode.CLASS_CHANGES) 1335 .setDiffType(ApiDiffType.API_NAME_CHANGE) 1336 .setOldMessage(olaClassName) 1337 .setNewMessage(newClassName); 1338 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 1339 diffInfos.push(diffInfo); 1340 } 1341 1342 /** 1343 * 处理interface节点,获取对应diff信息 1344 * 1345 * @param {ApiInfo} oldApiInfo 旧版本的interface节点信息 1346 * @param {ApiInfo} newApiInfo 新版本的interface节点信息 1347 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1348 * @return {*} {void} 1349 */ 1350 static diffInterface(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1351 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1352 const olaClassName: string = oldApiInfo.getApiName(); 1353 const newClassName: string = newApiInfo.getApiName(); 1354 if (olaClassName === newClassName) { 1355 return; 1356 } 1357 diffTypeInfo 1358 .setStatusCode(ApiStatusCode.CLASS_CHANGES) 1359 .setDiffType(ApiDiffType.API_NAME_CHANGE) 1360 .setOldMessage(olaClassName) 1361 .setNewMessage(newClassName); 1362 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 1363 diffInfos.push(diffInfo); 1364 } 1365 1366 /** 1367 * 处理namespace节点,获取对应diff信息 1368 * 1369 * @param {ApiInfo} oldApiInfo 旧版本的namespace节点信息 1370 * @param {ApiInfo} newApiInfo 新版本的namespace节点信息 1371 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1372 * @return {*} {void} 1373 */ 1374 static diffNamespace(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1375 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1376 const olaClassName: string = oldApiInfo.getApiName(); 1377 const newClassName: string = newApiInfo.getApiName(); 1378 if (olaClassName === newClassName) { 1379 return; 1380 } 1381 diffTypeInfo 1382 .setStatusCode(ApiStatusCode.CLASS_CHANGES) 1383 .setDiffType(ApiDiffType.API_NAME_CHANGE) 1384 .setOldMessage(olaClassName) 1385 .setNewMessage(newClassName); 1386 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 1387 diffInfos.push(diffInfo); 1388 } 1389 1390 /** 1391 * 处理属性节点,获取对应diff信息 1392 * 1393 * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息 1394 * @param {ApiInfo} newApiInfo 新版本的属性节点信息 1395 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1396 * @return {*} {void} 1397 */ 1398 static diffProperty(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1399 propertyDiffProcessors.forEach((propertyDiffProcessor: ApiSceneDiffProcessor) => { 1400 const diffType: DiffTypeInfo | undefined = propertyDiffProcessor(oldApiInfo, newApiInfo); 1401 if (!diffType) { 1402 return; 1403 } 1404 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 1405 oldApiInfo, 1406 newApiInfo, 1407 diffType.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 1408 ); 1409 diffInfos.push(diffInfo); 1410 }); 1411 } 1412 1413 /** 1414 * 处理属性节点的类型 1415 * 1416 * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息 1417 * @param {ApiInfo} newApiInfo 新版本的属性节点信息 1418 * @return {*} {(ApiDiffType | undefined)} 属性节点的类型的变化情况 1419 */ 1420 static diffPropertyType(oldApiInfo: PropertyInfo, newApiInfo: PropertyInfo): DiffTypeInfo | undefined { 1421 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1422 const oldPropertyType: string[] = oldApiInfo.getType(); 1423 const newPropertyType: string[] = newApiInfo.getType(); 1424 const oldPropertyIsReadOnly: boolean = oldApiInfo.getIsReadOnly(); 1425 const newPropertyIsReadOnly: boolean = newApiInfo.getIsReadOnly(); 1426 const oldPropertyTypeStr = oldPropertyType.toString().replace(/\r|\n|\s+|\>|\}/g, ''); 1427 const newPropertyTypeStr = newPropertyType.toString().replace(/\r|\n|\s+|\>|\}/g, ''); 1428 const isUnionType: boolean = newApiInfo.getTypeKind() === ts.SyntaxKind.UnionType ? true : false; 1429 if (oldPropertyTypeStr === newPropertyTypeStr) { 1430 return undefined; 1431 } 1432 diffTypeInfo.setOldMessage(oldPropertyType.toString()).setNewMessage(newPropertyType.toString()); 1433 if (oldPropertyTypeStr.replace(/\,|\;/g, '') === newPropertyTypeStr.replace(/\,|\;/g, '')) { 1434 return diffTypeInfo.setDiffType(ApiDiffType.PROPERTY_TYPE_SIGN_CHANGE); 1435 } 1436 1437 if (isUnionType && checkParentContainChild(oldPropertyType, newPropertyType)) { 1438 return diffTypeInfo.setDiffType( 1439 oldPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_REDUCE : ApiDiffType.PROPERTY_WRITABLE_REDUCE 1440 ); 1441 } 1442 1443 if (isUnionType && checkParentContainChild(newPropertyType, oldPropertyType)) { 1444 return diffTypeInfo.setDiffType( 1445 newPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_ADD : ApiDiffType.PROPERTY_WRITABLE_ADD 1446 ); 1447 } 1448 if (!isUnionType && StringUtils.hasSubstring(newPropertyTypeStr, oldPropertyTypeStr)) { 1449 return diffTypeInfo.setDiffType( 1450 newPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_ADD : ApiDiffType.PROPERTY_WRITABLE_ADD 1451 ); 1452 } 1453 if (!isUnionType && StringUtils.hasSubstring(oldPropertyTypeStr, newPropertyTypeStr)) { 1454 return diffTypeInfo.setDiffType( 1455 oldPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_REDUCE : ApiDiffType.PROPERTY_WRITABLE_REDUCE 1456 ); 1457 } 1458 return diffTypeInfo.setDiffType(ApiDiffType.PROPERTY_TYPE_CHANGE); 1459 } 1460 1461 /** 1462 * 处理属性节点的必选属性 1463 * 1464 * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息 1465 * @param {ApiInfo} newApiInfo 新版本的属性节点信息 1466 * @return {*} {(ApiDiffType | undefined)} 属性节点的必选属性的变化情况 1467 */ 1468 static diffPropertyRequired(oldApiInfo: PropertyInfo, newApiInfo: PropertyInfo): DiffTypeInfo | undefined { 1469 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1470 const oldPropertyName: string = oldApiInfo.getApiName(); 1471 const newPropertyName: string = newApiInfo.getApiName(); 1472 const oldPropertyIsReadOnly: boolean = oldApiInfo.getIsReadOnly(); 1473 //???只读属性是否会变为可写属性 1474 const propertyRequiredDiffMap: Map<string, ApiDiffType> = new Map([ 1475 //old是否必选_new是否必选_old是否只读 1476 ['_true_false_true', ApiDiffType.PROPERTY_READONLY_TO_UNREQUIRED], 1477 ['_false_true_true', ApiDiffType.PROPERTY_READONLY_TO_REQUIRED], 1478 ['_true_false_false', ApiDiffType.PROPERTY_WRITABLE_TO_UNREQUIRED], 1479 ['_false_true_false', ApiDiffType.PROPERTY_WRITABLE_TO_REQUIRED], 1480 ]); 1481 const oldPropertyISRequired: boolean = oldApiInfo.getIsRequired(); 1482 const newPropertyISRequired: boolean = newApiInfo.getIsRequired(); 1483 1484 if (oldPropertyName === newPropertyName && oldPropertyISRequired === newPropertyISRequired) { 1485 return undefined; 1486 } 1487 diffTypeInfo.setOldMessage(oldApiInfo.getDefinedText()).setNewMessage(newApiInfo.getDefinedText()); 1488 const paramRequiredStr: string = `_${!!oldPropertyISRequired}_${!!newPropertyISRequired}_${!!oldPropertyIsReadOnly}`; 1489 const paramRequiredType: ApiDiffType = propertyRequiredDiffMap.get(paramRequiredStr) as ApiDiffType; 1490 return diffTypeInfo.setDiffType(paramRequiredType); 1491 } 1492 1493 /** 1494 * 处理常量节点,获取对应diff信息 1495 * 1496 * @param {ApiInfo} oldApiInfo 旧版本的常量节点信息 1497 * @param {ApiInfo} newApiInfo 新版本的常量节点信息 1498 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1499 */ 1500 static diffConstant(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1501 constantDiffProcessors.forEach((constantDiffProcessor: ApiSceneDiffProcessor) => { 1502 const diffTypeInfo: DiffTypeInfo | undefined = constantDiffProcessor(oldApiInfo, newApiInfo); 1503 if (!diffTypeInfo) { 1504 return; 1505 } 1506 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 1507 oldApiInfo, 1508 newApiInfo, 1509 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 1510 ); 1511 diffInfos.push(diffInfo); 1512 }); 1513 } 1514 1515 /** 1516 * 处理常量节点的值 1517 * 1518 * @param {ConstantInfo} oldApiInfo 旧版本的常量节点信息 1519 * @param {ConstantInfo} newApiInfo 新版本的常量节点信息 1520 * @return {*} {(ApiDiffType | undefined)} 常量节点的值的变化情况 1521 */ 1522 static diffConstantValue(oldApiInfo: ApiInfo, newApiInfo: ApiInfo): DiffTypeInfo | undefined { 1523 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1524 const oldConstantValue: string = 1525 oldApiInfo.getApiType() === ApiType.CONSTANT 1526 ? (oldApiInfo as ConstantInfo).getValue() 1527 : (oldApiInfo as PropertyInfo).getType().join(); 1528 const newConstantValue: string = 1529 newApiInfo.getApiType() === ApiType.CONSTANT 1530 ? (newApiInfo as ConstantInfo).getValue() 1531 : (newApiInfo as PropertyInfo).getType().join(); 1532 if (oldConstantValue === newConstantValue) { 1533 return undefined; 1534 } 1535 diffTypeInfo.setOldMessage(oldConstantValue).setNewMessage(newConstantValue); 1536 return diffTypeInfo.setDiffType(ApiDiffType.CONSTANT_VALUE_CHANGE); 1537 } 1538 1539 /** 1540 * 处理自定义类型节点,过去对应diff信息 1541 * 1542 * @param {ApiInfo} oldApiInfo 旧版本的自定义类型节点信息 1543 * @param {ApiInfo} newApiInfo 新版本的自定义类型节点信息 1544 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1545 */ 1546 static diffTypeAlias(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1547 typeAliasDiffProcessors.forEach((typeAliasDiffProcessor: ApiSceneDiffProcessor) => { 1548 const diffTypeInfo: DiffTypeInfo | undefined = typeAliasDiffProcessor(oldApiInfo, newApiInfo); 1549 if (!diffTypeInfo) { 1550 return; 1551 } 1552 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo); 1553 diffInfos.push(diffInfo); 1554 }); 1555 const oldTypeAliasInfo: TypeAliasInfo = oldApiInfo as TypeAliasInfo; 1556 const newTypeAliasInfo: TypeAliasInfo = newApiInfo as TypeAliasInfo; 1557 // 自定义类型为方法 1558 if (oldTypeAliasInfo.getTypeIsFunction()) { 1559 const diffTypeInfos: DiffTypeInfo[] = ApiNodeDiffHelper.diffMethodParams( 1560 oldApiInfo as TypeAliasInfo, 1561 newApiInfo as TypeAliasInfo 1562 ); 1563 const diffTypeReturnInfo: DiffTypeInfo | undefined = ApiNodeDiffHelper.diffTypeAliasReturnType( 1564 oldApiInfo as TypeAliasInfo, 1565 newApiInfo as TypeAliasInfo 1566 ); 1567 diffTypeReturnInfo && diffTypeInfos.push(diffTypeReturnInfo); 1568 diffTypeInfos.forEach((info: DiffTypeInfo) => { 1569 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 1570 oldApiInfo, 1571 newApiInfo, 1572 info.setStatusCode(ApiStatusCode.TYPE_CHNAGES) 1573 ); 1574 diffInfos.push(diffInfo); 1575 }); 1576 } 1577 1578 if (oldTypeAliasInfo.getTypeIsObject() && newTypeAliasInfo.getTypeIsObject()) { 1579 const oldChildApiInfos: PropertyInfo[] = oldTypeAliasInfo.getTypeLiteralApiInfos(); 1580 const newChildApiInfos: PropertyInfo[] = newTypeAliasInfo.getTypeLiteralApiInfos(); 1581 const diffTypeInfos: BasicDiffInfo[] = ApiNodeDiffHelper.diffTypeLiteral(oldChildApiInfos, newChildApiInfos); 1582 diffInfos.push(...diffTypeInfos); 1583 } 1584 } 1585 1586 /** 1587 * 处理自定义类型节点的类型(类型值范围扩大/类型值范围缩小/类型值改变) 1588 * 1589 * @param {TypeAliasInfo} oldApiInfo 旧版本的自定义类型节点信息 1590 * @param {TypeAliasInfo} newApiInfo 新版本的自定义类型节点信息 1591 * @return {*} {(ApiDiffType | undefined)} 自定义类型节点的类型的变化情况 1592 */ 1593 static diffTypeAliasType(oldApiInfo: TypeAliasInfo, newApiInfo: TypeAliasInfo): DiffTypeInfo | undefined { 1594 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1595 const olaTypeAliasType: string[] = oldApiInfo.getType(); 1596 const newTypeAliasType: string[] = newApiInfo.getType(); 1597 const olaTypeAliasTypeStr: string = olaTypeAliasType.toString(); 1598 const newTypeAliasTypeStr: string = newTypeAliasType.toString(); 1599 // 1.两者定义相同,没有变化 1600 if (olaTypeAliasTypeStr.replace(/\r|\n|\s+|'|"/g, '') === newTypeAliasTypeStr.replace(/\r|\n|\s+|'|"/g, '')) { 1601 return undefined; 1602 } 1603 if (oldApiInfo.getTypeIsObject() && newApiInfo.getTypeIsObject()) { 1604 return undefined; 1605 } 1606 // 自定义函数类型 1607 if (oldApiInfo.getTypeIsFunction()) { 1608 return undefined; 1609 } 1610 // 2.两者定义不同 1611 const diffMethodType: DiffTypeChangeType = { 1612 PARAM_TYPE_CHANGE: ApiDiffType.TYPE_ALIAS_CHANGE, 1613 PARAM_TYPE_ADD: ApiDiffType.TYPE_ALIAS_ADD, 1614 PARAM_TYPE_REDUCE: ApiDiffType.TYPE_ALIAS_REDUCE, 1615 }; 1616 const diffType: number = diffChangeType(olaTypeAliasType, newTypeAliasType, diffMethodType); 1617 diffTypeInfo 1618 .setOldMessage(olaTypeAliasType.join(' | ')) 1619 .setNewMessage(newTypeAliasType.join(' | ')) 1620 .setStatusCode(ApiStatusCode.TYPE_CHNAGES) 1621 .setDiffType(diffType); 1622 return diffTypeInfo; 1623 } 1624 /** 1625 * 处理枚举值节点,获取对应diff信息 1626 * 1627 * @param {ApiInfo} oldApiInfo 旧版本的枚举值节点信息 1628 * @param {ApiInfo} newApiInfo 新版本的枚举值节点信息 1629 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1630 */ 1631 static diffEnum(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void { 1632 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1633 const oldEnumName: string = oldApiInfo.getApiName(); 1634 const newEnumName: string = newApiInfo.getApiName(); 1635 if (oldEnumName === newEnumName) { 1636 return; 1637 } 1638 diffTypeInfo.setDiffType(ApiDiffType.API_NAME_CHANGE).setOldMessage(oldEnumName).setNewMessage(newEnumName); 1639 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 1640 oldApiInfo, 1641 newApiInfo, 1642 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 1643 ); 1644 diffInfos.push(diffInfo); 1645 } 1646 1647 /** 1648 * 处理枚举值节点的每个元素,获取对应diff信息 1649 * 1650 * @param {EnumValueInfo} oldApiInfo 旧版本的枚举值节点元素信息 1651 * @param {EnumValueInfo} newApiInfo 新版本的枚举值节点元素信息 1652 * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合 1653 */ 1654 static diffEnumMember(oldApiInfo: EnumValueInfo, newApiInfo: EnumValueInfo, diffInfos: BasicDiffInfo[]): void { 1655 enumDiffProcessors.forEach((enumDiffProcessor: ApiSceneDiffProcessor) => { 1656 const diffTypeInfo: DiffTypeInfo | undefined = enumDiffProcessor(oldApiInfo, newApiInfo); 1657 if (!diffTypeInfo) { 1658 return; 1659 } 1660 const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo( 1661 oldApiInfo, 1662 newApiInfo, 1663 diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES) 1664 ); 1665 diffInfos.push(diffInfo); 1666 }); 1667 } 1668 1669 /** 1670 * 处理枚举值节点的每个元素的值 1671 * 1672 * @param {EnumValueInfo} oldApiInfo 旧版本的枚举值节点元素信息 1673 * @param {EnumValueInfo} newApiInfo 新版本的枚举值节点元素信息 1674 * @return {*} {(ApiDiffType | undefined)} 枚举值节点的每个元素的值的变化情况 1675 */ 1676 static diffEnumMemberValue(oldApiInfo: EnumValueInfo, newApiInfo: EnumValueInfo): DiffTypeInfo | undefined { 1677 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1678 const olaEnumMemberValue: string = oldApiInfo.getValue(); 1679 const newEnumMemberValue: string = newApiInfo.getValue(); 1680 if (olaEnumMemberValue === newEnumMemberValue) { 1681 return undefined; 1682 } 1683 diffTypeInfo.setOldMessage(olaEnumMemberValue).setNewMessage(newEnumMemberValue); 1684 return diffTypeInfo.setDiffType(ApiDiffType.ENUM_MEMBER_VALUE_CHANGE); 1685 } 1686 1687 /** 1688 * 处理通用类型节点的apiName 1689 * 1690 * @param {ApiInfo} oldApiInfo 旧版本的节点信息 1691 * @param {ApiInfo} newApiInfo 新版本的节点信息 1692 * @return {*} {(ApiDiffType | undefined)} apiName的变化情况 1693 */ 1694 static diffApiName(oldApiInfo: ApiInfo, newApiInfo: ApiInfo): DiffTypeInfo | undefined { 1695 const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo(); 1696 const olaConstantName: string = oldApiInfo.getApiName(); 1697 const newConstantName: string = newApiInfo.getApiName(); 1698 if (olaConstantName === newConstantName) { 1699 return undefined; 1700 } 1701 diffTypeInfo.setOldMessage(olaConstantName).setNewMessage(newConstantName); 1702 return diffTypeInfo.setDiffType(ApiDiffType.API_NAME_CHANGE); 1703 } 1704 1705 /** 1706 * 新旧版本参数个数没变化时,判断参数类型范围扩大/缩小/更改 1707 * 1708 * @param oldTypes 旧版本参数类型 1709 * @param newTypes 新版本参数类型 1710 * @param diffTypes 1711 * @returns 1712 */ 1713 static diffSingleParamType(oldTypes: string[], newTypes: string[], diffTypes: DiffTypeChangeType): number { 1714 const oldParamTypeStr: string = oldTypes 1715 .toString() 1716 .replace(/\r|\n|\s+|'|"|>/g, '') 1717 .replace(/\|/g, '\\|'); 1718 const newParamTypeStr: string = newTypes 1719 .toString() 1720 .replace(/\r|\n|\s+|'|"|>/g, '') 1721 .replace(/\|/g, '\\|'); 1722 if (StringUtils.hasSubstring(newParamTypeStr, oldParamTypeStr)) { 1723 return diffTypes.PARAM_TYPE_ADD; 1724 } 1725 if (StringUtils.hasSubstring(oldParamTypeStr, newParamTypeStr)) { 1726 return diffTypes.PARAM_TYPE_REDUCE; 1727 } 1728 return diffTypes.PARAM_TYPE_CHANGE; 1729 } 1730 } 1731 1732 /** 1733 * 检查父集是否完全包含子集 1734 * 1735 * @param {ParamInfo[]} parentInfos 父集节点信息 1736 * @param {ParamInfo[]} childInfos 子集节点信息 1737 * @returns {*} {boolean} 完全包含为true, 否则为false 1738 */ 1739 function checkIsContain(parentInfos: ParamInfo[], childInfos: ParamInfo[]): boolean { 1740 return childInfos.every((child: ParamInfo) => { 1741 const curChildName = child.getApiName(); 1742 // 父节点里面是否存在子节点的参数名称 1743 const curParentNode = parentInfos.find((item: ParamInfo) => item.getApiName() === curChildName); 1744 // 相同参数的类型是否一样 1745 return curParentNode && curParentNode.getApiType() === child.getApiType(); 1746 }); 1747 } 1748 1749 function checkParentContainChild(parentStrArr: string[], childStrArr: string[]): boolean { 1750 return childStrArr.every((child: string) => parentStrArr.includes(child)); 1751 } 1752 1753 interface DiffTypeChangeType { 1754 PARAM_TYPE_CHANGE: ApiDiffType; 1755 PARAM_TYPE_ADD: ApiDiffType; 1756 PARAM_TYPE_REDUCE: ApiDiffType; 1757 } 1758 // statusCode对应的几种变化类型 1759 interface DiffMethodType { 1760 POS_CHANGE: ApiDiffType; 1761 ADD_OPTIONAL_PARAM: ApiDiffType; 1762 ADD_REQUIRED_PARAM: ApiDiffType; 1763 REDUCE_PARAM: ApiDiffType; 1764 PARAM_TO_UNREQUIRED: ApiDiffType; 1765 PARAM_TO_REQUIRED: ApiDiffType; 1766 PARAM_CHANGE: ApiDiffType; 1767 } 1768 /** 1769 * 根据参数的差异来获取对应的statusCode 1770 * 1771 * @param {string[]} oldTypes 旧参数数组 1772 * @param {string[]} newTypes 新参数数组 1773 * @returns {*} {ApiDiffType} statusCode 1774 */ 1775 function diffChangeType(oldTypes: string[], newTypes: string[], diffTypes: DiffTypeChangeType): ApiDiffType { 1776 const oldLen: number = oldTypes.length; 1777 const newLen: number = newTypes.length; 1778 switch (oldLen - newLen) { 1779 case 0: 1780 return ApiNodeDiffHelper.diffSingleParamType(oldTypes, newTypes, diffTypes); 1781 case -newLen: 1782 return diffTypes.PARAM_TYPE_ADD; 1783 case oldLen: 1784 return diffTypes.PARAM_TYPE_REDUCE; 1785 default: 1786 if (oldLen > newLen) { 1787 return newTypes.every((type: string) => oldTypes.includes(type)) 1788 ? diffTypes.PARAM_TYPE_REDUCE 1789 : diffTypes.PARAM_TYPE_CHANGE; 1790 } else { 1791 return oldTypes.every((type: string) => newTypes.includes(type)) 1792 ? diffTypes.PARAM_TYPE_ADD 1793 : diffTypes.PARAM_TYPE_CHANGE; 1794 } 1795 } 1796 } 1797 1798 /** 1799 * 检查两个版本的相同位置的参数的参数名是否相同 1800 * 1801 * @param {ParamInfo[]} parentInfos 父节点信息 1802 * @param {ParamInfo[]} childInfos 子集节点信息 1803 * @returns {*} {boolean} 完全相同为true, 否则为false 1804 */ 1805 function checkIsSameOfSamePosition(parentInfos: ParamInfo[], childInfos: ParamInfo[]): boolean { 1806 return parentInfos.every((curParentItem: ParamInfo, idx: number) => { 1807 const curChildItem: ParamInfo = childInfos[idx]; 1808 return curParentItem.getApiName() === curChildItem.getApiName(); 1809 }); 1810 } 1811 1812 /** 1813 * 根据当前节点信息来拼接返回的新旧信息 1814 * 1815 * @param {ParamInfo} methodParams 函数参数的节点信息 1816 * @returns {*} {string} 字符串拼接后的节点信息 1817 */ 1818 function stitchMethodParameters(methodParams: ParamInfo[]): string { 1819 if (methodParams.length <= 1) { 1820 return methodParams[0].getDefinedText(); 1821 } 1822 return methodParams.reduce((preStr: string, curItem: ParamInfo, idx: number) => { 1823 let curStr: string = curItem.getDefinedText(); 1824 if (idx !== methodParams.length - 1) { 1825 curStr += ', '; 1826 } 1827 return (preStr += curStr); 1828 }, ''); 1829 } 1830 1831 /** 1832 * 根据节点信息和type生成需要的diff对象 1833 * 1834 * @param {(BasicApiInfo | undefined)} [oldApiInfo=undefined] 旧版本节点信息,默认undefined 1835 * @param {(BasicApiInfo | undefined)} [newApiInfo=undefined] 新版本节点信息,默认undefined 1836 * @param {ApiDiffType} diffType diff的节点类型 1837 * @return {*} {BasicDiffInfo} 生成的diff对象 1838 */ 1839 export function wrapDiffInfo( 1840 oldApiInfo: BasicApiInfo | undefined = undefined, 1841 newApiInfo: BasicApiInfo | undefined = undefined, 1842 diffTypeInfo: DiffTypeInfo, 1843 isNewFile?: boolean 1844 ): BasicDiffInfo { 1845 const newPropertyInfo = newApiInfo as PropertyInfo; 1846 const newMethodInfo = newApiInfo as MethodInfo; 1847 const parentApiType: string = newApiInfo && newApiInfo.getParentApiType() ? newApiInfo.getParentApiType() : ''; 1848 let isCompatible = true; 1849 if ( 1850 !isNewFile && 1851 parentApiTypeSet.has(parentApiType) && 1852 diffTypeInfo.getDiffType() === ApiDiffType.ADD && 1853 ((newApiInfo?.getApiType() === ApiType.METHOD && newMethodInfo.getIsRequired()) || 1854 (newApiInfo?.getApiType() === ApiType.PROPERTY && newPropertyInfo.getIsRequired())) 1855 ) { 1856 isCompatible = false; 1857 } 1858 const diffInfo: BasicDiffInfo = new BasicDiffInfo(); 1859 const diffType: ApiDiffType = diffTypeInfo.getDiffType(); 1860 const clonedOldApiInfo = oldApiInfo as ApiInfo; 1861 const clonedNewApiInfo = newApiInfo as ApiInfo; 1862 const oldApiLevel: boolean | undefined = clonedOldApiInfo?.getLastJsDocInfo()?.getIsSystemApi(); 1863 const newApiLevel: boolean | undefined = clonedNewApiInfo?.getLastJsDocInfo()?.getIsSystemApi(); 1864 let apiIsSameName: boolean | undefined = clonedNewApiInfo?.getIsSameNameFunction(); 1865 if (!newApiInfo) { 1866 apiIsSameName = clonedOldApiInfo?.getIsSameNameFunction(); 1867 } 1868 1869 if (oldApiInfo) { 1870 processOldApiDiff(oldApiInfo, diffInfo); 1871 } 1872 if (newApiInfo) { 1873 processNewApiDiff(newApiInfo, diffInfo); 1874 } 1875 diffInfo 1876 .setDiffType(diffType) 1877 .setDiffMessage(diffMap.get(diffType) as string) 1878 .setStatusCode(diffTypeInfo.getStatusCode()) 1879 .setIsCompatible(!isCompatible ? false : !incompatibleApiDiffTypes.has(diffType)) 1880 .setOldDescription(diffTypeInfo.getOldMessage()) 1881 .setNewDescription(diffTypeInfo.getNewMessage()) 1882 .setIsSystemapi(newApiLevel ? newApiLevel : oldApiLevel) 1883 .setIsSameNameFunction(apiIsSameName); 1884 return diffInfo; 1885 } 1886 1887 /** 1888 * 添加旧版本的基础信息 1889 * 1890 * @param {BasicApiInfo} oldApiInfo 旧版本的节点信息 1891 * @param {BasicDiffInfo} diffInfo 需要填充的diff对象 1892 */ 1893 function processOldApiDiff(oldApiInfo: BasicApiInfo, diffInfo: BasicDiffInfo): void { 1894 const clonedOldApiInfo: ApiInfo = oldApiInfo as ApiInfo; 1895 const kitInfo: string | undefined = clonedOldApiInfo.getLastJsDocInfo?.()?.getKit?.(); 1896 if (kitInfo) { 1897 diffInfo.setOldKitInfo(kitInfo); 1898 } 1899 1900 diffInfo 1901 .setOldApiDefinedText(oldApiInfo.getDefinedText()) 1902 .setApiType(oldApiInfo.getApiType()) 1903 .setOldApiName(oldApiInfo.getApiName()) 1904 .setOldDtsName(oldApiInfo.getFilePath()) 1905 .setOldHierarchicalRelations(oldApiInfo.getHierarchicalRelations()) 1906 .setOldPos(oldApiInfo.getPos()) 1907 .setOldSyscapField(oldApiInfo.getSyscap()); 1908 } 1909 1910 /** 1911 * 添加新版本的基础信息 1912 * 1913 * @param {BasicApiInfo} newApiInfo 新版本的节点信息 1914 * @param {BasicDiffInfo} diffInfo 需要填充的diff对象 1915 */ 1916 function processNewApiDiff(newApiInfo: BasicApiInfo, diffInfo: BasicDiffInfo): void { 1917 const clonedOldApiInfo: ApiInfo = newApiInfo as ApiInfo; 1918 const kitInfo: string | undefined = clonedOldApiInfo.getLastJsDocInfo?.()?.getKit?.(); 1919 if (kitInfo) { 1920 diffInfo.setNewKitInfo(kitInfo); 1921 } 1922 diffInfo 1923 .setNewApiDefinedText(newApiInfo.getDefinedText()) 1924 .setApiType(newApiInfo.getApiType()) 1925 .setNewApiName(newApiInfo.getApiName()) 1926 .setNewDtsName(newApiInfo.getFilePath()) 1927 .setNewHierarchicalRelations(newApiInfo.getHierarchicalRelations()) 1928 .setNewPos(newApiInfo.getPos()) 1929 .setNewSyscapField(newApiInfo.getSyscap()); 1930 } 1931 /** 1932 * api节点类型对应的处理方法,获取diff信息 1933 */ 1934 export const apiNodeDiffMethod: Map<string, ApiNodeDiffProcessor> = new Map([ 1935 [ApiType.PROPERTY, ApiNodeDiffHelper.diffProperty], 1936 [ApiType.CLASS, ApiNodeDiffHelper.diffClass], 1937 [ApiType.INTERFACE, ApiNodeDiffHelper.diffInterface], 1938 [ApiType.NAMESPACE, ApiNodeDiffHelper.diffNamespace], 1939 [ApiType.METHOD, ApiNodeDiffHelper.diffMethod], 1940 [ApiType.CONSTANT, ApiNodeDiffHelper.diffConstant], 1941 [ApiType.ENUM, ApiNodeDiffHelper.diffEnum], 1942 [ApiType.ENUM_VALUE, ApiNodeDiffHelper.diffEnumMember], 1943 [ApiType.TYPE_ALIAS, ApiNodeDiffHelper.diffTypeAlias], 1944 ]); 1945 1946 /** 1947 * api节点jsdoc需要处理的数据,获取diff信息 1948 */ 1949 export const jsDocDiffProcessors: JsDocDiffProcessor[] = [ 1950 JsDocDiffHelper.diffSyscap, 1951 JsDocDiffHelper.diffDeprecated, 1952 JsDocDiffHelper.diffPermissions, 1953 JsDocDiffHelper.diffIsForm, 1954 JsDocDiffHelper.diffIsCrossPlatForm, 1955 JsDocDiffHelper.diffModelLimitation, 1956 JsDocDiffHelper.diffIsSystemApi, 1957 JsDocDiffHelper.diffAtomicService, 1958 ]; 1959 1960 /** 1961 * 枚举值节点需要处理的数据 1962 */ 1963 export const enumDiffProcessors: ApiSceneDiffProcessor[] = [ 1964 ApiNodeDiffHelper.diffApiName, 1965 ApiNodeDiffHelper.diffEnumMemberValue, 1966 ]; 1967 1968 /** 1969 * 自定义类型节点需要处理的数据 1970 */ 1971 export const typeAliasDiffProcessors: ApiSceneDiffProcessor[] = [ 1972 ApiNodeDiffHelper.diffApiName, 1973 ApiNodeDiffHelper.diffTypeAliasType, 1974 ]; 1975 1976 /** 1977 * 常量节点需要处理的数据 1978 */ 1979 export const constantDiffProcessors: ApiSceneDiffProcessor[] = [ 1980 ApiNodeDiffHelper.diffApiName, 1981 ApiNodeDiffHelper.diffConstantValue, 1982 ]; 1983 1984 /** 1985 * 属性节点需要处理的数据 1986 */ 1987 export const propertyDiffProcessors: ApiSceneDiffProcessor[] = [ 1988 ApiNodeDiffHelper.diffApiName, 1989 ApiNodeDiffHelper.diffPropertyType, 1990 ApiNodeDiffHelper.diffPropertyRequired, 1991 ]; 1992 1993 /** 1994 * 属性节点需要处理的数据 1995 */ 1996 export const methodDiffProcessors: ApiScenesDiffProcessor[] = [ 1997 ApiNodeDiffHelper.diffApiName, 1998 ApiNodeDiffHelper.diffMethodReturnType, 1999 ApiNodeDiffHelper.diffMethodParams, 2000 ]; 2001} 2002