• 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} 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