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 TSC_SYSTEM_CODE, 34 traverseProgramSourceFiles 35} from '../../ets_checker'; 36import { TS_WATCH_END_MSG } from '../../pre_define'; 37import { 38 setChecker, 39 startTimeStatisticsLocation, 40 stopTimeStatisticsLocation, 41 CompilationTimeStatistics 42} from '../../utils'; 43import { 44 configureSyscapInfo, 45 configurePermission 46} from '../system_api/api_check_utils'; 47import { MemoryMonitor } from '../meomry_monitor/rollup-plugin-memory-monitor'; 48import { MemoryDefine } from '../meomry_monitor/memory_define'; 49import { LINTER_SUBSYSTEM_CODE } from '../../hvigor_error_code/hvigor_error_info'; 50import { ErrorCodeModule } from '../../hvigor_error_code/const/error_code_module'; 51 52export let tsWatchEmitter: EventEmitter | undefined = undefined; 53export let tsWatchEndPromise: Promise<void>; 54 55export function etsChecker() { 56 let executedOnce: boolean = false; 57 return { 58 name: 'etsChecker', 59 buildStart() { 60 const recordInfo = MemoryMonitor.recordStage(MemoryDefine.ROLLUP_PLUGIN_BUILD_START); 61 const compilationTime: CompilationTimeStatistics = new CompilationTimeStatistics(this.share, 'etsChecker', 'buildStart'); 62 if (process.env.watchMode === 'true' && process.env.triggerTsWatch === 'true') { 63 tsWatchEmitter = new EventEmitter(); 64 tsWatchEndPromise = new Promise<void>(resolve => { 65 tsWatchEmitter.on(TS_WATCH_END_MSG, () => { 66 resolve(); 67 }); 68 }); 69 } 70 if (this.share.projectConfig.deviceTypes) { 71 configureSyscapInfo(this.share.projectConfig); 72 } 73 if (this.share.projectConfig.permission) { 74 configurePermission(this.share.projectConfig); 75 } 76 if (this.share.projectConfig.integratedHsp) { 77 projectConfig.integratedHsp = this.share.projectConfig.integratedHsp; 78 projectConfig.resetBundleName = this.share.projectConfig.integratedHsp; 79 } 80 Object.assign(projectConfig, this.share.projectConfig); 81 Object.assign(this.share.projectConfig, { 82 compileHar: projectConfig.compileHar, 83 compileShared: projectConfig.compileShared, 84 moduleRootPath: projectConfig.moduleRootPath, 85 buildPath: projectConfig.buildPath, 86 isCrossplatform: projectConfig.isCrossplatform, 87 requestPermissions: projectConfig.requestPermissions, 88 definePermissions: projectConfig.definePermissions, 89 syscapIntersectionSet: projectConfig.syscapIntersectionSet, 90 syscapUnionSet: projectConfig.syscapUnionSet, 91 deviceTypesMessage: projectConfig.deviceTypesMessage, 92 compileSdkVersion: projectConfig.compileSdkVersion, 93 compatibleSdkVersion: projectConfig.compatibleSdkVersion, 94 runtimeOS: projectConfig.runtimeOS 95 }); 96 const logger = this.share.getLogger('etsChecker'); 97 const rootFileNames: string[] = []; 98 const resolveModulePaths: string[] = []; 99 rootFileNamesCollect(rootFileNames); 100 if (this.share && this.share.projectConfig && this.share.projectConfig.resolveModulePaths && 101 Array.isArray(this.share.projectConfig.resolveModulePaths)) { 102 resolveModulePaths.push(...this.share.projectConfig.resolveModulePaths); 103 } 104 if (process.env.watchMode === 'true') { 105 !executedOnce && serviceChecker(rootFileNames, logger, resolveModulePaths, compilationTime, this.share); 106 startTimeStatisticsLocation(compilationTime ? compilationTime.diagnosticTime : undefined); 107 if (executedOnce) { 108 const timePrinterInstance = ts.ArkTSLinterTimePrinter.getInstance(); 109 timePrinterInstance.setArkTSTimePrintSwitch(false); 110 const buildProgramRecordInfo = MemoryMonitor.recordStage(MemoryDefine.BUILDER_PROGRAM); 111 timePrinterInstance.appendTime(ts.TimePhase.START); 112 globalProgram.builderProgram = languageService.getBuilderProgram(/*withLinterProgram*/ true); 113 globalProgram.program = globalProgram.builderProgram.getProgram(); 114 traverseProgramSourceFiles(languageService.getProps()); 115 timePrinterInstance.appendTime(ts.TimePhase.GET_PROGRAM); 116 MemoryMonitor.stopRecordStage(buildProgramRecordInfo); 117 const collectFileToIgnore = MemoryMonitor.recordStage(MemoryDefine.COLLECT_FILE_TOIGNORE_RUN_TSLINTER); 118 collectFileToIgnoreDiagnostics(rootFileNames); 119 runArkTSLinter(getErrorCodeLogger(LINTER_SUBSYSTEM_CODE, this.share)); 120 MemoryMonitor.stopRecordStage(collectFileToIgnore); 121 } 122 executedOnce = true; 123 const allDiagnostics: ts.Diagnostic[] = globalProgram.builderProgram 124 .getSyntacticDiagnostics() 125 .concat(globalProgram.builderProgram.getSemanticDiagnostics()); 126 stopTimeStatisticsLocation(compilationTime ? compilationTime.diagnosticTime : undefined); 127 emitBuildInfo(); 128 let errorCodeLogger: Object | undefined = this.share?.getHvigorConsoleLogger ? 129 this.share?.getHvigorConsoleLogger(TSC_SYSTEM_CODE) : undefined; 130 131 allDiagnostics.forEach((diagnostic: ts.Diagnostic) => { 132 printDiagnostic(diagnostic, ErrorCodeModule.TSC, errorCodeLogger); 133 }); 134 fastBuildLogger.debug(TS_WATCH_END_MSG); 135 tsWatchEmitter.emit(TS_WATCH_END_MSG); 136 } else { 137 serviceChecker(rootFileNames, logger, resolveModulePaths, compilationTime, this.share); 138 } 139 setChecker(); 140 MemoryMonitor.stopRecordStage(recordInfo); 141 }, 142 shouldInvalidCache(): boolean { 143 // The generated js file might be different in some cases when we change the targetESVersion, 144 // so we need to regenerate them all when targetESVersion is changed. 145 return targetESVersionChanged; 146 } 147 }; 148} 149 150function getErrorCodeLogger(code: string, share: Object): Object | undefined { 151 return !!share?.getHvigorConsoleLogger ? share?.getHvigorConsoleLogger(code) : undefined; 152} 153 154function rootFileNamesCollect(rootFileNames: string[]): void { 155 const entryFiles: string[] = projectConfig.widgetCompile ? Object.values(projectConfig.cardEntryObj) : Object.values(projectConfig.entryObj); 156 entryFiles.forEach((fileName: string) => { 157 rootFileNames.push(path.resolve(fileName)); 158 }); 159} 160