11"use strict" ;
22Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
3+ const ts = require ( "typescript" ) ;
34const path = require ( "path" ) ;
45const input_1 = require ( "./input" ) ;
56const host_1 = require ( "./host" ) ;
@@ -9,7 +10,8 @@ const utils = require("./utils");
910 * Compiles a whole project, with full type checking
1011 */
1112class ProjectCompiler {
12- prepare ( project ) {
13+ prepare ( project , finalTransformers ) {
14+ this . finalTransformers = finalTransformers ;
1315 this . project = project ;
1416 this . hasSourceMap = false ;
1517 }
@@ -44,18 +46,25 @@ class ProjectCompiler {
4446 } )
4547 : this . project . typescript . createProgram ( rootFilenames , this . project . options , this . host , this . program ) ;
4648 const result = reporter_1 . emptyCompilationResult ( this . project . options . noEmit ) ;
47- result . optionsErrors = this . reportDiagnostics ( this . program . getOptionsDiagnostics ( ) ) ;
48- result . syntaxErrors = this . reportDiagnostics ( this . program . getSyntacticDiagnostics ( ) ) ;
49- result . globalErrors = this . reportDiagnostics ( this . program . getGlobalDiagnostics ( ) ) ;
50- result . semanticErrors = this . reportDiagnostics ( this . program . getSemanticDiagnostics ( ) ) ;
49+ const optionErrors = this . program . getOptionsDiagnostics ( ) ;
50+ const syntaxErrors = this . program . getSyntacticDiagnostics ( ) ;
51+ const globalErrors = this . program . getGlobalDiagnostics ( ) ;
52+ const semanticErrors = this . program . getSemanticDiagnostics ( ) ;
53+ result . optionsErrors = optionErrors . length ;
54+ result . syntaxErrors = syntaxErrors . length ;
55+ result . globalErrors = globalErrors . length ;
56+ result . semanticErrors = semanticErrors . length ;
57+ let declarationErrors = [ ] ;
5158 if ( this . project . options . declaration ) {
52- result . declarationErrors = this . program . getDeclarationDiagnostics ( ) . length ;
59+ declarationErrors = this . program . getDeclarationDiagnostics ( ) ;
60+ result . declarationErrors = declarationErrors . length ;
5361 }
62+ const preEmitDiagnostics = [ ...optionErrors , ...syntaxErrors , ...globalErrors , ...semanticErrors , ...declarationErrors ] ;
5463 if ( this . project . singleOutput ) {
5564 const output = {
5665 file : undefined
5766 } ;
58- this . emit ( result , ( fileName , content ) => {
67+ this . emit ( result , preEmitDiagnostics , ( fileName , content ) => {
5968 this . attachContentToFile ( output , fileName , content ) ;
6069 } ) ;
6170 this . emitFile ( output , currentDirectory ) ;
@@ -68,7 +77,7 @@ class ProjectCompiler {
6877 const file = this . project . input . getFile ( fileName ) ;
6978 output [ fileName ] = { file } ;
7079 }
71- this . emit ( result , ( fileName , content , writeByteOrderMark , onError , sourceFiles ) => {
80+ this . emit ( result , preEmitDiagnostics , ( fileName , content , writeByteOrderMark , onError , sourceFiles ) => {
7281 if ( sourceFiles . length !== 1 ) {
7382 throw new Error ( "Failure: sourceFiles in WriteFileCallback should have length 1, got " + sourceFiles . length ) ;
7483 }
@@ -106,11 +115,19 @@ class ProjectCompiler {
106115 break ;
107116 }
108117 }
109- emit ( result , callback ) {
110- const emitOutput = this . program . emit ( undefined , callback ) ;
111- result . emitErrors += emitOutput . diagnostics . length ;
112- this . reportDiagnostics ( emitOutput . diagnostics ) ;
118+ emit ( result , preEmitDiagnostics , callback ) {
119+ const emitOutput = this . program . emit ( undefined , callback , undefined , false , this . finalTransformers ? this . finalTransformers ( this . program ) : undefined ) ;
113120 result . emitSkipped = emitOutput . emitSkipped ;
121+ // `emitOutput.diagnostics` might contain diagnostics that were already part of `preEmitDiagnostics`.
122+ // See https://github.com/Microsoft/TypeScript/issues/20876
123+ // We use sortAndDeduplicateDiagnostics to remove duplicate diagnostics.
124+ // We then count the number of diagnostics in `diagnostics` that we not in `preEmitDiagnostics`
125+ // to count the number of emit diagnostics.
126+ const diagnostics = ts . sortAndDeduplicateDiagnostics ( [ ...preEmitDiagnostics , ...emitOutput . diagnostics ] ) ;
127+ result . emitErrors += diagnostics . length - preEmitDiagnostics . length ;
128+ for ( const error of diagnostics ) {
129+ this . project . output . diagnostic ( error ) ;
130+ }
114131 }
115132 emitFile ( { file, jsFileName, dtsFileName, dtsMapFileName, jsContent, dtsContent, dtsMapContent, jsMapContent } , currentDirectory ) {
116133 if ( ! jsFileName )
@@ -148,15 +165,12 @@ class ProjectCompiler {
148165 this . project . output . writeJs ( base , jsFileName , jsContent , jsMapContent , file ? file . gulp . cwd : currentDirectory , file ) ;
149166 }
150167 if ( dtsContent !== undefined ) {
168+ if ( dtsMapContent !== undefined ) {
169+ dtsContent = this . removeSourceMapComment ( dtsContent ) ;
170+ }
151171 this . project . output . writeDts ( baseDeclarations , dtsFileName , dtsContent , dtsMapContent , file ? file . gulp . cwd : currentDirectory , file ) ;
152172 }
153173 }
154- reportDiagnostics ( diagnostics ) {
155- for ( const error of diagnostics ) {
156- this . project . output . diagnostic ( error ) ;
157- }
158- return diagnostics . length ;
159- }
160174 removeSourceMapComment ( content ) {
161175 // By default the TypeScript automaticly inserts a source map comment.
162176 // This should be removed because gulp-sourcemaps takes care of that.
@@ -173,7 +187,8 @@ class FileCompiler {
173187 this . previousOutput = { } ;
174188 this . compilationResult = undefined ;
175189 }
176- prepare ( project ) {
190+ prepare ( project , finalTransformers ) {
191+ this . finalTransformers = finalTransformers ;
177192 this . project = project ;
178193 this . project . input . noParse = true ;
179194 this . compilationResult = reporter_1 . emptyCompilationResult ( this . project . options . noEmit ) ;
@@ -196,8 +211,13 @@ class FileCompiler {
196211 this . write ( file , old . fileName , old . diagnostics , old . content , old . sourceMap ) ;
197212 return ;
198213 }
199- const diagnostics = [ ] ;
200- const outputString = this . project . typescript . transpile ( file . content , this . project . options , file . fileNameOriginal , diagnostics ) ;
214+ const output = this . project . typescript . transpileModule ( file . content , {
215+ compilerOptions : this . project . options ,
216+ fileName : file . fileNameOriginal ,
217+ reportDiagnostics : true ,
218+ transformers : this . finalTransformers ? this . finalTransformers ( ) : undefined ,
219+ } ) ;
220+ const outputString = output . outputText ;
201221 let index = outputString . lastIndexOf ( '\n' ) ;
202222 let mapString = outputString . substring ( index + 1 ) ;
203223 if ( mapString . substring ( 0 , 1 ) === '\r' )
@@ -214,7 +234,7 @@ class FileCompiler {
214234 // map.sources[0] = path.relative(map.sourceRoot, file.gulp.path);
215235 const [ fileNameExtensionless ] = utils . splitExtension ( file . fileNameOriginal ) ;
216236 const [ , extension ] = utils . splitExtension ( map . file ) ; // js or jsx
217- this . write ( file , fileNameExtensionless + '.' + extension , diagnostics , outputString . substring ( 0 , index ) , JSON . stringify ( map ) ) ;
237+ this . write ( file , fileNameExtensionless + '.' + extension , output . diagnostics , outputString . substring ( 0 , index ) , JSON . stringify ( map ) ) ;
218238 }
219239 inputDone ( ) {
220240 this . project . output . finish ( this . compilationResult ) ;
0 commit comments