diff --git a/compiler/src/dmd/errors.d b/compiler/src/dmd/errors.d index 99a89c31d05..98086a19519 100644 --- a/compiler/src/dmd/errors.d +++ b/compiler/src/dmd/errors.d @@ -529,6 +529,11 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, if (!global.gag) { info.headerColor = Classification.warning; + if (global.params.v.messageStyle == MessageStyle.sarif) + { + generateSarifReport(loc, format, ap, info.kind); + return; + } verrorPrint(format, ap, info); if (global.params.useWarnings == DiagnosticReporting.error) global.warnings++; @@ -567,6 +572,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, if (global.params.v.messageStyle == MessageStyle.sarif) { generateSarifReport(loc, format, ap, info.kind); + return; } return; } diff --git a/compiler/src/dmd/sarif.d b/compiler/src/dmd/sarif.d index 98f1938af71..7eee37b9dd8 100644 --- a/compiler/src/dmd/sarif.d +++ b/compiler/src/dmd/sarif.d @@ -106,6 +106,26 @@ void generateSarifReport(const ref SourceLoc loc, const(char)* format, va_list a // Format the error message string formattedMessage = formatErrorMessage(format, ap); + // Map ErrorKind to SARIF levels + const(char)* level; + final switch (kind) { + case ErrorKind.error: + level = "error"; + break; + case ErrorKind.warning: + level = "warning"; + break; + case ErrorKind.deprecation: + level = "deprecation"; + break; + case ErrorKind.tip: + level = "note"; + break; + case ErrorKind.message: + level = "none"; + break; + } + // Create an OutBuffer to store the SARIF report OutBuffer ob; ob.doindent = true; @@ -134,36 +154,86 @@ void generateSarifReport(const ref SourceLoc loc, const(char)* format, va_list a // Tool Information ob.level += 1; ob.writestringln(`"tool": {`); + ob.level += 1; ob.writestringln(`"driver": {`); - ob.printf(`"name": "%s",`, global.compileEnv.vendor.ptr); - ob.printf(`"version": "%.*s",`, cast(int)length, rawVersionChars); + ob.level += 1; + + // Write "name" field + ob.writestring(`"name": "`); + ob.writestring(global.compileEnv.vendor.ptr); + ob.writestringln(`",`); + + // Write "version" field + ob.writestring(`"version": "`); + ob.writestring(cast(string)rawVersionChars[0 .. length]); + ob.writestringln(`",`); + + // Write "informationUri" field ob.writestringln(`"informationUri": "https://dlang.org/dmd.html"`); + ob.level -= 1; ob.writestringln("}"); + ob.level -= 1; ob.writestringln("},"); // Invocation Information ob.writestringln(`"invocations": [{`); + ob.level += 1; ob.writestringln(`"executionSuccessful": false`); + ob.level -= 1; ob.writestringln("}],"); // Results Array ob.writestringln(`"results": [{`); + ob.level += 1; ob.writestringln(`"ruleId": "DMD",`); - ob.printf(`"message": { "text": "%s" },`, formattedMessage.ptr); + + // Message Information + ob.writestringln(`"message": {`); + ob.level += 1; + ob.writestring(`"text": "`); + ob.writestring(formattedMessage.ptr); + ob.writestringln(`"`); + ob.level -= 1; + ob.writestringln(`},`); + + // Error Severity Level + ob.writestring(`"level": "`); + ob.writestring(level); + ob.writestringln(`",`); // Location Information ob.writestringln(`"locations": [{`); + ob.level += 1; ob.writestringln(`"physicalLocation": {`); + ob.level += 1; + + // Artifact Location ob.writestringln(`"artifactLocation": {`); + ob.level += 1; ob.writestring(`"uri": "`); ob.writestring(loc.filename); - ob.writestringln(`"},`); + ob.writestringln(`"`); + ob.level -= 1; + ob.writestringln(`},`); + + // Region Information ob.writestringln(`"region": {`); - ob.printf(`"startLine": %d,`, loc.linnum); - ob.printf(`"startColumn": %d`, loc.charnum); - ob.writestringln("}"); - ob.writestringln("}"); - ob.writestringln("}]"); + ob.level += 1; + ob.writestring(`"startLine": `); + ob.printf(`%d,`, loc.linnum); + ob.writestringln(``); + ob.writestring(`"startColumn": `); + ob.printf(`%d`, loc.charnum); + ob.writestringln(``); + ob.level -= 1; + ob.writestringln(`}`); + + // Close physicalLocation and locations + ob.level -= 1; + ob.writestringln(`}`); + ob.level -= 1; + ob.writestringln(`}]`); + ob.level -= 1; ob.writestringln("}]"); // Close the run and SARIF JSON diff --git a/compiler/test/fail_compilation/sarif_test.d b/compiler/test/fail_compilation/sarif_test.d index cbb94cb3a55..6f147e4fde9 100644 --- a/compiler/test/fail_compilation/sarif_test.d +++ b/compiler/test/fail_compilation/sarif_test.d @@ -6,23 +6,32 @@ TEST_OUTPUT: "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", "runs": [{ "tool": { - "driver": { - "name": "Digital Mars D","version": "2.110.0","informationUri": "https://dlang.org/dmd.html" - } + "driver": { + "name": "Digital Mars D", + "version": "2.110.0", + "informationUri": "https://dlang.org/dmd.html" + } }, "invocations": [{ - "executionSuccessful": false + "executionSuccessful": false }], "results": [{ - "ruleId": "DMD", - "message": { "text": "undefined identifier `x`" },"locations": [{ - "physicalLocation": { - "artifactLocation": { - "uri": "fail_compilation/sarif_test.d"}, - "region": { - "startLine": 34,"startColumn": 5} - } - }] + "ruleId": "DMD", + "message": { + "text": "undefined identifier `x`" + }, + "level": "error", + "locations": [{ + "physicalLocation": { + "artifactLocation": { + "uri": "fail_compilation/sarif_test.d" + }, + "region": { + "startLine": 43, + "startColumn": 5 + } + } + }] }] }] }