Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ namespace ts {
export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, host, oldProgram, configFileParsingDiagnostics }: BuilderCreationParameters) {
// Return same program if underlying program doesnt change
let oldState = oldProgram && oldProgram.getState();
if (oldState && newProgram === oldState.program && configFileParsingDiagnostics !== newProgram.getConfigFileParsingDiagnostics()) {
if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) {
newProgram = undefined;
oldState = undefined;
return oldProgram;
Expand Down
9 changes: 6 additions & 3 deletions src/compiler/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,12 @@ namespace ts {

function updateWatchCompilationHost(watchCompilerHost: WatchCompilerHost<EmitAndSemanticDiagnosticsBuilderProgram>) {
const compileUsingBuilder = watchCompilerHost.createProgram;
watchCompilerHost.createProgram = (rootNames, options, host, oldProgram) => {
enableStatistics(options);
return compileUsingBuilder(rootNames, options, host, oldProgram);
watchCompilerHost.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics) => {
Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram));
if (options !== undefined) {
enableStatistics(options);
}
return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics);
};
const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate;
watchCompilerHost.afterProgramCreate = builderProgram => {
Expand Down
18 changes: 11 additions & 7 deletions src/compiler/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,9 +625,19 @@ namespace ts {
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics);
hasChangedConfigFileParsingErrors = false;
}
return builderProgram;
}
else {
createNewProgram(program, hasInvalidatedResolution);
}

if (host.afterProgramCreate) {
host.afterProgramCreate(builderProgram);
}

return builderProgram;
}

function createNewProgram(program: Program, hasInvalidatedResolution: HasInvalidatedResolution) {
// Compile the program
if (watchLogLevel !== WatchLogLevel.None) {
writeLog("CreatingProgramWith::");
Expand Down Expand Up @@ -663,12 +673,6 @@ namespace ts {
}
missingFilePathsRequestedForRelease = undefined;
}

if (host.afterProgramCreate) {
host.afterProgramCreate(builderProgram);
}

return builderProgram;
}

function updateRootFileNames(files: string[]) {
Expand Down
22 changes: 22 additions & 0 deletions src/harness/unittests/tscWatchMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,28 @@ namespace ts.tscWatch {
checkProgramRootFiles(watch(), [commonFile1.path]);
});

it("works correctly when config file is changed but its content havent", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {},
"files": ["${commonFile1.path}", "${commonFile2.path}"]
}`
};
const files = [libFile, commonFile1, commonFile2, configFile];
const host = createWatchedSystem(files);
const watch = createWatchOfConfigFile(configFile.path, host);

checkProgramActualFiles(watch(), [libFile.path, commonFile1.path, commonFile2.path]);
checkOutputErrorsInitial(host, emptyArray);

host.modifyFile(configFile.path, configFile.content);
host.checkTimeoutQueueLengthAndRun(1); // reload the configured project

checkProgramActualFiles(watch(), [libFile.path, commonFile1.path, commonFile2.path]);
checkOutputErrorsIncremental(host, emptyArray);
});

it("files explicitly excluded in config file", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
Expand Down
40 changes: 25 additions & 15 deletions src/harness/virtualFileSystemWithWatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,21 +393,7 @@ interface Array<T> {}`
if (isString(fileOrDirectory.content)) {
// Update file
if (currentEntry.content !== fileOrDirectory.content) {
if (options && options.invokeFileDeleteCreateAsPartInsteadOfChange) {
this.removeFileOrFolder(currentEntry, returnFalse);
this.ensureFileOrFolder(fileOrDirectory);
}
else {
currentEntry.content = fileOrDirectory.content;
currentEntry.modifiedTime = this.now();
this.fs.get(getDirectoryPath(currentEntry.path)).modifiedTime = this.now();
if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) {
this.invokeDirectoryWatcher(getDirectoryPath(currentEntry.fullPath), currentEntry.fullPath);
}
else {
this.invokeFileWatcher(currentEntry.fullPath, FileWatcherEventKind.Changed);
}
}
this.modifyFile(fileOrDirectory.path, fileOrDirectory.content, options);
}
}
else {
Expand Down Expand Up @@ -446,6 +432,30 @@ interface Array<T> {}`
}
}

modifyFile(filePath: string, content: string, options?: Partial<ReloadWatchInvokeOptions>) {
const path = this.toFullPath(filePath);
const currentEntry = this.fs.get(path);
if (!currentEntry || !isFile(currentEntry)) {
throw new Error(`file not present: ${filePath}`);
}

if (options && options.invokeFileDeleteCreateAsPartInsteadOfChange) {
this.removeFileOrFolder(currentEntry, returnFalse);
this.ensureFileOrFolder({ path: filePath, content });
}
else {
currentEntry.content = content;
currentEntry.modifiedTime = this.now();
this.fs.get(getDirectoryPath(currentEntry.path)).modifiedTime = this.now();
if (options && options.invokeDirectoryWatcherInsteadOfFileChanged) {
this.invokeDirectoryWatcher(getDirectoryPath(currentEntry.fullPath), currentEntry.fullPath);
}
else {
this.invokeFileWatcher(currentEntry.fullPath, FileWatcherEventKind.Changed);
}
}
}

renameFolder(folderName: string, newFolderName: string) {
const fullPath = getNormalizedAbsolutePath(folderName, this.currentDirectory);
const path = this.toPath(fullPath);
Expand Down