• 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  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