1//===- SARIFTransformationReportFormat.cpp --------------------------------===//
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
9#include "clang/ScalableStaticAnalysis/SourceTransformation/SARIFTransformationReportFormat.h"
10#include "clang/Basic/Sarif.h"
11#include "clang/Basic/Version.h"
12#include "llvm/ADT/StringMap.h"
13#include "llvm/Support/Error.h"
14#include "llvm/Support/FileSystem.h"
15#include "llvm/Support/FormatVariadic.h"
16#include "llvm/Support/JSON.h"
17#include "llvm/Support/raw_ostream.h"
18
19using namespace clang;
20using namespace ssaf;
21
22llvm::Error ssaf::writeSARIFTransformationReport(const ReportDocument &Doc,
23 llvm::StringRef Path) {
24 std::error_code EC;
25 llvm::raw_fd_ostream OS(Path, EC, llvm::sys::fs::OF_None);
26 if (EC)
27 return llvm::createStringError(EC, S: "failed to open '" + Path + "'");
28
29 clang::SarifDocumentWriter Writer(Doc.SM);
30 std::string LongToolName =
31 "clang ScalableStaticAnalysisFramework source transformation (" +
32 Doc.TransformationName + ")";
33 Writer.createRun(ShortToolName: "clang-ssaf", LongToolName, CLANG_VERSION_STRING);
34
35 llvm::StringMap<size_t> RuleIndex;
36 for (const ReportResult &R : Doc.Results) {
37 if (RuleIndex.contains(Key: R.RuleId))
38 continue;
39 RuleIndex[R.RuleId] =
40 Writer.createRule(Rule: clang::SarifRule::create().setRuleId(R.RuleId));
41 }
42
43 for (const ReportResult &R : Doc.Results) {
44 clang::SarifResult Result = clang::SarifResult::create(RuleIdx: RuleIndex[R.RuleId])
45 .setRuleId(R.RuleId)
46 .setDiagnosticMessage(R.Message)
47 .setDiagnosticLevel(R.Level);
48 if (R.Range.isValid())
49 Result = Result.addLocations(DiagLocs: {R.Range});
50 Writer.appendResult(SarifResult: Result);
51 }
52
53 llvm::json::Value Document(Writer.createDocument());
54 OS << llvm::formatv(Fmt: "{0:2}", Vals&: Document) << "\n";
55 return llvm::Error::success();
56}
57