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