Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When there is no change in file text for program, no need to update program #51626

Merged
merged 2 commits into from Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/tsbuildPublic.ts
Expand Up @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions src/compiler/watch.ts
Expand Up @@ -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),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd to me that this looks like this, given compilerHost just defers to host.readFile too. Is it expected that CompilerHost is missing this parameter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are suppose to deprecate the encoding = charSet from compilerOptions Our APIs dont have that consistent everywhere.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compilerHost.readFile is normally used for module resolution only and it doesnt support passing encoding...

getCompilerOptions,
/*setParentNodes*/ undefined
),
Expand All @@ -768,6 +768,7 @@ export function createCompilerHostFromProgramHost(host: ProgramHost<any>, getCom
disableUseFileVersionAsSignature: host.disableUseFileVersionAsSignature,
storeFilesChangingSignatureDuringEmit: host.storeFilesChangingSignatureDuringEmit,
};
return compilerHost;
}

/** @internal */
Expand Down Expand Up @@ -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;
};
Expand Down
17 changes: 11 additions & 6 deletions src/compiler/watchPublic.ts
Expand Up @@ -48,6 +48,7 @@ import {
getNewLineCharacter,
getNormalizedAbsolutePath,
getParsedCommandLineOfConfigFile,
getSourceFileVersionAsHashFromText,
getTsBuildInfoEmitOutputFilePath,
HasInvalidatedResolutions,
isArray,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
22 changes: 22 additions & 0 deletions src/testRunner/unittests/tscWatch/watchEnvironment.ts
Expand Up @@ -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(),
}
]
});
});
2 changes: 1 addition & 1 deletion src/testRunner/unittests/virtualFileSystemWithWatch.ts
Expand Up @@ -759,7 +759,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);
Expand Down
Expand Up @@ -183,30 +183,6 @@ Input::
//// [/user/username/projects/noEmitOnError/src/main.ts] file written with same contents

Output::
>> Screen clear
[12:00:43 AM] File change detected. Starting incremental compilation...

src/main.ts:4:1 - error TS1005: ',' expected.

4 ;
  ~

[12:00:44 AM] Found 1 error. Watching for file changes.



Program root files: ["/user/username/projects/noEmitOnError/shared/types/db.ts","/user/username/projects/noEmitOnError/src/main.ts","/user/username/projects/noEmitOnError/src/other.ts"]
Program options: {"outDir":"/user/username/projects/noEmitOnError/dev-build","noEmitOnError":true,"watch":true,"assumeChangesOnlyAffectDirectDependencies":true,"incremental":true,"configFilePath":"/user/username/projects/noEmitOnError/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/noEmitOnError/shared/types/db.ts
/user/username/projects/noEmitOnError/src/main.ts
/user/username/projects/noEmitOnError/src/other.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::

PolledWatches::
/user/username/projects/noemitonerror/node_modules/@types:
Expand Down Expand Up @@ -243,9 +219,9 @@ const a = {

Output::
>> Screen clear
[12:00:48 AM] File change detected. Starting incremental compilation...
[12:00:46 AM] File change detected. Starting incremental compilation...

[12:01:06 AM] Found 0 errors. Watching for file changes.
[12:01:04 AM] Found 0 errors. Watching for file changes.



Expand Down Expand Up @@ -382,14 +358,14 @@ const a: string = 10;

Output::
>> Screen clear
[12:01:13 AM] File change detected. Starting incremental compilation...
[12:01:11 AM] File change detected. Starting incremental compilation...

src/main.ts:2:7 - error TS2322: Type 'number' is not assignable to type 'string'.

2 const a: string = 10;
   ~

[12:01:17 AM] Found 1 error. Watching for file changes.
[12:01:15 AM] Found 1 error. Watching for file changes.



Expand Down Expand Up @@ -521,30 +497,6 @@ Input::
//// [/user/username/projects/noEmitOnError/src/main.ts] file written with same contents

Output::
>> Screen clear
[12:01:25 AM] File change detected. Starting incremental compilation...

src/main.ts:2:7 - error TS2322: Type 'number' is not assignable to type 'string'.

2 const a: string = 10;
   ~

[12:01:26 AM] Found 1 error. Watching for file changes.



Program root files: ["/user/username/projects/noEmitOnError/shared/types/db.ts","/user/username/projects/noEmitOnError/src/main.ts","/user/username/projects/noEmitOnError/src/other.ts"]
Program options: {"outDir":"/user/username/projects/noEmitOnError/dev-build","noEmitOnError":true,"watch":true,"assumeChangesOnlyAffectDirectDependencies":true,"incremental":true,"configFilePath":"/user/username/projects/noEmitOnError/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/noEmitOnError/shared/types/db.ts
/user/username/projects/noEmitOnError/src/main.ts
/user/username/projects/noEmitOnError/src/other.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::

PolledWatches::
/user/username/projects/noemitonerror/node_modules/@types:
Expand Down Expand Up @@ -579,9 +531,9 @@ const a: string = "hello";

Output::
>> Screen clear
[12:01:30 AM] File change detected. Starting incremental compilation...
[12:01:26 AM] File change detected. Starting incremental compilation...

[12:01:37 AM] Found 0 errors. Watching for file changes.
[12:01:33 AM] Found 0 errors. Watching for file changes.



Expand Down Expand Up @@ -701,25 +653,6 @@ Input::
//// [/user/username/projects/noEmitOnError/src/main.ts] file written with same contents

Output::
>> Screen clear
[12:01:44 AM] File change detected. Starting incremental compilation...

[12:01:45 AM] Found 0 errors. Watching for file changes.



Program root files: ["/user/username/projects/noEmitOnError/shared/types/db.ts","/user/username/projects/noEmitOnError/src/main.ts","/user/username/projects/noEmitOnError/src/other.ts"]
Program options: {"outDir":"/user/username/projects/noEmitOnError/dev-build","noEmitOnError":true,"watch":true,"assumeChangesOnlyAffectDirectDependencies":true,"incremental":true,"configFilePath":"/user/username/projects/noEmitOnError/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/noEmitOnError/shared/types/db.ts
/user/username/projects/noEmitOnError/src/main.ts
/user/username/projects/noEmitOnError/src/other.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::

PolledWatches::
/user/username/projects/noemitonerror/node_modules/@types:
Expand Down
Expand Up @@ -103,30 +103,6 @@ Input::
//// [/user/username/projects/noEmitOnError/src/main.ts] file written with same contents

Output::
>> Screen clear
[12:00:36 AM] File change detected. Starting incremental compilation...

src/main.ts:4:1 - error TS1005: ',' expected.

4 ;
  ~

[12:00:37 AM] Found 1 error. Watching for file changes.



Program root files: ["/user/username/projects/noEmitOnError/shared/types/db.ts","/user/username/projects/noEmitOnError/src/main.ts","/user/username/projects/noEmitOnError/src/other.ts"]
Program options: {"outDir":"/user/username/projects/noEmitOnError/dev-build","noEmitOnError":true,"watch":true,"assumeChangesOnlyAffectDirectDependencies":true,"configFilePath":"/user/username/projects/noEmitOnError/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/noEmitOnError/shared/types/db.ts
/user/username/projects/noEmitOnError/src/main.ts
/user/username/projects/noEmitOnError/src/other.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::

PolledWatches::
/user/username/projects/noemitonerror/node_modules/@types:
Expand Down Expand Up @@ -163,9 +139,9 @@ const a = {

Output::
>> Screen clear
[12:00:41 AM] File change detected. Starting incremental compilation...
[12:00:39 AM] File change detected. Starting incremental compilation...

[12:00:58 AM] Found 0 errors. Watching for file changes.
[12:00:56 AM] Found 0 errors. Watching for file changes.



Expand Down Expand Up @@ -236,14 +212,14 @@ const a: string = 10;

Output::
>> Screen clear
[12:01:02 AM] File change detected. Starting incremental compilation...
[12:01:00 AM] File change detected. Starting incremental compilation...

src/main.ts:2:7 - error TS2322: Type 'number' is not assignable to type 'string'.

2 const a: string = 10;
   ~

[12:01:03 AM] Found 1 error. Watching for file changes.
[12:01:01 AM] Found 1 error. Watching for file changes.



Expand Down Expand Up @@ -291,30 +267,6 @@ Input::
//// [/user/username/projects/noEmitOnError/src/main.ts] file written with same contents

Output::
>> Screen clear
[12:01:08 AM] File change detected. Starting incremental compilation...

src/main.ts:2:7 - error TS2322: Type 'number' is not assignable to type 'string'.

2 const a: string = 10;
   ~

[12:01:09 AM] Found 1 error. Watching for file changes.



Program root files: ["/user/username/projects/noEmitOnError/shared/types/db.ts","/user/username/projects/noEmitOnError/src/main.ts","/user/username/projects/noEmitOnError/src/other.ts"]
Program options: {"outDir":"/user/username/projects/noEmitOnError/dev-build","noEmitOnError":true,"watch":true,"assumeChangesOnlyAffectDirectDependencies":true,"configFilePath":"/user/username/projects/noEmitOnError/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/noEmitOnError/shared/types/db.ts
/user/username/projects/noEmitOnError/src/main.ts
/user/username/projects/noEmitOnError/src/other.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::

PolledWatches::
/user/username/projects/noemitonerror/node_modules/@types:
Expand Down Expand Up @@ -349,9 +301,9 @@ const a: string = "hello";

Output::
>> Screen clear
[12:01:13 AM] File change detected. Starting incremental compilation...
[12:01:09 AM] File change detected. Starting incremental compilation...

[12:01:17 AM] Found 0 errors. Watching for file changes.
[12:01:13 AM] Found 0 errors. Watching for file changes.



Expand Down Expand Up @@ -405,25 +357,6 @@ Input::
//// [/user/username/projects/noEmitOnError/src/main.ts] file written with same contents

Output::
>> Screen clear
[12:01:21 AM] File change detected. Starting incremental compilation...

[12:01:22 AM] Found 0 errors. Watching for file changes.



Program root files: ["/user/username/projects/noEmitOnError/shared/types/db.ts","/user/username/projects/noEmitOnError/src/main.ts","/user/username/projects/noEmitOnError/src/other.ts"]
Program options: {"outDir":"/user/username/projects/noEmitOnError/dev-build","noEmitOnError":true,"watch":true,"assumeChangesOnlyAffectDirectDependencies":true,"configFilePath":"/user/username/projects/noEmitOnError/tsconfig.json"}
Program structureReused: Completely
Program files::
/a/lib/lib.d.ts
/user/username/projects/noEmitOnError/shared/types/db.ts
/user/username/projects/noEmitOnError/src/main.ts
/user/username/projects/noEmitOnError/src/other.ts

Semantic diagnostics in builder refreshed for::

No shapes updated in the builder::

PolledWatches::
/user/username/projects/noemitonerror/node_modules/@types:
Expand Down