@@ -15,8 +15,8 @@ import * as gnu_ld from '@cmt/diagnostics/gnu-ld';
1515import * as mvsc from '@cmt/diagnostics/msvc' ;
1616import * as iar from '@cmt/diagnostics/iar' ;
1717import * as iwyu from '@cmt/diagnostics/iwyu' ;
18+ import { FileDiagnostic , RawDiagnostic , RawDiagnosticParser , diagnosticSeverity } from '@cmt/diagnostics/util' ;
1819import { CustomParser } from '@cmt/diagnostics/custom' ;
19- import { FileDiagnostic , RawDiagnostic , RawDiagnosticParser } from '@cmt/diagnostics/util' ;
2020import { ConfigurationReader } from '@cmt/config' ;
2121import { fs } from '@cmt/pr' ;
2222
@@ -32,6 +32,12 @@ export class Compilers {
3232 iwyu = new iwyu . Parser ( ) ;
3333}
3434
35+ export interface RawDiagnosticWithSource {
36+ /** The parser that produced this diagnostic (e.g. 'GCC', 'MSVC'). Matches the keys used in `enableOutputParsers`. */
37+ source : string ;
38+ diagnostic : RawDiagnostic ;
39+ }
40+
3541export class CompileOutputConsumer implements OutputConsumer {
3642 readonly customParsers : Map < string , CustomParser > = new Map ( ) ;
3743
@@ -45,6 +51,21 @@ export class CompileOutputConsumer implements OutputConsumer {
4551
4652 compilers = new Compilers ( ) ;
4753
54+ private readonly _onDiagnosticEmitter = new vscode . EventEmitter < RawDiagnosticWithSource > ( ) ;
55+
56+ /**
57+ * Event fired when a new diagnostic is parsed from compiler output.
58+ * Includes the source parser name so subscribers can filter by `enableOutputParsers`
59+ * and set `diag.source` for display in the Problems pane.
60+ */
61+ get onDiagnostic ( ) {
62+ return this . _onDiagnosticEmitter . event ;
63+ }
64+
65+ dispose ( ) {
66+ this . _onDiagnosticEmitter . dispose ( ) ;
67+ }
68+
4869 // Defer all output to the `error` method
4970 output ( line : string ) {
5071 this . error ( line ) ;
@@ -53,13 +74,28 @@ export class CompileOutputConsumer implements OutputConsumer {
5374 error ( line : string ) {
5475 // Built-in parsers get first priority
5576 for ( const cand in this . compilers ) {
56- if ( this . compilers [ cand ] . handleLine ( line ) ) {
77+ const parser = this . compilers [ cand ] ;
78+ const countBefore = parser . diagnostics . length ;
79+ if ( parser . handleLine ( line ) ) {
80+ if ( parser . diagnostics . length > countBefore ) {
81+ this . _onDiagnosticEmitter . fire ( {
82+ source : cand . toUpperCase ( ) ,
83+ diagnostic : parser . diagnostics [ parser . diagnostics . length - 1 ]
84+ } ) ;
85+ }
5786 return ;
5887 }
5988 }
6089 // Custom user-defined parsers run after built-ins
61- for ( const [ , parser ] of this . customParsers ) {
90+ for ( const [ name , parser ] of this . customParsers ) {
91+ const countBefore = parser . diagnostics . length ;
6292 if ( parser . handleLine ( line ) ) {
93+ if ( parser . diagnostics . length > countBefore ) {
94+ this . _onDiagnosticEmitter . fire ( {
95+ source : name ,
96+ diagnostic : parser . diagnostics [ parser . diagnostics . length - 1 ]
97+ } ) ;
98+ }
6399 return ;
64100 }
65101 }
@@ -79,33 +115,10 @@ export class CompileOutputConsumer implements OutputConsumer {
79115 const diags_by_file = new Map < string , vscode . Diagnostic [ ] > ( ) ;
80116 const linkerHandler = this . createLinkerDiagnosticsHandler ( basePaths ) ;
81117
82- const severity_of = ( p : string ) => {
83- switch ( p ) {
84- case 'warning' :
85- return vscode . DiagnosticSeverity . Warning ;
86- case 'catastrophic error' :
87- case 'fatal error' :
88- case 'error' :
89- return vscode . DiagnosticSeverity . Error ;
90- case 'note' :
91- case 'info' :
92- case 'remark' :
93- return vscode . DiagnosticSeverity . Information ;
94- }
95- // tslint:disable-next-line
96- console . warn ( 'Unknown diagnostic severity level: ' + p ) ;
97- return undefined ;
98- } ;
99-
100- const by_source = {
101- GCC : this . compilers . gcc . diagnostics ,
102- MSVC : this . compilers . msvc . diagnostics ,
103- GHS : this . compilers . ghs . diagnostics ,
104- DIAB : this . compilers . diab . diagnostics ,
105- GNULD : this . compilers . gnuld . diagnostics ,
106- IAR : this . compilers . iar . diagnostics ,
107- IWYU : this . compilers . iwyu . diagnostics
108- } ;
118+ const by_source : Record < string , readonly RawDiagnostic [ ] > = { } ;
119+ for ( const name in this . compilers ) {
120+ by_source [ name . toUpperCase ( ) ] = this . compilers [ name ] . diagnostics ;
121+ }
109122 const parsers = util . objectPairs ( by_source )
110123 . filter ( ( [ source , _ ] ) => this . config . enableOutputParsers ?. includes ( source . toLowerCase ( ) ) ?? false ) ;
111124 const arrs : FileDiagnostic [ ] = [ ] ;
@@ -115,7 +128,7 @@ export class CompileOutputConsumer implements OutputConsumer {
115128 for ( const raw_diag of diags ) {
116129 await linkerHandler . collect ( raw_diag , source , arrs . length ) ;
117130 const filepath = await this . resolvePath ( raw_diag . file , basePaths ) ;
118- const severity = severity_of ( raw_diag . severity ) ;
131+ const severity = diagnosticSeverity ( raw_diag . severity ) ;
119132 if ( severity === undefined ) {
120133 continue ;
121134 }
@@ -148,7 +161,7 @@ export class CompileOutputConsumer implements OutputConsumer {
148161 for ( const [ name , parser ] of this . customParsers ) {
149162 for ( const raw_diag of parser . diagnostics ) {
150163 const filepath = await this . resolvePath ( raw_diag . file , basePaths ) ;
151- const severity = severity_of ( raw_diag . severity ) ;
164+ const severity = diagnosticSeverity ( raw_diag . severity ) ;
152165 if ( severity === undefined ) {
153166 continue ;
154167 }
@@ -323,8 +336,16 @@ export class CMakeBuildConsumer extends proc.CommandConsumer implements vscode.D
323336
324337 readonly compileConsumer : CompileOutputConsumer ;
325338
339+ /**
340+ * Event fired when a new diagnostic is parsed from compiler output
341+ */
342+ get onDiagnostic ( ) {
343+ return this . compileConsumer . onDiagnostic ;
344+ }
345+
326346 dispose ( ) {
327347 this . _onProgressEmitter . dispose ( ) ;
348+ this . compileConsumer . dispose ( ) ;
328349 }
329350
330351 error ( line : string ) {
0 commit comments