diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 7b20fb8e216..d349a9b626d 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -313,8 +313,7 @@ module ts {
}
function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
- var compilerHost = host.getCompilerHost();
- var sourceFilePath = getNormalizedAbsolutePath(sourceFile.filename, compilerHost.getCurrentDirectory());
+ var sourceFilePath = getNormalizedAbsolutePath(sourceFile.filename, host.getCurrentDirectory());
sourceFilePath = sourceFilePath.replace(host.getCommonSourceDirectory(), "");
return combinePaths(newDirPath, sourceFilePath);
}
@@ -331,16 +330,15 @@ module ts {
return emitOutputFilePathWithoutExtension + extension;
}
- function writeFile(compilerHost: CompilerHost, diagnostics: Diagnostic[], filename: string, data: string, writeByteOrderMark: boolean) {
- compilerHost.writeFile(filename, data, writeByteOrderMark, hostErrorMessage => {
+ function writeFile(host: EmitHost, diagnostics: Diagnostic[], filename: string, data: string, writeByteOrderMark: boolean) {
+ host.writeFile(filename, data, writeByteOrderMark, hostErrorMessage => {
diagnostics.push(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, filename, hostErrorMessage));
});
}
function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit {
- var newLine = host.getCompilerHost().getNewLine();
+ var newLine = host.getNewLine();
var compilerOptions = host.getCompilerOptions();
- var compilerHost = host.getCompilerHost();
var write: (s: string) => void;
var writeLine: () => void;
@@ -1402,8 +1400,8 @@ module ts {
declFileName = getRelativePathToDirectoryOrUrl(
getDirectoryPath(normalizeSlashes(jsFilePath)),
declFileName,
- compilerHost.getCurrentDirectory(),
- compilerHost.getCanonicalFileName,
+ host.getCurrentDirectory(),
+ host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ false);
referencePathsOutput += "/// " + newLine;
@@ -1464,21 +1462,20 @@ module ts {
}
}
- export function getDeclarationDiagnostics(program: Program, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
+ export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
var diagnostics: Diagnostic[] = [];
- var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, program, ".js");
- emitDeclarations(program, resolver, diagnostics, jsFilePath, targetSourceFile);
+ var jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
+ emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
return diagnostics;
}
// 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 {
// var program = resolver.getProgram();
- var compilerHost = host.getCompilerHost();
var compilerOptions = host.getCompilerOptions();
var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
var diagnostics: Diagnostic[] = [];
- var newLine = compilerHost.getNewLine();
+ var newLine = host.getNewLine();
function emitJavaScript(jsFilePath: string, root?: SourceFile) {
var writer = createTextWriter(newLine);
@@ -1704,8 +1701,8 @@ module ts {
sourceMapData.sourceMapSources.push(getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
node.filename,
- compilerHost.getCurrentDirectory(),
- compilerHost.getCanonicalFileName,
+ host.getCurrentDirectory(),
+ host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true));
sourceMapSourceIndex = sourceMapData.sourceMapSources.length - 1;
@@ -1801,7 +1798,7 @@ module ts {
function writeJavaScriptAndSourceMapFile(emitOutput: string, writeByteOrderMark: boolean) {
// Write source map file
encodeLastRecordedSourceMapSpan();
- writeFile(compilerHost, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(
+ writeFile(host, diagnostics, sourceMapData.sourceMapFilePath, serializeSourceMapContents(
3,
sourceMapData.sourceMapFile,
sourceMapData.sourceMapSourceRoot,
@@ -1849,8 +1846,8 @@ module ts {
sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
getDirectoryPath(normalizePath(jsFilePath)), // get the relative sourceMapDir path based on jsFilePath
combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
- compilerHost.getCurrentDirectory(),
- compilerHost.getCanonicalFileName,
+ host.getCurrentDirectory(),
+ host.getCanonicalFileName,
/*isAbsolutePathAnUrl*/ true);
}
else {
@@ -1886,7 +1883,7 @@ module ts {
}
function writeJavaScriptFile(emitOutput: string, writeByteOrderMark: boolean) {
- writeFile(compilerHost, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
+ writeFile(host, diagnostics, jsFilePath, emitOutput, writeByteOrderMark);
}
// Create a temporary variable with a unique unused name. The forLoopVariable parameter signals that the
@@ -4128,7 +4125,7 @@ module ts {
}
});
declarationOutput += emitDeclarationResult.synchronousDeclarationOutput.substring(appliedSyncOutputPos);
- writeFile(compilerHost, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
+ writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, compilerOptions.emitBOM);
}
}
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 8d81ec45679..cc309646c8a 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -91,6 +91,7 @@ module ts {
var diagnosticsProducingTypeChecker: TypeChecker;
var noDiagnosticsTypeChecker: TypeChecker;
+ var emitHost: EmitHost;
program = {
getSourceFile: getSourceFile,
@@ -104,9 +105,14 @@ module ts {
getCommonSourceDirectory: () => commonSourceDirectory,
emitFiles: invokeEmitter,
isEmitBlocked,
+ getCurrentDirectory: host.getCurrentDirectory,
};
return program;
+ function getEmitHost() {
+ return emitHost || (emitHost = createEmitHostFromProgram(program));
+ }
+
function hasEarlyErrors(sourceFile?: SourceFile): boolean {
return forEach(getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile), d => d.isEarly);
}
@@ -134,12 +140,12 @@ module ts {
var typeChecker = getDiagnosticsProducingTypeChecker();
typeChecker.getDiagnostics(targetSourceFile);
var resolver = typeChecker.getEmitResolver();
- return ts.getDeclarationDiagnostics(program, resolver, targetSourceFile);
+ return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
}
function invokeEmitter(targetSourceFile?: SourceFile) {
var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver();
- return emitFiles(resolver, program, targetSourceFile);
+ return emitFiles(resolver, getEmitHost(), targetSourceFile);
}
function getSourceFile(filename: string) {
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 0a00dff6d39..d606b40c0c8 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -906,10 +906,8 @@ module ts {
identifiers: Map;
}
- export interface Program {
- getSourceFile(filename: string): SourceFile;
+ export interface Program extends ScriptReferenceHost {
getSourceFiles(): SourceFile[];
- getCompilerOptions(): CompilerOptions;
getCompilerHost(): CompilerHost;
getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
@@ -1102,13 +1100,21 @@ module ts {
errorModuleName?: string // If the symbol is not visible from module, module's name
}
- export interface EmitHost {
- getSourceFile(filename: string): SourceFile;
- getSourceFiles(): SourceFile[];
- getCompilerHost(): CompilerHost;
+ export interface ScriptReferenceHost {
getCompilerOptions(): CompilerOptions;
- getCommonSourceDirectory(): string;
+ getSourceFile(filename: string): SourceFile;
+ getCurrentDirectory(): string;
+ }
+
+ export interface EmitHost extends ScriptReferenceHost {
+ getSourceFiles(): SourceFile[];
isEmitBlocked(sourceFile?: SourceFile): boolean;
+
+ getCommonSourceDirectory(): string;
+ getCanonicalFileName(fileName: string): string;
+ getNewLine(): string;
+
+ writeFile(filename: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
}
export interface EmitResolver {
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 8aa04811143..1b9d9caf326 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -636,10 +636,10 @@ module ts {
return undefined;
}
- export function tryResolveScriptReference(host: EmitHost, sourceFile: SourceFile, reference: FileReference) {
+ export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) {
if (!host.getCompilerOptions().noResolve) {
var referenceFileName = isRootedDiskPath(reference.filename) ? reference.filename : combinePaths(getDirectoryPath(sourceFile.filename), reference.filename);
- referenceFileName = getNormalizedAbsolutePath(referenceFileName, host.getCompilerHost().getCurrentDirectory());
+ referenceFileName = getNormalizedAbsolutePath(referenceFileName, host.getCurrentDirectory());
return host.getSourceFile(referenceFileName);
}
}
@@ -734,4 +734,18 @@ module ts {
return false;
}
+ export function createEmitHostFromProgram(program: Program): EmitHost {
+ var compilerHost = program.getCompilerHost();
+ return {
+ getCanonicalFileName: compilerHost.getCanonicalFileName,
+ getCommonSourceDirectory: program.getCommonSourceDirectory,
+ getCompilerOptions: program.getCompilerOptions,
+ getCurrentDirectory: compilerHost.getCurrentDirectory,
+ getNewLine: compilerHost.getNewLine,
+ getSourceFile: program.getSourceFile,
+ getSourceFiles: program.getSourceFiles,
+ isEmitBlocked: program.isEmitBlocked,
+ writeFile: compilerHost.writeFile,
+ };
+ }
}
\ No newline at end of file
diff --git a/src/services/services.ts b/src/services/services.ts
index 7e8a4b3b6a8..adc15378594 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -2224,7 +2224,6 @@ module ts {
var documentRegistry = documentRegistry;
var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
var activeCompletionSession: CompletionSession; // The current active completion session, used to get the completion entry details
- var writer: (filename: string, data: string, writeByteOrderMark: boolean) => void = undefined;
// Check if the localized messages json is set, otherwise query the host for it
if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
@@ -2267,7 +2266,6 @@ module ts {
return host.getDefaultLibFilename(options);
},
writeFile: (filename, data, writeByteOrderMark) => {
- writer(filename, data, writeByteOrderMark);
},
getCurrentDirectory: (): string => {
return host.getCurrentDirectory();
@@ -4854,7 +4852,7 @@ module ts {
var outputFiles: OutputFile[] = [];
- function getEmitOutputWriter(filename: string, data: string, writeByteOrderMark: boolean) {
+ function writeFile(filename: string, data: string, writeByteOrderMark: boolean) {
outputFiles.push({
name: filename,
writeByteOrderMark: writeByteOrderMark,
@@ -4862,13 +4860,12 @@ module ts {
});
}
- // Initialize writer for CompilerHost.writeFile
- writer = getEmitOutputWriter;
+ // Get an emit host from our program, but override the writeFile functionality to
+ // call our local writer function.
+ var emitHost = createEmitHostFromProgram(program);
+ emitHost.writeFile = writeFile;
- var emitOutput = program.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;
+ var emitOutput = emitFiles(getDiagnosticsProducingTypeChecker().getEmitResolver(), emitHost, sourceFile);
return {
outputFiles,