107ac75b1Sopenharmony_ci/* 207ac75b1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 307ac75b1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 407ac75b1Sopenharmony_ci * you may not use this file except in compliance with the License. 507ac75b1Sopenharmony_ci * You may obtain a copy of the License at 607ac75b1Sopenharmony_ci * 707ac75b1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 807ac75b1Sopenharmony_ci * 907ac75b1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1007ac75b1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1107ac75b1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1207ac75b1Sopenharmony_ci * See the License for the specific language governing permissions and 1307ac75b1Sopenharmony_ci * limitations under the License. 1407ac75b1Sopenharmony_ci */ 1507ac75b1Sopenharmony_ci 1607ac75b1Sopenharmony_ciimport fs from 'fs'; 1707ac75b1Sopenharmony_ciimport path from 'path'; 1807ac75b1Sopenharmony_ciimport * as ts from 'typescript'; 1907ac75b1Sopenharmony_ciimport { 2007ac75b1Sopenharmony_ci globalProgram, 2107ac75b1Sopenharmony_ci projectConfig 2207ac75b1Sopenharmony_ci} from '../main'; 2307ac75b1Sopenharmony_ciimport { 2407ac75b1Sopenharmony_ci toUnixPath, 2507ac75b1Sopenharmony_ci getRollupCache, 2607ac75b1Sopenharmony_ci setRollupCache 2707ac75b1Sopenharmony_ci} from './utils'; 2807ac75b1Sopenharmony_ciimport { 2907ac75b1Sopenharmony_ci resolveModuleNames, 3007ac75b1Sopenharmony_ci resolveTypeReferenceDirectives, 3107ac75b1Sopenharmony_ci fileHashScriptVersion, 3207ac75b1Sopenharmony_ci LanguageServiceCache, 3307ac75b1Sopenharmony_ci} from './ets_checker'; 3407ac75b1Sopenharmony_ciimport { ARKTS_LINTER_BUILD_INFO_SUFFIX } from './pre_define'; 3507ac75b1Sopenharmony_ci 3607ac75b1Sopenharmony_ciconst arkTSDir: string = 'ArkTS'; 3707ac75b1Sopenharmony_ciconst arkTSLinterOutputFileName: string = 'ArkTSLinter_output.json'; 3807ac75b1Sopenharmony_ciconst spaceNumBeforeJsonLine = 2; 3907ac75b1Sopenharmony_ci 4007ac75b1Sopenharmony_ciinterface OutputInfo { 4107ac75b1Sopenharmony_ci categoryInfo: string | undefined; 4207ac75b1Sopenharmony_ci fileName: string | undefined; 4307ac75b1Sopenharmony_ci line: number | undefined; 4407ac75b1Sopenharmony_ci character: number | undefined; 4507ac75b1Sopenharmony_ci messageText: string | ts.DiagnosticMessageChain; 4607ac75b1Sopenharmony_ci} 4707ac75b1Sopenharmony_ci 4807ac75b1Sopenharmony_ciexport enum ArkTSLinterMode { 4907ac75b1Sopenharmony_ci NOT_USE = 0, 5007ac75b1Sopenharmony_ci COMPATIBLE_MODE = 1, 5107ac75b1Sopenharmony_ci STANDARD_MODE = 2 5207ac75b1Sopenharmony_ci} 5307ac75b1Sopenharmony_ci 5407ac75b1Sopenharmony_ciexport enum ArkTSVersion { 5507ac75b1Sopenharmony_ci ArkTS_1_0, 5607ac75b1Sopenharmony_ci ArkTS_1_1, 5707ac75b1Sopenharmony_ci} 5807ac75b1Sopenharmony_ci 5907ac75b1Sopenharmony_ciexport type ProcessDiagnosticsFunc = (diagnostics: ts.Diagnostic) => void; 6007ac75b1Sopenharmony_ci 6107ac75b1Sopenharmony_cifunction getArkTSVersionString(arkTSVersion: ArkTSVersion): string { 6207ac75b1Sopenharmony_ci return arkTSVersion === ArkTSVersion.ArkTS_1_0 ? 'ArkTS_1_0' : 'ArkTS_1_1'; 6307ac75b1Sopenharmony_ci} 6407ac75b1Sopenharmony_ci 6507ac75b1Sopenharmony_ciexport function doArkTSLinter(arkTSVersion: ArkTSVersion, arkTSMode: ArkTSLinterMode, 6607ac75b1Sopenharmony_ci builderProgram: ts.BuilderProgram, printDiagnostic: ProcessDiagnosticsFunc, shouldWriteFile: boolean = true, 6707ac75b1Sopenharmony_ci buildInfoWriteFile?: ts.WriteFileCallback): ts.Diagnostic[] { 6807ac75b1Sopenharmony_ci if (arkTSMode === ArkTSLinterMode.NOT_USE) { 6907ac75b1Sopenharmony_ci return []; 7007ac75b1Sopenharmony_ci } 7107ac75b1Sopenharmony_ci 7207ac75b1Sopenharmony_ci let diagnostics: ts.Diagnostic[] = []; 7307ac75b1Sopenharmony_ci 7407ac75b1Sopenharmony_ci if (arkTSVersion === ArkTSVersion.ArkTS_1_0) { 7507ac75b1Sopenharmony_ci diagnostics = ts.ArkTSLinter_1_0.runArkTSLinter(builderProgram, /*srcFile*/ undefined, buildInfoWriteFile, 7607ac75b1Sopenharmony_ci getArkTSVersionString(arkTSVersion)); 7707ac75b1Sopenharmony_ci } else { 7807ac75b1Sopenharmony_ci diagnostics = ts.ArkTSLinter_1_1.runArkTSLinter(builderProgram, /*srcFile*/ undefined, buildInfoWriteFile, 7907ac75b1Sopenharmony_ci getArkTSVersionString(arkTSVersion)); 8007ac75b1Sopenharmony_ci } 8107ac75b1Sopenharmony_ci 8207ac75b1Sopenharmony_ci removeOutputFile(); 8307ac75b1Sopenharmony_ci if (diagnostics.length === 0) { 8407ac75b1Sopenharmony_ci return []; 8507ac75b1Sopenharmony_ci } 8607ac75b1Sopenharmony_ci 8707ac75b1Sopenharmony_ci if (arkTSMode === ArkTSLinterMode.COMPATIBLE_MODE) { 8807ac75b1Sopenharmony_ci processArkTSLinterReportAsWarning(diagnostics, printDiagnostic, shouldWriteFile); 8907ac75b1Sopenharmony_ci } else { 9007ac75b1Sopenharmony_ci processArkTSLinterReportAsError(diagnostics, printDiagnostic); 9107ac75b1Sopenharmony_ci } 9207ac75b1Sopenharmony_ci 9307ac75b1Sopenharmony_ci return diagnostics; 9407ac75b1Sopenharmony_ci} 9507ac75b1Sopenharmony_ci 9607ac75b1Sopenharmony_cifunction processArkTSLinterReportAsError(diagnostics: ts.Diagnostic[], printDiagnostic: ProcessDiagnosticsFunc): void { 9707ac75b1Sopenharmony_ci diagnostics.forEach((diagnostic: ts.Diagnostic) => { 9807ac75b1Sopenharmony_ci printDiagnostic(diagnostic); 9907ac75b1Sopenharmony_ci }); 10007ac75b1Sopenharmony_ci printArkTSLinterFAQ(diagnostics, printDiagnostic); 10107ac75b1Sopenharmony_ci} 10207ac75b1Sopenharmony_ci 10307ac75b1Sopenharmony_cifunction processArkTSLinterReportAsWarning(diagnostics: ts.Diagnostic[], printDiagnostic: ProcessDiagnosticsFunc, 10407ac75b1Sopenharmony_ci shouldWriteFile: boolean): void { 10507ac75b1Sopenharmony_ci const filePath = shouldWriteFile ? writeOutputFile(diagnostics) : undefined; 10607ac75b1Sopenharmony_ci if (filePath === undefined) { 10707ac75b1Sopenharmony_ci diagnostics.forEach((diagnostic: ts.Diagnostic) => { 10807ac75b1Sopenharmony_ci const originalCategory = diagnostic.category; 10907ac75b1Sopenharmony_ci diagnostic.category = ts.DiagnosticCategory.Warning; 11007ac75b1Sopenharmony_ci printDiagnostic(diagnostic); 11107ac75b1Sopenharmony_ci diagnostic.category = originalCategory; 11207ac75b1Sopenharmony_ci }); 11307ac75b1Sopenharmony_ci printArkTSLinterFAQ(diagnostics, printDiagnostic); 11407ac75b1Sopenharmony_ci return; 11507ac75b1Sopenharmony_ci } 11607ac75b1Sopenharmony_ci const logMessage = `Has ${diagnostics.length} ArkTS Linter Error. You can get the output in ${filePath}`; 11707ac75b1Sopenharmony_ci const arkTSDiagnostic: ts.Diagnostic = { 11807ac75b1Sopenharmony_ci file: undefined, 11907ac75b1Sopenharmony_ci start: undefined, 12007ac75b1Sopenharmony_ci length: undefined, 12107ac75b1Sopenharmony_ci messageText: logMessage, 12207ac75b1Sopenharmony_ci category: ts.DiagnosticCategory.Warning, 12307ac75b1Sopenharmony_ci code: -1, 12407ac75b1Sopenharmony_ci reportsUnnecessary: undefined, 12507ac75b1Sopenharmony_ci reportsDeprecated: undefined 12607ac75b1Sopenharmony_ci }; 12707ac75b1Sopenharmony_ci printDiagnostic(arkTSDiagnostic); 12807ac75b1Sopenharmony_ci 12907ac75b1Sopenharmony_ci printArkTSLinterFAQ(diagnostics, printDiagnostic); 13007ac75b1Sopenharmony_ci} 13107ac75b1Sopenharmony_ci 13207ac75b1Sopenharmony_cifunction writeOutputFile(diagnostics: ts.Diagnostic[]): string | undefined { 13307ac75b1Sopenharmony_ci let filePath: string = toUnixPath(projectConfig.cachePath); 13407ac75b1Sopenharmony_ci if (!fs.existsSync(filePath)) { 13507ac75b1Sopenharmony_ci return undefined; 13607ac75b1Sopenharmony_ci } 13707ac75b1Sopenharmony_ci filePath = toUnixPath(path.join(filePath, arkTSDir)); 13807ac75b1Sopenharmony_ci if (!fs.existsSync(filePath)) { 13907ac75b1Sopenharmony_ci fs.mkdirSync(filePath); 14007ac75b1Sopenharmony_ci } 14107ac75b1Sopenharmony_ci filePath = toUnixPath((path.join(filePath, arkTSLinterOutputFileName))); 14207ac75b1Sopenharmony_ci const outputInfo: OutputInfo[] = []; 14307ac75b1Sopenharmony_ci diagnostics.forEach((diagnostic: ts.Diagnostic) => { 14407ac75b1Sopenharmony_ci const { line, character }: ts.LineAndCharacter = 14507ac75b1Sopenharmony_ci diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!); 14607ac75b1Sopenharmony_ci outputInfo.push({ 14707ac75b1Sopenharmony_ci categoryInfo: diagnostic.category === ts.DiagnosticCategory.Error ? 'Error' : 'Warning', 14807ac75b1Sopenharmony_ci fileName: diagnostic.file?.fileName, 14907ac75b1Sopenharmony_ci line: line + 1, 15007ac75b1Sopenharmony_ci character: character + 1, 15107ac75b1Sopenharmony_ci messageText: diagnostic.messageText 15207ac75b1Sopenharmony_ci }); 15307ac75b1Sopenharmony_ci }); 15407ac75b1Sopenharmony_ci let output: string | undefined = filePath; 15507ac75b1Sopenharmony_ci try { 15607ac75b1Sopenharmony_ci fs.writeFileSync(filePath, JSON.stringify(outputInfo, undefined, spaceNumBeforeJsonLine)); 15707ac75b1Sopenharmony_ci } catch { 15807ac75b1Sopenharmony_ci output = undefined; 15907ac75b1Sopenharmony_ci } 16007ac75b1Sopenharmony_ci return output; 16107ac75b1Sopenharmony_ci} 16207ac75b1Sopenharmony_ci 16307ac75b1Sopenharmony_cifunction removeOutputFile(): void { 16407ac75b1Sopenharmony_ci let filePath: string = toUnixPath(projectConfig.cachePath); 16507ac75b1Sopenharmony_ci if (!fs.existsSync(filePath)) { 16607ac75b1Sopenharmony_ci return; 16707ac75b1Sopenharmony_ci } 16807ac75b1Sopenharmony_ci filePath = toUnixPath(path.join(filePath, arkTSDir)); 16907ac75b1Sopenharmony_ci if (!fs.existsSync(filePath)) { 17007ac75b1Sopenharmony_ci return; 17107ac75b1Sopenharmony_ci } 17207ac75b1Sopenharmony_ci filePath = toUnixPath((path.join(filePath, arkTSLinterOutputFileName))); 17307ac75b1Sopenharmony_ci if (fs.existsSync(filePath)) { 17407ac75b1Sopenharmony_ci fs.rmSync(filePath); 17507ac75b1Sopenharmony_ci } 17607ac75b1Sopenharmony_ci} 17707ac75b1Sopenharmony_ci 17807ac75b1Sopenharmony_cifunction printArkTSLinterFAQ(diagnostics: ts.Diagnostic[], printDiagnostic: ProcessDiagnosticsFunc): void { 17907ac75b1Sopenharmony_ci if (diagnostics === undefined || diagnostics.length === undefined || diagnostics.length <= 0) { 18007ac75b1Sopenharmony_ci return; 18107ac75b1Sopenharmony_ci } 18207ac75b1Sopenharmony_ci 18307ac75b1Sopenharmony_ci const logMessageFAQ = 'For details about ArkTS syntax errors, see FAQs'; 18407ac75b1Sopenharmony_ci const arkTSFAQDiagnostic: ts.Diagnostic = { 18507ac75b1Sopenharmony_ci file: undefined, 18607ac75b1Sopenharmony_ci start: undefined, 18707ac75b1Sopenharmony_ci length: undefined, 18807ac75b1Sopenharmony_ci messageText: logMessageFAQ, 18907ac75b1Sopenharmony_ci category: ts.DiagnosticCategory.Warning, 19007ac75b1Sopenharmony_ci code: -1, 19107ac75b1Sopenharmony_ci reportsUnnecessary: undefined, 19207ac75b1Sopenharmony_ci reportsDeprecated: undefined 19307ac75b1Sopenharmony_ci }; 19407ac75b1Sopenharmony_ci printDiagnostic(arkTSFAQDiagnostic); 19507ac75b1Sopenharmony_ci} 196