mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
When there is no change in file text for program, no need to update program (#51626)
* When fsEvent for change is repeated * When trying to check if program is uptodate, read the files from disk to determine the version instead of delaying so that new program is not created if file contents have not changed
This commit is contained in:
@@ -436,7 +436,7 @@ function createSolutionBuilderState<T extends BuilderProgram>(watch: boolean, ho
|
||||
// State of the solution
|
||||
const baseCompilerOptions = getCompilerOptionsOfBuildOptions(options);
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => state.projectCompilerOptions) as CompilerHost & ReadBuildProgramHost;
|
||||
setGetSourceFileAsHashVersioned(compilerHost, host);
|
||||
setGetSourceFileAsHashVersioned(compilerHost);
|
||||
compilerHost.getParsedCommandLine = fileName => parseConfigFile(state, fileName as ResolvedConfigFileName, toResolvedConfigFilePath(state, fileName as ResolvedConfigFileName));
|
||||
compilerHost.resolveModuleNames = maybeBind(host, host.resolveModuleNames);
|
||||
compilerHost.resolveTypeReferenceDirectives = maybeBind(host, host.resolveTypeReferenceDirectives);
|
||||
|
||||
@@ -739,9 +739,9 @@ export function createWatchFactory<Y = undefined>(host: WatchFactoryHost & { tra
|
||||
export function createCompilerHostFromProgramHost(host: ProgramHost<any>, getCompilerOptions: () => CompilerOptions, directoryStructureHost: DirectoryStructureHost = host): CompilerHost {
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
const hostGetNewLine = memoize(() => host.getNewLine());
|
||||
return {
|
||||
const compilerHost: CompilerHost = {
|
||||
getSourceFile: createGetSourceFile(
|
||||
(fileName, encoding) => host.readFile(fileName, encoding),
|
||||
(fileName, encoding) => !encoding ? compilerHost.readFile(fileName) : host.readFile(fileName, encoding),
|
||||
getCompilerOptions,
|
||||
/*setParentNodes*/ undefined
|
||||
),
|
||||
@@ -768,6 +768,7 @@ export function createCompilerHostFromProgramHost(host: ProgramHost<any>, getCom
|
||||
disableUseFileVersionAsSignature: host.disableUseFileVersionAsSignature,
|
||||
storeFilesChangingSignatureDuringEmit: host.storeFilesChangingSignatureDuringEmit,
|
||||
};
|
||||
return compilerHost;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -810,12 +811,12 @@ export function getSourceFileVersionAsHashFromText(host: Pick<CompilerHost, "cre
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost, host: { createHash?(data: string): string; }) {
|
||||
export function setGetSourceFileAsHashVersioned(compilerHost: CompilerHost) {
|
||||
const originalGetSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = (...args) => {
|
||||
const result = originalGetSourceFile.call(compilerHost, ...args);
|
||||
if (result) {
|
||||
result.version = getSourceFileVersionAsHashFromText(host, result.text);
|
||||
result.version = getSourceFileVersionAsHashFromText(compilerHost, result.text);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -48,6 +48,7 @@ import {
|
||||
getNewLineCharacter,
|
||||
getNormalizedAbsolutePath,
|
||||
getParsedCommandLineOfConfigFile,
|
||||
getSourceFileVersionAsHashFromText,
|
||||
getTsBuildInfoEmitOutputFilePath,
|
||||
HasInvalidatedResolutions,
|
||||
isArray,
|
||||
@@ -121,7 +122,7 @@ export function createIncrementalCompilerHost(options: CompilerOptions, system =
|
||||
host.createHash = maybeBind(system, system.createHash);
|
||||
host.disableUseFileVersionAsSignature = system.disableUseFileVersionAsSignature;
|
||||
host.storeFilesChangingSignatureDuringEmit = system.storeFilesChangingSignatureDuringEmit;
|
||||
setGetSourceFileAsHashVersioned(host, system);
|
||||
setGetSourceFileAsHashVersioned(host);
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
|
||||
return host;
|
||||
}
|
||||
@@ -429,7 +430,7 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
}
|
||||
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost;
|
||||
setGetSourceFileAsHashVersioned(compilerHost, host);
|
||||
setGetSourceFileAsHashVersioned(compilerHost);
|
||||
// Members for CompilerHost
|
||||
const getNewSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args);
|
||||
@@ -551,9 +552,9 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
const hasInvalidatedResolutions = resolutionCache.createHasInvalidatedResolutions(customHasInvalidatedResolutions);
|
||||
const {
|
||||
originalReadFile, originalFileExists, originalDirectoryExists,
|
||||
originalCreateDirectory, originalWriteFile,
|
||||
originalCreateDirectory, originalWriteFile, readFileWithCache
|
||||
} = changeCompilerHostLikeToUseCache(compilerHost, toPath);
|
||||
if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileName => compilerHost.fileExists(fileName), hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) {
|
||||
if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, path => getSourceVersion(path, readFileWithCache), fileName => compilerHost.fileExists(fileName), hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) {
|
||||
if (hasChangedConfigFileParsingErrors) {
|
||||
if (reportFileChangeDetectedOnCreateProgram) {
|
||||
reportWatchDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation);
|
||||
@@ -708,9 +709,13 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceVersion(path: Path): string | undefined {
|
||||
function getSourceVersion(path: Path, readFileWithCache: (file: string) => string | undefined): string | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
return !hostSourceFile || !hostSourceFile.version ? undefined : hostSourceFile.version;
|
||||
if (!hostSourceFile) return undefined;
|
||||
if (hostSourceFile.version) return hostSourceFile.version;
|
||||
// Read file and get new version
|
||||
const text = readFileWithCache(path);
|
||||
return text ? getSourceFileVersionAsHashFromText(compilerHost, text) : undefined;
|
||||
}
|
||||
|
||||
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) {
|
||||
|
||||
@@ -702,4 +702,26 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: "fsEvent for change is repeated",
|
||||
commandLineArgs: ["-w", "main.ts", "--extendedDiagnostics"],
|
||||
sys: () => createWatchedSystem({
|
||||
"/user/username/projects/project/main.ts": `let a: string = "Hello"`,
|
||||
[libFile.path]: libFile.content,
|
||||
}, { currentDirectory: "/user/username/projects/project" }),
|
||||
changes: [
|
||||
{
|
||||
caption: "change main.ts",
|
||||
change: sys => sys.replaceFileText("/user/username/projects/project/main.ts", "Hello", "Hello World"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "receive another change event without modifying the file",
|
||||
change: sys => sys.invokeFsWatches("/user/username/projects/project/main.ts", "change", /*modifiedTime*/ undefined, /*useTildeSuffix*/ undefined),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
@@ -686,7 +686,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
}
|
||||
|
||||
private invokeFsWatches(fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, useTildeSuffix: boolean | undefined) {
|
||||
invokeFsWatches(fullPath: string, eventName: "rename" | "change", modifiedTime: Date | undefined, useTildeSuffix: boolean | undefined) {
|
||||
this.invokeFsWatchesCallbacks(fullPath, eventName, modifiedTime, fullPath, useTildeSuffix);
|
||||
this.invokeFsWatchesCallbacks(getDirectoryPath(fullPath), eventName, modifiedTime, fullPath, useTildeSuffix);
|
||||
this.invokeRecursiveFsWatches(fullPath, eventName, modifiedTime, /*entryFullPath*/ undefined, useTildeSuffix);
|
||||
|
||||
Reference in New Issue
Block a user