Handle global augmentation in the module

This commit is contained in:
Sheetal Nandi
2018-11-09 16:41:18 -08:00
parent 43c447867b
commit 941d97c45a
2 changed files with 71 additions and 34 deletions

View File

@@ -368,7 +368,7 @@ namespace ts.BuilderState {
}
// If this is non module emit, or its a global file, it depends on all the source files
if (!state.referencedMap || (!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile))) {
if (!state.referencedMap || isFileAffectingGlobalScope(sourceFile)) {
return getAllFileNames(state, programOfThisState);
}
@@ -430,6 +430,22 @@ namespace ts.BuilderState {
return true;
}
/**
* Return true if file contains anything that augments to global scope we need to build them as if
* they are global files as well as module
*/
function containsGlobalScopeAugmentation(sourceFile: SourceFile) {
return some(sourceFile.moduleAugmentations, augmentation => isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration));
}
/**
* Return true if the file will invalidate all files because it affectes global scope
*/
function isFileAffectingGlobalScope(sourceFile: SourceFile) {
return containsGlobalScopeAugmentation(sourceFile) ||
!isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile);
}
/**
* Gets all files of the program excluding the default library file
*/
@@ -473,7 +489,7 @@ namespace ts.BuilderState {
* When program emits modular code, gets the files affected by the sourceFile whose shape has changed
*/
function getFilesAffectedByUpdatedShapeWhenModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile, cacheToUpdateSignature: Map<string>, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash | undefined, exportedModulesMapCache: ComputingExportedModulesMap | undefined) {
if (!isExternalModule(sourceFileWithUpdatedShape) && !containsOnlyAmbientModules(sourceFileWithUpdatedShape)) {
if (isFileAffectingGlobalScope(sourceFileWithUpdatedShape)) {
return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape);
}

View File

@@ -1565,15 +1565,13 @@ export class Data2 {
});
});
describe("updates errors in lib file when non module file changes", () => {
describe("updates errors in lib file", () => {
const currentDirectory = "/user/username/projects/myproject";
const field = "fullscreen";
const aFile: File = {
path: `${currentDirectory}/a.ts`,
content: `interface Document {
const fieldWithoutReadonly = `interface Document {
${field}: boolean;
}`
};
}`;
const libFileWithDocument: File = {
path: libFile.path,
content: `${libFile.content}
@@ -1586,40 +1584,63 @@ interface Document {
return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(field), field.length, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, field);
}
const files = [aFile, libFileWithDocument];
function verifyLibFileErrorsWith(aFile: File) {
const files = [aFile, libFileWithDocument];
function verifyLibErrors(options: CompilerOptions) {
const host = createWatchedSystem(files, { currentDirectory });
const watch = createWatchOfFilesAndCompilerOptions([aFile.path], host, options);
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsInitial(host, getErrors());
function verifyLibErrors(options: CompilerOptions) {
const host = createWatchedSystem(files, { currentDirectory });
const watch = createWatchOfFilesAndCompilerOptions([aFile.path], host, options);
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsInitial(host, getErrors());
host.writeFile(aFile.path, "var x = 10;");
host.runQueuedTimeoutCallbacks();
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsIncremental(host, emptyArray);
host.writeFile(aFile.path, aFile.content.replace(fieldWithoutReadonly, "var x: string;"));
host.runQueuedTimeoutCallbacks();
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsIncremental(host, emptyArray);
host.writeFile(aFile.path, aFile.content);
host.runQueuedTimeoutCallbacks();
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsIncremental(host, getErrors());
host.writeFile(aFile.path, aFile.content);
host.runQueuedTimeoutCallbacks();
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsIncremental(host, getErrors());
function getErrors() {
return [
...(options.skipLibCheck || options.skipDefaultLibCheck ? [] : [getDiagnostic(watch(), libFileWithDocument)]),
getDiagnostic(watch(), aFile)
];
function getErrors() {
return [
...(options.skipLibCheck || options.skipDefaultLibCheck ? [] : [getDiagnostic(watch(), libFileWithDocument)]),
getDiagnostic(watch(), aFile)
];
}
}
it("with default options", () => {
verifyLibErrors({});
});
it("with skipLibCheck", () => {
verifyLibErrors({ skipLibCheck: true });
});
it("with skipDefaultLibCheck", () => {
verifyLibErrors({ skipDefaultLibCheck: true });
});
}
it("with default options", () => {
verifyLibErrors({});
describe("when non module file changes", () => {
const aFile: File = {
path: `${currentDirectory}/a.ts`,
content: `${fieldWithoutReadonly}
var y: number;`
};
verifyLibFileErrorsWith(aFile);
});
it("with skipLibCheck", () => {
verifyLibErrors({ skipLibCheck: true });
});
it("with skipDefaultLibCheck", () => {
verifyLibErrors({ skipDefaultLibCheck: true });
describe("when module file with global definitions changes", () => {
const aFile: File = {
path: `${currentDirectory}/a.ts`,
content: `export {}
declare global {
${fieldWithoutReadonly}
var y: number;
}`
};
verifyLibFileErrorsWith(aFile);
});
});