• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}