@@ -7,7 +7,7 @@ namespace ts {
77 } : undefined ;
88
99 /**
10- * Create a function that reports error by writing to the system and handles the formating of the diagnostic
10+ * Create a function that reports error by writing to the system and handles the formatting of the diagnostic
1111 */
1212 export function createDiagnosticReporter ( system : System , pretty ?: boolean ) : DiagnosticReporter {
1313 const host : FormatDiagnosticsHost = system === sys && sysFormatDiagnosticsHost ? sysFormatDiagnosticsHost : {
@@ -101,16 +101,87 @@ namespace ts {
101101 return countWhere ( diagnostics , diagnostic => diagnostic . category === DiagnosticCategory . Error ) ;
102102 }
103103
104+ export function getFilesInErrorForSummary ( diagnostics : readonly Diagnostic [ ] ) : ( ReportFileInError | undefined ) [ ] {
105+ const filesInError =
106+ filter ( diagnostics , diagnostic => diagnostic . category === DiagnosticCategory . Error )
107+ . map (
108+ errorDiagnostic => {
109+ if ( errorDiagnostic . file === undefined ) return ;
110+ return `${ errorDiagnostic . file . fileName } ` ;
111+ } ) ;
112+ return filesInError . map ( ( fileName : string ) => {
113+ const diagnosticForFileName = find ( diagnostics , diagnostic =>
114+ diagnostic . file !== undefined && diagnostic . file . fileName === fileName
115+ ) ;
116+
117+ if ( diagnosticForFileName !== undefined ) {
118+ const { line } = getLineAndCharacterOfPosition ( diagnosticForFileName . file ! , diagnosticForFileName . start ! ) ;
119+ return {
120+ fileName,
121+ line : line + 1 ,
122+ } ;
123+ }
124+ } ) ;
125+ }
126+
104127 export function getWatchErrorSummaryDiagnosticMessage ( errorCount : number ) {
105128 return errorCount === 1 ?
106129 Diagnostics . Found_1_error_Watching_for_file_changes :
107130 Diagnostics . Found_0_errors_Watching_for_file_changes ;
108131 }
109132
110- export function getErrorSummaryText ( errorCount : number , newLine : string ) {
133+ export function getErrorSummaryText (
134+ errorCount : number ,
135+ filesInError : readonly ( ReportFileInError | undefined ) [ ] ,
136+ newLine : string
137+ ) {
111138 if ( errorCount === 0 ) return "" ;
112- const d = createCompilerDiagnostic ( errorCount === 1 ? Diagnostics . Found_1_error : Diagnostics . Found_0_errors , errorCount ) ;
113- return `${ newLine } ${ flattenDiagnosticMessageText ( d . messageText , newLine ) } ${ newLine } ${ newLine } ` ;
139+ const nonNilFiles = filesInError . filter ( fileInError => fileInError !== undefined ) ;
140+ const distinctFileNamesWithLines = nonNilFiles . map ( fileInError => `${ fileInError ! . fileName } :${ fileInError ! . line } ` )
141+ . filter ( ( value , index , self ) => self . indexOf ( value ) === index ) ;
142+ const d = errorCount === 1 ?
143+ createCompilerDiagnostic (
144+ filesInError [ 0 ] !== undefined ?
145+ Diagnostics . Found_1_error_in_1 :
146+ Diagnostics . Found_1_error ,
147+ errorCount ,
148+ distinctFileNamesWithLines [ 0 ] ) :
149+ createCompilerDiagnostic (
150+ distinctFileNamesWithLines . length === 0 ?
151+ Diagnostics . Found_0_errors :
152+ distinctFileNamesWithLines . length === 1 ?
153+ Diagnostics . Found_0_errors_in_1_file :
154+ Diagnostics . Found_0_errors_in_1_files ,
155+ errorCount ,
156+ distinctFileNamesWithLines . length ) ;
157+ return `${ newLine } ${ flattenDiagnosticMessageText ( d . messageText , newLine ) } ${ newLine } ${ newLine } ${ errorCount > 1 ? createTabularErrorsDisplay ( nonNilFiles ) : "" } ` ;
158+ }
159+
160+ function createTabularErrorsDisplay ( filesInError : ( ReportFileInError | undefined ) [ ] ) {
161+ const distinctFiles = filesInError . filter ( ( value , index , self ) => index === self . findIndex ( file => file ?. fileName === value ?. fileName ) ) ;
162+ if ( distinctFiles . length === 0 ) return "" ;
163+
164+ const numberLength = ( num : number ) => Math . log ( num ) * Math . LOG10E + 1 ;
165+ const fileToErrorCount = distinctFiles . map ( file => ( [ file , countWhere ( filesInError , fileInError => fileInError ! . fileName === file ! . fileName ) ] as const ) ) ;
166+ const maxErrors = fileToErrorCount . reduce ( ( acc , value ) => Math . max ( acc , value [ 1 ] || 0 ) , 0 ) ;
167+
168+ const headerRow = Diagnostics . Errors_Files . message ;
169+ const leftColumnHeadingLength = headerRow . split ( " " ) [ 0 ] . length ;
170+ const leftPaddingGoal = Math . max ( leftColumnHeadingLength , numberLength ( maxErrors ) ) ;
171+ const headerPadding = Math . max ( numberLength ( maxErrors ) - leftColumnHeadingLength , 0 ) ;
172+
173+ let tabularData = "" ;
174+ tabularData += " " . repeat ( headerPadding ) + headerRow + "\n" ;
175+ fileToErrorCount . forEach ( ( row ) => {
176+ const [ file , errorCount ] = row ;
177+ const errorCountDigitsLength = Math . log ( errorCount ) * Math . LOG10E + 1 | 0 ;
178+ const leftPadding = errorCountDigitsLength < leftPaddingGoal ?
179+ " " . repeat ( leftPaddingGoal - errorCountDigitsLength )
180+ : "" ;
181+ tabularData += `${ leftPadding } ${ errorCount } ${ file ! . fileName } :${ file ! . line } \n` ;
182+ } ) ;
183+
184+ return tabularData ;
114185 }
115186
116187 export function isBuilderProgram ( program : Program | BuilderProgram ) : program is BuilderProgram {
@@ -350,7 +421,7 @@ namespace ts {
350421 }
351422
352423 if ( reportSummary ) {
353- reportSummary ( getErrorCountForSummary ( diagnostics ) ) ;
424+ reportSummary ( getErrorCountForSummary ( diagnostics ) , getFilesInErrorForSummary ( diagnostics ) ) ;
354425 }
355426
356427 return {
@@ -656,7 +727,7 @@ namespace ts {
656727 builderProgram ,
657728 input . reportDiagnostic || createDiagnosticReporter ( system ) ,
658729 s => host . trace && host . trace ( s ) ,
659- input . reportErrorSummary || input . options . pretty ? errorCount => system . write ( getErrorSummaryText ( errorCount , system . newLine ) ) : undefined
730+ input . reportErrorSummary || input . options . pretty ? ( errorCount , filesInError ) => system . write ( getErrorSummaryText ( errorCount , filesInError , system . newLine ) ) : undefined
660731 ) ;
661732 if ( input . afterProgramEmitAndDiagnostics ) input . afterProgramEmitAndDiagnostics ( builderProgram ) ;
662733 return exitStatus ;
0 commit comments