• 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 { ErrorTagFormat, ErrorMessage, PermissionData } from '../../../typedef/checker/result_type';
17import { Comment } from '../../../typedef/parser/Comment';
18import { CommonFunctions, throwsTagDescriptionArr } from '../../../utils/checkUtils';
19import { ApiInfo, ApiType, ClassInfo, GenericInfo, TypeAliasInfo, TypeAliasType, TypeParamInfo } from '../../../typedef/parser/ApiInfoDefination';
20import { MethodInfo, PropertyInfo, ParamInfo } from '../../../typedef/parser/ApiInfoDefination';
21import { PunctuationMark } from '../../../utils/Constant';
22import { SystemCapability } from '../config/syscapConfigFile.json';
23import { module } from '../config/permissionConfigFile.json';
24import { toNumber } from 'lodash';
25import { ApiMaxVersion } from '../config/api_check_version.json';
26
27export class TagValueCheck {
28  /**
29   * all jsdoc tag value check
30   * @param { ApiInfo } singleApi
31   * @param { Comment.JsDocInfo } apiJsdoc
32   * @returns { ErrorTagFormat[] }
33   */
34  static tagValueCheck(singleApi: ApiInfo, apiJsdoc: Comment.JsDocInfo): ErrorTagFormat[] {
35    const tagValueError: ErrorTagFormat[] = [];
36    const tagsName: Comment.CommentTag[] | undefined = apiJsdoc.tags;
37    let throwsIndex: number = 0;
38    let paramIndex: number = -1;
39    if (tagsName === undefined) {
40      return tagValueError;
41    }
42    const tagsTag: string[] = [];
43    tagsName.forEach((tagName: Comment.CommentTag) => { tagsTag.push(tagName.tag); });
44    const isDeprecated: boolean = tagsTag.includes('deprecated');
45    tagsName.forEach((tag) => {
46      let errorTagInfo: ErrorTagFormat = {
47        state: true,
48        errorInfo: '',
49      };
50      switch (tag.tag) {
51        case 'since':
52          errorTagInfo = TagValueCheck.sinceTagValueCheck(singleApi, tag);
53          break;
54        case 'extends':
55        case 'implements':
56          errorTagInfo = !isDeprecated ? TagValueCheck.extendsTagValueCheck(singleApi, tag) : errorTagInfo;
57          break;
58        case 'enum':
59          errorTagInfo = !isDeprecated ? TagValueCheck.enumTagValueCheck(tag) : errorTagInfo;
60          break;
61        case 'returns':
62          errorTagInfo = !isDeprecated ? TagValueCheck.returnsTagValueCheck(singleApi, tag) : errorTagInfo;
63          break;
64        case 'namespace':
65        case 'typedef':
66        case 'struct':
67          errorTagInfo = !isDeprecated ? TagValueCheck.outerTagValueCheck(singleApi as ClassInfo, tag) : errorTagInfo;
68          break;
69        case 'type':
70          errorTagInfo = !isDeprecated ? TagValueCheck.typeTagValueCheck(singleApi, tag) : errorTagInfo;
71          break;
72        case 'syscap':
73          errorTagInfo = TagValueCheck.syscapTagValueCheck(tag);
74          break;
75        case 'default':
76          errorTagInfo = !isDeprecated ? TagValueCheck.defaultTagValueCheck(tag) : errorTagInfo;
77          break;
78        case 'deprecated':
79          errorTagInfo = TagValueCheck.deprecatedTagValueCheck(tag);
80          break;
81        case 'permission':
82          errorTagInfo = !isDeprecated ? TagValueCheck.permissionTagValueCheck(tag) : errorTagInfo;
83          break;
84        case 'throws':
85          if (singleApi.getLastJsDocInfo()?.deprecatedVersion === '-1') {
86            throwsIndex += 1;
87            errorTagInfo = !isDeprecated ? TagValueCheck.throwsTagValueCheck(tag, throwsIndex, tagsName) : errorTagInfo;
88          }
89          break;
90        case 'param':
91          paramIndex += 1;
92          errorTagInfo = !isDeprecated ? TagValueCheck.paramTagValueCheck(singleApi, tag, paramIndex) : errorTagInfo;
93          break;
94        case 'useinstead':
95          errorTagInfo = TagValueCheck.useinsteadTagValueCheck(tag);
96          break;
97        default:
98          break;
99      }
100      if (!errorTagInfo.state) {
101        tagValueError.push(errorTagInfo);
102      }
103    });
104    return tagValueError;
105  }
106
107  /**
108   * since tag value check
109   * @param { Comment.CommentTag } tag
110   * @returns { ErrorTagFormat }
111   */
112  static sinceTagValueCheck(singleApi: ApiInfo, tag: Comment.CommentTag): ErrorTagFormat {
113    const sinceValueCheckResult: ErrorTagFormat = {
114      state: true,
115      errorInfo: '',
116    };
117    const sinceValue: string = CommonFunctions.getSinceVersion(tag.name);
118    const sinceValueIsNumber: boolean = /^\d+$/.test(sinceValue);
119    const allSinceValue: string[] = [];
120    singleApi.getJsDocInfos().forEach((tagInfo: Comment.JsDocInfo) => {
121      allSinceValue.push(tagInfo.since);
122    });
123    const newSinceValueArr = Array.from(new Set(allSinceValue));
124    if (!sinceValueIsNumber) {
125      sinceValueCheckResult.state = false;
126      sinceValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_SINCE;
127    } else if (toNumber(sinceValue) > toNumber(ApiMaxVersion)) {
128      sinceValueCheckResult.state = false;
129      sinceValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_SINCE_NUMBER;
130    }
131    if (allSinceValue.length !== newSinceValueArr.length) {
132      sinceValueCheckResult.state = false;
133      sinceValueCheckResult.errorInfo = sinceValueCheckResult.errorInfo + ErrorMessage.ERROR_INFO_VALUE_SINCE_JSDOC;
134    }
135    return sinceValueCheckResult;
136  }
137
138  /**
139   * extends tag value check
140   * @param { ApiInfo } singleApi
141   * @param { Comment.CommentTag } tag
142   * @returns { ErrorTagFormat }
143   */
144  static extendsTagValueCheck(singleApi: ApiInfo, tag: Comment.CommentTag): ErrorTagFormat {
145    const extendsValueCheckResult: ErrorTagFormat = {
146      state: true,
147      errorInfo: '',
148    };
149    let extendsTagValue: string = tag.name + tag.description;
150    if (singleApi.getApiType() === ApiType.CLASS || singleApi.getApiType() === ApiType.INTERFACE) {
151      const extendsApiValue: string = CommonFunctions.getExtendsApiValue(singleApi);
152      const ImplementsApiValue: string = CommonFunctions.getImplementsApiValue(singleApi);
153      if (tag.tag === 'extends' && extendsTagValue.replace(/\s/g, '') !== extendsApiValue) {
154        extendsValueCheckResult.state = false;
155        extendsValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_EXTENDS;
156      }
157      if (tag.tag === 'implements' && extendsTagValue !== ImplementsApiValue) {
158        extendsValueCheckResult.state = false;
159        extendsValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_IMPLEMENTS;
160      }
161    }
162    return extendsValueCheckResult;
163  }
164
165  /**
166   * enum tag value check
167   * @param { Comment.CommentTag } tag
168   * @returns { ErrorTagFormat }
169   */
170  static enumTagValueCheck(tag: Comment.CommentTag): ErrorTagFormat {
171    const enumValueCheckResult: ErrorTagFormat = {
172      state: true,
173      errorInfo: '',
174    };
175    const enumValues = ['string', 'number'];
176    if (enumValues.indexOf(tag.type) === -1) {
177      enumValueCheckResult.state = false;
178      enumValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_ENUM;
179    }
180    return enumValueCheckResult;
181  }
182
183  /**
184   * retuens tag value check
185   * @param { ApiInfo } singleApi
186   * @param { Comment.CommentTag } tag
187   * @returns { ErrorTagFormat }
188   */
189  static returnsTagValueCheck(singleApi: ApiInfo, tag: Comment.CommentTag): ErrorTagFormat {
190    const returnsValueCheckResult: ErrorTagFormat = {
191      state: true,
192      errorInfo: '',
193    };
194    const returnsTagValue: string = tag.type.replace(/\s/g, '');
195    let returnsApiValue: string[] = [];
196    const legalApiArr: string[] = [ApiType.METHOD, ApiType.TYPE_ALIAS];
197    if (!legalApiArr.includes(singleApi.getApiType())) {
198      return returnsValueCheckResult;
199    }
200    const spacealCase: string[] = CommonFunctions.judgeSpecialCase((singleApi as MethodInfo).returnValueType);
201    if (singleApi.getApiType() === ApiType.TYPE_ALIAS) {
202      returnsApiValue.push((singleApi as TypeAliasInfo).getReturnType().join());
203    } else {
204      returnsApiValue = spacealCase.length > 0 ? spacealCase : (singleApi as MethodInfo).getReturnValue();
205    }
206
207    if (returnsApiValue.length === 0) {
208      returnsValueCheckResult.state = false;
209      returnsValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_RETURNS;
210    } else if (returnsTagValue !== returnsApiValue.join('|').replace(/\s/g, '')) {
211      returnsValueCheckResult.state = false;
212      returnsValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_RETURNS;
213    }
214    return returnsValueCheckResult;
215  }
216
217  /**
218   * namespace tag value check
219   * @param { ClassInfo } singleApi
220   * @param { Comment.CommentTag } tag
221   * @returns { ErrorTagFormat }
222   */
223  static outerTagValueCheck(singleApi: ClassInfo, tag: Comment.CommentTag): ErrorTagFormat {
224    const outerValueCheckResult: ErrorTagFormat = {
225      state: true,
226      errorInfo: '',
227    };
228    let tagValue: string = tag.name;
229    let tagType: string = tag.type;
230    let apiValue: string = singleApi.getApiName();
231    const definedText: string = singleApi.getDefinedText();
232    if (tag.tag === 'namespace' && tagValue !== apiValue) {
233      outerValueCheckResult.state = false;
234      outerValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_NAMESPACE;
235    }
236    if (tag.tag === 'typedef') {
237      if (singleApi.getApiType() === ApiType.TYPE_ALIAS) {
238        const ordinaryTagValue: string = (singleApi as ApiInfo as TypeAliasInfo).getType().join('|').replace(/\s/g, '');
239        const typeIsFuction: boolean = (singleApi as ApiInfo as TypeAliasInfo).getTypeIsFunction();
240        const typeIsObject: boolean = (singleApi as ApiInfo as TypeAliasInfo).getTypeName() === TypeAliasType.OBJECT_TYPE;
241        apiValue = typeIsFuction ? 'function' : typeIsObject ? 'object' : ordinaryTagValue;
242      } else {
243        const genericArr: GenericInfo[] = singleApi.getGenericInfo();
244        if (genericArr.length > 0) {
245          let genericInfo = genericArr.map((generic) => {
246            return generic.getGenericContent();
247          }).join(',');
248          apiValue = apiValue + '<' + genericInfo + '>';
249        }
250      }
251      if (singleApi.getApiType() === 'Interface' && tagValue !== apiValue) {
252        outerValueCheckResult.state = false;
253        outerValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_TYPEDEF;
254      } else if (singleApi.getApiType() === ApiType.TYPE_ALIAS && !singleApi.getIsExport() &&
255        tagType.replace(/\s/g, '') !== apiValue) {
256        outerValueCheckResult.state = false;
257        outerValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_TYPEDEF;
258      }
259    }
260    if (tag.tag === 'struct' && tagType !== apiValue) {
261      outerValueCheckResult.state = false;
262      outerValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_STRUCT;
263    }
264    return outerValueCheckResult;
265  }
266
267  /**
268   * type tag value check
269   * @param { ApiInfo } singleApi
270   * @param { Comment.CommentTag } tag
271   * @returns { ErrorTagFormat }
272   */
273  static typeTagValueCheck(singleApi: ApiInfo, tag: Comment.CommentTag): ErrorTagFormat {
274    const typeValueCheckResult: ErrorTagFormat = {
275      state: true,
276      errorInfo: '',
277    };
278    if (singleApi.getApiType() !== ApiType.PROPERTY) {
279      return typeValueCheckResult;
280    }
281    let typeTagValue: string = tag.type.replace(/\s/g, '');
282    let typeApiValue: string[] = [];
283    const spacealCase: string[] = CommonFunctions.judgeSpecialCase((singleApi as PropertyInfo).typeKind);
284    if (spacealCase.length > 0) {
285      typeApiValue = spacealCase;
286    } else {
287      typeApiValue = (singleApi as PropertyInfo).type;
288    }
289
290    let typeApiUnionValue: string = typeApiValue.join('|').replace(/\s/g, '');
291    const isOptional: boolean = !(singleApi as PropertyInfo).getIsRequired();
292    if (isOptional && typeApiValue.length === 1) {
293      typeApiUnionValue = '?' + typeApiUnionValue;
294    } else if (isOptional && typeApiValue.length > 1) {
295      typeApiUnionValue = '?(' + typeApiUnionValue + ')';
296    }
297    if (typeTagValue.replace(/\s/g, '') !== typeApiUnionValue.replace(/\s/g, '')) {
298      typeValueCheckResult.state = false;
299      typeValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_TYPE;
300    }
301    return typeValueCheckResult;
302  }
303  /**
304   * syacap tag value check
305   * @param { Comment.CommentTag } tag
306   * @returns { ErrorTagFormat }
307   */
308  static syscapTagValueCheck(tag: Comment.CommentTag): ErrorTagFormat {
309    const syscapValueCheckResult: ErrorTagFormat = {
310      state: true,
311      errorInfo: '',
312    };
313    const syscapRule: string[] = SystemCapability;
314    const syscapTagValue: string = tag.name;
315    if (!syscapRule.includes(syscapTagValue)) {
316      syscapValueCheckResult.state = false;
317      syscapValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_SYSCAP;
318    }
319    return syscapValueCheckResult;
320  }
321  /**
322   * default tag value check
323   * @param { Comment.CommentTag } tag
324   * @returns { ErrorTagFormat }
325   */
326  static defaultTagValueCheck(tag: Comment.CommentTag): ErrorTagFormat {
327    const defaultValueCheckResult: ErrorTagFormat = {
328      state: true,
329      errorInfo: '',
330    };
331    const defaultTagValue: string = tag.name + tag.type;
332    if (defaultTagValue.length === 0) {
333      defaultValueCheckResult.state = false;
334      defaultValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_DEFAULT;
335    }
336    return defaultValueCheckResult;
337  }
338
339  /**
340   * deprecated tag value check
341   * @param { Comment.CommentTag } tag
342   * @returns { ErrorTagFormat }
343   */
344  static deprecatedTagValueCheck(tag: Comment.CommentTag): ErrorTagFormat {
345    const deprecatedValueCheckResult: ErrorTagFormat = {
346      state: true,
347      errorInfo: '',
348    };
349    const deprecatedFixedField: string = tag.name;
350
351    const deprecatedVersion: string = CommonFunctions.getSinceVersion(tag.description);
352    const isNumber: boolean = /^\d+$/.test(deprecatedVersion);
353    if (deprecatedFixedField !== 'since' || !isNumber) {
354      deprecatedValueCheckResult.state = false;
355      deprecatedValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_DEPRECATED;
356    }
357    return deprecatedValueCheckResult;
358  }
359  /**
360   * permission tag value check
361   * @param { Comment.CommentTag } tag
362   * @returns { ErrorTagFormat }
363   */
364  static permissionTagValueCheck(tag: Comment.CommentTag): ErrorTagFormat {
365    const permissionValueCheckResult: ErrorTagFormat = {
366      state: true,
367      errorInfo: '',
368    };
369
370    const permissionRuleDatas: PermissionData[] = module.definePermissions as PermissionData[];
371    const permissionRule: string[] = [];
372    permissionRuleDatas.forEach((permissionRuleData: PermissionData) => {
373      permissionRule.push(permissionRuleData.name);
374    });
375    const permissionTagValue: string = tag.name + tag.description;
376    const permissionArr = permissionTagValue
377      .replace(/(\s|\(|\))/g, '')
378      .replace(/(or|and)/g, '$')
379      .split('$');
380    permissionArr.forEach((permissionItem) => {
381      if (!permissionRule.includes(permissionItem)) {
382        permissionValueCheckResult.state = false;
383        permissionValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_PERMISSION;
384      }
385    });
386    return permissionValueCheckResult;
387  }
388
389  /**
390   * throws tag value check
391   * @param { Comment.CommentTag } tag
392   * @param { number } throwsIndex
393   * @returns { ErrorTagFormat }
394   */
395  static throwsTagValueCheck(tag: Comment.CommentTag, throwsIndex: number, tagsName: Comment.CommentTag[] | undefined): ErrorTagFormat {
396    const throwsValueCheckResult: ErrorTagFormat = {
397      state: true,
398      errorInfo: '',
399    };
400    const throwsTagType: string = tag.type;
401    const throwsTagName: string = tag.name;
402    const isNumber: boolean = /^\d+$/.test(throwsTagName);
403    if (throwsTagType !== 'BusinessError') {
404      throwsValueCheckResult.state = false;
405      throwsValueCheckResult.errorInfo = CommonFunctions.createErrorInfo(ErrorMessage.ERROR_INFO_VALUE1_THROWS, [
406        JSON.stringify(throwsIndex),
407      ]);
408    }
409    if (!isNumber) {
410      throwsValueCheckResult.state = false;
411      throwsValueCheckResult.errorInfo = CommonFunctions.createErrorInfo(ErrorMessage.ERROR_INFO_VALUE2_THROWS, [
412        JSON.stringify(throwsIndex),
413      ]);
414    } else if (throwsTagName === '401') {
415      const specialThrowsDescription: string = tag.description;
416      const throws401DescriptionStartIndexof: number = specialThrowsDescription.indexOf(throwsTagDescriptionArr[0]);
417      const throws401DescriptionOneIndexof: number = specialThrowsDescription.indexOf(throwsTagDescriptionArr[1]);
418      const throws401DescriptionTwoIndexof: number = specialThrowsDescription.indexOf(throwsTagDescriptionArr[2]);
419      const throws401DescriptionThreeIndexof: number = specialThrowsDescription.indexOf(throwsTagDescriptionArr[3]);
420      const hasDescriptionContent: boolean = throws401DescriptionOneIndexof !== -1 ||
421        throws401DescriptionTwoIndexof !== -1 || throws401DescriptionThreeIndexof !== -1;
422      const descriptionReg = new RegExp(`${throwsTagDescriptionArr[0]}|${throwsTagDescriptionArr[1]}|${throwsTagDescriptionArr[2]}|${throwsTagDescriptionArr[3]}|<br>`, 'g');
423      const hasElseString: boolean = /[A-Za-z]+/.test(specialThrowsDescription.replace(descriptionReg, ''));
424      if (throws401DescriptionStartIndexof === -1 || throws401DescriptionStartIndexof > 1 || !hasDescriptionContent ||
425        hasElseString) {
426        throwsValueCheckResult.state = false;
427        throwsValueCheckResult.errorInfo = throwsValueCheckResult.errorInfo + ErrorMessage.ERROR_INFO_VALUE3_THROWS;
428      }
429    }
430    const allTagName: string[] = [];
431    tagsName?.forEach((tag: Comment.CommentTag) => {
432      allTagName.push(tag.tag);
433    });
434    return throwsValueCheckResult;
435  }
436
437  /**
438   * param tag value check
439   * @param { ApiInfo } singleApi
440   * @param { Comment.CommentTag } tag
441   * @param { number } paramIndex
442   * @returns { ErrorTagFormat }
443   */
444  static paramTagValueCheck(singleApi: ApiInfo, tag: Comment.CommentTag, paramIndex: number): ErrorTagFormat {
445    const paramValueCheckResult: ErrorTagFormat = {
446      state: true,
447      errorInfo: '',
448    };
449    const legalApiArr: string[] = [ApiType.METHOD, ApiType.TYPE_ALIAS];
450    if (!legalApiArr.includes(singleApi.getApiType())) {
451      return paramValueCheckResult;
452    }
453    const paramTagType: string = tag.type.replace(/\s/g, '');
454    const paramTagName: string = tag.name;
455
456
457    let paramApiName: string = '';
458    let paramApiType: string[] = [];
459
460    if (singleApi.getApiType() === ApiType.TYPE_ALIAS) {
461      const typeParams: ParamInfo[] = (singleApi as TypeAliasInfo).getParamInfos();
462      paramApiName = typeParams.length > paramIndex ? typeParams[paramIndex].getApiName() : '';
463      paramApiType = typeParams.length > paramIndex ? typeParams[paramIndex].getType() : [''];
464    } else {
465      const paramApiInfos: ParamInfo[] = (singleApi as MethodInfo).getParams();
466      paramApiName = paramApiInfos[paramIndex]?.getApiName();
467      const spacealCase: string[] = paramApiInfos[paramIndex] ?
468        CommonFunctions.judgeSpecialCase(paramApiInfos[paramIndex].paramType) : [];
469      paramApiType = spacealCase.length > 0 ? spacealCase : paramApiInfos[paramIndex]?.getType();
470    }
471
472    if (paramTagName !== paramApiName) {
473      paramValueCheckResult.state = false;
474      paramValueCheckResult.errorInfo = CommonFunctions.createErrorInfo(ErrorMessage.ERROR_INFO_VALUE_PARAM, [
475        JSON.stringify(paramIndex + 1),
476        JSON.stringify(paramIndex + 1),
477      ]);
478    }
479    if (paramApiType === undefined || paramTagType !== paramApiType.join('|').replace(/\s/g, '')) {
480      paramValueCheckResult.state = false;
481      paramValueCheckResult.errorInfo =
482        paramValueCheckResult.errorInfo +
483        CommonFunctions.createErrorInfo(ErrorMessage.ERROR_INFO_TYPE_PARAM, [
484          JSON.stringify(paramIndex + 1),
485          JSON.stringify(paramIndex + 1),
486        ]);
487    }
488
489    return paramValueCheckResult;
490  }
491
492  /**
493   *
494   * 1.引用不同文件的api接口
495   * xxx.xxx#xxx
496   *
497   * 2.引用不同文件的模块接口
498   * xxx.xxx
499   *
500   * 3.引用不同文件的api事件接口
501   * xxx.xxx#event:xxx
502   */
503  /**
504   * useinstead format check
505   * @param { string } moduleValue
506   * @returns { boolean }
507   */
508  static checkModule(moduleValue: string): boolean {
509    return (
510      /^[A-Za-z0-9_]+\b(\.[A-Za-z0-9_]+\b)*$/.test(moduleValue) ||
511      /^[A-Za-z0-9_]+\b(\.[A-Za-z0-9_]+\b)*\#[A-Za-z0-9_]+\b$/.test(moduleValue) ||
512      /^[A-Za-z0-9_]+\b(\.[A-Za-z0-9_]+\b)*\#event:[A-Za-z0-9_]+\b$/.test(moduleValue)
513    );
514  }
515  /**
516   * Split useinstead value to determine if the file belongs to arkui.
517   * @param { string } useinsteadTagValue
518   * @param { ErrorTagFormat } useinsteadValueCheckResult
519   */
520  static splitUseinsteadValue(useinsteadTagValue: string, useinsteadValueCheckResult: ErrorTagFormat): void {
521    if (!useinsteadTagValue || useinsteadTagValue === '') {
522      useinsteadValueCheckResult.state = false;
523      useinsteadValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_USEINSTEAD;
524    }
525    // 拆分字符串
526    const splitArray: string[] = useinsteadTagValue.split(/\//g);
527    const MODEL_COUNT: number = 1;
528    const MODEL_COUNTS: number = 2;
529    const FILENAME_MODEL_COUNT: number = 1;
530    if (splitArray.length === MODEL_COUNT) {
531      // 同一文件
532      useinsteadValueCheckResult.state =
533        splitArray[0].indexOf(PunctuationMark.LEFT_BRACKET) === -1 &&
534        splitArray[0].indexOf(PunctuationMark.RIGHT_BRACKET) === -1 &&
535        TagValueCheck.checkModule(splitArray[0]);
536    } else if (splitArray.length === MODEL_COUNTS) {
537      // 不同文件
538      const fileNameArray: string[] = splitArray[0].split('.');
539      if (fileNameArray.length === FILENAME_MODEL_COUNT) {
540        // arkui
541        useinsteadValueCheckResult.state =
542          useinsteadValueCheckResult.state &&
543          /^[A-Za-z0-9_]+\b$/.test(fileNameArray[0]) &&
544          TagValueCheck.checkModule(splitArray[1]);
545      } else {
546        // 非arkui
547        let checkFileName: boolean = true;
548        for (let i = 0; i < fileNameArray.length; i++) {
549          checkFileName =
550            checkFileName &&
551            fileNameArray[0] === 'ohos' &&
552            /^[A-Za-z0-9_]+\b$/.test(fileNameArray[i]);
553        }
554        if (
555          !checkFileName ||
556          (!TagValueCheck.checkModule(splitArray[1]) &&
557            splitArray[1].indexOf(PunctuationMark.LEFT_BRACKET) === -1 &&
558            splitArray[1].indexOf(PunctuationMark.RIGHT_BRACKET) === -1)
559        ) {
560          useinsteadValueCheckResult.state = false;
561        }
562      }
563    } else {
564      // 格式错误
565      useinsteadValueCheckResult.state = false;
566    }
567    if (!useinsteadValueCheckResult.state) {
568      useinsteadValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_USEINSTEAD;
569    }
570  }
571  /**
572   * useinstead tag value check
573   * @param { Comment.CommentTag } tag
574   * @returns { ErrorTagFormat }
575   */
576  static useinsteadTagValueCheck(tag: Comment.CommentTag): ErrorTagFormat {
577    let useinsteadValueCheckResult: ErrorTagFormat = {
578      state: true,
579      errorInfo: '',
580    };
581    const useinsteadTagValue: string = tag.name;
582    if (useinsteadTagValue === '') {
583      useinsteadValueCheckResult.state = false;
584      useinsteadValueCheckResult.errorInfo = ErrorMessage.ERROR_INFO_VALUE_USEINSTEAD;
585    } else {
586      TagValueCheck.splitUseinsteadValue(useinsteadTagValue, useinsteadValueCheckResult);
587    }
588    return useinsteadValueCheckResult;
589  }
590}
591