Remove lib file errors when all files are to be emitted.

Fixes #26389
This commit is contained in:
Sheetal Nandi 2018-11-09 12:23:54 -08:00
parent 93206993ed
commit a27b29f025
2 changed files with 144 additions and 1 deletions

View file

@ -38,6 +38,10 @@ namespace ts {
* Already seen affected files
*/
seenAffectedFiles: Map<true> | undefined;
/**
* program corresponding to this state
*/
cleanedDiagnosticsOfLibFiles?: boolean;
/**
* True if the semantic diagnostics were copied from the old state
*/
@ -83,6 +87,8 @@ namespace ts {
// Update changed files and copy semantic diagnostics if we can
const referencedMap = state.referencedMap;
const oldReferencedMap = useOldState ? oldState!.referencedMap : undefined;
const copyDeclarationFileDiagnostics = canCopySemanticDiagnostics && !compilerOptions.skipLibCheck === !oldState!.program.getCompilerOptions().skipLibCheck;
const copyLibFileDiagnostics = copyDeclarationFileDiagnostics && !compilerOptions.skipDefaultLibCheck === !oldState!.program.getCompilerOptions().skipDefaultLibCheck;
state.fileInfos.forEach((info, sourceFilePath) => {
let oldInfo: Readonly<BuilderState.FileInfo> | undefined;
let newReferences: BuilderState.ReferencedSet | undefined;
@ -101,6 +107,11 @@ namespace ts {
state.changedFilesSet.set(sourceFilePath, true);
}
else if (canCopySemanticDiagnostics) {
const sourceFile = state.program.getSourceFileByPath(sourceFilePath as Path)!;
if (sourceFile.isDeclarationFile && !copyDeclarationFileDiagnostics) { return; }
if (sourceFile.hasNoDefaultLib && !copyLibFileDiagnostics) { return; }
// Unchanged file copy diagnostics
const diagnostics = oldState!.semanticDiagnosticsPerFile!.get(sourceFilePath);
if (diagnostics) {
@ -193,6 +204,19 @@ namespace ts {
return;
}
// Clean lib file diagnostics if its all files excluding default files to emit
if (state.allFilesExcludingDefaultLibraryFile === state.affectedFiles && !state.cleanedDiagnosticsOfLibFiles) {
state.cleanedDiagnosticsOfLibFiles = true;
const options = state.program.getCompilerOptions();
if (forEach(state.program.getSourceFiles(), f =>
!contains(state.allFilesExcludingDefaultLibraryFile, f) &&
!skipTypeChecking(f, options) &&
removeSemanticDiagnosticsOf(state, f.path)
)) {
return;
}
}
// If there was change in signature for the changed file,
// then delete the semantic diagnostics for files that are affected by using exports of this module
@ -268,7 +292,7 @@ namespace ts {
*/
function removeSemanticDiagnosticsOf(state: BuilderProgramState, path: Path) {
if (!state.semanticDiagnosticsFromOldState) {
return false;
return true;
}
state.semanticDiagnosticsFromOldState.delete(path);
state.semanticDiagnosticsPerFile!.delete(path);

View file

@ -1564,6 +1564,125 @@ export class Data2 {
verifyTransitiveExports([libFile, app, lib2Public, lib2Data, lib2Data2, lib1Public, lib1ToolsPublic, lib1ToolsInterface]);
});
});
describe("updates errors in lib file when non module file changes", () => {
const currentDirectory = "/user/username/projects/myproject";
const field = "fullscreen";
const aFile: File = {
path: `${currentDirectory}/a.ts`,
content: `interface Document {
${field}: boolean;
}`
};
const libFileWithDocument: File = {
path: libFile.path,
content: `${libFile.content}
interface Document {
readonly ${field}: boolean;
}`
};
function getDiagnostic(program: Program, file: File) {
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 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);
host.runQueuedTimeoutCallbacks();
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
checkOutputErrorsIncremental(host, getErrors());
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("when skipLibCheck and skipDefaultLibCheck changes", () => {
const currentDirectory = "/user/username/projects/myproject";
const field = "fullscreen";
const aFile: File = {
path: `${currentDirectory}/a.ts`,
content: `interface Document {
${field}: boolean;
}`
};
const bFile: File = {
path: `${currentDirectory}/b.d.ts`,
content: `interface Document {
${field}: boolean;
}`
};
const libFileWithDocument: File = {
path: libFile.path,
content: `${libFile.content}
interface Document {
readonly ${field}: boolean;
}`
};
const configFile: File = {
path: `${currentDirectory}/tsconfig.json`,
content: "{}"
};
const files = [aFile, bFile, configFile, libFileWithDocument];
const host = createWatchedSystem(files, { currentDirectory });
const watch = createWatchOfConfigFile("tsconfig.json", host);
verifyProgramFiles();
checkOutputErrorsInitial(host, [
getDiagnostic(libFileWithDocument),
getDiagnostic(aFile),
getDiagnostic(bFile)
]);
verifyConfigChange({ skipLibCheck: true }, [aFile]);
verifyConfigChange({ skipDefaultLibCheck: true }, [aFile, bFile]);
verifyConfigChange({}, [libFileWithDocument, aFile, bFile]);
verifyConfigChange({ skipDefaultLibCheck: true }, [aFile, bFile]);
verifyConfigChange({ skipLibCheck: true }, [aFile]);
verifyConfigChange({}, [libFileWithDocument, aFile, bFile]);
function verifyConfigChange(compilerOptions: CompilerOptions, errorInFiles: ReadonlyArray<File>) {
host.writeFile(configFile.path, JSON.stringify({ compilerOptions }));
host.runQueuedTimeoutCallbacks();
verifyProgramFiles();
checkOutputErrorsIncremental(host, errorInFiles.map(getDiagnostic));
}
function getDiagnostic(file: File) {
return getDiagnosticOfFileFromProgram(watch(), file.path, file.content.indexOf(field), field.length, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, field);
}
function verifyProgramFiles() {
checkProgramActualFiles(watch(), [aFile.path, bFile.path, libFile.path]);
}
});
});
describe("tsc-watch emit with outFile or out setting", () => {