• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  TypeParamInfo,
29} from '../../typedef/parser/ApiInfoDefination';
30import { Comment } from '../../typedef/parser/Comment';
31import {
32  ApiDiffType,
33  ApiStatusCode,
34  ApiNodeDiffProcessor,
35  ApiSceneDiffProcessor,
36  ApiScenesDiffProcessor,
37  BasicDiffInfo,
38  DiffTypeInfo,
39  diffMap,
40  incompatibleApiDiffTypes,
41  JsDocDiffProcessor,
42  parentApiTypeSet
43} from '../../typedef/diff/ApiInfoDiff';
44import { StringUtils } from '../../utils/StringUtils';
45import { CharMapType, CompareReturnObjType, PermissionsProcessorHelper, RangeChange } from './PermissionsProcessor';
46import { DecoratorInfo } from '../../typedef/parser/Decorator';
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(
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 apiType: string = newApiInfo.getApiType();
596      if (oldApiInfo.getApiType() !== apiType) {
597        return;
598      }
599      const apiNodeDiff: ApiNodeDiffProcessor | undefined = apiNodeDiffMethod.get(apiType);
600      if (!apiNodeDiff) {
601        return;
602      }
603      apiNodeDiff(oldApiInfo, newApiInfo, diffInfos);
604    }
605
606    /**
607     * 处理type类型
608     *
609     * @static
610     * @param {string} oldType 旧版本的type字符串
611     * @param {string} newType 新版本的type字符串
612     * @return { ApiDiffType | undefined}  type范围的变化情况
613     * @memberof ApiNodeDiffHelper
614     */
615    static diffBaseType(oldType: string, newType: string): DiffTypeInfo | undefined {
616      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
617      if (oldType === newType) {
618        return undefined;
619      }
620      diffTypeInfo.setStatusCode(ApiStatusCode.TYPE_CHNAGES).setOldMessage(oldType).setNewMessage(newType);
621      if (oldType === '') {
622        return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE);
623      }
624      if (newType === '') {
625        return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE);
626      }
627      const permiss: PermissionsProcessorHelper = new PermissionsProcessorHelper(typeCharMap);
628      const compareVal: CompareReturnObjType = permiss.comparePermissions(oldType, newType);
629      if (compareVal.range === RangeChange.DOWN) {
630        return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_SMALLER);
631      }
632      if (compareVal.range === RangeChange.UP) {
633        return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_BIGGER);
634      }
635      return diffTypeInfo.setDiffType(ApiDiffType.TYPE_RANGE_CHANGE);
636    }
637
638    /**
639     * 处理方法节点,获取对应diff信息
640     *
641     * @param {ApiInfo} oldApiInfo 旧版本的方法节点信息
642     * @param {ApiInfo} newApiInfo 新版本的方法节点信息
643     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
644     */
645    static diffMethod(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
646      methodDiffProcessors.forEach((methodDiffProcessor: ApiScenesDiffProcessor) => {
647        const diffTypeInfo: DiffTypeInfo[] | DiffTypeInfo | undefined = methodDiffProcessor(
648          oldApiInfo as MethodInfo,
649          newApiInfo as MethodInfo
650        );
651        if (!diffTypeInfo) {
652          return;
653        }
654        if (diffTypeInfo instanceof Array) {
655          diffTypeInfo.forEach((info: DiffTypeInfo) => {
656            const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
657              oldApiInfo,
658              newApiInfo,
659              info.setStatusCode(ApiStatusCode.FUNCTION_CHANGES)
660            );
661            diffInfos.push(diffInfo);
662          });
663        } else {
664          const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
665            oldApiInfo,
666            newApiInfo,
667            diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES)
668          );
669          diffInfos.push(diffInfo);
670        }
671      });
672    }
673    static diffTypeAliasReturnType(oldApiInfo: TypeAliasInfo, newApiInfo: TypeAliasInfo): DiffTypeInfo | undefined {
674      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
675      const oldReturnType: string[] = oldApiInfo.getReturnType()?.split('|');
676      const newReturnType: string[] = newApiInfo.getReturnType()?.split('|');
677      const olaMethodTypeStr = oldReturnType.toString().replace(/\r|\n|\s+|'|"/g, '');
678      const newMethodTypeStr = newReturnType.toString().replace(/\r|\n|\s+|'|"/g, '');
679      if (olaMethodTypeStr === newMethodTypeStr) {
680        return undefined;
681      }
682      diffTypeInfo.setOldMessage(olaMethodTypeStr).setNewMessage(newMethodTypeStr);
683      if (checkParentContainChild(newReturnType, oldReturnType)) {
684        return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_FUNCTION_RETURN_TYPE_ADD);
685      }
686      if (checkParentContainChild(oldReturnType, newReturnType)) {
687        return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_FUNCTION_RETURN_TYPE_REDUCE);
688      }
689      // 旧版本不包含新版本,新版本也不含旧版本,就定义为返回值变更
690      return diffTypeInfo.setDiffType(ApiDiffType.TYPE_ALIAS_FUNCTION_RETURN_TYPE_CHANGE);
691    }
692    /**
693     * 处理方法节点的返回值
694     *
695     * @param {MethodInfo} oldApiInfo 旧版本的方法节点信息
696     * @param {MethodInfo} newApiInfo 新版本的方法节点信息
697     * @return {*}  {(ApiDiffType | undefined)} 方法节点的返回值的变化情况
698     */
699    static diffMethodReturnType(oldApiInfo: MethodInfo, newApiInfo: MethodInfo): DiffTypeInfo | undefined {
700      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
701      const oldReturnType: string[] = oldApiInfo.getReturnValue();
702      const newReturnType: string[] = newApiInfo.getReturnValue();
703      const oldMethodTypeStr = oldReturnType.toString().replace(/\r|\n|\s+|'|"|>/g, '');
704      const newMethodTypeStr = newReturnType.toString().replace(/\r|\n|\s+|'|"|>/g, '');
705      if (oldMethodTypeStr === newMethodTypeStr) {
706        return undefined;
707      }
708      diffTypeInfo.setOldMessage(oldReturnType.toString()).setNewMessage(newReturnType.toString());
709      if (checkParentContainChild(newReturnType, oldReturnType)) {
710        return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_ADD);
711      }
712      if (StringUtils.hasSubstring(newMethodTypeStr, oldMethodTypeStr)) {
713        return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_ADD);
714      }
715      if (checkParentContainChild(oldReturnType, newReturnType)) {
716        return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_REDUCE);
717      }
718      if (StringUtils.hasSubstring(oldMethodTypeStr, newMethodTypeStr)) {
719        return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_REDUCE);
720      }
721      // 旧版本不包含新版本,新版本也不含旧版本,就定义为返回值变更
722      return diffTypeInfo.setDiffType(ApiDiffType.FUNCTION_RETURN_TYPE_CHANGE);
723    }
724
725    /**
726     *
727     * @param isTypeAlias 是否为自定义节点类型
728     * @returns {*} {DiffMethodType} 当前节点类型对应的修改类型
729     */
730    static getDiffMethodTypes(isTypeAlias: boolean): DiffMethodType & DiffTypeChangeType {
731      if (isTypeAlias) {
732        return {
733          POS_CHANGE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_POS_CHAHGE,
734          ADD_OPTIONAL_PARAM: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_UNREQUIRED_ADD,
735          ADD_REQUIRED_PARAM: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_REQUIRED_ADD,
736          REDUCE_PARAM: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_REDUCE,
737          PARAM_TYPE_CHANGE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TYPE_CHANGE,
738          PARAM_TYPE_ADD: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TYPE_ADD,
739          PARAM_TYPE_REDUCE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TYPE_REDUCE,
740          PARAM_TO_UNREQUIRED: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TO_UNREQUIRED,
741          PARAM_TO_REQUIRED: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_TO_REQUIRED,
742          PARAM_CHANGE: ApiDiffType.TYPE_ALIAS_FUNCTION_PARAM_CHANGE,
743        };
744      } else {
745        return {
746          POS_CHANGE: ApiDiffType.FUNCTION_PARAM_POS_CHANGE,
747          ADD_OPTIONAL_PARAM: ApiDiffType.FUNCTION_PARAM_UNREQUIRED_ADD,
748          ADD_REQUIRED_PARAM: ApiDiffType.FUNCTION_PARAM_REQUIRED_ADD,
749          REDUCE_PARAM: ApiDiffType.FUNCTION_PARAM_REDUCE,
750          PARAM_TYPE_CHANGE: ApiDiffType.FUNCTION_PARAM_TYPE_CHANGE,
751          PARAM_TYPE_ADD: ApiDiffType.FUNCTION_PARAM_TYPE_ADD,
752          PARAM_TYPE_REDUCE: ApiDiffType.FUNCTION_PARAM_TYPE_REDUCE,
753          PARAM_TO_UNREQUIRED: ApiDiffType.FUNCTION_PARAM_TO_UNREQUIRED,
754          PARAM_TO_REQUIRED: ApiDiffType.FUNCTION_PARAM_TO_REQUIRED,
755          PARAM_CHANGE: ApiDiffType.FUNCTION_PARAM_CHANGE,
756        };
757      }
758    }
759    /**
760     * 处理方法节点的参数,获取对应diff信息
761     *
762     * @param {MethodInfo} oldApiInfo 旧版本的方法节点信息
763     * @param {MethodInfo} newApiInfo 新版本的方法节点信息
764     * @return {*}  {ApiDiffType[]}  返回各个参数的变化情况
765     */
766    static diffMethodParams(
767      oldApiInfo: MethodInfo | TypeAliasInfo,
768      newApiInfo: MethodInfo | TypeAliasInfo
769    ): DiffTypeInfo[] {
770      const diffTypeInfos: DiffTypeInfo[] = [];
771      const isTypeAlias: boolean = oldApiInfo.getApiType() === 'TypeAlias';
772      const oldMethodParams: ParamInfo[] = isTypeAlias
773        ? (oldApiInfo as TypeAliasInfo).getParamInfos()
774        : (oldApiInfo as MethodInfo).getParams();
775      const newMethodParams: ParamInfo[] = isTypeAlias
776        ? (newApiInfo as TypeAliasInfo).getParamInfos()
777        : (newApiInfo as MethodInfo).getParams();
778      const diffMethodType: DiffMethodType & DiffTypeChangeType = ApiNodeDiffHelper.getDiffMethodTypes(isTypeAlias);
779
780      ApiNodeDiffHelper.diffParamsPosition(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
781      ApiNodeDiffHelper.diffNewOptionalParam(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
782      ApiNodeDiffHelper.diffNewRequiredParam(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
783      ApiNodeDiffHelper.diffReducedParam(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
784      ApiNodeDiffHelper.diffParamTypeChange(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
785      ApiNodeDiffHelper.diffParamChange(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
786      ApiNodeDiffHelper.diffMethodParamChange(oldMethodParams, newMethodParams, diffTypeInfos, diffMethodType);
787      return diffTypeInfos;
788    }
789    /**
790     * 方法参数名变化,且不属于新增、减少的情况,归纳为方法参数变化,
791     *
792     * @param {ParamInfo[]} oldMethodParams 函数旧参数节点信息
793     * @param {ParamInfo[]} newMethodParams 函数新参数节点信息
794     * @param diffTypeInfos 处理好的结果信息
795     */
796    static diffMethodParamChange(
797      oldMethodParams: ParamInfo[],
798      newMethodParams: ParamInfo[],
799      diffTypeInfos: DiffTypeInfo[],
800      diffMethodType: DiffMethodType
801    ): void {
802      const oldParamLen: number = oldMethodParams.length;
803      const newParamLen: number = newMethodParams.length;
804      // 1.新旧版本参数一个不存在即不符合,直接返回
805      if (!oldParamLen || !newParamLen) {
806        return;
807      }
808      // 2. 判断新旧版本参数名称相同的参数的个数和新旧版本的参数是否相同,相同即为新增或者减少参数
809      // 2.1 循环得到所有的参数名称
810      const oldParamNames: string[] = [];
811      const newParamNames: string[] = [];
812      for (let i: number = 0; i < Math.max(oldParamLen, newParamLen); i++) {
813        const newCur: ParamInfo = newMethodParams[i];
814        const oldCur: ParamInfo = oldMethodParams[i];
815        newCur && newParamNames.push(newCur.getApiName());
816        oldCur && oldParamNames.push(oldCur.getApiName());
817      }
818      // 2.2 找出旧版本不同的参数名称
819      const oldDiffParams: ParamInfo[] = oldMethodParams.filter(
820        (oldParam: ParamInfo) => !newParamNames.includes(oldParam.getApiName())
821      );
822      // 2.3 得到参数相同的个数
823      const sameParamsLength: number = oldParamLen - oldDiffParams.length;
824      // 2.4 判断新旧版本参数名称相同的参数的个数和新旧版本的参数是否相同,相同即为新增或者减少参数
825      if (sameParamsLength === oldParamLen || sameParamsLength === newParamLen) {
826        return;
827      }
828
829      let oldDiffInfos: ParamInfo[] = oldMethodParams;
830      let newDiffInfos: ParamInfo[] = newMethodParams;
831      // 3.将新旧版本参数信息中前面检查出来的信息去掉
832      diffTypeInfos.forEach((diffInfo: DiffTypeInfo) => {
833        // 循环已经得到的结果信息,找到新旧版本里不在已经得到的结果信息里面的参数信息
834        oldDiffInfos = oldDiffInfos.filter(
835          (oldDiffInfo: ParamInfo) => diffInfo.getOldMessage() !== oldDiffInfo.getDefinedText()
836        );
837        newDiffInfos = newDiffInfos.filter(
838          (newDiffInfo: ParamInfo) => diffInfo.getNewMessage() !== newDiffInfo.getDefinedText()
839        );
840      });
841      // 4.剩下的部分就是发生变化的部分,生成返回信息
842      const oldNamesStr: string = stitchMethodParameters(oldDiffInfos);
843      const newNamesStr: string = stitchMethodParameters(newDiffInfos);
844      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
845      diffTypeInfo.setDiffType(diffMethodType.PARAM_CHANGE).setOldMessage(oldNamesStr).setNewMessage(newNamesStr);
846      diffTypeInfos.push(diffTypeInfo);
847    }
848    /**
849     * 比较函数位置发生变化
850     *
851     * @param {ParamInfo[]} oldMethodParams 函数旧参数节点信息
852     * @param {ParamInfo[]} newMethodParams 函数新参数节点信息
853     * @param diffTypeInfos
854     */
855    static diffParamsPosition(
856      oldMethodParams: ParamInfo[],
857      newMethodParams: ParamInfo[],
858      diffTypeInfos: DiffTypeInfo[],
859      diffMethodType: DiffMethodType
860    ): void {
861      const oldParamLen: number = oldMethodParams.length;
862      const newParamLen: number = newMethodParams.length;
863      // 1.如果旧版本的参数长度不大于1,或者两者长度不一致,直接返回
864      if (oldParamLen <= 1 || oldParamLen !== newParamLen) {
865        return;
866      }
867      // 2.判断两个版本的相同位置的参数名称是否一致,相同直接返回
868      const isSamePosition: boolean = checkIsSameOfSamePosition(newMethodParams, oldMethodParams);
869      if (isSamePosition) {
870        return;
871      }
872      // 3.如果旧版本的参数不完全包含新版本的参数或者两个版本的参数是否完全一致,一个不符合直接返回
873      const isContain: boolean = checkIsContain(oldMethodParams, newMethodParams);
874      if (!isContain) {
875        return;
876      }
877      // 4.上述情况都不符合,处理返回信息
878      const oldNamesStr: string = stitchMethodParameters(oldMethodParams);
879      const newNamesStr: string = stitchMethodParameters(newMethodParams);
880      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
881      diffTypeInfo.setDiffType(diffMethodType.POS_CHANGE).setOldMessage(oldNamesStr).setNewMessage(newNamesStr);
882      diffTypeInfos.push(diffTypeInfo);
883    }
884
885    /**
886     * 函数新增可选参数
887     *
888     * @param oldMethodParams
889     * @param newMethodParams
890     * @param diffTypeInfos
891     */
892    static diffNewOptionalParam(
893      oldMethodParams: ParamInfo[],
894      newMethodParams: ParamInfo[],
895      diffTypeInfos: DiffTypeInfo[],
896      diffMethodType: DiffMethodType
897    ): void {
898      const oldParamLen: number = oldMethodParams.length;
899      const newParamLen: number = newMethodParams.length;
900      // 1.如果新版本参数为空或者旧版本参数长度大于或者等于新版本参数长度,直接返回
901      if (newParamLen === 0 || oldParamLen >= newParamLen) {
902        return;
903      }
904      // 2.新版本参数需要完全包含旧版本,如果不包含,直接返回
905      const isContain: boolean = checkIsContain(newMethodParams, oldMethodParams);
906      if (!isContain) {
907        return;
908      }
909      // 3.是否存在新增的可选参数
910      const oldParamNames: string[] = oldMethodParams.map((oldParam: ParamInfo) => oldParam.getApiName());
911      const addParams: ParamInfo[] = newMethodParams.filter((newParam: ParamInfo) => {
912        const curParamName: string = newParam.getApiName();
913        return !oldParamNames.includes(curParamName) && !newParam.getIsRequired();
914      });
915      // 4.新版本新增的参数是否存在参数是可选类型,不存在直接返回
916      if (!addParams.length) {
917        return;
918      }
919      // 5.存在新增的参数是可选参数,处理返回信息
920      const addParamNamesStr: string = stitchMethodParameters(addParams);
921      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
922      diffTypeInfo.setOldMessage('').setDiffType(diffMethodType.ADD_OPTIONAL_PARAM).setNewMessage(addParamNamesStr);
923      diffTypeInfos.push(diffTypeInfo);
924    }
925
926    /**
927     * 函数新增必选参数
928     *
929     * @param oldMethodParams
930     * @param newMethodParams
931     * @param diffTypeInfos
932     */
933    static diffNewRequiredParam(
934      oldMethodParams: ParamInfo[],
935      newMethodParams: ParamInfo[],
936      diffTypeInfos: DiffTypeInfo[],
937      diffMethodType: DiffMethodType
938    ): void {
939      const oldParamLen: number = oldMethodParams.length;
940      const newParamLen: number = newMethodParams.length;
941      // 1.如果新版本参数为空或者旧版本参数长度大于或者等于新版本参数长度,直接返回
942      if (newParamLen === 0 || oldParamLen >= newParamLen) {
943        return;
944      }
945      // 2.新版本参数需要完全包含旧版本,如果不包含,直接返回
946      const isContain: boolean = checkIsContain(newMethodParams, oldMethodParams);
947      if (!isContain) {
948        return;
949      }
950      // 3.是否存在新增的必选参数
951      const oldParamNames: string[] = oldMethodParams.map((oldParam: ParamInfo) => oldParam.getApiName());
952      const addParams: ParamInfo[] = newMethodParams.filter((newParam: ParamInfo) => {
953        const curParamName: string = newParam.getApiName();
954        return !oldParamNames.includes(curParamName) && newParam.getIsRequired();
955      });
956      // 4.新版本新增的参数是否存在参数是必选类型,不存在直接返回
957      if (!addParams.length) {
958        return;
959      }
960      // 5.存在新增的参数是可选参数,处理返回信息
961      const addParamNamesStr: string = stitchMethodParameters(addParams);
962      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
963      diffTypeInfo.setDiffType(diffMethodType.ADD_REQUIRED_PARAM).setOldMessage('').setNewMessage(addParamNamesStr);
964      diffTypeInfos.push(diffTypeInfo);
965    }
966
967    /**
968     * 函数删除参数
969     *
970     * @param oldMethodParams
971     * @param newMethodParams
972     * @param diffTypeInfos
973     */
974    static diffReducedParam(
975      oldMethodParams: ParamInfo[],
976      newMethodParams: ParamInfo[],
977      diffTypeInfos: DiffTypeInfo[],
978      diffMethodType: DiffMethodType
979    ): void {
980      const oldParamLen: number = oldMethodParams.length;
981      const newParamLen: number = newMethodParams.length;
982      // 1.旧版本参数为空或者新版本参数长度大于或者等于旧版本参数长度,直接返回
983      if (oldParamLen === 0 || newParamLen >= oldParamLen) {
984        return;
985      }
986      // 2.如果旧版本的参数不包含新版本的参数,直接返回
987      const isContain: boolean = checkIsContain(oldMethodParams, newMethodParams);
988      if (newParamLen > 0 && !isContain) {
989        return;
990      }
991      // 3.参数减少,处理返回信息
992      const newParamNames: string[] = newMethodParams.map((newParam: ParamInfo) => newParam.getApiName());
993      const reduceParams: ParamInfo[] = oldMethodParams.filter(
994        (oldParam: ParamInfo) => !newParamNames.includes(oldParam.getApiName())
995      );
996      const reduceNamesStr: string = stitchMethodParameters(reduceParams);
997      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
998      diffTypeInfo.setDiffType(diffMethodType.REDUCE_PARAM).setOldMessage(reduceNamesStr).setNewMessage('');
999      diffTypeInfos.push(diffTypeInfo);
1000    }
1001    /**
1002     * 比较参数必选/可选的变更,(可选->必选,必选->可选)
1003     *
1004     * @param oldMethodParams
1005     * @param newMethodParams
1006     * @param diffTypeInfos
1007     */
1008    static diffParamChange(
1009      oldMethodParams: ParamInfo[],
1010      newMethodParams: ParamInfo[],
1011      diffTypeInfos: DiffTypeInfo[],
1012      diffMethodType: DiffMethodType
1013    ): void {
1014      // 1.新旧版本的参数长度应大于0
1015      const oldParamLen: number = oldMethodParams.length;
1016      const newParamLen: number = newMethodParams.length;
1017      if (!oldParamLen || !newParamLen) {
1018        return;
1019      }
1020      // 2.找到参数名称一致和参数类型一致的参数进行比较,不存在直接返回
1021      const sameParamInfos: ParamInfo[] = oldMethodParams.filter((oldParam: ParamInfo) => {
1022        const oldParamName: string = oldParam.getApiName();
1023        return newMethodParams.find((newParam: ParamInfo) => newParam.getApiName() === oldParamName);
1024      });
1025      if (!sameParamInfos.length) {
1026        return;
1027      }
1028      // 3.比较参数名和类型一致是否发生了可选/必选的变化,参数类型不需要计较
1029      sameParamInfos.forEach((sameInfo: ParamInfo, idx: number) => {
1030        const curOldParamName: string = sameInfo.getApiName();
1031        const curNewParam: ParamInfo = newMethodParams.find(
1032          (newParam: ParamInfo) => newParam.getApiName() === curOldParamName
1033        )!;
1034        if (curNewParam.getIsRequired() !== sameInfo.getIsRequired()) {
1035          // 参数发生了可选/必选的变化,处理返回信息
1036          const oldMessage = sameInfo.getDefinedText();
1037          const newMessage = curNewParam.getDefinedText();
1038          const changeType: number = sameInfo.getIsRequired()
1039            ? diffMethodType.PARAM_TO_UNREQUIRED
1040            : diffMethodType.PARAM_TO_REQUIRED;
1041          const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1042          diffTypeInfo.setDiffType(changeType).setOldMessage(oldMessage).setNewMessage(newMessage);
1043          diffTypeInfos.push(diffTypeInfo);
1044        }
1045      });
1046    }
1047
1048    /**
1049     * 比较参数类型的变更,(参数类型范围扩大/参数类型范围缩小/参数类型变更)
1050     *
1051     * @param oldMethodParams
1052     * @param newMethodParams
1053     * @param diffTypeInfos
1054     */
1055    static diffParamTypeChange(
1056      oldMethodParams: ParamInfo[],
1057      newMethodParams: ParamInfo[],
1058      diffTypeInfos: DiffTypeInfo[],
1059      diffMethodType: DiffMethodType & DiffTypeChangeType
1060    ): void {
1061      //1.判断新旧版本参数长度大于0
1062      const oldParamLen: number = oldMethodParams.length;
1063      const newParamLen: number = newMethodParams.length;
1064      if (!oldParamLen || !newParamLen) {
1065        return;
1066      }
1067      const newParamName: string[] = newMethodParams.map((newParam: ParamInfo) => newParam.getApiName());
1068      // 2.需要新旧版本存在参数名称一致的,不存在直接返回
1069      const sameParamInfo: ParamInfo[] = oldMethodParams.filter((oldParam: ParamInfo) =>
1070        newParamName.includes(oldParam.getApiName())
1071      );
1072      if (!sameParamInfo.length) {
1073        return;
1074      }
1075      // 3.寻找参数名称相同的情况下的参数类型变化的
1076      sameParamInfo.forEach((curSame: ParamInfo, idx: number) => {
1077        const oldParamTypes: string[] = curSame.getType();
1078        const curNewParam: ParamInfo = newMethodParams.find(
1079          (newParam: ParamInfo) => newParam.getApiName() === curSame.getApiName()
1080        )!;
1081        const newParamTypes: string[] = curNewParam.getType();
1082        // 处理参数类型不一样的,生成返回信息
1083        if (oldParamTypes.toString().replace(/\r|\n|\s+|'|"/g, '') !== newParamTypes.toString().replace(/\r|\n|\s+|'|"/g, '')) {
1084          // 根据参数的差异来获取对应的statusCode
1085          const diffType: number = diffChangeType(oldParamTypes, newParamTypes, diffMethodType);
1086          const oldMessage: string = curSame.getDefinedText();
1087          const newMessage: string = curNewParam.getDefinedText();
1088          const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1089          diffTypeInfo.setDiffType(diffType).setOldMessage(oldMessage).setNewMessage(newMessage);
1090          diffTypeInfos.push(diffTypeInfo);
1091        }
1092      });
1093    }
1094
1095    /**
1096     * 处理方法节点的参数名称
1097     *
1098     * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息
1099     * @param {ParamInfo} newApiInfo 新版本的参数节点信息
1100     * @return {*}  {(ApiDiffType | undefined)} 方法节点的参数名称的变化情况
1101     */
1102    static diffMethodParamName(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined {
1103      const oldParamName: string = oldApiInfo.getApiName();
1104      const newParamName: string = newApiInfo.getApiName();
1105      if (oldParamName === newParamName) {
1106        return undefined;
1107      }
1108      return ApiDiffType.FUNCTION_PARAM_NAME_CHANGE;
1109    }
1110
1111    /**
1112     * 处理方法节点的参数类型
1113     *
1114     * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息
1115     * @param {ParamInfo} newApiInfo 新版本的参数节点信息
1116     * @return {*}  {(ApiDiffType | undefined)} 方法节点的参数类型的变化情况
1117     */
1118    static diffMethodParamType(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined {
1119      const oldParamType: string[] = oldApiInfo.getType();
1120      const newParamType: string[] = newApiInfo.getType();
1121      const oldParamTypeStr: string = oldParamType
1122        .toString()
1123        .replace(/\r|\n|\s+|'|"/g, '')
1124        .replace(/\|/g, '\\|');
1125      const newParamTypeStr: string = newParamType
1126        .toString()
1127        .replace(/\r|\n|\s+|'|"/g, '')
1128        .replace(/\|/g, `\\|`);
1129      if (oldParamTypeStr === newParamTypeStr) {
1130        return undefined;
1131      }
1132      if (StringUtils.hasSubstring(newParamTypeStr, oldParamTypeStr)) {
1133        return ApiDiffType.FUNCTION_PARAM_TYPE_ADD;
1134      }
1135      if (StringUtils.hasSubstring(oldParamTypeStr, newParamTypeStr)) {
1136        return ApiDiffType.FUNCTION_PARAM_TYPE_REDUCE;
1137      }
1138      return ApiDiffType.FUNCTION_PARAM_TYPE_CHANGE;
1139    }
1140
1141    /**
1142     * 处理方法节点的参数必选
1143     *
1144     * @param {ParamInfo} oldApiInfo 旧版本的参数节点信息
1145     * @param {ParamInfo} newApiInfo 新版本的参数节点信息
1146     * @return {*}  {(ApiDiffType | undefined)} 方法节点的必选参数的变化情况
1147     */
1148    static diffMethodParamRequired(oldApiInfo: ParamInfo, newApiInfo: ParamInfo): ApiDiffType | undefined {
1149      const oldParamISRequired: boolean = oldApiInfo.getIsRequired();
1150      const newParamISRequired: boolean = newApiInfo.getIsRequired();
1151      if (oldParamISRequired === newParamISRequired) {
1152        return undefined;
1153      }
1154      return newParamISRequired ? ApiDiffType.FUNCTION_PARAM_TO_REQUIRED : ApiDiffType.FUNCTION_PARAM_TO_UNREQUIRED;
1155    }
1156
1157    /**
1158     * 处理class节点,获取对应diff信息
1159     *
1160     * @param {ApiInfo} oldApiInfo 旧版本的class节点信息
1161     * @param {ApiInfo} newApiInfo 新版本的class节点信息
1162     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1163     * @return {*}  {void}
1164     */
1165    static diffClass(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1166      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1167      const olaClassName: string = oldApiInfo.getApiName();
1168      const newClassName: string = newApiInfo.getApiName();
1169      if (olaClassName === newClassName) {
1170        return;
1171      }
1172      diffTypeInfo
1173        .setStatusCode(ApiStatusCode.CLASS_CHANGES)
1174        .setDiffType(ApiDiffType.API_NAME_CHANGE)
1175        .setOldMessage(olaClassName)
1176        .setNewMessage(newClassName);
1177      const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo);
1178      diffInfos.push(diffInfo);
1179    }
1180
1181    /**
1182     * 处理interface节点,获取对应diff信息
1183     *
1184     * @param {ApiInfo} oldApiInfo 旧版本的interface节点信息
1185     * @param {ApiInfo} newApiInfo 新版本的interface节点信息
1186     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1187     * @return {*}  {void}
1188     */
1189    static diffInterface(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1190      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1191      const olaClassName: string = oldApiInfo.getApiName();
1192      const newClassName: string = newApiInfo.getApiName();
1193      if (olaClassName === newClassName) {
1194        return;
1195      }
1196      diffTypeInfo
1197        .setStatusCode(ApiStatusCode.CLASS_CHANGES)
1198        .setDiffType(ApiDiffType.API_NAME_CHANGE)
1199        .setOldMessage(olaClassName)
1200        .setNewMessage(newClassName);
1201      const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo);
1202      diffInfos.push(diffInfo);
1203    }
1204
1205    /**
1206     * 处理namespace节点,获取对应diff信息
1207     *
1208     * @param {ApiInfo} oldApiInfo 旧版本的namespace节点信息
1209     * @param {ApiInfo} newApiInfo 新版本的namespace节点信息
1210     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1211     * @return {*}  {void}
1212     */
1213    static diffNamespace(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1214      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1215      const olaClassName: string = oldApiInfo.getApiName();
1216      const newClassName: string = newApiInfo.getApiName();
1217      if (olaClassName === newClassName) {
1218        return;
1219      }
1220      diffTypeInfo
1221        .setStatusCode(ApiStatusCode.CLASS_CHANGES)
1222        .setDiffType(ApiDiffType.API_NAME_CHANGE)
1223        .setOldMessage(olaClassName)
1224        .setNewMessage(newClassName);
1225      const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo);
1226      diffInfos.push(diffInfo);
1227    }
1228
1229    /**
1230     * 处理属性节点,获取对应diff信息
1231     *
1232     * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息
1233     * @param {ApiInfo} newApiInfo 新版本的属性节点信息
1234     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1235     * @return {*}  {void}
1236     */
1237    static diffProperty(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1238      propertyDiffProcessors.forEach((propertyDiffProcessor: ApiSceneDiffProcessor) => {
1239        const diffType: DiffTypeInfo | undefined = propertyDiffProcessor(oldApiInfo, newApiInfo);
1240        if (!diffType) {
1241          return;
1242        }
1243        const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
1244          oldApiInfo,
1245          newApiInfo,
1246          diffType.setStatusCode(ApiStatusCode.FUNCTION_CHANGES)
1247        );
1248        diffInfos.push(diffInfo);
1249      });
1250    }
1251
1252    /**
1253     * 处理属性节点的类型
1254     *
1255     * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息
1256     * @param {ApiInfo} newApiInfo 新版本的属性节点信息
1257     * @return {*}  {(ApiDiffType | undefined)} 属性节点的类型的变化情况
1258     */
1259    static diffPropertyType(oldApiInfo: PropertyInfo, newApiInfo: PropertyInfo): DiffTypeInfo | undefined {
1260      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1261      const olaPropertyType: string[] = oldApiInfo.getType();
1262      const newPropertyType: string[] = newApiInfo.getType();
1263      const oldPropertyIsReadOnly: boolean = oldApiInfo.getIsReadOnly();
1264      const newPropertyIsReadOnly: boolean = newApiInfo.getIsReadOnly();
1265      const olaPropertyTypeStr = olaPropertyType.toString().replace(/\r|\n|\s+/g, '');
1266      const newPropertyTypeStr = newPropertyType.toString().replace(/\r|\n|\s+/g, '');
1267      if (olaPropertyTypeStr === newPropertyTypeStr) {
1268        return undefined;
1269      }
1270      diffTypeInfo.setOldMessage(olaPropertyType.toString()).setNewMessage(newPropertyType.toString());
1271      if (olaPropertyTypeStr.replace(/\,|\;/g, '') === newPropertyTypeStr.replace(/\,|\;/g, '')) {
1272        return diffTypeInfo.setDiffType(ApiDiffType.PROPERTY_TYPE_SIGN_CHANGE);
1273      }
1274      if (StringUtils.hasSubstring(newPropertyTypeStr, olaPropertyTypeStr)) {
1275        return diffTypeInfo.setDiffType(
1276          newPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_ADD : ApiDiffType.PROPERTY_WRITABLE_ADD
1277        );
1278      }
1279      if (StringUtils.hasSubstring(olaPropertyTypeStr, newPropertyTypeStr)) {
1280        return diffTypeInfo.setDiffType(
1281          oldPropertyIsReadOnly ? ApiDiffType.PROPERTY_READONLY_REDUCE : ApiDiffType.PROPERTY_WRITABLE_REDUCE
1282        );
1283      }
1284      return diffTypeInfo.setDiffType(ApiDiffType.PROPERTY_TYPE_CHANGE);
1285    }
1286
1287    /**
1288     * 处理属性节点的必选属性
1289     *
1290     * @param {ApiInfo} oldApiInfo 旧版本的属性节点信息
1291     * @param {ApiInfo} newApiInfo 新版本的属性节点信息
1292     * @return {*}  {(ApiDiffType | undefined)} 属性节点的必选属性的变化情况
1293     */
1294    static diffPropertyRequired(oldApiInfo: PropertyInfo, newApiInfo: PropertyInfo): DiffTypeInfo | undefined {
1295      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1296      const oldPropertyName: string = oldApiInfo.getApiName();
1297      const newPropertyName: string = newApiInfo.getApiName();
1298      const oldPropertyIsReadOnly: boolean = oldApiInfo.getIsReadOnly();
1299      //???只读属性是否会变为可写属性
1300      const propertyRequiredDiffMap: Map<string, ApiDiffType> = new Map([
1301        //old是否必选_new是否必选_old是否只读
1302        ['_true_false_true', ApiDiffType.PROPERTY_READONLY_TO_UNREQUIRED],
1303        ['_false_true_true', ApiDiffType.PROPERTY_READONLY_TO_REQUIRED],
1304        ['_true_false_false', ApiDiffType.PROPERTY_WRITABLE_TO_UNREQUIRED],
1305        ['_false_true_false', ApiDiffType.PROPERTY_WRITABLE_TO_REQUIRED],
1306      ]);
1307      const oldPropertyISRequired: boolean = oldApiInfo.getIsRequired();
1308      const newPropertyISRequired: boolean = newApiInfo.getIsRequired();
1309
1310      if (oldPropertyName === newPropertyName && oldPropertyISRequired === newPropertyISRequired) {
1311        return undefined;
1312      }
1313      diffTypeInfo.setOldMessage(oldApiInfo.getDefinedText()).setNewMessage(newApiInfo.getDefinedText());
1314      const paramRequiredStr: string = `_${!!oldPropertyISRequired}_${!!newPropertyISRequired}_${!!oldPropertyIsReadOnly}`;
1315      const paramRequiredType: ApiDiffType = propertyRequiredDiffMap.get(paramRequiredStr) as ApiDiffType;
1316      return diffTypeInfo.setDiffType(paramRequiredType);
1317    }
1318
1319    /**
1320     * 处理常量节点,获取对应diff信息
1321     *
1322     * @param {ApiInfo} oldApiInfo 旧版本的常量节点信息
1323     * @param {ApiInfo} newApiInfo 新版本的常量节点信息
1324     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1325     */
1326    static diffConstant(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1327      constantDiffProcessors.forEach((constantDiffProcessor: ApiSceneDiffProcessor) => {
1328        const diffTypeInfo: DiffTypeInfo | undefined = constantDiffProcessor(oldApiInfo, newApiInfo);
1329        if (!diffTypeInfo) {
1330          return;
1331        }
1332        const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
1333          oldApiInfo,
1334          newApiInfo,
1335          diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES)
1336        );
1337        diffInfos.push(diffInfo);
1338      });
1339    }
1340
1341    /**
1342     * 处理常量节点的值
1343     *
1344     * @param {ConstantInfo} oldApiInfo 旧版本的常量节点信息
1345     * @param {ConstantInfo} newApiInfo 新版本的常量节点信息
1346     * @return {*}  {(ApiDiffType | undefined)} 常量节点的值的变化情况
1347     */
1348    static diffConstantValue(oldApiInfo: ConstantInfo, newApiInfo: ConstantInfo): DiffTypeInfo | undefined {
1349      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1350      const olaConstantValue: string = oldApiInfo.getValue();
1351      const newConstantValue: string = newApiInfo.getValue();
1352      if (olaConstantValue === newConstantValue) {
1353        return undefined;
1354      }
1355      diffTypeInfo.setOldMessage(olaConstantValue).setNewMessage(newConstantValue);
1356      return diffTypeInfo.setDiffType(ApiDiffType.CONSTANT_VALUE_CHANGE);
1357    }
1358
1359    /**
1360     * 处理自定义类型节点,过去对应diff信息
1361     *
1362     * @param {ApiInfo} oldApiInfo 旧版本的自定义类型节点信息
1363     * @param {ApiInfo} newApiInfo 新版本的自定义类型节点信息
1364     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1365     */
1366    static diffTypeAlias(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1367      typeAliasDiffProcessors.forEach((typeAliasDiffProcessor: ApiSceneDiffProcessor) => {
1368        const diffTypeInfo: DiffTypeInfo | undefined = typeAliasDiffProcessor(oldApiInfo, newApiInfo);
1369        if (!diffTypeInfo) {
1370          return;
1371        }
1372        const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(oldApiInfo, newApiInfo, diffTypeInfo);
1373        diffInfos.push(diffInfo);
1374      });
1375      // 自定义类型为方法
1376      if ((oldApiInfo as TypeAliasInfo).getTypeIsFunction()) {
1377        const diffTypeInfos: DiffTypeInfo[] = ApiNodeDiffHelper.diffMethodParams(
1378          oldApiInfo as TypeAliasInfo,
1379          newApiInfo as TypeAliasInfo
1380        );
1381        const diffTypeReturnInfo: DiffTypeInfo | undefined = ApiNodeDiffHelper.diffTypeAliasReturnType(
1382          oldApiInfo as TypeAliasInfo,
1383          newApiInfo as TypeAliasInfo
1384        );
1385        diffTypeReturnInfo && diffTypeInfos.push(diffTypeReturnInfo);
1386        diffTypeInfos.forEach((info: DiffTypeInfo) => {
1387          const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
1388            oldApiInfo,
1389            newApiInfo,
1390            info.setStatusCode(ApiStatusCode.TYPE_CHNAGES)
1391          );
1392          diffInfos.push(diffInfo);
1393        });
1394      }
1395    }
1396
1397    /**
1398     * 处理自定义类型节点的类型(类型值范围扩大/类型值范围缩小/类型值改变)
1399     *
1400     * @param {TypeAliasInfo} oldApiInfo 旧版本的自定义类型节点信息
1401     * @param {TypeAliasInfo} newApiInfo 新版本的自定义类型节点信息
1402     * @return {*}  {(ApiDiffType | undefined)} 自定义类型节点的类型的变化情况
1403     */
1404    static diffTypeAliasType(oldApiInfo: TypeAliasInfo, newApiInfo: TypeAliasInfo): DiffTypeInfo | undefined {
1405      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1406      const olaTypeAliasType: string[] = oldApiInfo.getType();
1407      const newTypeAliasType: string[] = newApiInfo.getType();
1408      const olaTypeAliasTypeStr: string = olaTypeAliasType.toString();
1409      const newTypeAliasTypeStr: string = newTypeAliasType.toString();
1410      // 1.两者定义相同,没有变化
1411      if (olaTypeAliasTypeStr.replace(/\r|\n|\s+|'|"/g, '') === newTypeAliasTypeStr.replace(/\r|\n|\s+|'|"/g, '')) {
1412        return undefined;
1413      }
1414      // 自定义函数类型
1415      if (oldApiInfo.getTypeIsFunction()) {
1416        return undefined;
1417      }
1418      // 2.两者定义不同
1419      const diffMethodType: DiffTypeChangeType = {
1420        PARAM_TYPE_CHANGE: ApiDiffType.TYPE_ALIAS_CHANGE,
1421        PARAM_TYPE_ADD: ApiDiffType.TYPE_ALIAS_ADD,
1422        PARAM_TYPE_REDUCE: ApiDiffType.TYPE_ALIAS_REDUCE,
1423      };
1424      const diffType: number = diffChangeType(olaTypeAliasType, newTypeAliasType, diffMethodType);
1425      diffTypeInfo
1426        .setOldMessage(olaTypeAliasType.join(' | '))
1427        .setNewMessage(newTypeAliasType.join(' | '))
1428        .setStatusCode(ApiStatusCode.TYPE_CHNAGES)
1429        .setDiffType(diffType);
1430      return diffTypeInfo;
1431    }
1432    /**
1433     * 处理枚举值节点,获取对应diff信息
1434     *
1435     * @param {ApiInfo} oldApiInfo 旧版本的枚举值节点信息
1436     * @param {ApiInfo} newApiInfo 新版本的枚举值节点信息
1437     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1438     */
1439    static diffEnum(oldApiInfo: ApiInfo, newApiInfo: ApiInfo, diffInfos: BasicDiffInfo[]): void {
1440      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1441      const oldEnumName: string = oldApiInfo.getApiName();
1442      const newEnumName: string = newApiInfo.getApiName();
1443      if (oldEnumName === newEnumName) {
1444        return;
1445      }
1446      diffTypeInfo.setDiffType(ApiDiffType.API_NAME_CHANGE).setOldMessage(oldEnumName).setNewMessage(newEnumName);
1447      const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
1448        oldApiInfo,
1449        newApiInfo,
1450        diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES)
1451      );
1452      diffInfos.push(diffInfo);
1453    }
1454
1455    /**
1456     * 处理枚举值节点的每个元素,获取对应diff信息
1457     *
1458     * @param {EnumValueInfo} oldApiInfo 旧版本的枚举值节点元素信息
1459     * @param {EnumValueInfo} newApiInfo 新版本的枚举值节点元素信息
1460     * @param {BasicDiffInfo[]} diffInfos 各个节点diff信息集合
1461     */
1462    static diffEnumMember(oldApiInfo: EnumValueInfo, newApiInfo: EnumValueInfo, diffInfos: BasicDiffInfo[]): void {
1463      enumDiffProcessors.forEach((enumDiffProcessor: ApiSceneDiffProcessor) => {
1464        const diffTypeInfo: DiffTypeInfo | undefined = enumDiffProcessor(oldApiInfo, newApiInfo);
1465        if (!diffTypeInfo) {
1466          return;
1467        }
1468        const diffInfo: BasicDiffInfo = DiffProcessorHelper.wrapDiffInfo(
1469          oldApiInfo,
1470          newApiInfo,
1471          diffTypeInfo.setStatusCode(ApiStatusCode.FUNCTION_CHANGES)
1472        );
1473        diffInfos.push(diffInfo);
1474      });
1475    }
1476
1477    /**
1478     * 处理枚举值节点的每个元素的值
1479     *
1480     * @param {EnumValueInfo} oldApiInfo 旧版本的枚举值节点元素信息
1481     * @param {EnumValueInfo} newApiInfo 新版本的枚举值节点元素信息
1482     * @return {*}  {(ApiDiffType | undefined)} 枚举值节点的每个元素的值的变化情况
1483     */
1484    static diffEnumMemberValue(oldApiInfo: EnumValueInfo, newApiInfo: EnumValueInfo): DiffTypeInfo | undefined {
1485      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1486      const olaEnumMemberValue: string = oldApiInfo.getValue();
1487      const newEnumMemberValue: string = newApiInfo.getValue();
1488      if (olaEnumMemberValue === newEnumMemberValue) {
1489        return undefined;
1490      }
1491      diffTypeInfo.setOldMessage(olaEnumMemberValue).setNewMessage(newEnumMemberValue);
1492      return diffTypeInfo.setDiffType(ApiDiffType.ENUM_MEMBER_VALUE_CHANGE);
1493    }
1494
1495    /**
1496     * 处理通用类型节点的apiName
1497     *
1498     * @param {ApiInfo} oldApiInfo 旧版本的节点信息
1499     * @param {ApiInfo} newApiInfo 新版本的节点信息
1500     * @return {*}  {(ApiDiffType | undefined)} apiName的变化情况
1501     */
1502    static diffApiName(oldApiInfo: ApiInfo, newApiInfo: ApiInfo): DiffTypeInfo | undefined {
1503      const diffTypeInfo: DiffTypeInfo = new DiffTypeInfo();
1504      const olaConstantName: string = oldApiInfo.getApiName();
1505      const newConstantName: string = newApiInfo.getApiName();
1506      if (olaConstantName === newConstantName) {
1507        return undefined;
1508      }
1509      diffTypeInfo.setOldMessage(olaConstantName).setNewMessage(newConstantName);
1510      return diffTypeInfo.setDiffType(ApiDiffType.API_NAME_CHANGE);
1511    }
1512
1513    /**
1514     * 新旧版本参数个数没变化时,判断参数类型范围扩大/缩小/更改
1515     *
1516     * @param oldTypes 旧版本参数类型
1517     * @param newTypes 新版本参数类型
1518     * @param diffTypes
1519     * @returns
1520     */
1521    static diffSingleParamType(oldTypes: string[], newTypes: string[], diffTypes: DiffTypeChangeType): number {
1522      const oldParamTypeStr: string = oldTypes
1523        .toString()
1524        .replace(/\r|\n|\s+|'|"|>/g, '')
1525        .replace(/\|/g, '\\|');
1526      const newParamTypeStr: string = newTypes
1527        .toString()
1528        .replace(/\r|\n|\s+|'|"|>/g, '')
1529        .replace(/\|/g, '\\|');
1530      if (StringUtils.hasSubstring(newParamTypeStr, oldParamTypeStr)) {
1531        return diffTypes.PARAM_TYPE_ADD;
1532      }
1533      if (StringUtils.hasSubstring(oldParamTypeStr, newParamTypeStr)) {
1534        return diffTypes.PARAM_TYPE_REDUCE;
1535      }
1536      return diffTypes.PARAM_TYPE_CHANGE;
1537    }
1538  }
1539
1540  /**
1541   * 检查父集是否完全包含子集
1542   *
1543   * @param {ParamInfo[]} parentInfos 父集节点信息
1544   * @param {ParamInfo[]} childInfos 子集节点信息
1545   * @returns {*} {boolean} 完全包含为true, 否则为false
1546   */
1547  function checkIsContain(parentInfos: ParamInfo[], childInfos: ParamInfo[]): boolean {
1548    return childInfos.every((child: ParamInfo) => {
1549      const curChildName = child.getApiName();
1550      // 父节点里面是否存在子节点的参数名称
1551      const curParentNode = parentInfos.find((item: ParamInfo) => item.getApiName() === curChildName);
1552      // 相同参数的类型是否一样
1553      return curParentNode && curParentNode.getApiType() === child.getApiType();
1554    });
1555  }
1556
1557  function checkParentContainChild(parentStrArr: string[], childStrArr: string[]): boolean {
1558    return childStrArr.every((child: string) => parentStrArr.includes(child));
1559  }
1560
1561  interface DiffTypeChangeType {
1562    PARAM_TYPE_CHANGE: ApiDiffType;
1563    PARAM_TYPE_ADD: ApiDiffType;
1564    PARAM_TYPE_REDUCE: ApiDiffType;
1565  }
1566  // statusCode对应的几种变化类型
1567  interface DiffMethodType {
1568    POS_CHANGE: ApiDiffType;
1569    ADD_OPTIONAL_PARAM: ApiDiffType;
1570    ADD_REQUIRED_PARAM: ApiDiffType;
1571    REDUCE_PARAM: ApiDiffType;
1572    PARAM_TO_UNREQUIRED: ApiDiffType;
1573    PARAM_TO_REQUIRED: ApiDiffType;
1574    PARAM_CHANGE: ApiDiffType;
1575  }
1576  /**
1577   * 根据参数的差异来获取对应的statusCode
1578   *
1579   * @param {string[]} oldTypes 旧参数数组
1580   * @param {string[]} newTypes 新参数数组
1581   * @returns {*} {ApiDiffType} statusCode
1582   */
1583  function diffChangeType(oldTypes: string[], newTypes: string[], diffTypes: DiffTypeChangeType): ApiDiffType {
1584    const oldLen: number = oldTypes.length;
1585    const newLen: number = newTypes.length;
1586    switch (oldLen - newLen) {
1587      case 0:
1588        return DiffProcessorHelper.ApiNodeDiffHelper.diffSingleParamType(oldTypes, newTypes, diffTypes);
1589      case -newLen:
1590        return diffTypes.PARAM_TYPE_ADD;
1591      case oldLen:
1592        return diffTypes.PARAM_TYPE_REDUCE;
1593      default:
1594        if (oldLen > newLen) {
1595          return newTypes.every((type: string) => oldTypes.includes(type))
1596            ? diffTypes.PARAM_TYPE_REDUCE
1597            : diffTypes.PARAM_TYPE_CHANGE;
1598        } else {
1599          return oldTypes.every((type: string) => newTypes.includes(type))
1600            ? diffTypes.PARAM_TYPE_ADD
1601            : diffTypes.PARAM_TYPE_CHANGE;
1602        }
1603    }
1604  }
1605
1606  /**
1607   * 检查两个版本的相同位置的参数的参数名是否相同
1608   *
1609   * @param {ParamInfo[]} parentInfos 父节点信息
1610   * @param {ParamInfo[]} childInfos 子集节点信息
1611   * @returns {*} {boolean} 完全相同为true, 否则为false
1612   */
1613  function checkIsSameOfSamePosition(parentInfos: ParamInfo[], childInfos: ParamInfo[]): boolean {
1614    return parentInfos.every((curParentItem: ParamInfo, idx: number) => {
1615      const curChildItem: ParamInfo = childInfos[idx];
1616      return curParentItem.getApiName() === curChildItem.getApiName();
1617    });
1618  }
1619
1620  /**
1621   * 根据当前节点信息来拼接返回的新旧信息
1622   *
1623   * @param {ParamInfo} methodParams 函数参数的节点信息
1624   * @returns {*} {string} 字符串拼接后的节点信息
1625   */
1626  function stitchMethodParameters(methodParams: ParamInfo[]): string {
1627    if (methodParams.length <= 1) {
1628      return methodParams[0].getDefinedText();
1629    }
1630    return methodParams.reduce((preStr: string, curItem: ParamInfo, idx: number) => {
1631      let curStr: string = curItem.getDefinedText();
1632      if (idx !== methodParams.length - 1) {
1633        curStr += ', ';
1634      }
1635      return (preStr += curStr);
1636    }, '');
1637  }
1638
1639  /**
1640   * 根据节点信息和type生成需要的diff对象
1641   *
1642   * @param {(BasicApiInfo | undefined)} [oldApiInfo=undefined] 旧版本节点信息,默认undefined
1643   * @param {(BasicApiInfo | undefined)} [newApiInfo=undefined] 新版本节点信息,默认undefined
1644   * @param {ApiDiffType} diffType diff的节点类型
1645   * @return {*}  {BasicDiffInfo} 生成的diff对象
1646   */
1647  export function wrapDiffInfo(
1648    oldApiInfo: BasicApiInfo | undefined = undefined,
1649    newApiInfo: BasicApiInfo | undefined = undefined,
1650    diffTypeInfo: DiffTypeInfo,
1651    isNewFile?: boolean
1652  ): BasicDiffInfo {
1653    const newPropertyInfo = newApiInfo as PropertyInfo;
1654    const newMethodInfo = newApiInfo as MethodInfo;
1655    const parentApiType: string = (newApiInfo && newApiInfo.getParentApiType()) ? newApiInfo.getParentApiType() : '';
1656    let isCompatible = true;
1657    if (
1658      !isNewFile && parentApiTypeSet.has(parentApiType) &&
1659      diffTypeInfo.getDiffType() === ApiDiffType.ADD &&
1660      ((newApiInfo?.getApiType() === ApiType.METHOD && newMethodInfo.getIsRequired()) ||
1661        (newApiInfo?.getApiType() === ApiType.PROPERTY && newPropertyInfo.getIsRequired()))
1662    ) {
1663      isCompatible = false;
1664    }
1665    const diffInfo: BasicDiffInfo = new BasicDiffInfo();
1666    const diffType: ApiDiffType = diffTypeInfo.getDiffType();
1667    const clonedOldApiInfo = oldApiInfo as ApiInfo;
1668    const clonedNewApiInfo = newApiInfo as ApiInfo;
1669    const oldApiLevel: boolean | undefined = clonedOldApiInfo?.getLastJsDocInfo()?.getIsSystemApi();
1670    const newApiLevel: boolean | undefined = clonedNewApiInfo?.getLastJsDocInfo()?.getIsSystemApi();
1671    let apiIsSameName: boolean | undefined = clonedNewApiInfo?.getIsSameNameFunction();
1672    if (!newApiInfo) {
1673      apiIsSameName = clonedOldApiInfo?.getIsSameNameFunction();
1674    }
1675
1676    if (oldApiInfo) {
1677      processOldApiDiff(oldApiInfo, diffInfo);
1678    }
1679    if (newApiInfo) {
1680      processNewApiDiff(newApiInfo, diffInfo);
1681    }
1682    diffInfo
1683      .setDiffType(diffType)
1684      .setDiffMessage(diffMap.get(diffType) as string)
1685      .setStatusCode(diffTypeInfo.getStatusCode())
1686      .setIsCompatible(!isCompatible ? false : !incompatibleApiDiffTypes.has(diffType))
1687      .setOldDescription(diffTypeInfo.getOldMessage())
1688      .setNewDescription(diffTypeInfo.getNewMessage())
1689      .setIsSystemapi(newApiLevel ? newApiLevel : oldApiLevel)
1690      .setIsSameNameFunction(apiIsSameName);
1691    return diffInfo;
1692  }
1693
1694  /**
1695   * 添加旧版本的基础信息
1696   *
1697   * @param {BasicApiInfo} oldApiInfo 旧版本的节点信息
1698   * @param {BasicDiffInfo} diffInfo 需要填充的diff对象
1699   */
1700  function processOldApiDiff(oldApiInfo: BasicApiInfo, diffInfo: BasicDiffInfo): void {
1701    const clonedOldApiInfo: ApiInfo = oldApiInfo as ApiInfo;
1702    const kitInfo: string | undefined = clonedOldApiInfo.getLastJsDocInfo()?.getKit();
1703    if (kitInfo) {
1704      diffInfo.setOldKitInfo(kitInfo);
1705    }
1706
1707    diffInfo
1708      .setOldApiDefinedText(oldApiInfo.getDefinedText())
1709      .setApiType(oldApiInfo.getApiType())
1710      .setOldApiName(oldApiInfo.getApiName())
1711      .setOldDtsName(oldApiInfo.getFilePath())
1712      .setOldHierarchicalRelations(oldApiInfo.getHierarchicalRelations())
1713      .setOldPos(oldApiInfo.getPos())
1714      .setOldSyscapField(oldApiInfo.getSyscap());
1715  }
1716
1717  /**
1718   * 添加新版本的基础信息
1719   *
1720   * @param {BasicApiInfo} newApiInfo 新版本的节点信息
1721   * @param {BasicDiffInfo} diffInfo 需要填充的diff对象
1722   */
1723  function processNewApiDiff(newApiInfo: BasicApiInfo, diffInfo: BasicDiffInfo): void {
1724    const clonedOldApiInfo: ApiInfo = newApiInfo as ApiInfo;
1725    const kitInfo: string | undefined = clonedOldApiInfo.getLastJsDocInfo()?.getKit();
1726    if (kitInfo) {
1727      diffInfo.setNewKitInfo(kitInfo);
1728    }
1729    diffInfo
1730      .setNewApiDefinedText(newApiInfo.getDefinedText())
1731      .setApiType(newApiInfo.getApiType())
1732      .setNewApiName(newApiInfo.getApiName())
1733      .setNewDtsName(newApiInfo.getFilePath())
1734      .setNewHierarchicalRelations(newApiInfo.getHierarchicalRelations())
1735      .setNewPos(newApiInfo.getPos())
1736      .setNewSyscapField(newApiInfo.getSyscap());
1737  }
1738  /**
1739   * api节点类型对应的处理方法,获取diff信息
1740   */
1741  export const apiNodeDiffMethod: Map<string, ApiNodeDiffProcessor> = new Map([
1742    [ApiType.PROPERTY, ApiNodeDiffHelper.diffProperty],
1743    [ApiType.CLASS, ApiNodeDiffHelper.diffClass],
1744    [ApiType.INTERFACE, ApiNodeDiffHelper.diffInterface],
1745    [ApiType.NAMESPACE, ApiNodeDiffHelper.diffNamespace],
1746    [ApiType.METHOD, ApiNodeDiffHelper.diffMethod],
1747    [ApiType.CONSTANT, ApiNodeDiffHelper.diffConstant],
1748    [ApiType.ENUM, ApiNodeDiffHelper.diffEnum],
1749    [ApiType.ENUM_VALUE, ApiNodeDiffHelper.diffEnumMember],
1750    [ApiType.TYPE_ALIAS, DiffProcessorHelper.ApiNodeDiffHelper.diffTypeAlias],
1751  ]);
1752
1753  /**
1754   * api节点jsdoc需要处理的数据,获取diff信息
1755   */
1756  export const jsDocDiffProcessors: JsDocDiffProcessor[] = [
1757    JsDocDiffHelper.diffSyscap,
1758    JsDocDiffHelper.diffDeprecated,
1759    JsDocDiffHelper.diffPermissions,
1760    JsDocDiffHelper.diffIsForm,
1761    JsDocDiffHelper.diffIsCrossPlatForm,
1762    JsDocDiffHelper.diffModelLimitation,
1763    JsDocDiffHelper.diffIsSystemApi,
1764    JsDocDiffHelper.diffAtomicService,
1765  ];
1766
1767  /**
1768   * 枚举值节点需要处理的数据
1769   */
1770  export const enumDiffProcessors: ApiSceneDiffProcessor[] = [
1771    ApiNodeDiffHelper.diffApiName,
1772    ApiNodeDiffHelper.diffEnumMemberValue,
1773  ];
1774
1775  /**
1776   * 自定义类型节点需要处理的数据
1777   */
1778  export const typeAliasDiffProcessors: ApiSceneDiffProcessor[] = [
1779    ApiNodeDiffHelper.diffApiName,
1780    ApiNodeDiffHelper.diffTypeAliasType,
1781  ];
1782
1783  /**
1784   * 常量节点需要处理的数据
1785   */
1786  export const constantDiffProcessors: ApiSceneDiffProcessor[] = [
1787    ApiNodeDiffHelper.diffApiName,
1788    ApiNodeDiffHelper.diffConstantValue,
1789  ];
1790
1791  /**
1792   * 属性节点需要处理的数据
1793   */
1794  export const propertyDiffProcessors: ApiSceneDiffProcessor[] = [
1795    ApiNodeDiffHelper.diffApiName,
1796    ApiNodeDiffHelper.diffPropertyType,
1797    ApiNodeDiffHelper.diffPropertyRequired,
1798  ];
1799
1800  /**
1801   * 属性节点需要处理的数据
1802   */
1803  export const methodDiffProcessors: ApiScenesDiffProcessor[] = [
1804    ApiNodeDiffHelper.diffApiName,
1805    ApiNodeDiffHelper.diffMethodReturnType,
1806    ApiNodeDiffHelper.diffMethodParams,
1807  ];
1808}
1809