Ensure getEmitOutput only check the file requested

This commit is contained in:
Mohamed Hegazy 2014-12-01 23:15:13 -08:00
parent af324d1226
commit 08165c0b17
16 changed files with 142 additions and 69 deletions

View file

@ -85,7 +85,6 @@ module ts {
getDiagnostics,
getDeclarationDiagnostics,
getGlobalDiagnostics,
checkProgram,
getParentOfSymbol,
getNarrowedTypeOfSymbol,
getDeclaredTypeOfSymbol,
@ -8634,10 +8633,6 @@ module ts {
}
}
function checkProgram() {
forEach(program.getSourceFiles(), checkSourceFile);
}
function getSortedDiagnostics(): Diagnostic[]{
Debug.assert(fullTypeCheck, "diagnostics are available only in the full typecheck mode");
@ -8650,12 +8645,11 @@ module ts {
}
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[]{
if (sourceFile) {
checkSourceFile(sourceFile);
return filter(getSortedDiagnostics(), d => d.file === sourceFile);
}
checkProgram();
forEach(program.getSourceFiles(), checkSourceFile);
return getSortedDiagnostics();
}
@ -9173,9 +9167,9 @@ module ts {
return isImportResolvedToValue(getSymbolOfNode(node));
}
function hasSemanticErrors() {
function hasSemanticErrors(sourceFile?: SourceFile) {
// Return true if there is any semantic error in a file or globally
return getDiagnostics().length > 0 || getGlobalDiagnostics().length > 0;
return getDiagnostics(sourceFile).length > 0 || getGlobalDiagnostics().length > 0;
}
function isEmitBlocked(sourceFile?: SourceFile): boolean {
@ -9293,7 +9287,6 @@ module ts {
function invokeEmitter(targetSourceFile?: SourceFile) {
var resolver = createResolver();
checkProgram();
return emitFiles(resolver, targetSourceFile);
}

View file

@ -3791,20 +3791,14 @@ module ts {
}
}
var hasSemanticErrors = resolver.hasSemanticErrors();
var isEmitBlocked = resolver.isEmitBlocked(targetSourceFile);
function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
if (!isEmitBlocked) {
emitJavaScript(jsFilePath, sourceFile);
if (!hasSemanticErrors && compilerOptions.declaration) {
writeDeclarationFile(jsFilePath, sourceFile);
}
}
}
var hasSemanticErrors: boolean = false;
var isEmitBlocked: boolean = false;
if (targetSourceFile === undefined) {
// No targetSourceFile is specified (e.g. calling emitter from batch compiler)
hasSemanticErrors = resolver.hasSemanticErrors();
isEmitBlocked = resolver.isEmitBlocked();
forEach(program.getSourceFiles(), sourceFile => {
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
var jsFilePath = getOwnEmitOutputFilePath(sourceFile, program, ".js");
@ -3820,16 +3814,35 @@ module ts {
// targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service)
if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
// If shouldEmitToOwnFile returns true or targetSourceFile is an external module file, then emit targetSourceFile in its own output file
hasSemanticErrors = resolver.hasSemanticErrors(targetSourceFile);
isEmitBlocked = resolver.isEmitBlocked(targetSourceFile);
var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, program, ".js");
emitFile(jsFilePath, targetSourceFile);
}
else if (!isDeclarationFile(targetSourceFile) && compilerOptions.out) {
// Otherwise, if --out is specified and targetSourceFile is not a declaration file,
// Emit all, non-external-module file, into one single output file
forEach(program.getSourceFiles(), sourceFile => {
if (!shouldEmitToOwnFile(sourceFile, compilerOptions)) {
hasSemanticErrors = hasSemanticErrors || resolver.hasSemanticErrors(sourceFile);
isEmitBlocked = isEmitBlocked || resolver.isEmitBlocked(sourceFile);
}
});
emitFile(compilerOptions.out);
}
}
function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
if (!isEmitBlocked) {
emitJavaScript(jsFilePath, sourceFile);
if (!hasSemanticErrors && compilerOptions.declaration) {
writeDeclarationFile(jsFilePath, sourceFile);
}
}
}
// Sort and make the unique list of diagnostics
diagnostics.sort(compareDiagnostics);
diagnostics = deduplicateSortedDiagnostics(diagnostics);

View file

@ -861,7 +861,6 @@ module ts {
getIdentifierCount(): number;
getSymbolCount(): number;
getTypeCount(): number;
checkProgram(): void;
emitFiles(targetSourceFile?: SourceFile): EmitResult;
getParentOfSymbol(symbol: Symbol): Symbol;
getNarrowedTypeOfSymbol(symbol: Symbol, node: Node): Type;
@ -973,7 +972,7 @@ module ts {
isTopLevelValueImportWithEntityName(node: ImportDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
getEnumMemberValue(node: EnumMember): number;
hasSemanticErrors(): boolean;
hasSemanticErrors(sourceFile?: SourceFile): boolean;
isDeclarationVisible(node: Declaration): boolean;
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableOrParameterDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;

View file

@ -2217,11 +2217,10 @@ module FourSlash {
// TODO (drosen): We need to enforce checking on these tests.
var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true }, host);
var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true);
checker.checkProgram();
var errs = program.getDiagnostics().concat(checker.getDiagnostics());
if (errs.length > 0) {
throw new Error('Error compiling ' + fileName + ': ' + errs.map(e => e.messageText).join('\r\n'));
var errors = program.getDiagnostics().concat(checker.getDiagnostics());
if (errors.length > 0) {
throw new Error('Error compiling ' + fileName + ': ' + errors.map(e => e.messageText).join('\r\n'));
}
checker.emitFiles();
result = result || ''; // Might have an empty fourslash file

View file

@ -801,7 +801,6 @@ module Harness {
useCaseSensitiveFileNames));
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
checker.checkProgram();
var isEmitBlocked = checker.isEmitBlocked();

View file

@ -4665,18 +4665,14 @@ module ts {
function getEmitOutput(filename: string): EmitOutput {
synchronizeHostData();
filename = normalizeSlashes(filename);
var compilerOptions = program.getCompilerOptions();
var targetSourceFile = program.getSourceFile(filename); // Current selected file to be output
// If --out flag is not specified, shouldEmitToOwnFile is true. Otherwise shouldEmitToOwnFile is false.
var shouldEmitToOwnFile = ts.shouldEmitToOwnFile(targetSourceFile, compilerOptions);
var emitOutput: EmitOutput = {
outputFiles: [],
emitOutputStatus: undefined,
};
var sourceFile = getSourceFile(filename);
var outputFiles: OutputFile[] = [];
function getEmitOutputWriter(filename: string, data: string, writeByteOrderMark: boolean) {
emitOutput.outputFiles.push({
outputFiles.push({
name: filename,
writeByteOrderMark: writeByteOrderMark,
text: data
@ -4686,41 +4682,15 @@ module ts {
// Initialize writer for CompilerHost.writeFile
writer = getEmitOutputWriter;
var containSyntacticErrors = false;
if (shouldEmitToOwnFile) {
// Check only the file we want to emit
containSyntacticErrors = containErrors(program.getDiagnostics(targetSourceFile));
} else {
// Check the syntactic of only sourceFiles that will get emitted into single output
// Terminate the process immediately if we encounter a syntax error from one of the sourceFiles
containSyntacticErrors = forEach(program.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
// If emit to a single file then we will check all files that do not have external module
return containErrors(program.getDiagnostics(sourceFile));
}
return false;
});
}
if (containSyntacticErrors) {
// If there is a syntax error, terminate the process and report outputStatus
emitOutput.emitOutputStatus = EmitReturnStatus.AllOutputGenerationSkipped;
// Reset writer back to undefined to make sure that we produce an error message
// if CompilerHost.writeFile is called when we are not in getEmitOutput
writer = undefined;
return emitOutput;
}
// Perform semantic and force a type check before emit to ensure that all symbols are updated
// EmitFiles will report if there is an error from TypeChecker and Emitter
// Depend whether we will have to emit into a single file or not either emit only selected file in the project, emit all files into a single file
var emitFilesResult = getFullTypeCheckChecker().emitFiles(targetSourceFile);
emitOutput.emitOutputStatus = emitFilesResult.emitResultStatus;
var emitOutput = getFullTypeCheckChecker().emitFiles(sourceFile);
// Reset writer back to undefined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in getEmitOutput
writer = undefined;
return emitOutput;
return {
outputFiles,
emitOutputStatus: emitOutput.emitResultStatus
};
}
function getMeaningFromDeclaration(node: Node): SemanticMeaning {

View file

@ -0,0 +1,2 @@
EmitOutputStatus : AllOutputGenerationSkipped

View file

@ -0,0 +1,8 @@
EmitOutputStatus : Succeeded
Filename : tests/cases/fourslash/inputFile1.js
// File to emit, does not contain semantic errors
// expected to be emitted correctelly regardless of the semantic errors in the other file
var noErrors = true;
Filename : tests/cases/fourslash/inputFile1.d.ts
declare var noErrors: boolean;

View file

@ -0,0 +1,8 @@
EmitOutputStatus : DeclarationGenerationSkipped
Filename : out.js
// File to emit, does not contain semantic errors, but --out is passed
// expected to not generate declarations because of the semantic errors in the other file
var noErrors = true;
// File not emitted, and contains semantic errors
var semanticError = "string";

View file

@ -0,0 +1,6 @@
EmitOutputStatus : Succeeded
Filename : tests/cases/fourslash/inputFile1.js
// File to emit, does not contain syntactic errors
// expected to be emitted correctelly regardless of the syntactic errors in the other file
var noErrors = true;

View file

@ -0,0 +1,2 @@
EmitOutputStatus : AllOutputGenerationSkipped

View file

@ -0,0 +1,10 @@
/// <reference path="fourslash.ts" />
// @BaselineFile: getEmitOutputWithEarlySyntacticErrors.baseline
// @Filename: inputFile1.ts
// @emitThisFile: true
//// // File contains early errors. All outputs should be skipped.
//// const uninitialized_const_error;
verify.baselineGetEmitOutput();

View file

@ -0,0 +1,16 @@
/// <reference path="fourslash.ts" />
// @BaselineFile: getEmitOutputWithSemanticErrorsForMultipleFiles.baseline
// @declaration: true
// @Filename: inputFile1.ts
// @emitThisFile: true
//// // File to emit, does not contain semantic errors
//// // expected to be emitted correctelly regardless of the semantic errors in the other file
//// var noErrors = true;
// @Filename: inputFile2.ts
//// // File not emitted, and contains semantic errors
//// var semanticError: boolean = "string";
verify.baselineGetEmitOutput();

View file

@ -0,0 +1,17 @@
/// <reference path="fourslash.ts" />
// @BaselineFile: getEmitOutputWithSemanticErrorsForMultipleFiles2.baseline
// @declaration: true
// @out: out.js
// @Filename: inputFile1.ts
// @emitThisFile: true
//// // File to emit, does not contain semantic errors, but --out is passed
//// // expected to not generate declarations because of the semantic errors in the other file
//// var noErrors = true;
// @Filename: inputFile2.ts
//// // File not emitted, and contains semantic errors
//// var semanticError: boolean = "string";
verify.baselineGetEmitOutput();

View file

@ -0,0 +1,15 @@
/// <reference path="fourslash.ts" />
// @BaselineFile: getEmitOutputWithSyntacticErrorsForMultipleFiles.baseline
// @Filename: inputFile1.ts
// @emitThisFile: true
//// // File to emit, does not contain syntactic errors
//// // expected to be emitted correctelly regardless of the syntactic errors in the other file
//// var noErrors = true;
// @Filename: inputFile2.ts
//// // File not emitted, and contains syntactic errors
//// var syntactic Error;
verify.baselineGetEmitOutput();

View file

@ -0,0 +1,16 @@
/// <reference path="fourslash.ts" />
// @BaselineFile: getEmitOutputWithSyntacticErrorsForMultipleFiles2.baseline
// @out: out.js
// @Filename: inputFile1.ts
// @emitThisFile: true
//// // File to emit, does not contain syntactic errors, but --out is passed
//// // expected to not generate outputs because of the syntactic errors in the other file.
//// var noErrors = true;
// @Filename: inputFile2.ts
//// // File not emitted, and contains syntactic errors
//// var syntactic Error;
verify.baselineGetEmitOutput();