diff --git a/compiler/src/do_arkTS_linter.ts b/compiler/src/do_arkTS_linter.ts index 9742ae0db68f85dc99b335673b57b4ac0ba875ea..2a66ab094dc61786c7dc37b0f528acd5029fbc18 100644 --- a/compiler/src/do_arkTS_linter.ts +++ b/compiler/src/do_arkTS_linter.ts @@ -56,11 +56,6 @@ export enum ArkTSVersion { ArkTS_1_1, } -export interface ArkTSProgram { - builderProgram: ts.BuilderProgram, - wasStrict: boolean -} - export type ProcessDiagnosticsFunc = (diagnostics: ts.Diagnostic) => void; function getArkTSVersionString(arkTSVersion: ArkTSVersion): string { @@ -68,8 +63,7 @@ function getArkTSVersionString(arkTSVersion: ArkTSVersion): string { } export function doArkTSLinter(arkTSVersion: ArkTSVersion, arkTSMode: ArkTSLinterMode, - builderProgram: ArkTSProgram, reverseStrictProgram: ArkTSProgram, - printDiagnostic: ProcessDiagnosticsFunc, shouldWriteFile: boolean = true, + builderProgram: ts.BuilderProgram, printDiagnostic: ProcessDiagnosticsFunc, shouldWriteFile: boolean = true, buildInfoWriteFile?: ts.WriteFileCallback): ts.Diagnostic[] { if (arkTSMode === ArkTSLinterMode.NOT_USE) { return []; @@ -78,11 +72,11 @@ export function doArkTSLinter(arkTSVersion: ArkTSVersion, arkTSMode: ArkTSLinter let diagnostics: ts.Diagnostic[] = []; if (arkTSVersion === ArkTSVersion.ArkTS_1_0) { - diagnostics = ts.ArkTSLinter_1_0.runArkTSLinter(builderProgram, reverseStrictProgram, - /*srcFile*/ undefined, buildInfoWriteFile, getArkTSVersionString(arkTSVersion)); + diagnostics = ts.ArkTSLinter_1_0.runArkTSLinter(builderProgram, /*srcFile*/ undefined, buildInfoWriteFile, + getArkTSVersionString(arkTSVersion)); } else { - diagnostics = ts.ArkTSLinter_1_1.runArkTSLinter(builderProgram, reverseStrictProgram, - /*srcFile*/ undefined, buildInfoWriteFile, getArkTSVersionString(arkTSVersion)); + diagnostics = ts.ArkTSLinter_1_1.runArkTSLinter(builderProgram, /*srcFile*/ undefined, buildInfoWriteFile, + getArkTSVersionString(arkTSVersion)); } removeOutputFile(); @@ -199,96 +193,3 @@ function printArkTSLinterFAQ(diagnostics: ts.Diagnostic[], printDiagnostic: Proc }; printDiagnostic(arkTSFAQDiagnostic); } - -function setCompilerOptions(originProgram: ts.Program, wasStrict: boolean): ts.CompilerOptions { - const compilerOptions: ts.CompilerOptions = { ...originProgram.getCompilerOptions() }; - const inversedOptions = getStrictOptions(wasStrict); - - Object.assign(compilerOptions, inversedOptions); - compilerOptions.allowJs = true; - compilerOptions.checkJs = true; - compilerOptions.tsBuildInfoFile = path.resolve(projectConfig.cachePath, '..', ARKTS_LINTER_BUILD_INFO_SUFFIX); - - return compilerOptions; -} - -export function getReverseStrictBuilderProgram(rollupShareObject: any, originProgram: ts.Program, - wasStrict: boolean): ts.BuilderProgram { - let cacheKey: string = 'linter_service'; - let cache: LanguageServiceCache | undefined = getRollupCache(rollupShareObject, projectConfig, cacheKey); - - let service: ts.LanguageService | undefined = cache?.service; - const currentHash: string | undefined = rollupShareObject?.projectConfig?.pkgJsonFileHash; - const lastHash: string | undefined = cache?.pkgJsonFileHash; - // It's not supported to modify oh-package.json5 file under watch mode, so there is no need to rebuild here - const shouldRebuild: boolean | undefined = (process.env.watchMode === 'true') ? - false : (currentHash && lastHash && currentHash !== lastHash); - if (!service && process.env.watchMode === 'true') { - service = globalProgram.strictLanguageService; - } - if (!service || shouldRebuild) { - // Create language service for linter - // Revert strict options for linter program - const compilerOptions: ts.CompilerOptions = setCompilerOptions(originProgram, !wasStrict); - const servicesHost: ts.LanguageServiceHost = { - getScriptFileNames: () => [...originProgram.getRootFileNames()], - getScriptVersion: fileHashScriptVersion, - getScriptSnapshot: fileName => { - if (!fs.existsSync(fileName)) { - return undefined; - } - return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); - }, - getCurrentDirectory: () => process.cwd(), - getCompilationSettings: () => compilerOptions, - getDefaultLibFileName: options => ts.getDefaultLibFilePath(options), - fileExists: ts.sys.fileExists, - readFile: ts.sys.readFile, - readDirectory: ts.sys.readDirectory, - resolveModuleNames: resolveModuleNames, - resolveTypeReferenceDirectives: resolveTypeReferenceDirectives, - directoryExists: ts.sys.directoryExists, - getDirectories: ts.sys.getDirectories, - getFileCheckedModuleInfo: (containFilePath: string) => { - return { - fileNeedCheck: true, - checkPayload: undefined, - currentFileName: containFilePath, - }; - } - }; - - service = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()); - } - - service.updateRootFiles([...originProgram.getRootFileNames()]); - const newCache: LanguageServiceCache = {service: service, pkgJsonFileHash: currentHash}; - setRollupCache(rollupShareObject, projectConfig, cacheKey, newCache); - if (process.env.watchMode === 'true') { - globalProgram.strictLanguageService = service; - } - - return service.getBuilderProgram(); -} - -function getStrictOptions(strict = true): object { - return { - strictNullChecks: strict, - strictFunctionTypes: strict, - strictPropertyInitialization: strict, - noImplicitReturns: strict, - }; -} - -/** - * Returns true if options were initially strict - */ -export function wasOptionsStrict(compilerOptions: ts.CompilerOptions): boolean { - const strictOptions = getStrictOptions(); - let wasStrict = false; - Object.keys(strictOptions).forEach(x => { - wasStrict = wasStrict || !!compilerOptions[x]; - }); - // wasStrict evaluates true if any of the strict options was set - return wasStrict; -} diff --git a/compiler/src/ets_checker.ts b/compiler/src/ets_checker.ts index 1ef0730baf1f57f3ac00aed770acb673a88bcc8a..93658bf494a644702e44bb47a79ed2f9a49f7cf6 100644 --- a/compiler/src/ets_checker.ts +++ b/compiler/src/ets_checker.ts @@ -86,10 +86,7 @@ import { tsWatchEmitter } from './fast_build/ets_ui/rollup-plugin-ets-checker'; import { doArkTSLinter, ArkTSLinterMode, - ArkTSProgram, ArkTSVersion, - getReverseStrictBuilderProgram, - wasOptionsStrict } from './do_arkTS_linter'; import { getJsDocNodeCheckConfig, @@ -118,7 +115,7 @@ export function readDeaclareFiles(): string[] { } const buildInfoWriteFile: ts.WriteFileCallback = (fileName: string, data: string) => { - if (fileName.endsWith(TS_BUILD_INFO_SUFFIX)) { + if (fileName.includes(TS_BUILD_INFO_SUFFIX)) { const fd: number = fs.openSync(fileName, 'w'); fs.writeSync(fd, data, undefined, 'utf8'); fs.closeSync(fd); @@ -150,7 +147,8 @@ function setCompilerOptions(resolveModulePaths: string[]): void { const suffix: string = projectConfig.hotReload ? HOT_RELOAD_BUILD_INFO_SUFFIX : TS_BUILD_INFO_SUFFIX; const buildInfoPath: string = path.resolve(projectConfig.cachePath, '..', suffix); Object.assign(compilerOptions, { - 'allowJs': false, + 'allowJs': getArkTSLinterMode() !== ArkTSLinterMode.NOT_USE ? true : false, + 'checkJs': getArkTSLinterMode() !== ArkTSLinterMode.NOT_USE ? false : undefined, 'emitNodeModulesFiles': true, 'importsNotUsedAsValues': ts.ImportsNotUsedAsValues.Preserve, 'module': ts.ModuleKind.CommonJS, @@ -430,15 +428,17 @@ export function serviceChecker(rootFileNames: string[], newLogger: Object = null timePrinterInstance.setArkTSTimePrintSwitch(false); timePrinterInstance.appendTime(ts.TimePhase.START); startTimeStatisticsLocation(compilationTime ? compilationTime.createProgramTime : undefined); - globalProgram.builderProgram = languageService.getBuilderProgram(); + + globalProgram.builderProgram = languageService.getBuilderProgram(/*withLinterProgram*/ true); globalProgram.program = globalProgram.builderProgram.getProgram(); props = languageService.getProps(); timePrinterInstance.appendTime(ts.TimePhase.GET_PROGRAM); stopTimeStatisticsLocation(compilationTime ? compilationTime.createProgramTime : undefined); collectAllFiles(globalProgram.program); + collectFileToIgnoreDiagnostics(rootFileNames); startTimeStatisticsLocation(compilationTime ? compilationTime.runArkTSLinterTime : undefined); - runArkTSLinter(rollupShareObject); + runArkTSLinter(); stopTimeStatisticsLocation(compilationTime ? compilationTime.runArkTSLinterTime : undefined); if (process.env.watchMode !== 'true') { @@ -553,10 +553,58 @@ function containFormError(message: string): boolean { return false; } +let fileToIgnoreDiagnostics: Set | undefined = undefined; + +function collectFileToThrowDiagnostics(file: string, fileToThrowDiagnostics: Set) { + const normalizedFilePath: string = path.resolve(file); + const unixFilePath: string = toUnixPath(file); + if (fileToThrowDiagnostics.has(unixFilePath)) { + return; + } + + fileToThrowDiagnostics.add(unixFilePath); + if (path.extname(file) === EXTNAME_JS || + !cache[normalizedFilePath] || cache[normalizedFilePath].children.length === 0) { + return; + } + cache[normalizedFilePath].children.forEach(file => { + collectFileToThrowDiagnostics(file, fileToThrowDiagnostics); + }); +} + +export function collectFileToIgnoreDiagnostics(rootFileNames: string[]): void { + if (getArkTSLinterMode() === ArkTSLinterMode.NOT_USE) { + return; + } + + // With arkts linter enabled, `allowJs` option is set to true, resulting JavaScript-referenced files are included + // in the program and checking process, potentially introducing new errors. For instance, in scenarios where + // an ets file imports js file imports ts file, it’s necessary to filter out errors from ts files. + let fileToThrowDiagnostics: Set = new Set(); + rootFileNames.forEach(file => { + collectFileToThrowDiagnostics(file, fileToThrowDiagnostics); + }); + + fileToIgnoreDiagnostics = new Set(); + globalProgram.program.getSourceFiles().forEach(sourceFile => { + sourceFile.fileName && fileToIgnoreDiagnostics.add(toUnixPath(sourceFile.fileName)); + }); + + fileToThrowDiagnostics.forEach(file => { + fileToIgnoreDiagnostics.delete(file); + }) +} + export function printDiagnostic(diagnostic: ts.Diagnostic): void { if (projectConfig.ignoreWarning) { return; } + + if (fileToIgnoreDiagnostics && diagnostic.file && diagnostic.file.fileName && + fileToIgnoreDiagnostics.has(toUnixPath(diagnostic.file.fileName))) { + return; + } + const message: string = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); if (validateError(message)) { if (process.env.watchMode !== 'true' && !projectConfig.xtsMode) { @@ -857,7 +905,7 @@ function createOrUpdateCache(resolvedModules: ts.ResolvedModuleFull[], containin const children: string[] = []; const error: boolean = false; resolvedModules.forEach(moduleObj => { - if (moduleObj && moduleObj.resolvedFileName && /(? { const visitor: ts.Visitor = node => { // only transform static import/export declaration @@ -90,7 +90,7 @@ export function processKitImport(): Function { // process [ConstEnum] + [TypeExportImport] + [KitImport] transforming const processedNode: ts.SourceFile = ts.visitEachChild(ts.getTypeExportImportAndConstEnumTransformer(context)(node), visitor, context); - ModuleSourceFile.newSourceFile(path.normalize(processedNode.fileName), processedNode); + ModuleSourceFile.newSourceFile(id, processedNode); return node; // this node not used for [writeFile] } // process KitImport transforming diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index d5d355bafe1a44b5e22149368e8b513cdf6d6d9c..7943068aa937a72e476d468ea6baca206a8caa75 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -224,9 +224,9 @@ function checkComponentDecorator(source: string, filePath: string, }); if (process.env.compileTool === 'rollup') { if (result.entryCount > 0) { - storedFileInfo.wholeFileInfo[path.resolve(sourceFile.fileName)].hasEntry = true; + storedFileInfo.wholeFileInfo[filePath].hasEntry = true; } else { - storedFileInfo.wholeFileInfo[path.resolve(sourceFile.fileName)].hasEntry = false; + storedFileInfo.wholeFileInfo[filePath].hasEntry = false; } } validateEntryAndPreviewCount(result, fileQuery, sourceFile.fileName, projectConfig.isPreview,