diff --git a/compiler/src/dmd/cli.d b/compiler/src/dmd/cli.d index 2274ab4c1ad8..e721a2c798d7 100644 --- a/compiler/src/dmd/cli.d +++ b/compiler/src/dmd/cli.d @@ -825,13 +825,14 @@ dmd -cov -unittest myprog.d Option("vcolumns", "print character (column) numbers in diagnostics" ), - Option("verror-style=[digitalmars|gnu]", + Option("verror-style=[digitalmars|gnu|sarif]", "set the style for file/line number annotations on compiler messages", `Set the style for file/line number annotations on compiler messages, where: $(DL $(DT digitalmars)$(DD 'file(line[,column]): message'. This is the default.) $(DT gnu)$(DD 'file:line[:column]: message', conforming to the GNU standard used by gcc and clang.) + $(DT sarif)$(DD 'Generates JSON output conforming to the SARIF (Static Analysis Results Interchange Format) standard, useful for integration with tools like GitHub and other SARIF readers.') )`, ), Option("verror-supplements=", diff --git a/compiler/src/dmd/errors.d b/compiler/src/dmd/errors.d index aeeb11500605..a5c9c35e18ad 100644 --- a/compiler/src/dmd/errors.d +++ b/compiler/src/dmd/errors.d @@ -615,7 +615,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, // Fix: Convert filename to const(char)* using .ptr Loc sourceLoc = Loc(info.loc.filename.ptr, info.loc.linnum, info.loc.charnum); - if (global.params.sarifEnabled) + if (global.params.v.messageStyle == MessageStyle.sarif) { generateSarifReport(sourceLoc, format, ap, info.kind); } @@ -651,7 +651,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, // Fix: Convert filename to const(char)* using .ptr Loc sourceLoc = Loc(info.loc.filename.ptr, info.loc.linnum, info.loc.charnum); - if (global.params.sarifEnabled) + if (global.params.v.messageStyle == MessageStyle.sarif) { generateSarifReport(sourceLoc, format, ap, info.kind); } @@ -689,7 +689,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, // Fix: Convert filename to const(char)* using .ptr Loc sourceLoc = Loc(info.loc.filename.ptr, info.loc.linnum, info.loc.charnum); - if (global.params.sarifEnabled) + if (global.params.v.messageStyle == MessageStyle.sarif) { generateSarifReport(sourceLoc, format, ap, info.kind); } @@ -709,7 +709,7 @@ private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, fflush(stdout); // ensure it gets written out in case of compiler aborts // Fix: Convert filename to const(char)* using .ptr Loc sourceLoc = Loc(info.loc.filename.ptr, info.loc.linnum, info.loc.charnum); - if (global.params.sarifEnabled) + if (global.params.v.messageStyle == MessageStyle.sarif) { generateSarifReport(sourceLoc, format, ap, info.kind); } diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index c5ebc5c3a10e..8e186f5e29a6 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -374,6 +374,7 @@ enum class MessageStyle : uint8_t { digitalmars = 0u, gnu = 1u, + sarif = 2u, }; struct Loc final @@ -8232,7 +8233,6 @@ struct Param final bool addMain; bool allInst; bool bitfields; - bool sarifEnabled; CppStdRevision cplusplus; Help help; Verbose v; @@ -8320,7 +8320,6 @@ struct Param final addMain(), allInst(), bitfields(), - sarifEnabled(false), cplusplus((CppStdRevision)201103u), help(), v(), @@ -8378,7 +8377,7 @@ struct Param final timeTraceFile() { } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, bool sarifEnabled = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array imppath = Array(), Array fileImppath = Array(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) : + Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array imppath = Array(), Array fileImppath = Array(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) : obj(obj), multiobj(multiobj), trace(trace), @@ -8402,7 +8401,6 @@ struct Param final addMain(addMain), allInst(allInst), bitfields(bitfields), - sarifEnabled(sarifEnabled), cplusplus(cplusplus), help(help), v(v), diff --git a/compiler/src/dmd/globals.d b/compiler/src/dmd/globals.d index 7d193c6cfe22..ccb63e330e9e 100644 --- a/compiler/src/dmd/globals.d +++ b/compiler/src/dmd/globals.d @@ -170,7 +170,6 @@ extern (C++) struct Param bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations bool bitfields; // support C style bit fields - bool sarifEnabled = false; // New flag to track SARIF reporting CppStdRevision cplusplus = CppStdRevision.cpp11; // version of C++ standard to support diff --git a/compiler/src/dmd/globals.h b/compiler/src/dmd/globals.h index 138e4f10fb6e..5348d614ebb3 100644 --- a/compiler/src/dmd/globals.h +++ b/compiler/src/dmd/globals.h @@ -35,7 +35,8 @@ enum enum class MessageStyle : unsigned char { digitalmars, // file(line,column): message - gnu // file:line:column: message + gnu, // file:line:column: message + sarif // JSON SARIF output, see https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html }; // The state of array bounds checking @@ -173,7 +174,6 @@ struct Param d_bool addMain; // add a default main() function d_bool allInst; // generate code for all template instantiations d_bool bitfields; // support C style bit fields - d_bool sarifEnabled; // New flag for SARIF support CppStdRevision cplusplus; // version of C++ name mangling to support Help help; diff --git a/compiler/src/dmd/location.d b/compiler/src/dmd/location.d index 76f6af76db38..078706859101 100644 --- a/compiler/src/dmd/location.d +++ b/compiler/src/dmd/location.d @@ -28,8 +28,8 @@ enum MessageStyle : ubyte { digitalmars, /// filename.d(line): message gnu, /// filename.d:line: message, see https://www.gnu.org/prep/standards/html_node/Errors.html + sarif /// JSON SARIF output, see https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html } - /** A source code location @@ -223,6 +223,9 @@ void writeSourceLoc(ref OutBuffer buf, buf.print(loc.column); } break; + case MessageStyle.sarif: // https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html + // No formatting needed here for SARIF + break; } } diff --git a/compiler/src/dmd/mars.d b/compiler/src/dmd/mars.d index eef5e85379fc..a2e202cf33d8 100644 --- a/compiler/src/dmd/mars.d +++ b/compiler/src/dmd/mars.d @@ -681,10 +681,6 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param return false; } } - else if (arg == "--sarif") // Custom SARIF flag handling - { - global.params.sarifEnabled = true; // Set SARIF flag - } else if (startsWith(p + 1, "check")) // https://dlang.org/dmd.html#switch-check { enum len = "-check=".length; @@ -1038,8 +1034,11 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param case "gnu": params.v.messageStyle = MessageStyle.gnu; break; + case "sarif": + params.v.messageStyle = MessageStyle.sarif; + break; default: - error("unknown error style '%.*s', must be 'digitalmars' or 'gnu'", cast(int) style.length, style.ptr); + error("unknown error style '%.*s', must be 'digitalmars', 'gnu', or 'sarif'", cast(int) style.length, style.ptr); } } else if (startsWith(p + 1, "target")) diff --git a/compiler/test/fail_compilation/sarif_test.d b/compiler/test/fail_compilation/sarif_test.d index e6a8da6cf741..4ef66f0499f2 100644 --- a/compiler/test/fail_compilation/sarif_test.d +++ b/compiler/test/fail_compilation/sarif_test.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/sarif_test.d(33): Error: undefined identifier `x` +fail_compilation/sarif_test.d: Error: undefined identifier `x` { "invocation": { "executionSuccessful": false @@ -27,7 +27,7 @@ fail_compilation/sarif_test.d(33): Error: undefined identifier `x` } --- */ -// REQUIRED_ARGS: --sarif +// REQUIRED_ARGS: -verror-style=sarif void main() { x = 5; // Undefined variable to trigger the error