================
@@ -195,6 +210,97 @@ class ErrorReporter {
     }
     for (const auto &Note : Error.Notes)
       reportNote(Note);
+
+    if (SarifWriter)
+      exportSarifResult(Error, Loc);
+  }
+
+  SmallVector<ThreadFlow, 8> createThreadFlows(const ClangTidyError &Error) {
+    SmallVector<ThreadFlow, 8> Flows;
+    if (!StringRef(Error.DiagnosticName).starts_with("clang-analyzer-"))
+      return Flows;
+
+    Flows.reserve(Error.Notes.size());
+    for (const tooling::DiagnosticMessage &Note : Error.Notes) {
+      tooling::FileByteRange FBR;
+      if (Note.Ranges.empty()) {
+        FBR.FilePath = Note.FilePath;
+        FBR.FileOffset = Note.FileOffset;
+        FBR.Length = 1;
+      } else {
+        FBR = Note.Ranges.front();
+      }
+      const CharSourceRange Range = getRange(FBR);
+      Flows.push_back(
+          ThreadFlow::create().setRange(Range).setMessage(Note.Message));
+    }
+    return Flows;
+  }
+
+  static std::string buildClangTidyHelpURI(StringRef Name) {
+    const auto [Module, Check] = Name.starts_with("clang-analyzer-")
+                                     ? Name.rsplit('-')
+                                     : Name.split('-');
+    return llvm::formatv(
+        "https://clang.llvm.org/extra/clang-tidy/checks/{0}/{1}.html";, Module,
+        Check);
+  }
+
+  void exportSarifResult(const ClangTidyError &Error,
+                         const SourceLocation Loc) {
+    assert(SarifWriter &&
+           "SarifWriter must be initialized to export SARIF results");
+
+    const auto [RuleIndexEntryIt, Inserted] =
+        SarifRuleIdx.try_emplace(Error.DiagnosticName, 0);
+    size_t &RuleIndex = RuleIndexEntryIt->second;
+
+    const DiagnosticsEngine::Level EffectiveLevel =
+        Error.IsWarningAsError
+            ? DiagnosticsEngine::Error
+            : static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
+
+    if (Inserted) {
+      const StringRef Name = Error.DiagnosticName;
+      SarifRule Rule =
+          SarifRule::create().setRuleId(Name).setName(Name).setDescription(
+              Error.Message.Message);
+
+      if (!Name.starts_with("clang-diagnostic"))
+        Rule = Rule.setHelpURI(buildClangTidyHelpURI(Name));
+
+      Rule = addDiagnosticLevelToRule(Rule, EffectiveLevel);
+      if (SarifWriter)
+        RuleIndex = SarifWriter->createRule(Rule);
+    }
+
+    const SarifResult Result =
+        SarifResult::create(RuleIndex)
+            .setDiagnosticMessage(Error.Message.Message)
+            .setDiagnosticLevel(getSarifResultLevel(EffectiveLevel))
+            .setThreadFlows(createThreadFlows(Error))
+            .addLocations(getResultRanges(Error, Loc));
+
+    if (SarifWriter)
+      SarifWriter->appendResult(Result);
+  }
+
+  SmallVector<CharSourceRange, 4> getResultRanges(const ClangTidyError &Error,
+                                                  SourceLocation Loc) {
+    SmallVector<CharSourceRange, 4> Ranges;
+    Ranges.reserve(Error.Message.Ranges.size());
+    for (const FileByteRange &FBR : Error.Message.Ranges)
+      Ranges.push_back(getRange(FBR));
+
+    if (Ranges.empty() && Loc.isValid()) {
+      // Some Clang-Tidy diagnostics are issued with a single location (not a
+      // range). For these, we create a range of length 1 at the diagnostic
+      // location. As, SARIF results require a character range for each
+      // location.
+      Ranges.push_back(
+          CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(1)));
+    }
+    return Ranges;
----------------
matthew-j-code wrote:

I believe and empty locations is valid here, from SARIF  §3.27.12 : A result 
object SHOULD contain a property named locations whose value is an array of 
zero or more location objects (§3.28) each of which specifies a location where 
the result occurred.

Inside SarifDocumentWriter::appendResult there is a check for empty locations, 
and omits it:
```
if (!Result.Locations.empty()) {
    json::Array Locs;
    for (auto &Range : Result.Locations) {
      Locs.emplace_back(createLocation(createPhysicalLocation(Range)));
    }
    Ret["locations"] = std::move(Locs);
  }
  ```
  
  

https://github.com/llvm/llvm-project/pull/219182
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to