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