Move checking semantic diagnostics into emitFiles function rather than

getEmitOutput
This commit is contained in:
Yui T
2014-09-10 09:57:26 -07:00
parent 537f55cede
commit 6ef41a74c7
6 changed files with 67 additions and 47 deletions
+6
View File
@@ -7181,6 +7181,11 @@ module ts {
return target !== unknownSymbol && ((target.flags & SymbolFlags.Value) !== 0);
}
function hasSemanticErrors() {
// Return true if there is any semantic error in a file or globally
return (getDiagnostics().length > 0) || (getGlobalDiagnostics().length > 0);
}
function shouldEmitDeclarations() {
// If the declaration emit and there are no errors being reported in program or by checker
// declarations can be emitted
@@ -7258,6 +7263,7 @@ module ts {
getNodeCheckFlags: getNodeCheckFlags,
getEnumMemberValue: getEnumMemberValue,
isTopLevelValueImportedViaEntityName: isTopLevelValueImportedViaEntityName,
hasSemanticErrors: hasSemanticErrors,
shouldEmitDeclarations: shouldEmitDeclarations,
isDeclarationVisible: isDeclarationVisible,
isImplementationOfOverload: isImplementationOfOverload,
+22 -2
View File
@@ -48,8 +48,8 @@ module ts {
}
function getOwnEmitOutputFilePath(sourceFile: SourceFile, extension: string) {
if (program.getCompilerOptions().outDir) {
var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(getSourceFilePathInNewDir(program.getCompilerOptions().outDir, sourceFile));
if (compilerOptions.outDir) {
var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(getSourceFilePathInNewDir(compilerOptions.outDir, sourceFile));
}
else {
var emitOutputFilePathWithoutExtension = getModuleNameFromFilename(sourceFile.filename);
@@ -3183,7 +3183,27 @@ module ts {
diagnostics.sort(compareDiagnostics);
diagnostics = deduplicateSortedDiagnostics(diagnostics);
var returnCode = EmitReturnStatus.Succeeded;
// Check if there is any diagnostic in an error category; if so, there is an emitter error
var hasEmitterError = forEach(diagnostics, diagnostic => diagnostic.category === DiagnosticCategory.Error);
if (resolver.hasSemanticErrors() && !compilerOptions.declaration) {
// There is an semantic errror when output javascript file
// Output JS file with semantic error
returnCode = EmitReturnStatus.JSGeneratedWithSemanticErrors;
}
else if (resolver.hasSemanticErrors() && compilerOptions.declaration) {
// There is an semantic errror when output javascript and declaration file
// Output JS file with semantic error, not output declaration file
returnCode = EmitReturnStatus.DeclarationGenerationSkipped;
}
else if (hasEmitterError) {
returnCode = EmitReturnStatus.EmitErrorsEncountered;
}
return {
emitResultStatus: returnCode,
errors: diagnostics,
sourceMaps: sourceMapDataList
};
+11
View File
@@ -588,7 +588,17 @@ module ts {
sourceMapDecodedMappings: SourceMapSpan[];
}
// Return code used by getEmitOutput function to indicate status of the function
export enum EmitReturnStatus {
Succeeded = 0, // All outputs generated as requested (.js, .map, .d.ts), no errors reported
AllOutputGenerationSkipped = 1, // No .js generated because of syntax errors, or compiler options errors, nothing generated
JSGeneratedWithSemanticErrors = 2, // .js and .map generated with semantic errors
DeclarationGenerationSkipped = 3, // .d.ts generation skipped because of semantic errors or declaration emitter specific errors; Output .js with semantic errors
EmitErrorsEncountered = 4 // Emitter errors occured during emitting process
}
export interface EmitResult {
emitResultStatus: EmitReturnStatus;
errors: Diagnostic[];
sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}
@@ -660,6 +670,7 @@ module ts {
isTopLevelValueImportedViaEntityName(node: ImportDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
getEnumMemberValue(node: EnumMember): number;
hasSemanticErrors(): boolean;
shouldEmitDeclarations(): boolean;
isDeclarationVisible(node: Declaration): boolean;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
+3 -3
View File
@@ -458,7 +458,7 @@ module FourSlash {
}
}
public verifyEmitOutput(state: ts.EmitOutputResult, filename?: string) {
public verifyEmitOutput(state: ts.EmitReturnStatus, filename?: string) {
if (this.enableDeclaration) {
this.languageServiceShimHost.setCompilationSettings({ generateDeclarationFiles: true });
}
@@ -474,8 +474,8 @@ module FourSlash {
var emit = this.languageService.getEmitOutput(this.activeFile.fileName);
if (emit.emitOutputResult !== state) {
throw new Error("Expected emitOutputResult '" + state + "', but actual emitOutputResult '" + emit.emitOutputResult + "'");
if (emit.emitOutputStatus !== state) {
throw new Error("Expected emitOutputResult '" + state + "', but actual emitOutputResult '" + emit.emitOutputStatus + "'");
}
var passed = true;
+15 -35
View File
@@ -663,16 +663,9 @@ module ts {
docComment: string;
}
export enum EmitOutputResult {
Succeeded,
FailedBecauseOfSyntaxErrors,
FailedBecauseOfCompilerOptionsErrors,
FailedToGenerateDeclarationsBecauseOfSemanticErrors
}
export interface EmitOutput {
outputFiles: OutputFile[];
emitOutputResult: EmitOutputResult;
emitOutputStatus: EmitReturnStatus;
}
export enum OutputFileType {
@@ -2846,56 +2839,43 @@ module ts {
function getEmitOutput(filename: string): EmitOutput {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
var sourceFile = getSourceFile(filename);
var sourceFile = program.getSourceFile(filename);
var compilerOptions = program.getCompilerOptions();
var emitToSingleFile = ts.shouldEmitToOwnFile(program.getSourceFile(filename), compilerOptions);
var emitToSingleFile = ts.shouldEmitToOwnFile(sourceFile, compilerOptions);
var emitDeclaration = compilerOptions.declaration;
var emitResult: EmitOutput = {
var emitOutput: EmitOutput = {
outputFiles: [],
emitOutputResult: undefined,
emitOutputStatus: undefined,
};
// Initialize writer for CompilerHost.writeFile
writer = function (fileName: string, data: string, writeByteOrderMark: boolean) {
var outputFile: OutputFile = {
emitOutput.outputFiles.push({
name: fileName,
writeByteOrderMark: writeByteOrderMark,
text: data
}
emitResult.outputFiles.push(outputFile);
});
}
var syntacticDiagnostics = emitToSingleFile
? program.getDiagnostics(sourceFile)
: program.getDiagnostics();
program.getGlobalDiagnostics();
var globalSyntacticDiagnostics = program.getGlobalDiagnostics();
// If there is any syntactic error, terminate the process
if (containErrors(syntacticDiagnostics)) {
emitResult.emitOutputResult = EmitOutputResult.FailedBecauseOfSyntaxErrors;
return emitResult;
emitOutput.emitOutputStatus = EmitReturnStatus.AllOutputGenerationSkipped;
return emitOutput;
}
// Perform semantic and force a type check before emit to ensure that all symbols are updated
var semanticDiagnostics = emitToSingleFile
? getFullTypeCheckChecker().getDiagnostics(getSourceFile(filename).getSourceFile())
: getFullTypeCheckChecker().getDiagnostics();
getFullTypeCheckChecker().getGlobalDiagnostics();
var emitOutput = getFullTypeCheckChecker().emitFiles();
// EmitFiles will report if there is an error from TypeChecker and Emitter
var emitFilesResult = getFullTypeCheckChecker().emitFiles();
emitOutput.emitOutputStatus = emitFilesResult.emitResultStatus;
if (emitDeclaration && containErrors(semanticDiagnostics)) {
emitResult.emitOutputResult = EmitOutputResult.FailedToGenerateDeclarationsBecauseOfSemanticErrors;
}
else if (emitDeclaration && containErrors(emitOutput.errors)) {
emitResult.emitOutputResult = EmitOutputResult.FailedToGenerateDeclarationsBecauseOfSemanticErrors;
}
else {
emitResult.emitOutputResult = EmitOutputResult.Succeeded;
}
// Reset writer back to underfined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in an emitting stage
// Reset writer back to underfined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in getEmitOutput
this.writer = undefined;
return emitResult;
return emitOutput;
}
/// Syntactic features
+10 -7
View File
@@ -44,14 +44,17 @@ enum TypingFidelity {
High = FourSlash.TypingFidelity.High
}
// We have to duplicate EmitOutputResult from Services.ts to expose the enum to getEmitOutput testcases in fourslah
enum EmitOutputResult {
Succeeded,
FailedBecauseOfSyntaxErrors,
FailedBecauseOfCompilerOptionsErrors,
FailedToGenerateDeclarationsBecauseOfSemanticErrors
// Return code used by getEmitOutput function to indicate status of the function
// It is a duplicate of the one in types.ts to expose it to testcases in fourslash
enum EmitReturnStatus {
Succeeded = 0, // All outputs generated as requested (.js, .map, .d.ts), no errors reported
AllOutputGenerationSkipped = 1, // No .js generated because of syntax errors, or compiler options errors, nothing generated
JSGeneratedWithSemanticErrors = 2, // .js and .map generated with semantic errors
DeclarationGenerationSkipped = 3, // .d.ts generation skipped because of semantic errors or declaration emitter specific errors; Output .js with semantic errors
EmitErrorsEncountered = 4 // Emitter errors occured during emitting process
}
module FourSlashInterface {
declare var FourSlash;
@@ -263,7 +266,7 @@ module FourSlashInterface {
FourSlash.currentTestState.verifyEval(expr, value);
}
public emitOutput(expectedState: EmitOutputResult, expectedFilename?: string) {
public emitOutput(expectedState: EmitReturnStatus, expectedFilename?: string) {
FourSlash.currentTestState.verifyEmitOutput(expectedState, expectedFilename);
}