[clang] 1bd2b2d - Add support for specifying the severity of a SARIF Result

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 19 04:15:07 PDT 2022


Author: Vaibhav Yenamandra
Date: 2022-08-19T07:14:50-04:00
New Revision: 1bd2b2dce2a92dd2777f4fe08098b8f19e3fb593

URL: https://github.com/llvm/llvm-project/commit/1bd2b2dce2a92dd2777f4fe08098b8f19e3fb593
DIFF: https://github.com/llvm/llvm-project/commit/1bd2b2dce2a92dd2777f4fe08098b8f19e3fb593.diff

LOG: Add support for specifying the severity of a SARIF Result

* Extend SarifResult with level property, and allow rule configuration
* Create SarifReportingConfiguration which allow configuring rules with
a default priority, severity and an enable-toggle
* Support for setting the level property[1] of a result.

If unset, it defaults to "warning", which is the result of an empty
default configuration on rules[2]

[1]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317648
[2]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317855

Differential Revision: https://reviews.llvm.org/D131084

Added: 
    

Modified: 
    clang/include/clang/Basic/Sarif.h
    clang/lib/Basic/Sarif.cpp
    clang/unittests/Basic/SarifTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Sarif.h b/clang/include/clang/Basic/Sarif.h
index 818d78668ff15..3d169e1122b12 100644
--- a/clang/include/clang/Basic/Sarif.h
+++ b/clang/include/clang/Basic/Sarif.h
@@ -145,6 +145,25 @@ class SarifArtifact {
 
 enum class ThreadFlowImportance { Important, Essential, Unimportant };
 
+/// The level of severity associated with a \ref SarifResult.
+///
+/// Of all the levels, \c None is the only one that is not associated with
+/// a failure.
+///
+/// A typical mapping for clang's DiagnosticKind to SarifResultLevel would look
+/// like:
+/// * \c None: \ref clang::DiagnosticsEngine::Level::Remark, \ref clang::DiagnosticsEngine::Level::Ignored
+/// * \c Note: \ref clang::DiagnosticsEngine::Level::Note
+/// * \c Warning: \ref clang::DiagnosticsEngine::Level::Warning
+/// * \c Error could be generated from one of:
+///   - \ref clang::DiagnosticsEngine::Level::Warning with \c -Werror
+///   - \ref clang::DiagnosticsEngine::Level::Error
+///   - \ref clang::DiagnosticsEngine::Level::Fatal when \ref clang::DiagnosticsEngine::ErrorsAsFatal is set.
+///
+/// Reference:
+/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317648">level property</a>
+enum class SarifResultLevel { None, Note, Warning, Error };
+
 /// A thread flow is a sequence of code locations that specify a possible path
 /// through a single thread of execution.
 /// A thread flow in SARIF is related to a code flow which describes
@@ -183,6 +202,47 @@ class ThreadFlow {
   }
 };
 
+/// A SARIF Reporting Configuration (\c reportingConfiguration) object contains
+/// properties for a \ref SarifRule that can be configured at runtime before
+/// analysis begins.
+///
+/// Reference:
+/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317852">reportingConfiguration object</a>
+class SarifReportingConfiguration {
+  friend class clang::SarifDocumentWriter;
+
+  bool Enabled = true;
+  SarifResultLevel Level = SarifResultLevel::Warning;
+  float Rank = -1.0f;
+
+  SarifReportingConfiguration() = default;
+
+public:
+  static SarifReportingConfiguration create() { return {}; };
+
+  SarifReportingConfiguration disable() {
+    Enabled = false;
+    return *this;
+  }
+
+  SarifReportingConfiguration enable() {
+    Enabled = true;
+    return *this;
+  }
+
+  SarifReportingConfiguration setLevel(SarifResultLevel TheLevel) {
+    Level = TheLevel;
+    return *this;
+  }
+
+  SarifReportingConfiguration setRank(float TheRank) {
+    assert(TheRank >= 0.0f && "Rule rank cannot be smaller than 0.0");
+    assert(TheRank <= 100.0f && "Rule rank cannot be larger than 100.0");
+    Rank = TheRank;
+    return *this;
+  }
+};
+
 /// A SARIF rule (\c reportingDescriptor object) contains information that
 /// describes a reporting item generated by a tool. A reporting item is
 /// either a result of analysis or notification of a condition encountered by
@@ -201,8 +261,9 @@ class SarifRule {
   std::string Id;
   std::string Description;
   std::string HelpURI;
+  SarifReportingConfiguration DefaultConfiguration;
 
-  SarifRule() = default;
+  SarifRule() : DefaultConfiguration(SarifReportingConfiguration::create()) {}
 
 public:
   static SarifRule create() { return {}; }
@@ -226,6 +287,12 @@ class SarifRule {
     HelpURI = RuleHelpURI.str();
     return *this;
   }
+
+  SarifRule
+  setDefaultConfiguration(const SarifReportingConfiguration &Configuration) {
+    DefaultConfiguration = Configuration;
+    return *this;
+  }
 };
 
 /// A SARIF result (also called a "reporting item") is a unit of output
@@ -257,6 +324,7 @@ class SarifResult {
   std::string DiagnosticMessage;
   llvm::SmallVector<CharSourceRange, 8> Locations;
   llvm::SmallVector<ThreadFlow, 8> ThreadFlows;
+  llvm::Optional<SarifResultLevel> LevelOverride;
 
   SarifResult() = delete;
   explicit SarifResult(uint32_t RuleIdx) : RuleIdx(RuleIdx) {}
@@ -293,6 +361,11 @@ class SarifResult {
     ThreadFlows.assign(ThreadFlowResults.begin(), ThreadFlowResults.end());
     return *this;
   }
+
+  SarifResult setDiagnosticLevel(const SarifResultLevel &TheLevel) {
+    LevelOverride = TheLevel;
+    return *this;
+  }
 };
 
 /// This class handles creating a valid SARIF document given various input

diff  --git a/clang/lib/Basic/Sarif.cpp b/clang/lib/Basic/Sarif.cpp
index faca9c508c080..73be86b57df77 100644
--- a/clang/lib/Basic/Sarif.cpp
+++ b/clang/lib/Basic/Sarif.cpp
@@ -180,6 +180,21 @@ static StringRef importanceToStr(ThreadFlowImportance I) {
   llvm_unreachable("Fully covered switch is not so fully covered");
 }
 
+static StringRef resultLevelToStr(SarifResultLevel R) {
+  switch (R) {
+  case SarifResultLevel::None:
+    return "none";
+  case SarifResultLevel::Note:
+    return "note";
+  case SarifResultLevel::Warning:
+    return "warning";
+  case SarifResultLevel::Error:
+    return "error";
+  }
+  llvm_unreachable("Potentially un-handled SarifResultLevel. "
+                   "Is the switch not fully covered?");
+}
+
 static json::Object
 createThreadFlowLocation(json::Object &&Location,
                          const ThreadFlowImportance &Importance) {
@@ -253,10 +268,15 @@ void SarifDocumentWriter::endRun() {
   json::Object &Tool = getCurrentTool();
   json::Array Rules;
   for (const SarifRule &R : CurrentRules) {
+    json::Object Config{
+        {"enabled", R.DefaultConfiguration.Enabled},
+        {"level", resultLevelToStr(R.DefaultConfiguration.Level)},
+        {"rank", R.DefaultConfiguration.Rank}};
     json::Object Rule{
         {"name", R.Name},
         {"id", R.Id},
-        {"fullDescription", json::Object{{"text", R.Description}}}};
+        {"fullDescription", json::Object{{"text", R.Description}}},
+        {"defaultConfiguration", std::move(Config)}};
     if (!R.HelpURI.empty())
       Rule["helpUri"] = R.HelpURI;
     Rules.emplace_back(std::move(Rule));
@@ -358,9 +378,12 @@ void SarifDocumentWriter::appendResult(const SarifResult &Result) {
   size_t RuleIdx = Result.RuleIdx;
   assert(RuleIdx < CurrentRules.size() &&
          "Trying to reference a rule that doesn't exist");
+  const SarifRule &Rule = CurrentRules[RuleIdx];
+  assert(Rule.DefaultConfiguration.Enabled &&
+         "Cannot add a result referencing a disabled Rule");
   json::Object Ret{{"message", createMessage(Result.DiagnosticMessage)},
                    {"ruleIndex", static_cast<int64_t>(RuleIdx)},
-                   {"ruleId", CurrentRules[RuleIdx].Id}};
+                   {"ruleId", Rule.Id}};
   if (!Result.Locations.empty()) {
     json::Array Locs;
     for (auto &Range : Result.Locations) {
@@ -370,6 +393,10 @@ void SarifDocumentWriter::appendResult(const SarifResult &Result) {
   }
   if (!Result.ThreadFlows.empty())
     Ret["codeFlows"] = json::Array{createCodeFlow(Result.ThreadFlows)};
+
+  Ret["level"] = resultLevelToStr(
+      Result.LevelOverride.value_or(Rule.DefaultConfiguration.Level));
+
   json::Object &Run = getCurrentRun();
   json::Array *Results = Run.getArray("results");
   Results->emplace_back(std::move(Ret));

diff  --git a/clang/unittests/Basic/SarifTest.cpp b/clang/unittests/Basic/SarifTest.cpp
index e647d362fcc66..fb68f4a4b99b8 100644
--- a/clang/unittests/Basic/SarifTest.cpp
+++ b/clang/unittests/Basic/SarifTest.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Sarif.h"
-#include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/FileSystemOptions.h"
@@ -33,9 +32,9 @@ using LineCol = std::pair<unsigned int, unsigned int>;
 
 static std::string serializeSarifDocument(llvm::json::Object &&Doc) {
   std::string Output;
-  llvm::json::Value value(std::move(Doc));
+  llvm::json::Value Value(std::move(Doc));
   llvm::raw_string_ostream OS{Output};
-  OS << llvm::formatv("{0}", value);
+  OS << llvm::formatv("{0}", Value);
   OS.flush();
   return Output;
 }
@@ -86,7 +85,7 @@ TEST_F(SarifDocumentWriterTest, canCreateEmptyDocument) {
   const llvm::json::Object &EmptyDoc = Writer.createDocument();
   std::vector<StringRef> Keys(EmptyDoc.size());
   std::transform(EmptyDoc.begin(), EmptyDoc.end(), Keys.begin(),
-                 [](auto item) { return item.getFirst(); });
+                 [](auto Item) { return Item.getFirst(); });
 
   // THEN:
   ASSERT_THAT(Keys, testing::UnorderedElementsAre("$schema", "version"));
@@ -113,17 +112,17 @@ TEST_F(SarifDocumentWriterTest, canCreateDocumentWithOneRun) {
   ASSERT_EQ(Runs->size(), 1UL);
 
   // The tool associated with the run was the tool
-  const llvm::json::Object *driver =
+  const llvm::json::Object *Driver =
       Runs->begin()->getAsObject()->getObject("tool")->getObject("driver");
-  ASSERT_THAT(driver, testing::NotNull());
+  ASSERT_THAT(Driver, testing::NotNull());
 
-  ASSERT_TRUE(driver->getString("name").has_value());
-  ASSERT_TRUE(driver->getString("fullName").has_value());
-  ASSERT_TRUE(driver->getString("language").has_value());
+  ASSERT_TRUE(Driver->getString("name").has_value());
+  ASSERT_TRUE(Driver->getString("fullName").has_value());
+  ASSERT_TRUE(Driver->getString("language").has_value());
 
-  EXPECT_EQ(driver->getString("name").value(), ShortName);
-  EXPECT_EQ(driver->getString("fullName").value(), LongName);
-  EXPECT_EQ(driver->getString("language").value(), "en-US");
+  EXPECT_EQ(Driver->getString("name").value(), ShortName);
+  EXPECT_EQ(Driver->getString("fullName").value(), LongName);
+  EXPECT_EQ(Driver->getString("language").value(), "en-US");
 }
 
 TEST_F(SarifDocumentWriterTest, addingResultsWillCrashIfThereIsNoRun) {
@@ -147,6 +146,47 @@ TEST_F(SarifDocumentWriterTest, addingResultsWillCrashIfThereIsNoRun) {
   ASSERT_DEATH(Writer.appendResult(EmptyResult), Matcher);
 }
 
+TEST_F(SarifDocumentWriterTest, settingInvalidRankWillCrash) {
+#if defined(NDEBUG) || !GTEST_HAS_DEATH_TEST
+  GTEST_SKIP() << "This death test is only available for debug builds.";
+#endif
+  // GIVEN:
+  SarifDocumentWriter Writer{SourceMgr};
+
+  // WHEN:
+  // A SarifReportingConfiguration is created with an invalid "rank"
+  // * Ranks below 0.0 are invalid
+  // * Ranks above 100.0 are invalid
+
+  // THEN: The builder will crash in either case
+  EXPECT_DEATH(SarifReportingConfiguration::create().setRank(-1.0),
+               ::testing::HasSubstr("Rule rank cannot be smaller than 0.0"));
+  EXPECT_DEATH(SarifReportingConfiguration::create().setRank(101.0),
+               ::testing::HasSubstr("Rule rank cannot be larger than 100.0"));
+}
+
+TEST_F(SarifDocumentWriterTest, creatingResultWithDisabledRuleWillCrash) {
+#if defined(NDEBUG) || !GTEST_HAS_DEATH_TEST
+  GTEST_SKIP() << "This death test is only available for debug builds.";
+#endif
+
+  // GIVEN:
+  SarifDocumentWriter Writer{SourceMgr};
+
+  // WHEN:
+  // A disabled Rule is created, and a result is create referencing this rule
+  const auto &Config = SarifReportingConfiguration::create().disable();
+  auto RuleIdx =
+      Writer.createRule(SarifRule::create().setDefaultConfiguration(Config));
+  const SarifResult &Result = SarifResult::create(RuleIdx);
+
+  // THEN:
+  // SarifResult::create(...) will produce a crash
+  ASSERT_DEATH(
+      Writer.appendResult(Result),
+      ::testing::HasSubstr("Cannot add a result referencing a disabled Rule"));
+}
+
 // Test adding rule and result shows up in the final document
 TEST_F(SarifDocumentWriterTest, addingResultWithValidRuleAndRunIsOk) {
   // GIVEN:
@@ -160,9 +200,9 @@ TEST_F(SarifDocumentWriterTest, addingResultWithValidRuleAndRunIsOk) {
   // WHEN:
   Writer.createRun("sarif test", "sarif test runner");
   unsigned RuleIdx = Writer.createRule(Rule);
-  const SarifResult &result = SarifResult::create(RuleIdx);
+  const SarifResult &Result = SarifResult::create(RuleIdx);
 
-  Writer.appendResult(result);
+  Writer.appendResult(Result);
   const llvm::json::Object &Doc = Writer.createDocument();
 
   // THEN:
@@ -199,10 +239,10 @@ TEST_F(SarifDocumentWriterTest, addingResultWithValidRuleAndRunIsOk) {
   EXPECT_TRUE(Artifacts->empty());
 }
 
-TEST_F(SarifDocumentWriterTest, checkSerializingResults) {
+TEST_F(SarifDocumentWriterTest, checkSerializingResultsWithDefaultRuleConfig) {
   // GIVEN:
   const std::string ExpectedOutput =
-      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[],"columnKind":"unicodeCodePoints","results":[{"message":{"text":""},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
+      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[],"columnKind":"unicodeCodePoints","results":[{"level":"warning","message":{"text":""},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"defaultConfiguration":{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
 
   SarifDocumentWriter Writer{SourceMgr};
   const SarifRule &Rule =
@@ -213,8 +253,34 @@ TEST_F(SarifDocumentWriterTest, checkSerializingResults) {
 
   // WHEN: A run contains a result
   Writer.createRun("sarif test", "sarif test runner", "1.0.0");
-  unsigned ruleIdx = Writer.createRule(Rule);
-  const SarifResult &Result = SarifResult::create(ruleIdx);
+  unsigned RuleIdx = Writer.createRule(Rule);
+  const SarifResult &Result = SarifResult::create(RuleIdx);
+  Writer.appendResult(Result);
+  std::string Output = serializeSarifDocument(Writer.createDocument());
+
+  // THEN:
+  ASSERT_THAT(Output, ::testing::StrEq(ExpectedOutput));
+}
+
+TEST_F(SarifDocumentWriterTest, checkSerializingResultsWithCustomRuleConfig) {
+  // GIVEN:
+  const std::string ExpectedOutput =
+      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[],"columnKind":"unicodeCodePoints","results":[{"level":"error","message":{"text":""},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"defaultConfiguration":{"enabled":true,"level":"error","rank":35.5},"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
+
+  SarifDocumentWriter Writer{SourceMgr};
+  const SarifRule &Rule =
+      SarifRule::create()
+          .setRuleId("clang.unittest")
+          .setDescription("Example rule created during unit tests")
+          .setName("clang unit test")
+          .setDefaultConfiguration(SarifReportingConfiguration::create()
+                                       .setLevel(SarifResultLevel::Error)
+                                       .setRank(35.5));
+
+  // WHEN: A run contains a result
+  Writer.createRun("sarif test", "sarif test runner", "1.0.0");
+  unsigned RuleIdx = Writer.createRule(Rule);
+  const SarifResult &Result = SarifResult::create(RuleIdx);
   Writer.appendResult(Result);
   std::string Output = serializeSarifDocument(Writer.createDocument());
 
@@ -226,7 +292,7 @@ TEST_F(SarifDocumentWriterTest, checkSerializingResults) {
 TEST_F(SarifDocumentWriterTest, checkSerializingArtifacts) {
   // GIVEN:
   const std::string ExpectedOutput =
-      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[{"length":40,"location":{"index":0,"uri":"file:///main.cpp"},"mimeType":"text/plain","roles":["resultFile"]}],"columnKind":"unicodeCodePoints","results":[{"locations":[{"physicalLocation":{"artifactLocation":{"index":0},"region":{"endColumn":14,"startColumn":14,"startLine":3}}}],"message":{"text":"expected ';' after top level declarator"},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
+      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[{"length":40,"location":{"index":0,"uri":"file:///main.cpp"},"mimeType":"text/plain","roles":["resultFile"]}],"columnKind":"unicodeCodePoints","results":[{"level":"error","locations":[{"physicalLocation":{"artifactLocation":{"index":0},"region":{"endColumn":14,"startColumn":14,"startLine":3}}}],"message":{"text":"expected ';' after top level declarator"},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"defaultConfiguration":{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
 
   SarifDocumentWriter Writer{SourceMgr};
   const SarifRule &Rule =
@@ -252,8 +318,10 @@ TEST_F(SarifDocumentWriterTest, checkSerializingArtifacts) {
   DiagLocs.push_back(SourceCSR);
 
   const SarifResult &Result =
-      SarifResult::create(RuleIdx).setLocations(DiagLocs).setDiagnosticMessage(
-          "expected ';' after top level declarator");
+      SarifResult::create(RuleIdx)
+          .setLocations(DiagLocs)
+          .setDiagnosticMessage("expected ';' after top level declarator")
+          .setDiagnosticLevel(SarifResultLevel::Error);
   Writer.appendResult(Result);
   std::string Output = serializeSarifDocument(Writer.createDocument());
 
@@ -264,7 +332,7 @@ TEST_F(SarifDocumentWriterTest, checkSerializingArtifacts) {
 TEST_F(SarifDocumentWriterTest, checkSerializingCodeflows) {
   // GIVEN:
   const std::string ExpectedOutput =
-      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[{"length":27,"location":{"index":1,"uri":"file:///test-header-1.h"},"mimeType":"text/plain","roles":["resultFile"]},{"length":30,"location":{"index":2,"uri":"file:///test-header-2.h"},"mimeType":"text/plain","roles":["resultFile"]},{"length":28,"location":{"index":3,"uri":"file:///test-header-3.h"},"mimeType":"text/plain","roles":["resultFile"]},{"length":41,"location":{"index":0,"uri":"file:///main.cpp"},"mimeType":"text/plain","roles":["resultFile"]}],"columnKind":"unicodeCodePoints","results":[{"codeFlows":[{"threadFlows":[{"locations":[{"importance":"essential","location":{"message":{"text":"Message #1"},"physicalLocation":{"artifactLocation":{"index":1},"region":{"endColumn":8,"endLine":2,"startColumn":1,"startLine":1}}}},{"importance":"important","location":{"message":{"text":"Message #2"},"physicalLocation":{"artifactLocation":{"index":2},"region":{"endColumn":8,"endLine":2,"startColumn":1,"startLine":1}}}},{"importance":"unimportant","location":{"message":{"text":"Message #3"},"physicalLocation":{"artifactLocation":{"index":3},"region":{"endColumn":8,"endLine":2,"startColumn":1,"startLine":1}}}}]}]}],"locations":[{"physicalLocation":{"artifactLocation":{"index":0},"region":{"endColumn":8,"endLine":2,"startColumn":5,"startLine":2}}}],"message":{"text":"Redefinition of 'foo'"},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
+      R"({"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json","runs":[{"artifacts":[{"length":27,"location":{"index":1,"uri":"file:///test-header-1.h"},"mimeType":"text/plain","roles":["resultFile"]},{"length":30,"location":{"index":2,"uri":"file:///test-header-2.h"},"mimeType":"text/plain","roles":["resultFile"]},{"length":28,"location":{"index":3,"uri":"file:///test-header-3.h"},"mimeType":"text/plain","roles":["resultFile"]},{"length":41,"location":{"index":0,"uri":"file:///main.cpp"},"mimeType":"text/plain","roles":["resultFile"]}],"columnKind":"unicodeCodePoints","results":[{"codeFlows":[{"threadFlows":[{"locations":[{"importance":"essential","location":{"message":{"text":"Message #1"},"physicalLocation":{"artifactLocation":{"index":1},"region":{"endColumn":8,"endLine":2,"startColumn":1,"startLine":1}}}},{"importance":"important","location":{"message":{"text":"Message #2"},"physicalLocation":{"artifactLocation":{"index":2},"region":{"endColumn":8,"endLine":2,"startColumn":1,"startLine":1}}}},{"importance":"unimportant","location":{"message":{"text":"Message #3"},"physicalLocation":{"artifactLocation":{"index":3},"region":{"endColumn":8,"endLine":2,"startColumn":1,"startLine":1}}}}]}]}],"level":"warning","locations":[{"physicalLocation":{"artifactLocation":{"index":0},"region":{"endColumn":8,"endLine":2,"startColumn":5,"startLine":2}}}],"message":{"text":"Redefinition of 'foo'"},"ruleId":"clang.unittest","ruleIndex":0}],"tool":{"driver":{"fullName":"sarif test runner","informationUri":"https://clang.llvm.org/docs/UsersManual.html","language":"en-US","name":"sarif test","rules":[{"defaultConfiguration":{"enabled":true,"level":"warning","rank":-1},"fullDescription":{"text":"Example rule created during unit tests"},"id":"clang.unittest","name":"clang unit test"}],"version":"1.0.0"}}}],"version":"2.1.0"})";
 
   const char *SourceText = "int foo = 0;\n"
                            "int foo = 1;\n"
@@ -280,22 +348,22 @@ TEST_F(SarifDocumentWriterTest, checkSerializingCodeflows) {
           .setDescription("Example rule created during unit tests")
           .setName("clang unit test");
 
-  constexpr unsigned int NUM_CASES = 3;
-  llvm::SmallVector<ThreadFlow, NUM_CASES> Threadflows;
-  const char *HeaderTexts[NUM_CASES]{("#pragma once\n"
-                                      "#include <foo>"),
-                                     ("#ifndef FOO\n"
-                                      "#define FOO\n"
-                                      "#endif"),
-                                     ("#ifdef FOO\n"
-                                      "#undef FOO\n"
-                                      "#endif")};
-  const char *HeaderNames[NUM_CASES]{"/test-header-1.h", "/test-header-2.h",
-                                     "/test-header-3.h"};
-  ThreadFlowImportance Importances[NUM_CASES]{
-      ThreadFlowImportance::Essential, ThreadFlowImportance::Important,
-      ThreadFlowImportance::Unimportant};
-  for (size_t Idx = 0; Idx != NUM_CASES; ++Idx) {
+  constexpr unsigned int NumCases = 3;
+  llvm::SmallVector<ThreadFlow, NumCases> Threadflows;
+  const char *HeaderTexts[NumCases]{("#pragma once\n"
+                                     "#include <foo>"),
+                                    ("#ifndef FOO\n"
+                                     "#define FOO\n"
+                                     "#endif"),
+                                    ("#ifdef FOO\n"
+                                     "#undef FOO\n"
+                                     "#endif")};
+  const char *HeaderNames[NumCases]{"/test-header-1.h", "/test-header-2.h",
+                                    "/test-header-3.h"};
+  ThreadFlowImportance Importances[NumCases]{ThreadFlowImportance::Essential,
+                                             ThreadFlowImportance::Important,
+                                             ThreadFlowImportance::Unimportant};
+  for (size_t Idx = 0; Idx != NumCases; ++Idx) {
     FileID FID = registerSource(HeaderNames[Idx], HeaderTexts[Idx]);
     CharSourceRange &&CSR = getFakeCharSourceRange(FID, {1, 1}, {2, 8});
     std::string Message = llvm::formatv("Message #{0}", Idx + 1);
@@ -309,10 +377,12 @@ TEST_F(SarifDocumentWriterTest, checkSerializingCodeflows) {
   // WHEN: A result containing code flows and diagnostic locations is added
   Writer.createRun("sarif test", "sarif test runner", "1.0.0");
   unsigned RuleIdx = Writer.createRule(Rule);
-  const SarifResult &Result = SarifResult::create(RuleIdx)
-                                  .setLocations({DiagLoc})
-                                  .setDiagnosticMessage("Redefinition of 'foo'")
-                                  .setThreadFlows(Threadflows);
+  const SarifResult &Result =
+      SarifResult::create(RuleIdx)
+          .setLocations({DiagLoc})
+          .setDiagnosticMessage("Redefinition of 'foo'")
+          .setThreadFlows(Threadflows)
+          .setDiagnosticLevel(SarifResultLevel::Warning);
   Writer.appendResult(Result);
   std::string Output = serializeSarifDocument(Writer.createDocument());
 


        


More information about the cfe-commits mailing list