Skip to content

Commit bb307f8

Browse files
Simplify the API for emitting code from the Program instance.
1 parent b6d083f commit bb307f8

19 files changed

Lines changed: 263 additions & 152 deletions

src/compiler/emitter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1504,8 +1504,9 @@ module ts {
15041504
return diagnostics;
15051505
}
15061506

1507+
// @internal
15071508
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compilerOnSave feature
1508-
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile?: SourceFile): EmitResult {
1509+
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
15091510
var compilerOptions = host.getCompilerOptions();
15101511
var languageVersion = compilerOptions.target || ScriptTarget.ES3;
15111512
var sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;

src/compiler/program.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ module ts {
9090

9191
var diagnosticsProducingTypeChecker: TypeChecker;
9292
var noDiagnosticsTypeChecker: TypeChecker;
93-
var emitHost: EmitHost;
9493

9594
program = {
9695
getSourceFile: getSourceFile,
@@ -105,7 +104,7 @@ module ts {
105104
getTypeChecker,
106105
getDiagnosticsProducingTypeChecker,
107106
getCommonSourceDirectory: () => commonSourceDirectory,
108-
emitFiles: invokeEmitter,
107+
emit,
109108
isEmitBlocked,
110109
getCurrentDirectory: host.getCurrentDirectory,
111110
getEmitResolver: () => getDiagnosticsProducingTypeChecker().getEmitResolver(),
@@ -116,10 +115,22 @@ module ts {
116115
};
117116
return program;
118117

119-
function getEmitHost() {
120-
return emitHost || (emitHost = createEmitHostFromProgram(program));
118+
function getEmitHost(writeFileCallback?: WriteFileCallback) {
119+
var compilerHost = program.getCompilerHost();
120+
return {
121+
getCanonicalFileName: compilerHost.getCanonicalFileName,
122+
getCommonSourceDirectory: program.getCommonSourceDirectory,
123+
getCompilerOptions: program.getCompilerOptions,
124+
getCurrentDirectory: compilerHost.getCurrentDirectory,
125+
getNewLine: compilerHost.getNewLine,
126+
getSourceFile: program.getSourceFile,
127+
getSourceFiles: program.getSourceFiles,
128+
isEmitBlocked: program.isEmitBlocked,
129+
writeFile: writeFileCallback || compilerHost.writeFile,
130+
};
121131
}
122132

133+
123134
function isEmitBlocked(sourceFile?: SourceFile): boolean {
124135
if (options.noEmitOnError) {
125136
return getDiagnostics(sourceFile).length !== 0 || getTypeCheckerDiagnostics(sourceFile).length !== 0;
@@ -143,9 +154,10 @@ module ts {
143154
return ts.getDeclarationDiagnostics(getEmitHost(), resolver, targetSourceFile);
144155
}
145156

146-
function invokeEmitter(targetSourceFile?: SourceFile) {
157+
function emit(targetSourceFile?: SourceFile, writeFileCallback?: WriteFileCallback) {
147158
var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver();
148-
return emitFiles(resolver, getEmitHost(), targetSourceFile);
159+
var host = getEmitHost(writeFileCallback);
160+
return emitFiles(resolver, host, targetSourceFile);
149161
}
150162

151163
function getSourceFile(fileName: string) {

src/compiler/tsc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ module ts {
346346
}
347347
else {
348348
var emitStart = new Date().getTime();
349-
var emitOutput = program.emitFiles();
349+
var emitOutput = program.emit();
350350
var emitErrors = emitOutput.diagnostics;
351351
exitStatus = emitOutput.emitResultStatus;
352352
var reportStart = new Date().getTime();

src/compiler/types.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -927,10 +927,27 @@ module ts {
927927
getCurrentDirectory(): string;
928928
}
929929

930+
export interface WriteFileCallback {
931+
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
932+
}
933+
930934
export interface Program extends ScriptReferenceHost {
931935
getSourceFiles(): SourceFile[];
932936
getCompilerHost(): CompilerHost;
933-
getEmitResolver(): EmitResolver;
937+
938+
/**
939+
* Emits the javascript and declaration files. If targetSourceFile is not specified, then
940+
* the javascript and declaration files will be produced for all the files in this program.
941+
* If targetSourceFile is specified, then only the javascript and declaration for that
942+
* specific file will be generated.
943+
*
944+
* If writeFile is not specified then the writeFile callback from getCompilerHost() will be
945+
* used for writing the javascript and declaration files. Otherwise, the writeFile parameter
946+
* will be invoked when writing the javascript and declaration files.
947+
*/
948+
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
949+
950+
isEmitBlocked(sourceFile?: SourceFile): boolean;
934951

935952
// These will merge with the below diagnostics function in a followup checkin.
936953
getTypeCheckerDiagnostics(sourceFile?: SourceFile): Diagnostic[];
@@ -951,9 +968,6 @@ module ts {
951968
getTypeChecker(): TypeChecker;
952969
getCommonSourceDirectory(): string;
953970

954-
emitFiles(targetSourceFile?: SourceFile): EmitResult;
955-
isEmitBlocked(sourceFile?: SourceFile): boolean;
956-
957971
// For testing purposes only. Should not be used by any other consumers (including the
958972
// language service).
959973
/* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
@@ -1671,7 +1685,7 @@ module ts {
16711685
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
16721686
getDefaultLibFileName(options: CompilerOptions): string;
16731687
getCancellationToken? (): CancellationToken;
1674-
writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
1688+
writeFile: WriteFileCallback;
16751689
getCurrentDirectory(): string;
16761690
getCanonicalFileName(fileName: string): string;
16771691
useCaseSensitiveFileNames(): boolean;

src/compiler/utilities.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ module ts {
3131
getCanonicalFileName(fileName: string): string;
3232
getNewLine(): string;
3333

34-
writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
34+
writeFile: WriteFileCallback;
3535
}
3636

3737
// Pool writers to avoid needing to allocate them for every symbol we write.
@@ -843,21 +843,6 @@ module ts {
843843
return false;
844844
}
845845

846-
export function createEmitHostFromProgram(program: Program): EmitHost {
847-
var compilerHost = program.getCompilerHost();
848-
return {
849-
getCanonicalFileName: compilerHost.getCanonicalFileName,
850-
getCommonSourceDirectory: program.getCommonSourceDirectory,
851-
getCompilerOptions: program.getCompilerOptions,
852-
getCurrentDirectory: compilerHost.getCurrentDirectory,
853-
getNewLine: compilerHost.getNewLine,
854-
getSourceFile: program.getSourceFile,
855-
getSourceFiles: program.getSourceFiles,
856-
isEmitBlocked: program.isEmitBlocked,
857-
writeFile: compilerHost.writeFile,
858-
};
859-
}
860-
861846
export function textSpanEnd(span: TextSpan) {
862847
return span.start + span.length
863848
}

src/harness/fourslash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2216,7 +2216,7 @@ module FourSlash {
22162216
if (errors.length > 0) {
22172217
throw new Error('Error compiling ' + fileName + ': ' + errors.map(e => e.messageText).join('\r\n'));
22182218
}
2219-
program.emitFiles();
2219+
program.emit();
22202220
result = result || ''; // Might have an empty fourslash file
22212221

22222222
// Compile and execute the test

src/harness/harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ module Harness {
10861086
// only emit if there weren't parse errors
10871087
var emitResult: ts.EmitResult;
10881088
if (!isEmitBlocked) {
1089-
emitResult = program.emitFiles();
1089+
emitResult = program.emit();
10901090
}
10911091

10921092
var errors: HarnessDiagnostic[] = [];

src/harness/projectsRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class ProjectRunner extends RunnerBase {
131131
var sourceMapData: ts.SourceMapData[] = null;
132132
if (!errors.length) {
133133
errors = program.getTypeCheckerDiagnostics();
134-
var emitResult = program.emitFiles();
134+
var emitResult = program.emit();
135135
errors = ts.concatenate(errors, emitResult.diagnostics);
136136
sourceMapData = emitResult.sourceMaps;
137137

src/services/services.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4664,12 +4664,7 @@ module ts {
46644664
});
46654665
}
46664666

4667-
// Get an emit host from our program, but override the writeFile functionality to
4668-
// call our local writer function.
4669-
var emitHost = createEmitHostFromProgram(program);
4670-
emitHost.writeFile = writeFile;
4671-
4672-
var emitOutput = emitFiles(program.getEmitResolver(), emitHost, sourceFile);
4667+
var emitOutput = program.emit(sourceFile, writeFile);
46734668

46744669
return {
46754670
outputFiles,

tests/baselines/reference/APISample_compile.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import ts = require("typescript");
1616
export function compile(fileNames: string[], options: ts.CompilerOptions): void {
1717
var host = ts.createCompilerHost(options);
1818
var program = ts.createProgram(fileNames, options, host);
19-
var result = program.emitFiles();
19+
var result = program.emit();
2020

2121
var allDiagnostics = program.getDiagnostics()
2222
.concat(program.getTypeCheckerDiagnostics())
@@ -737,19 +737,31 @@ declare module "typescript" {
737737
getSourceFile(fileName: string): SourceFile;
738738
getCurrentDirectory(): string;
739739
}
740+
interface WriteFileCallback {
741+
(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
742+
}
740743
interface Program extends ScriptReferenceHost {
741744
getSourceFiles(): SourceFile[];
742745
getCompilerHost(): CompilerHost;
743-
getEmitResolver(): EmitResolver;
746+
/**
747+
* Emits the javascript and declaration files. If targetSourceFile is not specified, then
748+
* the javascript and declaration files will be produced for all the files in this program.
749+
* If targetSourceFile is specified, then only the javascript and declaration for that
750+
* specific file will be generated.
751+
*
752+
* If writeFile is not specified then the writeFile callback from getCompilerHost() will be
753+
* used for writing the javascript and declaration files. Otherwise, the writeFile parameter
754+
* will be invoked when writing the javascript and declaration files.
755+
*/
756+
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
757+
isEmitBlocked(sourceFile?: SourceFile): boolean;
744758
getTypeCheckerDiagnostics(sourceFile?: SourceFile): Diagnostic[];
745759
getTypeCheckerGlobalDiagnostics(): Diagnostic[];
746760
getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
747761
getGlobalDiagnostics(): Diagnostic[];
748762
getDeclarationDiagnostics(sourceFile: SourceFile): Diagnostic[];
749763
getTypeChecker(): TypeChecker;
750764
getCommonSourceDirectory(): string;
751-
emitFiles(targetSourceFile?: SourceFile): EmitResult;
752-
isEmitBlocked(sourceFile?: SourceFile): boolean;
753765
}
754766
interface SourceMapSpan {
755767
emittedLine: number;
@@ -1338,7 +1350,7 @@ declare module "typescript" {
13381350
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
13391351
getDefaultLibFileName(options: CompilerOptions): string;
13401352
getCancellationToken?(): CancellationToken;
1341-
writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void;
1353+
writeFile: WriteFileCallback;
13421354
getCurrentDirectory(): string;
13431355
getCanonicalFileName(fileName: string): string;
13441356
useCaseSensitiveFileNames(): boolean;
@@ -1916,7 +1928,7 @@ var ts = require("typescript");
19161928
function compile(fileNames, options) {
19171929
var host = ts.createCompilerHost(options);
19181930
var program = ts.createProgram(fileNames, options, host);
1919-
var result = program.emitFiles();
1931+
var result = program.emit();
19201932
var allDiagnostics = program.getDiagnostics().concat(program.getTypeCheckerDiagnostics()).concat(result.diagnostics);
19211933
allDiagnostics.forEach(function (diagnostic) {
19221934
var lineChar = diagnostic.file.getLineAndCharacterFromPosition(diagnostic.start);

0 commit comments

Comments
 (0)