@@ -13,6 +13,16 @@ export interface ICompiler {
1313 inputDone ( ) : void ;
1414}
1515
16+ interface OutputFile {
17+ file : File | undefined ;
18+
19+ jsFileName ?: string ;
20+ dtsFileName ?: string ;
21+ jsContent ?: string ;
22+ jsMapContent ?: string ;
23+ dtsContent ?: string ;
24+ }
25+
1626/**
1727 * Compiles a whole project, with full type checking
1828 */
@@ -61,69 +71,85 @@ export class ProjectCompiler implements ICompiler {
6171 ) ;
6272
6373 this . program = this . project . typescript . createProgram ( rootFilenames , this . project . options , this . host , this . program ) ;
64- const preEmitDiagnostics = this . project . typescript . getPreEmitDiagnostics ( this . program ) ;
65-
74+
6675 const result = emptyCompilationResult ( ) ;
67- result . optionsErrors = this . program . getOptionsDiagnostics ( ) . length ;
68- result . syntaxErrors = this . program . getSyntacticDiagnostics ( ) . length ;
69- result . globalErrors = this . program . getGlobalDiagnostics ( ) . length ;
70- result . semanticErrors = this . program . getSemanticDiagnostics ( ) . length ;
76+ result . optionsErrors = this . reportDiagnostics ( this . program . getOptionsDiagnostics ( ) ) ;
77+ result . syntaxErrors = this . reportDiagnostics ( this . program . getSyntacticDiagnostics ( ) ) ;
78+ result . globalErrors = this . reportDiagnostics ( this . program . getGlobalDiagnostics ( ) ) ;
79+ result . semanticErrors = this . reportDiagnostics ( this . program . getSemanticDiagnostics ( ) ) ;
7180 if ( this . project . options . declaration ) {
7281 result . declarationErrors = this . program . getDeclarationDiagnostics ( ) . length ;
7382 }
7483
75- this . reportDiagnostics ( preEmitDiagnostics ) ;
84+ if ( this . project . singleOutput ) {
85+ const output : OutputFile = {
86+ file : undefined
87+ } ;
7688
77- const emitOutput = this . program . emit ( ) ;
78- result . emitErrors = emitOutput . diagnostics . length ;
79- result . emitSkipped = emitOutput . emitSkipped ;
89+ this . emit ( result , ( fileName , content ) => {
90+ this . attachContentToFile ( output , fileName , content ) ;
91+ } ) ;
8092
81- if ( this . project . singleOutput ) {
82- this . emitFile ( result , currentDirectory ) ;
93+ this . emitFile ( output , currentDirectory ) ;
8394 } else {
84- // Emit files one by one
85- for ( const fileName of this . host . input . getFileNames ( true ) ) {
95+ const output : utils . Map < OutputFile > = { } ;
96+
97+ const input = this . host . input . getFileNames ( true ) ;
98+
99+ for ( let i = 0 ; i < input . length ; i ++ ) {
100+ const fileName = utils . normalizePath ( input [ i ] ) ;
86101 const file = this . project . input . getFile ( fileName ) ;
87102
88- this . emitFile ( result , currentDirectory , file ) ;
103+ output [ fileName ] = { file } ;
104+ }
105+
106+ this . emit ( result , ( fileName , content , writeByteOrderMark , onError , sourceFiles ) => {
107+ if ( sourceFiles . length !== 1 ) {
108+ throw new Error ( "Failure: sourceFiles in WriteFileCallback should have length 1, got " + sourceFiles . length ) ;
109+ }
110+
111+ const fileNameOriginal = utils . normalizePath ( sourceFiles [ 0 ] . fileName ) ;
112+ const file = output [ fileNameOriginal ] ;
113+ if ( ! file ) return ;
114+
115+ this . attachContentToFile ( file , fileName , content ) ;
116+ } ) ;
117+
118+ for ( let i = 0 ; i < input . length ; i ++ ) {
119+ const fileName = utils . normalizePath ( input [ i ] ) ;
120+ this . emitFile ( output [ fileName ] , currentDirectory ) ;
89121 }
90122 }
91123
92124 this . project . output . finish ( result ) ;
93125 }
94126
95- private emitFile ( result : CompilationResult , currentDirectory : string , file ?: File ) {
96- let jsFileName : string ;
97- let dtsFileName : string ;
98- let jsContent : string ;
99- let dtsContent : string ;
100- let jsMapContent : string ;
101-
102- const emitOutput = this . program . emit ( file && file . ts , ( fileName : string , content : string ) => {
103- const [ , extension ] = utils . splitExtension ( fileName , [ 'd.ts' ] ) ;
104- switch ( extension ) {
105- case 'js' :
106- case 'jsx' :
107- jsFileName = fileName ;
108- jsContent = content ;
109- break ;
110- case 'd.ts' :
111- dtsFileName = fileName ;
112- dtsContent = content ;
113- break ;
114- case 'map' :
115- jsMapContent = content ;
116- break ;
117- }
118- } ) ;
127+ private attachContentToFile ( file : OutputFile , fileName : string , content : string ) {
128+ const [ , extension ] = utils . splitExtension ( fileName , [ 'd.ts' ] ) ;
129+ switch ( extension ) {
130+ case 'js' :
131+ case 'jsx' :
132+ file . jsFileName = fileName ;
133+ file . jsContent = content ;
134+ break ;
135+ case 'd.ts' :
136+ file . dtsFileName = fileName ;
137+ file . dtsContent = content ;
138+ break ;
139+ case 'map' :
140+ file . jsMapContent = content ;
141+ break ;
142+ }
143+ }
144+ private emit ( result : CompilationResult , callback : ts . WriteFileCallback ) {
145+ const emitOutput = this . program . emit ( undefined , callback ) ;
119146
120147 result . emitErrors += emitOutput . diagnostics . length ;
121148 this . reportDiagnostics ( emitOutput . diagnostics ) ;
122149
123- if ( emitOutput . emitSkipped ) {
124- result . emitSkipped = true ;
125- }
126-
150+ result . emitSkipped = emitOutput . emitSkipped ;
151+ }
152+ private emitFile ( { file, jsFileName, dtsFileName, jsContent, dtsContent, jsMapContent } : OutputFile , currentDirectory : string ) {
127153 if ( ! jsFileName ) return ;
128154
129155 let base : string ;
@@ -163,6 +189,7 @@ export class ProjectCompiler implements ICompiler {
163189 for ( const error of diagnostics ) {
164190 this . project . output . diagnostic ( error ) ;
165191 }
192+ return diagnostics . length ;
166193 }
167194
168195 private removeSourceMapComment ( content : string ) : string {
0 commit comments