Clean things up so the services layer can easily emit without having to contort compiler hosts.

This commit is contained in:
Cyrus Najmabadi
2014-12-16 14:42:58 -08:00
parent f5ad79fe7a
commit 5a2fb94a95
5 changed files with 61 additions and 41 deletions
+17 -20
View File
@@ -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 += "/// <reference path=\"" + declFileName + "\" />" + 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);
}
}
+8 -2
View File
@@ -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) {
+14 -8
View File
@@ -906,10 +906,8 @@ module ts {
identifiers: Map<string>;
}
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 {
+16 -2
View File
@@ -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,
};
}
}
+6 -9
View File
@@ -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,