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