1/* 2 * Copyright (c) 2023-2025 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 * as ts from 'typescript'; 17import type { CommandLineOptions } from '../CommandLineOptions'; 18import { formTscOptions } from './FormTscOptions'; 19import { logTscDiagnostic } from '../utils/functions/LogTscDiagnostic'; 20import type { LinterConfig } from '../LinterConfig'; 21import { TSCCompiledProgramSimple, TSCCompiledProgramWithDiagnostics } from '../ts-diagnostics/TSCCompiledProgram'; 22import { Logger } from '../Logger'; 23 24export type createProgramCallback = (createProgramOptions: ts.CreateProgramOptions) => ts.Program; 25 26function compile( 27 cmdOptions: CommandLineOptions, 28 overrideCompilerOptions: ts.CompilerOptions, 29 createProgramCb?: createProgramCallback 30): ts.Program { 31 const createProgramOptions = formTscOptions(cmdOptions, overrideCompilerOptions); 32 const program = createProgramCb ? createProgramCb(createProgramOptions) : ts.createProgram(createProgramOptions); 33 // Log Tsc errors if needed 34 if (cmdOptions.logTscErrors) { 35 const diagnostics = ts.getPreEmitDiagnostics(program); 36 logTscDiagnostic(diagnostics, Logger.info); 37 } 38 return program; 39} 40 41export function compileLintOptions( 42 cmdOptions: CommandLineOptions, 43 createProgramCb?: createProgramCallback 44): LinterConfig { 45 const linterConfig = cmdOptions.disableStrictDiagnostics ? 46 compileSimpleProgram(cmdOptions, createProgramCb) : 47 compileWithStrictDiagnostics(cmdOptions, createProgramCb); 48 49 linterConfig.cmdOptions.linterOptions.etsLoaderPath = getEtsLoaderPath(linterConfig); 50 return linterConfig; 51} 52 53function compileSimpleProgram(cmdOptions: CommandLineOptions, createProgramCb?: createProgramCallback): LinterConfig { 54 const program = compile(cmdOptions, getOverrideCompilerOptions(true), createProgramCb); 55 return { 56 cmdOptions: cmdOptions, 57 tscCompiledProgram: new TSCCompiledProgramSimple(program) 58 }; 59} 60 61function compileWithStrictDiagnostics( 62 cmdOptions: CommandLineOptions, 63 createProgramCb?: createProgramCallback 64): LinterConfig { 65 const strict = compile(cmdOptions, getOverrideCompilerOptions(true), createProgramCb); 66 const nonStrict = compile(cmdOptions, getOverrideCompilerOptions(false), createProgramCb); 67 return { 68 cmdOptions: cmdOptions, 69 tscCompiledProgram: new TSCCompiledProgramWithDiagnostics(strict, nonStrict, cmdOptions.inputFiles) 70 }; 71} 72 73function getOverrideCompilerOptions(strict: boolean): ts.CompilerOptions { 74 return { 75 strict: false, 76 alwaysStrict: false, 77 noImplicitAny: false, 78 noImplicitThis: false, 79 strictBindCallApply: false, 80 useUnknownInCatchVariables: false, 81 strictNullChecks: strict, 82 strictFunctionTypes: strict, 83 strictPropertyInitialization: strict, 84 noImplicitReturns: strict 85 }; 86} 87 88export function getEtsLoaderPath(linterConfig: LinterConfig): string | undefined { 89 const tsProgram = linterConfig.tscCompiledProgram.getProgram(); 90 return tsProgram.getCompilerOptions().etsLoaderPath; 91} 92