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 */ 15 16import path from 'path'; 17import { EventEmitter } from 'events'; 18import * as ts from 'typescript'; 19 20import { 21 projectConfig, 22 globalProgram 23} from '../../../main'; 24import { 25 serviceChecker, 26 languageService, 27 printDiagnostic, 28 fastBuildLogger, 29 emitBuildInfo, 30 runArkTSLinter, 31 targetESVersionChanged, 32 collectFileToIgnoreDiagnostics 33} from '../../ets_checker'; 34import { TS_WATCH_END_MSG } from '../../pre_define'; 35import { 36 setChecker, 37 startTimeStatisticsLocation, 38 stopTimeStatisticsLocation, 39 CompilationTimeStatistics 40} from '../../utils'; 41import { 42 configureSyscapInfo, 43 configurePermission 44} from '../system_api/api_check_utils'; 45 46export let tsWatchEmitter: EventEmitter | undefined = undefined; 47export let tsWatchEndPromise: Promise<void>; 48 49export function etsChecker() { 50 let executedOnce: boolean = false; 51 return { 52 name: 'etsChecker', 53 buildStart() { 54 const compilationTime: CompilationTimeStatistics = new CompilationTimeStatistics(this.share, 'etsChecker', 'buildStart'); 55 if (process.env.watchMode === 'true' && process.env.triggerTsWatch === 'true') { 56 tsWatchEmitter = new EventEmitter(); 57 tsWatchEndPromise = new Promise<void>(resolve => { 58 tsWatchEmitter.on(TS_WATCH_END_MSG, () => { 59 resolve(); 60 }); 61 }); 62 } 63 if (this.share.projectConfig.deviceTypes) { 64 configureSyscapInfo(this.share.projectConfig); 65 } 66 if (this.share.projectConfig.permission) { 67 configurePermission(this.share.projectConfig); 68 } 69 if (this.share.projectConfig.integratedHsp) { 70 projectConfig.integratedHsp = this.share.projectConfig.integratedHsp; 71 projectConfig.resetBundleName = this.share.projectConfig.integratedHsp; 72 } 73 Object.assign(projectConfig, this.share.projectConfig); 74 Object.assign(this.share.projectConfig, { 75 compileHar: projectConfig.compileHar, 76 compileShared: projectConfig.compileShared, 77 moduleRootPath: projectConfig.moduleRootPath, 78 buildPath: projectConfig.buildPath, 79 isCrossplatform: projectConfig.isCrossplatform, 80 requestPermissions: projectConfig.requestPermissions, 81 definePermissions: projectConfig.definePermissions, 82 syscapIntersectionSet: projectConfig.syscapIntersectionSet, 83 syscapUnionSet: projectConfig.syscapUnionSet, 84 deviceTypesMessage: projectConfig.deviceTypesMessage, 85 compileSdkVersion: projectConfig.compileSdkVersion, 86 compatibleSdkVersion: projectConfig.compatibleSdkVersion, 87 runtimeOS: projectConfig.runtimeOS 88 }); 89 const logger = this.share.getLogger('etsChecker'); 90 const rootFileNames: string[] = []; 91 const resolveModulePaths: string[] = []; 92 rootFileNamesCollect(rootFileNames); 93 if (this.share && this.share.projectConfig && this.share.projectConfig.resolveModulePaths && 94 Array.isArray(this.share.projectConfig.resolveModulePaths)) { 95 resolveModulePaths.push(...this.share.projectConfig.resolveModulePaths); 96 } 97 if (process.env.watchMode === 'true') { 98 !executedOnce && serviceChecker(rootFileNames, logger, resolveModulePaths, compilationTime, this.share); 99 startTimeStatisticsLocation(compilationTime ? compilationTime.diagnosticTime : undefined); 100 if (executedOnce) { 101 const timePrinterInstance = ts.ArkTSLinterTimePrinter.getInstance(); 102 timePrinterInstance.setArkTSTimePrintSwitch(false); 103 timePrinterInstance.appendTime(ts.TimePhase.START); 104 globalProgram.builderProgram = languageService.getBuilderProgram(/*withLinterProgram*/ true); 105 globalProgram.program = globalProgram.builderProgram.getProgram(); 106 timePrinterInstance.appendTime(ts.TimePhase.GET_PROGRAM); 107 collectFileToIgnoreDiagnostics(rootFileNames); 108 runArkTSLinter(); 109 } 110 executedOnce = true; 111 const allDiagnostics: ts.Diagnostic[] = globalProgram.builderProgram 112 .getSyntacticDiagnostics() 113 .concat(globalProgram.builderProgram.getSemanticDiagnostics()); 114 stopTimeStatisticsLocation(compilationTime ? compilationTime.diagnosticTime : undefined); 115 emitBuildInfo(); 116 allDiagnostics.forEach((diagnostic: ts.Diagnostic) => { 117 printDiagnostic(diagnostic); 118 }); 119 fastBuildLogger.debug(TS_WATCH_END_MSG); 120 tsWatchEmitter.emit(TS_WATCH_END_MSG); 121 } else { 122 serviceChecker(rootFileNames, logger, resolveModulePaths, compilationTime, this.share); 123 } 124 setChecker(); 125 }, 126 shouldInvalidCache(): boolean { 127 // The generated js file might be different in some cases when we change the targetESVersion, 128 // so we need to regenerate them all when targetESVersion is changed. 129 return targetESVersionChanged; 130 } 131 }; 132} 133 134function rootFileNamesCollect(rootFileNames: string[]): void { 135 const entryFiles: string[] = projectConfig.widgetCompile ? Object.values(projectConfig.cardEntryObj) : Object.values(projectConfig.entryObj); 136 entryFiles.forEach((fileName: string) => { 137 rootFileNames.push(path.resolve(fileName)); 138 }); 139} 140