Merge pull request #23753 from Microsoft/emptyOptions

Handle the test case when tsconfig file changes without needing to update the program
This commit is contained in:
Sheetal Nandi 2018-04-30 10:42:14 -07:00 committed by GitHub
commit 33ba2509a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 26 deletions

View File

@ -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;

View File

@ -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 => {

View File

@ -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::");
@ -663,12 +673,6 @@ namespace ts {
}
missingFilePathsRequestedForRelease = undefined;
}
if (host.afterProgramCreate) {
host.afterProgramCreate(builderProgram);
}
return builderProgram;
}
function updateRootFileNames(files: string[]) {

View File

@ -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",

View File

@ -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 {
@ -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);