• 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 */
15import fs from 'fs';
16import path from 'path';
17import ts from 'typescript';
18import { Check } from './api_check_plugin';
19import { AddErrorLogs } from './compile_info';
20import {
21  ApiResultSimpleInfo,
22  ErrorType,
23  ErrorID,
24  LogType,
25  ErrorLevel,
26  ApiResultInfo,
27  ApiCheckInfo,
28  ErrorBaseInfo,
29} from '../../../typedef/checker/result_type';
30import { StringConstant } from '../../../utils/Constant';
31import { CommonFunctions, CompolerOptions, ObtainFullPath } from '../../../utils/checkUtils';
32import { compositiveResult, compositiveLocalResult } from '../../../utils/checkUtils';
33
34export class TsSyntaxCheck {
35  /**
36   * ts语法检查工具入口
37   * @param { string } url -File path for storing critical information.
38   */
39  static checkAPISyntax(url: string): ApiResultSimpleInfo[] {
40    const tsResult: ApiResultSimpleInfo[] = [];
41    const tsLocalResult: ApiResultInfo[] = [];
42    if (fs.existsSync(url)) {
43      const fullFilesPath: string[] = [];
44      ObtainFullPath.getFullFiles(path.resolve(__dirname, '../../../../../../api'), fullFilesPath);
45      const files: Array<string> = Check.getMdFiles(url);
46      const program: ts.Program = ts.createProgram({
47        rootNames: fullFilesPath,
48        options: CompolerOptions.getCompolerOptions(),
49      });
50      //ts存在bug,仅为解决无法绑定sourcefile根节点的问题
51      program.getTypeChecker();
52      const programSourceFiles: readonly ts.SourceFile[] = program.getSourceFiles();
53      const host: ts.CompilerHost = ts.createCompilerHost(CompolerOptions.getCompolerOptions());
54      const diagnostics: ts.Diagnostic[] = ts.runArkTSLinter(program, host);
55      files.forEach((filePath: string, index: number) => {
56        TsSyntaxCheck.checkAPISyntaxCallback(
57          filePath,
58          program,
59          diagnostics,
60          programSourceFiles,
61          compositiveResult,
62          compositiveLocalResult
63        );
64        console.log(`api check scaning file in no ${++index}!`);
65      });
66    }
67    return tsResult;
68  }
69  /**
70   * ts检查主要处理过程
71   * @param { string } fileName
72   * @param { ts.Program } program
73   * @param { ts.Diagnostic[] } diagnostics
74   * @param { readonly ts.SourceFile[] } programSourceFiles
75   * @param { ApiResultSimpleInfo[] } tsResult
76   * @param { ApiResultInfo[] } checkErrorAllInfos
77   */
78  static checkAPISyntaxCallback(
79    fileName: string,
80    program: ts.Program,
81    diagnostics: ts.Diagnostic[],
82    programSourceFiles: readonly ts.SourceFile[],
83    tsResult: ApiResultSimpleInfo[],
84    checkErrorAllInfos: ApiResultInfo[]
85  ): void {
86    const fileContent: string = fs.readFileSync(fileName, StringConstant.UTF8);
87    const node: ts.Node = ts.createSourceFile(fileName, fileContent, ts.ScriptTarget.ES2017, true);
88    const fileSuffix: string = fileName.substring(fileName.lastIndexOf('.'), fileName.length);
89    // tsc诊断日志
90    if (fileSuffix === '.ts') {
91      const targetSourceFile: ts.SourceFile = node.getSourceFile();
92      programSourceFiles.forEach((programSourceFile) => {
93        if (programSourceFile.fileName !== targetSourceFile.fileName) {
94          return;
95        }
96        const result: readonly ts.Diagnostic[] = program.getSemanticDiagnostics(programSourceFile);
97        result.forEach((item) => {
98          const filePath: string = item.file?.fileName as string;
99          const fileName: string = filePath.substring(filePath.indexOf('api'), filePath.length);
100          const apiInfo: ApiCheckInfo = new ApiCheckInfo();
101          AddErrorLogs.addAPICheckErrorLogs(apiInfo, compositiveResult, compositiveLocalResult);
102        });
103      });
104    }
105    // ArkTS诊断日志
106    if (fileSuffix === '.ets') {
107      diagnostics.forEach((item) => {
108        if (path.normalize(item.file?.fileName as string) === path.normalize(fileName)) {
109          const filePath: string = item.file?.fileName as string;
110          const fileName: string = filePath.substring(filePath.indexOf('api'), filePath.length);
111          const errorBaseInfo: ErrorBaseInfo = new ErrorBaseInfo();
112          errorBaseInfo
113            .setErrorID(ErrorID.TS_SYNTAX_ERROR_ID)
114            .setErrorLevel(ErrorLevel.MIDDLE)
115            .setErrorType(ErrorType.PARAMETER_ERRORS)
116            .setLogType(LogType.LOG_JSDOC)
117            .setErrorInfo(item.messageText as string);
118          const apiInfoTsCheck: ApiCheckInfo = CommonFunctions.getErrorInfo(undefined, undefined, fileName,
119            errorBaseInfo);
120          AddErrorLogs.addAPICheckErrorLogs(apiInfoTsCheck, compositiveResult, compositiveLocalResult);
121        }
122      });
123    }
124  }
125}
126