Yi Kong | 8328301 | 2023-12-13 12:57:00 +0900 | [diff] [blame^] | 1 | //== clang/Basic/Sarif.h - SARIF Diagnostics Object Model -------*- C++ -*--==// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// \file |
| 9 | /// Defines clang::SarifDocumentWriter, clang::SarifRule, clang::SarifResult. |
| 10 | /// |
| 11 | /// The document built can be accessed as a JSON Object. |
| 12 | /// Several value semantic types are also introduced which represent properties |
| 13 | /// of the SARIF standard, such as 'artifact', 'result', 'rule'. |
| 14 | /// |
| 15 | /// A SARIF (Static Analysis Results Interchange Format) document is JSON |
| 16 | /// document that describes in detail the results of running static analysis |
| 17 | /// tools on a project. Each (non-trivial) document consists of at least one |
| 18 | /// "run", which are themselves composed of details such as: |
| 19 | /// * Tool: The tool that was run |
| 20 | /// * Rules: The rules applied during the tool run, represented by |
| 21 | /// \c reportingDescriptor objects in SARIF |
| 22 | /// * Results: The matches for the rules applied against the project(s) being |
| 23 | /// evaluated, represented by \c result objects in SARIF |
| 24 | /// |
| 25 | /// Reference: |
| 26 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html">The SARIF standard</a> |
| 27 | /// 2. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317836">SARIF<pre>reportingDescriptor</pre></a> |
| 28 | /// 3. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317638">SARIF<pre>result</pre></a> |
| 29 | //===----------------------------------------------------------------------===// |
| 30 | |
| 31 | #ifndef LLVM_CLANG_BASIC_SARIF_H |
| 32 | #define LLVM_CLANG_BASIC_SARIF_H |
| 33 | |
| 34 | #include "clang/Basic/SourceLocation.h" |
| 35 | #include "clang/Basic/Version.h" |
| 36 | #include "llvm/ADT/ArrayRef.h" |
| 37 | #include "llvm/ADT/SmallVector.h" |
| 38 | #include "llvm/ADT/StringMap.h" |
| 39 | #include "llvm/ADT/StringRef.h" |
| 40 | #include "llvm/Support/JSON.h" |
| 41 | #include <cassert> |
| 42 | #include <cstddef> |
| 43 | #include <cstdint> |
| 44 | #include <initializer_list> |
| 45 | #include <optional> |
| 46 | #include <string> |
| 47 | |
| 48 | namespace clang { |
| 49 | |
| 50 | class SarifDocumentWriter; |
| 51 | class SourceManager; |
| 52 | |
| 53 | namespace detail { |
| 54 | |
| 55 | /// \internal |
| 56 | /// An artifact location is SARIF's way of describing the complete location |
| 57 | /// of an artifact encountered during analysis. The \c artifactLocation object |
| 58 | /// typically consists of a URI, and/or an index to reference the artifact it |
| 59 | /// locates. |
| 60 | /// |
| 61 | /// This builder makes an additional assumption: that every artifact encountered |
| 62 | /// by \c clang will be a physical, top-level artifact. Which is why the static |
| 63 | /// creation method \ref SarifArtifactLocation::create takes a mandatory URI |
| 64 | /// parameter. The official standard states that either a \c URI or \c Index |
| 65 | /// must be available in the object, \c clang picks the \c URI as a reasonable |
| 66 | /// default, because it intends to deal in physical artifacts for now. |
| 67 | /// |
| 68 | /// Reference: |
| 69 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317427">artifactLocation object</a> |
| 70 | /// 2. \ref SarifArtifact |
| 71 | class SarifArtifactLocation { |
| 72 | private: |
| 73 | friend class clang::SarifDocumentWriter; |
| 74 | |
| 75 | std::optional<uint32_t> Index; |
| 76 | std::string URI; |
| 77 | |
| 78 | SarifArtifactLocation() = delete; |
| 79 | explicit SarifArtifactLocation(const std::string &URI) : URI(URI) {} |
| 80 | |
| 81 | public: |
| 82 | static SarifArtifactLocation create(llvm::StringRef URI) { |
| 83 | return SarifArtifactLocation{URI.str()}; |
| 84 | } |
| 85 | |
| 86 | SarifArtifactLocation setIndex(uint32_t Idx) { |
| 87 | Index = Idx; |
| 88 | return *this; |
| 89 | } |
| 90 | }; |
| 91 | |
| 92 | /// \internal |
| 93 | /// An artifact in SARIF is any object (a sequence of bytes) addressable by |
| 94 | /// a URI (RFC 3986). The most common type of artifact for clang's use-case |
| 95 | /// would be source files. SARIF's artifact object is described in detail in |
| 96 | /// section 3.24. |
| 97 | // |
| 98 | /// Since every clang artifact MUST have a location (there being no nested |
| 99 | /// artifacts), the creation method \ref SarifArtifact::create requires a |
| 100 | /// \ref SarifArtifactLocation object. |
| 101 | /// |
| 102 | /// Reference: |
| 103 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317611">artifact object</a> |
| 104 | class SarifArtifact { |
| 105 | private: |
| 106 | friend class clang::SarifDocumentWriter; |
| 107 | |
| 108 | std::optional<uint32_t> Offset; |
| 109 | std::optional<size_t> Length; |
| 110 | std::string MimeType; |
| 111 | SarifArtifactLocation Location; |
| 112 | llvm::SmallVector<std::string, 4> Roles; |
| 113 | |
| 114 | SarifArtifact() = delete; |
| 115 | |
| 116 | explicit SarifArtifact(const SarifArtifactLocation &Loc) : Location(Loc) {} |
| 117 | |
| 118 | public: |
| 119 | static SarifArtifact create(const SarifArtifactLocation &Loc) { |
| 120 | return SarifArtifact{Loc}; |
| 121 | } |
| 122 | |
| 123 | SarifArtifact setOffset(uint32_t ArtifactOffset) { |
| 124 | Offset = ArtifactOffset; |
| 125 | return *this; |
| 126 | } |
| 127 | |
| 128 | SarifArtifact setLength(size_t NumBytes) { |
| 129 | Length = NumBytes; |
| 130 | return *this; |
| 131 | } |
| 132 | |
| 133 | SarifArtifact setRoles(std::initializer_list<llvm::StringRef> ArtifactRoles) { |
| 134 | Roles.assign(ArtifactRoles.begin(), ArtifactRoles.end()); |
| 135 | return *this; |
| 136 | } |
| 137 | |
| 138 | SarifArtifact setMimeType(llvm::StringRef ArtifactMimeType) { |
| 139 | MimeType = ArtifactMimeType.str(); |
| 140 | return *this; |
| 141 | } |
| 142 | }; |
| 143 | |
| 144 | } // namespace detail |
| 145 | |
| 146 | enum class ThreadFlowImportance { Important, Essential, Unimportant }; |
| 147 | |
| 148 | /// The level of severity associated with a \ref SarifResult. |
| 149 | /// |
| 150 | /// Of all the levels, \c None is the only one that is not associated with |
| 151 | /// a failure. |
| 152 | /// |
| 153 | /// A typical mapping for clang's DiagnosticKind to SarifResultLevel would look |
| 154 | /// like: |
| 155 | /// * \c None: \ref clang::DiagnosticsEngine::Level::Remark, \ref clang::DiagnosticsEngine::Level::Ignored |
| 156 | /// * \c Note: \ref clang::DiagnosticsEngine::Level::Note |
| 157 | /// * \c Warning: \ref clang::DiagnosticsEngine::Level::Warning |
| 158 | /// * \c Error could be generated from one of: |
| 159 | /// - \ref clang::DiagnosticsEngine::Level::Warning with \c -Werror |
| 160 | /// - \ref clang::DiagnosticsEngine::Level::Error |
| 161 | /// - \ref clang::DiagnosticsEngine::Level::Fatal when \ref clang::DiagnosticsEngine::ErrorsAsFatal is set. |
| 162 | /// |
| 163 | /// Reference: |
| 164 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317648">level property</a> |
| 165 | enum class SarifResultLevel { None, Note, Warning, Error }; |
| 166 | |
| 167 | /// A thread flow is a sequence of code locations that specify a possible path |
| 168 | /// through a single thread of execution. |
| 169 | /// A thread flow in SARIF is related to a code flow which describes |
| 170 | /// the progress of one or more programs through one or more thread flows. |
| 171 | /// |
| 172 | /// Reference: |
| 173 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317744">threadFlow object</a> |
| 174 | /// 2. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317740">codeFlow object</a> |
| 175 | class ThreadFlow { |
| 176 | friend class SarifDocumentWriter; |
| 177 | |
| 178 | CharSourceRange Range; |
| 179 | ThreadFlowImportance Importance; |
| 180 | std::string Message; |
| 181 | |
| 182 | ThreadFlow() = default; |
| 183 | |
| 184 | public: |
| 185 | static ThreadFlow create() { return {}; } |
| 186 | |
| 187 | ThreadFlow setRange(const CharSourceRange &ItemRange) { |
| 188 | assert(ItemRange.isCharRange() && |
| 189 | "ThreadFlows require a character granular source range!"); |
| 190 | Range = ItemRange; |
| 191 | return *this; |
| 192 | } |
| 193 | |
| 194 | ThreadFlow setImportance(const ThreadFlowImportance &ItemImportance) { |
| 195 | Importance = ItemImportance; |
| 196 | return *this; |
| 197 | } |
| 198 | |
| 199 | ThreadFlow setMessage(llvm::StringRef ItemMessage) { |
| 200 | Message = ItemMessage.str(); |
| 201 | return *this; |
| 202 | } |
| 203 | }; |
| 204 | |
| 205 | /// A SARIF Reporting Configuration (\c reportingConfiguration) object contains |
| 206 | /// properties for a \ref SarifRule that can be configured at runtime before |
| 207 | /// analysis begins. |
| 208 | /// |
| 209 | /// Reference: |
| 210 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317852">reportingConfiguration object</a> |
| 211 | class SarifReportingConfiguration { |
| 212 | friend class clang::SarifDocumentWriter; |
| 213 | |
| 214 | bool Enabled = true; |
| 215 | SarifResultLevel Level = SarifResultLevel::Warning; |
| 216 | float Rank = -1.0f; |
| 217 | |
| 218 | SarifReportingConfiguration() = default; |
| 219 | |
| 220 | public: |
| 221 | static SarifReportingConfiguration create() { return {}; }; |
| 222 | |
| 223 | SarifReportingConfiguration disable() { |
| 224 | Enabled = false; |
| 225 | return *this; |
| 226 | } |
| 227 | |
| 228 | SarifReportingConfiguration enable() { |
| 229 | Enabled = true; |
| 230 | return *this; |
| 231 | } |
| 232 | |
| 233 | SarifReportingConfiguration setLevel(SarifResultLevel TheLevel) { |
| 234 | Level = TheLevel; |
| 235 | return *this; |
| 236 | } |
| 237 | |
| 238 | SarifReportingConfiguration setRank(float TheRank) { |
| 239 | assert(TheRank >= 0.0f && "Rule rank cannot be smaller than 0.0"); |
| 240 | assert(TheRank <= 100.0f && "Rule rank cannot be larger than 100.0"); |
| 241 | Rank = TheRank; |
| 242 | return *this; |
| 243 | } |
| 244 | }; |
| 245 | |
| 246 | /// A SARIF rule (\c reportingDescriptor object) contains information that |
| 247 | /// describes a reporting item generated by a tool. A reporting item is |
| 248 | /// either a result of analysis or notification of a condition encountered by |
| 249 | /// the tool. Rules are arbitrary but are identifiable by a hierarchical |
| 250 | /// rule-id. |
| 251 | /// |
| 252 | /// This builder provides an interface to create SARIF \c reportingDescriptor |
| 253 | /// objects via the \ref SarifRule::create static method. |
| 254 | /// |
| 255 | /// Reference: |
| 256 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317836">reportingDescriptor object</a> |
| 257 | class SarifRule { |
| 258 | friend class clang::SarifDocumentWriter; |
| 259 | |
| 260 | std::string Name; |
| 261 | std::string Id; |
| 262 | std::string Description; |
| 263 | std::string HelpURI; |
| 264 | SarifReportingConfiguration DefaultConfiguration; |
| 265 | |
| 266 | SarifRule() : DefaultConfiguration(SarifReportingConfiguration::create()) {} |
| 267 | |
| 268 | public: |
| 269 | static SarifRule create() { return {}; } |
| 270 | |
| 271 | SarifRule setName(llvm::StringRef RuleName) { |
| 272 | Name = RuleName.str(); |
| 273 | return *this; |
| 274 | } |
| 275 | |
| 276 | SarifRule setRuleId(llvm::StringRef RuleId) { |
| 277 | Id = RuleId.str(); |
| 278 | return *this; |
| 279 | } |
| 280 | |
| 281 | SarifRule setDescription(llvm::StringRef RuleDesc) { |
| 282 | Description = RuleDesc.str(); |
| 283 | return *this; |
| 284 | } |
| 285 | |
| 286 | SarifRule setHelpURI(llvm::StringRef RuleHelpURI) { |
| 287 | HelpURI = RuleHelpURI.str(); |
| 288 | return *this; |
| 289 | } |
| 290 | |
| 291 | SarifRule |
| 292 | setDefaultConfiguration(const SarifReportingConfiguration &Configuration) { |
| 293 | DefaultConfiguration = Configuration; |
| 294 | return *this; |
| 295 | } |
| 296 | }; |
| 297 | |
| 298 | /// A SARIF result (also called a "reporting item") is a unit of output |
| 299 | /// produced when one of the tool's \c reportingDescriptor encounters a match |
| 300 | /// on the file being analysed by the tool. |
| 301 | /// |
| 302 | /// This builder provides a \ref SarifResult::create static method that can be |
| 303 | /// used to create an empty shell onto which attributes can be added using the |
| 304 | /// \c setX(...) methods. |
| 305 | /// |
| 306 | /// For example: |
| 307 | /// \code{.cpp} |
| 308 | /// SarifResult result = SarifResult::create(...) |
| 309 | /// .setRuleId(...) |
| 310 | /// .setDiagnosticMessage(...); |
| 311 | /// \endcode |
| 312 | /// |
| 313 | /// Reference: |
| 314 | /// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317638">SARIF<pre>result</pre></a> |
| 315 | class SarifResult { |
| 316 | friend class clang::SarifDocumentWriter; |
| 317 | |
| 318 | // NOTE: |
| 319 | // This type cannot fit all possible indexes representable by JSON, but is |
| 320 | // chosen because it is the largest unsigned type that can be safely |
| 321 | // converted to an \c int64_t. |
| 322 | uint32_t RuleIdx; |
| 323 | std::string RuleId; |
| 324 | std::string DiagnosticMessage; |
| 325 | llvm::SmallVector<CharSourceRange, 8> Locations; |
| 326 | llvm::SmallVector<ThreadFlow, 8> ThreadFlows; |
| 327 | std::optional<SarifResultLevel> LevelOverride; |
| 328 | |
| 329 | SarifResult() = delete; |
| 330 | explicit SarifResult(uint32_t RuleIdx) : RuleIdx(RuleIdx) {} |
| 331 | |
| 332 | public: |
| 333 | static SarifResult create(uint32_t RuleIdx) { return SarifResult{RuleIdx}; } |
| 334 | |
| 335 | SarifResult setIndex(uint32_t Idx) { |
| 336 | RuleIdx = Idx; |
| 337 | return *this; |
| 338 | } |
| 339 | |
| 340 | SarifResult setRuleId(llvm::StringRef Id) { |
| 341 | RuleId = Id.str(); |
| 342 | return *this; |
| 343 | } |
| 344 | |
| 345 | SarifResult setDiagnosticMessage(llvm::StringRef Message) { |
| 346 | DiagnosticMessage = Message.str(); |
| 347 | return *this; |
| 348 | } |
| 349 | |
| 350 | SarifResult setLocations(llvm::ArrayRef<CharSourceRange> DiagLocs) { |
| 351 | #ifndef NDEBUG |
| 352 | for (const auto &Loc : DiagLocs) { |
| 353 | assert(Loc.isCharRange() && |
| 354 | "SARIF Results require character granular source ranges!"); |
| 355 | } |
| 356 | #endif |
| 357 | Locations.assign(DiagLocs.begin(), DiagLocs.end()); |
| 358 | return *this; |
| 359 | } |
| 360 | SarifResult setThreadFlows(llvm::ArrayRef<ThreadFlow> ThreadFlowResults) { |
| 361 | ThreadFlows.assign(ThreadFlowResults.begin(), ThreadFlowResults.end()); |
| 362 | return *this; |
| 363 | } |
| 364 | |
| 365 | SarifResult setDiagnosticLevel(const SarifResultLevel &TheLevel) { |
| 366 | LevelOverride = TheLevel; |
| 367 | return *this; |
| 368 | } |
| 369 | }; |
| 370 | |
| 371 | /// This class handles creating a valid SARIF document given various input |
| 372 | /// attributes. However, it requires an ordering among certain method calls: |
| 373 | /// |
| 374 | /// 1. Because every SARIF document must contain at least 1 \c run, callers |
| 375 | /// must ensure that \ref SarifDocumentWriter::createRun is called before |
| 376 | /// any other methods. |
| 377 | /// 2. If SarifDocumentWriter::endRun is called, callers MUST call |
| 378 | /// SarifDocumentWriter::createRun, before invoking any of the result |
| 379 | /// aggregation methods such as SarifDocumentWriter::appendResult etc. |
| 380 | class SarifDocumentWriter { |
| 381 | private: |
| 382 | const llvm::StringRef SchemaURI{ |
| 383 | "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/" |
| 384 | "sarif-schema-2.1.0.json"}; |
| 385 | const llvm::StringRef SchemaVersion{"2.1.0"}; |
| 386 | |
| 387 | /// \internal |
| 388 | /// Return a pointer to the current tool. Asserts that a run exists. |
| 389 | llvm::json::Object &getCurrentTool(); |
| 390 | |
| 391 | /// \internal |
| 392 | /// Checks if there is a run associated with this document. |
| 393 | /// |
| 394 | /// \return true on success |
| 395 | bool hasRun() const; |
| 396 | |
| 397 | /// \internal |
| 398 | /// Reset portions of the internal state so that the document is ready to |
| 399 | /// receive data for a new run. |
| 400 | void reset(); |
| 401 | |
| 402 | /// \internal |
| 403 | /// Return a mutable reference to the current run, after asserting it exists. |
| 404 | /// |
| 405 | /// \note It is undefined behavior to call this if a run does not exist in |
| 406 | /// the SARIF document. |
| 407 | llvm::json::Object &getCurrentRun(); |
| 408 | |
| 409 | /// Create a code flow object for the given threadflows. |
| 410 | /// See \ref ThreadFlow. |
| 411 | /// |
| 412 | /// \note It is undefined behavior to call this if a run does not exist in |
| 413 | /// the SARIF document. |
| 414 | llvm::json::Object |
| 415 | createCodeFlow(const llvm::ArrayRef<ThreadFlow> ThreadFlows); |
| 416 | |
| 417 | /// Add the given threadflows to the ones this SARIF document knows about. |
| 418 | llvm::json::Array |
| 419 | createThreadFlows(const llvm::ArrayRef<ThreadFlow> ThreadFlows); |
| 420 | |
| 421 | /// Add the given \ref CharSourceRange to the SARIF document as a physical |
| 422 | /// location, with its corresponding artifact. |
| 423 | llvm::json::Object createPhysicalLocation(const CharSourceRange &R); |
| 424 | |
| 425 | public: |
| 426 | SarifDocumentWriter() = delete; |
| 427 | |
| 428 | /// Create a new empty SARIF document with the given source manager. |
| 429 | SarifDocumentWriter(const SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} |
| 430 | |
| 431 | /// Release resources held by this SARIF document. |
| 432 | ~SarifDocumentWriter() = default; |
| 433 | |
| 434 | /// Create a new run with which any upcoming analysis will be associated. |
| 435 | /// Each run requires specifying the tool that is generating reporting items. |
| 436 | void createRun(const llvm::StringRef ShortToolName, |
| 437 | const llvm::StringRef LongToolName, |
| 438 | const llvm::StringRef ToolVersion = CLANG_VERSION_STRING); |
| 439 | |
| 440 | /// If there is a current run, end it. |
| 441 | /// |
| 442 | /// This method collects various book-keeping required to clear and close |
| 443 | /// resources associated with the current run, but may also allocate some |
| 444 | /// for the next run. |
| 445 | /// |
| 446 | /// Calling \ref endRun before associating a run through \ref createRun leads |
| 447 | /// to undefined behaviour. |
| 448 | void endRun(); |
| 449 | |
| 450 | /// Associate the given rule with the current run. |
| 451 | /// |
| 452 | /// Returns an integer rule index for the created rule that is unique within |
| 453 | /// the current run, which can then be used to create a \ref SarifResult |
| 454 | /// to add to the current run. Note that a rule must exist before being |
| 455 | /// referenced by a result. |
| 456 | /// |
| 457 | /// \pre |
| 458 | /// There must be a run associated with the document, failing to do so will |
| 459 | /// cause undefined behaviour. |
| 460 | size_t createRule(const SarifRule &Rule); |
| 461 | |
| 462 | /// Append a new result to the currently in-flight run. |
| 463 | /// |
| 464 | /// \pre |
| 465 | /// There must be a run associated with the document, failing to do so will |
| 466 | /// cause undefined behaviour. |
| 467 | /// \pre |
| 468 | /// \c RuleIdx used to create the result must correspond to a rule known by |
| 469 | /// the SARIF document. It must be the value returned by a previous call |
| 470 | /// to \ref createRule. |
| 471 | void appendResult(const SarifResult &SarifResult); |
| 472 | |
| 473 | /// Return the SARIF document in its current state. |
| 474 | /// Calling this will trigger a copy of the internal state including all |
| 475 | /// reported diagnostics, resulting in an expensive call. |
| 476 | llvm::json::Object createDocument(); |
| 477 | |
| 478 | private: |
| 479 | /// Source Manager to use for the current SARIF document. |
| 480 | const SourceManager &SourceMgr; |
| 481 | |
| 482 | /// Flag to track the state of this document: |
| 483 | /// A closed document is one on which a new runs must be created. |
| 484 | /// This could be a document that is freshly created, or has recently |
| 485 | /// finished writing to a previous run. |
| 486 | bool Closed = true; |
| 487 | |
| 488 | /// A sequence of SARIF runs. |
| 489 | /// Each run object describes a single run of an analysis tool and contains |
| 490 | /// the output of that run. |
| 491 | /// |
| 492 | /// Reference: <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317484">run object</a> |
| 493 | llvm::json::Array Runs; |
| 494 | |
| 495 | /// The list of rules associated with the most recent active run. These are |
| 496 | /// defined using the diagnostics passed to the SarifDocument. Each rule |
| 497 | /// need not be unique through the result set. E.g. there may be several |
| 498 | /// 'syntax' errors throughout code under analysis, each of which has its |
| 499 | /// own specific diagnostic message (and consequently, RuleId). Rules are |
| 500 | /// also known as "reportingDescriptor" objects in SARIF. |
| 501 | /// |
| 502 | /// Reference: <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317556">rules property</a> |
| 503 | llvm::SmallVector<SarifRule, 32> CurrentRules; |
| 504 | |
| 505 | /// The list of artifacts that have been encountered on the most recent active |
| 506 | /// run. An artifact is defined in SARIF as a sequence of bytes addressable |
| 507 | /// by a URI. A common example for clang's case would be files named by |
| 508 | /// filesystem paths. |
| 509 | llvm::StringMap<detail::SarifArtifact> CurrentArtifacts; |
| 510 | }; |
| 511 | } // namespace clang |
| 512 | |
| 513 | #endif // LLVM_CLANG_BASIC_SARIF_H |