From b47148b93e70d6d4e4120e4e62df8e11d9b40f6a Mon Sep 17 00:00:00 2001 From: lihong Date: Sat, 2 Apr 2022 18:10:55 +0800 Subject: [PATCH] lihong67@huawei.com fix watch mode syntax check. Signed-off-by: lihong Change-Id: I715822ef5964b2798f94ae6235972b142f64c6e5 --- compiler/main.js | 5 +- compiler/src/compile_info.ts | 76 ++++++++----- compiler/src/ets_checker.ts | 136 +++++++++++++++-------- compiler/src/process_component_member.ts | 2 + compiler/webpack.config.js | 4 +- 5 files changed, 144 insertions(+), 79 deletions(-) diff --git a/compiler/main.js b/compiler/main.js index a9ff5a1..f2044d3 100644 --- a/compiler/main.js +++ b/compiler/main.js @@ -322,7 +322,10 @@ function hashProjectPath(projectPath) { return process.env.hashProjectPath; } -const globalProgram = { program: null }; +const globalProgram = { + program: null, + watchProgram: null +}; exports.globalProgram = globalProgram; exports.projectConfig = projectConfig; diff --git a/compiler/src/compile_info.ts b/compiler/src/compile_info.ts index 3aad9bb..91d0f93 100644 --- a/compiler/src/compile_info.ts +++ b/compiler/src/compile_info.ts @@ -41,11 +41,9 @@ import { import { MODULE_SHARE_PATH, BUILD_SHARE_PATH } from './pre_define'; import { createLanguageService, - dollarCollection, appComponentCollection, - decoratorParamsCollection, - extendCollection, - importModuleCollection + importModuleCollection, + createWatchCompilerHost } from './ets_checker'; import { globalProgram } from '../main'; @@ -156,29 +154,21 @@ export class ResultStates { Object.values(projectConfig.entryObj).forEach((fileName: string) => { rootFileNames.push(fileName.replace('?entry', '')); }); - const languageService: ts.LanguageService = createLanguageService(rootFileNames); - globalProgram.program = languageService.getProgram(); - const rootProgram: ts.Program = globalProgram.program; - props.push(...dollarCollection, ...decoratorParamsCollection, ...extendCollection); - let allDiagnostics: ts.Diagnostic[] = rootProgram - .getSyntacticDiagnostics() - .concat(rootProgram.getSemanticDiagnostics()) - .concat(rootProgram.getDeclarationDiagnostics()); - allDiagnostics = allDiagnostics.filter((item) => { - return this.validateError(ts.flattenDiagnosticMessageText(item.messageText, '\n')); - }); - this.mErrorCount += allDiagnostics.length; - allDiagnostics.forEach((diagnostic: ts.Diagnostic) => { - const message: string = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); - if (diagnostic.file) { - const { line, character }: ts.LineAndCharacter = - diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!); - logger.error(this.red, - `ETS:ERROR File: ${diagnostic.file.fileName}:${line + 1}:${character + 1}\n ${message}\n`); - } else { - logger.error(this.red, `ETS:ERROR: ${message}`); - } - }); + if (process.env.watchMode === 'true') { + globalProgram.watchProgram = ts.createWatchProgram( + createWatchCompilerHost(rootFileNames, this.printDiagnostic.bind(this), + this.delayPrintLogCount.bind(this))); + } else { + const languageService: ts.LanguageService = createLanguageService(rootFileNames); + globalProgram.program = languageService.getProgram(); + const allDiagnostics: ts.Diagnostic[] = globalProgram.program + .getSyntacticDiagnostics() + .concat(globalProgram.program.getSemanticDiagnostics()) + .concat(globalProgram.program.getDeclarationDiagnostics()); + allDiagnostics.forEach((diagnostic: ts.Diagnostic) => { + this.printDiagnostic(diagnostic); + }); + } }); compiler.hooks.done.tap('Result States', (stats: Stats) => { @@ -214,6 +204,21 @@ export class ResultStates { } } + private printDiagnostic(diagnostic: ts.Diagnostic): void { + const message: string = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + if (this.validateError(message)) { + this.mErrorCount += 1; + if (diagnostic.file) { + const { line, character }: ts.LineAndCharacter = + diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!); + logger.error(this.red, + `ETS:ERROR File: ${diagnostic.file.fileName}:${line + 1}:${character + 1}\n ${message}\n`); + } else { + logger.error(this.red, `ETS:ERROR: ${message}`); + } + } + } + private writeUseOSFiles(): void { let info: string = ''; if (!fs.existsSync(projectConfig.aceSoPath)) { @@ -230,6 +235,23 @@ export class ResultStates { private printResult(): void { this.printWarning(); this.printError(); + if (process.env.watchMode === 'true') { + process.env.watchEts = 'end'; + this.delayPrintLogCount(); + } else { + this.printLogCount(); + } + } + + private delayPrintLogCount() { + if (process.env.watchEts === 'end' && process.env.watchTs === 'end') { + this.printLogCount(); + process.env.watchEts = 'start'; + process.env.watchTs = 'start'; + } + } + + private printLogCount(): void { if (this.mErrorCount + this.warningCount + this.noteCount > 0) { let result: string; let resultInfo: string = ''; diff --git a/compiler/src/ets_checker.ts b/compiler/src/ets_checker.ts index 3119c88..2ea4b23 100644 --- a/compiler/src/ets_checker.ts +++ b/compiler/src/ets_checker.ts @@ -35,6 +35,7 @@ import { import { JS_BIND_COMPONENTS } from './component_map'; import { getName } from './process_component_build'; import { INNER_COMPONENT_NAMES } from './component_map'; +import { props } from './compile_info'; function readDeaclareFiles(): string[] { const declarationsFileNames: string[] = []; @@ -47,14 +48,15 @@ function readDeaclareFiles(): string[] { return declarationsFileNames; } -export function createLanguageService(rootFileNames: string[]): ts.LanguageService { - const compilerOptions: ts.CompilerOptions = ts.readConfigFile( - path.resolve(__dirname, '../tsconfig.json'), ts.sys.readFile).config.compilerOptions; +const compilerOptions: ts.CompilerOptions = ts.readConfigFile( + path.resolve(__dirname, '../tsconfig.json'), ts.sys.readFile).config.compilerOptions; +function setCompilerOptions() { Object.assign(compilerOptions, { 'allowJs': false, 'importsNotUsedAsValues': ts.ImportsNotUsedAsValues.Preserve, 'module': ts.ModuleKind.CommonJS, 'moduleResolution': ts.ModuleResolutionKind.NodeJs, + 'noEmit': true, 'target': ts.ScriptTarget.ES2017, 'baseUrl': path.resolve(projectConfig.projectPath), 'paths': { @@ -67,6 +69,10 @@ export function createLanguageService(rootFileNames: string[]): ts.LanguageServi 'lib.es2020.d.ts' ] }); +} + +export function createLanguageService(rootFileNames: string[]): ts.LanguageService { + setCompilerOptions(); const files: ts.MapLike<{ version: number }> = {}; const servicesHost: ts.LanguageServiceHost = { getScriptFileNames: () => [...rootFileNames, ...readDeaclareFiles()], @@ -88,57 +94,88 @@ export function createLanguageService(rootFileNames: string[]): ts.LanguageServi fileExists: ts.sys.fileExists, readFile: ts.sys.readFile, readDirectory: ts.sys.readDirectory, - resolveModuleNames(moduleNames: string[], containingFile: string): ts.ResolvedModuleFull[] { - const resolvedModules: ts.ResolvedModuleFull[] = []; - for (const moduleName of moduleNames) { - const result = ts.resolveModuleName(moduleName, containingFile, compilerOptions, { - fileExists(fileName: string): boolean { - return ts.sys.fileExists(fileName); - }, - readFile(fileName: string): string | undefined { - return ts.sys.readFile(fileName); - } - }); - if (result.resolvedModule) { - resolvedModules.push(result.resolvedModule); - } else if (/^@(system|ohos)/.test(moduleName.trim())) { - const modulePath: string = path.resolve(__dirname, '../../../api', moduleName + '.d.ts'); - if (ts.sys.fileExists(modulePath)) { - resolvedModules.push(getResolveModule(modulePath, '.d.ts')); - } else { - resolvedModules.push(null); - } - } else if (/\.ets$/.test(moduleName)) { - const modulePath: string = path.resolve(path.dirname(containingFile), moduleName); - if (ts.sys.fileExists(modulePath)) { - resolvedModules.push(getResolveModule(modulePath, '.ets')); - } else { - resolvedModules.push(null); - } - } else if (/\.ts$/.test(moduleName)) { - const modulePath: string = path.resolve(path.dirname(containingFile), moduleName); - if (ts.sys.fileExists(modulePath)) { - resolvedModules.push(getResolveModule(modulePath, '.ts')); - } else { - resolvedModules.push(null); - } - } else { - const modulePath: string = path.resolve(__dirname, '../../../api', moduleName + '.d.ts'); - if (ts.sys.fileExists(modulePath)) { - resolvedModules.push(getResolveModule(modulePath, '.d.ts')); - } else { - resolvedModules.push(null); - } - } - } - return resolvedModules; - }, + resolveModuleNames: resolveModuleNames, directoryExists: ts.sys.directoryExists, getDirectories: ts.sys.getDirectories }; return ts.createLanguageService(servicesHost, ts.createDocumentRegistry()); } +function resolveModuleNames(moduleNames: string[], containingFile: string): ts.ResolvedModuleFull[] { + const resolvedModules: ts.ResolvedModuleFull[] = []; + for (const moduleName of moduleNames) { + const result = ts.resolveModuleName(moduleName, containingFile, compilerOptions, { + fileExists(fileName: string): boolean { + return ts.sys.fileExists(fileName); + }, + readFile(fileName: string): string | undefined { + return ts.sys.readFile(fileName); + } + }); + if (result.resolvedModule) { + resolvedModules.push(result.resolvedModule); + } else if (/^@(system|ohos)/.test(moduleName.trim())) { + const modulePath: string = path.resolve(__dirname, '../../../api', moduleName + '.d.ts'); + if (ts.sys.fileExists(modulePath)) { + resolvedModules.push(getResolveModule(modulePath, '.d.ts')); + } else { + resolvedModules.push(null); + } + } else if (/\.ets$/.test(moduleName)) { + const modulePath: string = path.resolve(path.dirname(containingFile), moduleName); + if (ts.sys.fileExists(modulePath)) { + resolvedModules.push(getResolveModule(modulePath, '.ets')); + } else { + resolvedModules.push(null); + } + } else if (/\.ts$/.test(moduleName)) { + const modulePath: string = path.resolve(path.dirname(containingFile), moduleName); + if (ts.sys.fileExists(modulePath)) { + resolvedModules.push(getResolveModule(modulePath, '.ts')); + } else { + resolvedModules.push(null); + } + } else { + const modulePath: string = path.resolve(__dirname, '../../../api', moduleName + '.d.ts'); + if (ts.sys.fileExists(modulePath)) { + resolvedModules.push(getResolveModule(modulePath, '.d.ts')); + } else { + resolvedModules.push(null); + } + } + } + return resolvedModules; +} + +export function createWatchCompilerHost(rootFileNames: string[], + reportDiagnostic: ts.DiagnosticReporter, delayPrintLogCount: Function +): ts.WatchCompilerHostOfFilesAndCompilerOptions { + setCompilerOptions(); + const createProgram = ts.createSemanticDiagnosticsBuilderProgram; + const host = ts.createWatchCompilerHost( + [...rootFileNames, ...readDeaclareFiles()], compilerOptions, + ts.sys, createProgram, reportDiagnostic, + (diagnostic: ts.Diagnostic) => { + // End of compilation in watch mode flag. + if ([6193, 6194].includes(diagnostic.code)) { + process.env.watchTs = 'end'; + delayPrintLogCount(); + } + }); + host.readFile = (fileName: string) => { + if (!fs.existsSync(fileName)) { + return undefined; + } + if (/(?