@@ -37,6 +37,23 @@ enum ErrorKind
37
37
message,
38
38
}
39
39
40
+ /**
41
+ Represents a diagnostic message generated during compilation, such as errors, warnings, or other messages.
42
+
43
+ Params:
44
+ loc = The location in the source code where the diagnostic was generated (includes file, line, and column).
45
+ message = The text of the diagnostic message, describing the issue.
46
+ kind = The type of diagnostic, indicating whether it is an error, warning, deprecation, etc.
47
+ */
48
+ struct Diagnostic
49
+ {
50
+ SourceLoc loc;
51
+ string message;
52
+ ErrorKind kind;
53
+ }
54
+
55
+ Diagnostic[] diagnostics; // Global array to store diagnostics
56
+
40
57
/* **************************
41
58
* Error message sink for D compiler.
42
59
*/
@@ -101,6 +118,153 @@ class ErrorSinkCompiler : ErrorSink
101
118
verrorReport(loc, format, ap, ErrorKind.message);
102
119
va_end(ap);
103
120
}
121
+
122
+ void plugSink ()
123
+ {
124
+ // Only proceed if there are collected diagnostics
125
+ if (diagnostics.length > 0 )
126
+ {
127
+ OutBuffer ob;
128
+ ob.doindent = true ;
129
+
130
+ // Extract and clean the version string
131
+ string toolVersion = global.versionString();
132
+ // Remove 'v' prefix if it exists
133
+ if (toolVersion.length > 0 && toolVersion[0 ] == ' v' ) {
134
+ toolVersion = toolVersion[1 .. $];
135
+ }
136
+ // Find the first non-numeric character after the version number
137
+ size_t length = toolVersion.length;
138
+ const (char )* nonNumeric = strchr(toolVersion.ptr, ' -' );
139
+ if (nonNumeric) {
140
+ length = cast (size_t )(nonNumeric - toolVersion.ptr);
141
+ }
142
+ string cleanedVersion = toolVersion[0 .. length];
143
+
144
+ // Build SARIF report
145
+ ob.writestringln(" {" );
146
+ ob.level = 1 ;
147
+ ob.writestringln(` "version": "2.1.0",` );
148
+ ob.writestringln(` "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json",` );
149
+ ob.writestringln(` "runs": [{` );
150
+
151
+ // Tool Information
152
+ ob.level += 1 ;
153
+ ob.writestringln(` "tool": {` );
154
+ ob.level += 1 ;
155
+ ob.writestringln(` "driver": {` );
156
+ ob.level += 1 ;
157
+
158
+ // Write "name" field
159
+ ob.writestring(` "name": "` );
160
+ ob.writestring(global.compileEnv.vendor.ptr);
161
+ ob.writestringln(` ",` );
162
+
163
+ // Write "version" field
164
+ ob.writestring(` "version": "` );
165
+ ob.writestring(cleanedVersion);
166
+ ob.writestringln(` ",` );
167
+ ob.writestring(` "informationUri": "https://dlang.org/dmd.html"` );
168
+ ob.writestringln(" " );
169
+ ob.level -= 1 ;
170
+ ob.writestringln(" }" );
171
+ ob.level -= 1 ;
172
+ ob.writestringln(" }," );
173
+
174
+ // Invocation Information
175
+ ob.writestringln(` "invocations": [{` );
176
+ ob.level += 1 ;
177
+ ob.writestring(` "executionSuccessful": false` );
178
+ ob.writestringln(" " );
179
+ ob.level -= 1 ;
180
+ ob.writestringln(" }]," );
181
+
182
+ // Results Array
183
+ ob.writestringln(` "results": [` );
184
+ ob.level += 1 ;
185
+
186
+ foreach (idx, diag; diagnostics)
187
+ {
188
+ ob.writestringln(" {" );
189
+ ob.level += 1 ;
190
+
191
+ // Rule ID
192
+ ob.writestring(` "ruleId": "DMD-ERROR",` );
193
+ ob.writestringln(" " );
194
+
195
+ // Message Information
196
+ ob.writestringln(` "message": {` );
197
+ ob.level += 1 ;
198
+ ob.writestring(` "text": "` );
199
+ ob.writestring(diag.message);
200
+ ob.writestringln(` "` );
201
+ ob.level -= 1 ;
202
+ ob.writestringln(" }," );
203
+
204
+ // Error Severity Level
205
+ ob.writestring(` "level": "error",` );
206
+ ob.writestringln(" " );
207
+
208
+ // Location Information
209
+ ob.writestringln(` "locations": [{` );
210
+ ob.level += 1 ;
211
+ ob.writestringln(` "physicalLocation": {` );
212
+ ob.level += 1 ;
213
+
214
+ // Artifact Location
215
+ ob.writestringln(` "artifactLocation": {` );
216
+ ob.level += 1 ;
217
+ ob.writestring(` "uri": "` );
218
+ ob.writestring(diag.loc.filename);
219
+ ob.writestringln(` "` );
220
+ ob.level -= 1 ;
221
+ ob.writestringln(" }," );
222
+
223
+
224
+ // Region Information
225
+ ob.writestringln(` "region": {` );
226
+ ob.level += 1 ;
227
+ ob.writestring(` "startLine": ` );
228
+ ob.printf(` %d,` , diag.loc.linnum);
229
+ ob.writestringln(" " );
230
+ ob.writestring(` "startColumn": ` );
231
+ ob.printf(` %d` , diag.loc.charnum);
232
+ ob.writestringln(" " );
233
+ ob.level -= 1 ;
234
+ ob.writestringln(" }" );
235
+
236
+ // Close physicalLocation and locations
237
+ ob.level -= 1 ;
238
+ ob.writestringln(" }" );
239
+ ob.level -= 1 ;
240
+ ob.writestringln(" }]" );
241
+
242
+ // Closing brace for each diagnostic item
243
+ ob.level -= 1 ;
244
+ if (idx < diagnostics.length - 1 ) {
245
+ ob.writestringln(" }," );
246
+ } else {
247
+ ob.writestringln(" }" );
248
+ }
249
+ }
250
+
251
+ // Close results, run, and JSON document
252
+ ob.level -= 1 ;
253
+ ob.writestringln(" ]" );
254
+ ob.level -= 1 ;
255
+ ob.writestringln(" }]" );
256
+ ob.level -= 1 ;
257
+ ob.writestringln(" }" );
258
+
259
+ // Print the SARIF output to stdout
260
+ const (char )* sarifOutput = ob.extractChars();
261
+ fputs(sarifOutput, stdout);
262
+ fflush(stdout);
263
+
264
+ // Clear diagnostics after generating the report
265
+ diagnostics.length = 0 ;
266
+ }
267
+ }
104
268
}
105
269
106
270
@@ -467,6 +631,14 @@ private extern(C++) void verrorReport(const Loc loc, const(char)* format, va_lis
467
631
private extern (C++ ) void verrorReport(const SourceLoc loc, const (char )* format, va_list ap, ErrorKind kind, const (char )* p1 = null , const (char )* p2 = null )
468
632
{
469
633
auto info = ErrorInfo(loc, kind, p1, p2);
634
+
635
+ // Buffer to hold the fully formatted message
636
+ char [1024 ] buffer;
637
+ int written = vsnprintf(buffer.ptr, buffer.length, format, ap);
638
+
639
+ // Handle any truncation that may have occurred
640
+ string formattedMessage = cast (string ) buffer[0 .. (written < 0 ? 0 : written)].dup ;
641
+
470
642
final switch (info.kind)
471
643
{
472
644
case ErrorKind.error:
@@ -476,7 +648,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format,
476
648
info.headerColor = Classification.error;
477
649
if (global.params.v.messageStyle == MessageStyle.sarif)
478
650
{
479
- generateSarifReport (loc, format, ap, info. kind, false );
651
+ diagnostics ~= Diagnostic (loc, formattedMessage, kind);
480
652
return ;
481
653
}
482
654
verrorPrint(format, ap, info);
@@ -510,7 +682,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format,
510
682
info.headerColor = Classification.deprecation;
511
683
if (global.params.v.messageStyle == MessageStyle.sarif)
512
684
{
513
- generateSarifReport (loc, format, ap, info. kind, false );
685
+ diagnostics ~= Diagnostic (loc, formattedMessage, kind);
514
686
return ;
515
687
}
516
688
verrorPrint(format, ap, info);
@@ -531,7 +703,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format,
531
703
info.headerColor = Classification.warning;
532
704
if (global.params.v.messageStyle == MessageStyle.sarif)
533
705
{
534
- generateSarifReport (loc, format, ap, info. kind, false );
706
+ diagnostics ~= Diagnostic (loc, formattedMessage, kind);
535
707
return ;
536
708
}
537
709
verrorPrint(format, ap, info);
@@ -551,7 +723,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format,
551
723
info.headerColor = Classification.tip;
552
724
if (global.params.v.messageStyle == MessageStyle.sarif)
553
725
{
554
- generateSarifReport (loc, format, ap, info. kind, false );
726
+ diagnostics ~= Diagnostic (loc, formattedMessage, kind);
555
727
return ;
556
728
}
557
729
verrorPrint(format, ap, info);
@@ -571,7 +743,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format,
571
743
fflush(stdout); // ensure it gets written out in case of compiler aborts
572
744
if (global.params.v.messageStyle == MessageStyle.sarif)
573
745
{
574
- generateSarifReport (loc, format, ap, info. kind, false );
746
+ diagnostics ~= Diagnostic (loc, formattedMessage, kind);
575
747
return ;
576
748
}
577
749
return ;
0 commit comments