Simplify the API for emitting and reporting exit statuses to callers.

This commit is contained in:
Cyrus Najmabadi
2015-02-05 15:50:18 -08:00
parent e7f6693eda
commit 66a363f449
42 changed files with 199 additions and 260 deletions

View File

@@ -1508,7 +1508,8 @@ module ts {
// @internal
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compilerOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult
{
var compilerOptions = host.getCompilerOptions();
var languageVersion = compilerOptions.target || ScriptTarget.ES3;
var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
@@ -1541,19 +1542,8 @@ module ts {
// Sort and make the unique list of diagnostics
diagnostics = sortAndDeduplicateDiagnostics(diagnostics);
// Update returnCode if there is any EmitterError
var hasEmitterError = forEach(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error);
// Check and update returnCode for syntactic and semantic
var emitResultStatus: EmitReturnStatus;
if (hasEmitterError) {
emitResultStatus = EmitReturnStatus.EmitErrorsEncountered;
} else {
emitResultStatus = EmitReturnStatus.Succeeded;
}
return {
emitResultStatus,
emitSkipped: false,
diagnostics,
sourceMaps: sourceMapDataList
};

View File

@@ -174,20 +174,20 @@ module ts {
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
// immediately bail out.
if (options.noEmitOnError && getPreEmitDiagnostics(this).length > 0) {
return { diagnostics: [], sourceMaps: undefined, emitResultStatus: EmitReturnStatus.DiagnosticsPresent_AllOutputsSkipped };
return { diagnostics: [], sourceMaps: undefined, emitSkipped: true };
}
var start = new Date().getTime();
var result = emitFiles(
var emitResult = emitFiles(
getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile),
getEmitHost(writeFileCallback),
sourceFile);
emitTime += new Date().getTime() - start;
return result;
return emitResult;
}
function getSourceFile(fileName: string) {
fileName = host.getCanonicalFileName(fileName);
return hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;

View File

@@ -165,7 +165,7 @@ module ts {
if (commandLine.options.locale) {
if (!isJSONSupported()) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
}
@@ -174,29 +174,29 @@ module ts {
// setting up localization, report them and quit.
if (commandLine.errors.length > 0) {
reportDiagnostics(commandLine.errors);
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (commandLine.options.version) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, version));
return sys.exit(EmitReturnStatus.Succeeded);
return sys.exit(ExitStatus.Success);
}
if (commandLine.options.help) {
printVersion();
printHelp();
return sys.exit(EmitReturnStatus.Succeeded);
return sys.exit(ExitStatus.Success);
}
if (commandLine.options.project) {
if (!isJSONSupported()) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
configFileName = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json"));
if (commandLine.fileNames.length !== 0) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
}
else if (commandLine.fileNames.length === 0 && isJSONSupported()) {
@@ -206,13 +206,13 @@ module ts {
if (commandLine.fileNames.length === 0 && !configFileName) {
printVersion();
printHelp();
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.Success);
}
if (commandLine.options.watch) {
if (!sys.watchFile) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (configFileName) {
configFileWatcher = sys.watchFile(configFileName, configFileChanged);
@@ -229,12 +229,12 @@ module ts {
var configObject = readConfigFile(configFileName);
if (!configObject) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0, configFileName));
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
var configParseResult = parseConfigFile(configObject, getDirectoryPath(configFileName));
if (configParseResult.errors.length > 0) {
reportDiagnostics(configParseResult.errors);
return sys.exit(EmitReturnStatus.CompilerOptionsErrors);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
rootFileNames = configParseResult.fileNames;
compilerOptions = extend(commandLine.options, configParseResult.options);
@@ -362,33 +362,46 @@ module ts {
return { program, exitStatus };
function compileProgram(): EmitReturnStatus {
function compileProgram(): ExitStatus {
// First get any syntactic errors.
var errors = program.getSyntacticDiagnostics();
reportDiagnostics(errors);
var diagnostics = program.getSyntacticDiagnostics();
reportDiagnostics(diagnostics);
// If we didn't have any syntactic errors, then also try getting the global and
// semantic errors.
if (errors.length === 0) {
var errors = program.getGlobalDiagnostics();
reportDiagnostics(errors);
if (diagnostics.length === 0) {
var diagnostics = program.getGlobalDiagnostics();
reportDiagnostics(diagnostics);
if (errors.length === 0) {
var errors = program.getSemanticDiagnostics();
reportDiagnostics(errors);
if (diagnostics.length === 0) {
var diagnostics = program.getSemanticDiagnostics();
reportDiagnostics(diagnostics);
}
}
// If the user doesn't want us to emit, then we're done at this point.
if (compilerOptions.noEmit) {
return EmitReturnStatus.Succeeded;
return diagnostics.length
? ExitStatus.DiagnosticsPresent_OutputsSkipped
: ExitStatus.Success;
}
// Otherwise, emit and report any errors we ran into.
var emitOutput = program.emit();
reportDiagnostics(emitOutput.diagnostics);
return emitOutput.emitResultStatus;
// If the emitter didn't emit anything, then pass that value along.
if (emitOutput.emitSkipped) {
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
}
// The emitter emitted something, inform the caller if that happened in the presence
// of diagnostics or not.
if (diagnostics.length > 0 || emitOutput.diagnostics.length > 0) {
ExitStatus.DiagnosticsPresent_OutputsGenerated;
}
return ExitStatus.Success;
}
}

View File

@@ -981,31 +981,21 @@ module ts {
}
// Return code used by getEmitOutput function to indicate status of the function
export enum EmitReturnStatus {
// All outputs generated if requested (.js, .map, .d.ts), no errors reported
Succeeded = 0,
export enum ExitStatus {
// Compiler ran successfully. Either this was a simple do-nothing compilation (for example,
// when -version or -help was provided, or this was a normal compilation, no diagnostics
// were produced, and all outputs were generated successfully.
Success = 0,
// No .js, .map or d.ts generated because of diagnostics and the presence of the
// -noEmitOnError optoin.
DiagnosticsPresent_AllOutputsSkipped = 1,
// Diagnostics were produced and because of them no code was generated.
DiagnosticsPresent_OutputsSkipped = 1,
// .js and .map generated. However, diagnostics were generated as well.
// No .d.ts was requested or generated.
DiagnosticsPresent_JavaScriptGenerated = 2,
// .js, .map generated. .d.ts was requested but was not generated due to the
// presence of diagnostics.
DiagnosticsPresent_JavaScriptGenerated_DeclarationNotGenerated = 3,
// Emitter errors occurred during emitting process.
EmitErrorsEncountered = 4,
// Errors occurred in parsing compiler options, nothing generated
CompilerOptionsErrors = 5,
// Diagnostics were produced and outputs were generated in spite of them.
DiagnosticsPresent_OutputsGenerated = 2,
}
export interface EmitResult {
emitResultStatus: EmitReturnStatus;
emitSkipped: boolean;
diagnostics: Diagnostic[];
sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}

View File

@@ -1140,11 +1140,10 @@ module FourSlash {
// Loop through all the emittedFiles and emit them one by one
emitFiles.forEach(emitFile => {
var emitOutput = this.languageService.getEmitOutput(emitFile.fileName);
var emitOutputStatus = emitOutput.emitOutputStatus;
// Print emitOutputStatus in readable format
resultString += "EmitOutputStatus : " + ts.EmitReturnStatus[emitOutputStatus] + ts.sys.newLine;
resultString += "EmitSkipped: " + emitOutput.emitSkipped + ts.sys.newLine;
if (emitOutputStatus !== ts.EmitReturnStatus.Succeeded) {
if (emitOutput.emitSkipped) {
resultString += "Diagnostics:" + ts.sys.newLine;
var diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram());
for (var i = 0, n = diagnostics.length; i < n; i++) {

View File

@@ -1122,7 +1122,7 @@ module ts {
export interface EmitOutput {
outputFiles: OutputFile[];
emitOutputStatus: EmitReturnStatus;
emitSkipped: boolean;
}
export const enum OutputFileType {
@@ -4664,7 +4664,7 @@ module ts {
return {
outputFiles,
emitOutputStatus: emitOutput.emitResultStatus
emitSkipped: emitOutput.emitSkipped
};
}