1/* 2 * Copyright (c) 2022-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 16namespace ts { 17export namespace ArkTSLinter_1_0 { 18 19export interface ArkTSProgram { 20 builderProgram: BuilderProgram, 21 wasStrict: boolean 22} 23 24function makeDiag(category: DiagnosticCategory, code: number, file: SourceFile, start: number, length: number, messageText: string): Diagnostic { 25 return { category, code, file, start, length, messageText }; 26} 27 28export function translateDiag(srcFile: SourceFile, problemInfo: ProblemInfo): Diagnostic { 29 const LINTER_MSG_CODE_START = -1; 30 const severity = (problemInfo.severity === Utils.ProblemSeverity.ERROR ? DiagnosticCategory.Error : DiagnosticCategory.Warning); 31 return makeDiag(severity, LINTER_MSG_CODE_START /*+ problemInfo.ruleTag */, srcFile , problemInfo.start, (problemInfo.end - problemInfo.start + 1), problemInfo.rule); 32} 33 34export function runArkTSLinter(tsBuilderProgram: ArkTSProgram, reverseStrictBuilderProgram: ArkTSProgram, 35 srcFile?: SourceFile, buildInfoWriteFile?: WriteFileCallback): Diagnostic[] { 36 TypeScriptLinter.errorLineNumbersString = ""; 37 TypeScriptLinter.warningLineNumbersString = ""; 38 let diagnostics: Diagnostic[] = []; 39 40 LinterConfig.initStatic(); 41 42 const tscDiagnosticsLinter = new TSCCompiledProgram(tsBuilderProgram, reverseStrictBuilderProgram); 43 const strictProgram = tscDiagnosticsLinter.getStrictProgram(); 44 tscDiagnosticsLinter.doAllGetDiagnostics(); 45 46 let srcFiles: SourceFile[] = []; 47 if(!!srcFile) { 48 srcFiles.push(srcFile); 49 } 50 else { 51 srcFiles = strictProgram.getSourceFiles() as SourceFile[]; 52 } 53 54 const tscStrictDiagnostics = getTscDiagnostics(tscDiagnosticsLinter, srcFiles); 55 56 if (!!buildInfoWriteFile) { 57 tscDiagnosticsLinter.getStrictBuilderProgram().emitBuildInfo(buildInfoWriteFile); 58 tscDiagnosticsLinter.getNonStrictBuilderProgram().emitBuildInfo(buildInfoWriteFile); 59 } 60 61 TypeScriptLinter.initGlobals(); 62 63 for(const fileToLint of srcFiles) { 64 TypeScriptLinter.initStatic(); 65 if(TypeScriptLinter.lintEtsOnly && fileToLint.scriptKind !==ScriptKind.ETS) { 66 continue; 67 } 68 69 const linter = new TypeScriptLinter(fileToLint, strictProgram, tscStrictDiagnostics); 70 Utils.setTypeChecker(TypeScriptLinter.tsTypeChecker); 71 linter.lint(); 72 73 // Get list of bad nodes from the current run. 74 const currentDiagnostics = tscStrictDiagnostics.get(fileToLint.fileName) ?? []; 75 TypeScriptLinter.problemsInfos.forEach( 76 (x) => currentDiagnostics.push(translateDiag(fileToLint, x)) 77 ); 78 diagnostics.push(...currentDiagnostics); 79 } 80 81 releaseReferences(); 82 return diagnostics; 83} 84 85// reclaiming memory for Hvigor with "no-parallel" and "daemon", . 86function releaseReferences(): void { 87 TypeScriptLinter.clearTsTypeChecker(); 88 Utils.clearTypeChecker(); 89 Utils.clearTrueSymbolAtLocationCache(); 90} 91 92/** 93 * Extracts TSC diagnostics emitted by strict checks. 94 * Function might be time-consuming, as it runs second compilation. 95 * @param sourceFiles AST of the processed files 96 * @param tscDiagnosticsLinter linter initialized with the processed program 97 * @returns problems found by TSC, mapped by `SourceFile.fileName` field 98 */ 99function getTscDiagnostics( 100 tscDiagnosticsLinter: TSCCompiledProgram, 101 sourceFiles: SourceFile[], 102): Map<Diagnostic[]> { 103 const strictDiagnostics = new Map<string, Diagnostic[]>(); 104 sourceFiles.forEach(file => { 105 const diagnostics = tscDiagnosticsLinter.getStrictDiagnostics(file.fileName); 106 if (diagnostics.length !== 0) { 107 strictDiagnostics.set(normalizePath(file.fileName), diagnostics); 108 } 109 }); 110 return strictDiagnostics; 111} 112 113} 114}