Skip to content

Commit

Permalink
Update the SARIF exporter to SARIF 2.1
Browse files Browse the repository at this point in the history
This updates the SARIF exporter to produce SARIF 2.1 output. The bulk of the diffs come from two changes to SARIF:
* oasis-tcs/sarif-spec#309
* oasis-tcs/sarif-spec#179

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

llvm-svn: 370068
  • Loading branch information
jranieri-grammatech committed Aug 27, 2019
1 parent 4a2a653 commit fce4324
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 152 deletions.
85 changes: 42 additions & 43 deletions clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,40 +106,40 @@ static std::string fileNameToURI(StringRef Filename) {
return Ret.str().str();
}

static json::Object createFileLocation(const FileEntry &FE) {
static json::Object createArtifactLocation(const FileEntry &FE) {
return json::Object{{"uri", fileNameToURI(getFileName(FE))}};
}

static json::Object createFile(const FileEntry &FE) {
return json::Object{{"fileLocation", createFileLocation(FE)},
static json::Object createArtifact(const FileEntry &FE) {
return json::Object{{"location", createArtifactLocation(FE)},
{"roles", json::Array{"resultFile"}},
{"length", FE.getSize()},
{"mimeType", "text/plain"}};
}

static json::Object createFileLocation(const FileEntry &FE,
json::Array &Files) {
static json::Object createArtifactLocation(const FileEntry &FE,
json::Array &Artifacts) {
std::string FileURI = fileNameToURI(getFileName(FE));

// See if the Files array contains this URI already. If it does not, create
// a new file object to add to the array.
auto I = llvm::find_if(Files, [&](const json::Value &File) {
// See if the Artifacts array contains this URI already. If it does not,
// create a new artifact object to add to the array.
auto I = llvm::find_if(Artifacts, [&](const json::Value &File) {
if (const json::Object *Obj = File.getAsObject()) {
if (const json::Object *FileLoc = Obj->getObject("fileLocation")) {
if (const json::Object *FileLoc = Obj->getObject("location")) {
Optional<StringRef> URI = FileLoc->getString("uri");
return URI && URI->equals(FileURI);
}
}
return false;
});

// Calculate the index within the file location array so it can be stored in
// Calculate the index within the artifact array so it can be stored in
// the JSON object.
auto Index = static_cast<unsigned>(std::distance(Files.begin(), I));
if (I == Files.end())
Files.push_back(createFile(FE));
auto Index = static_cast<unsigned>(std::distance(Artifacts.begin(), I));
if (I == Artifacts.end())
Artifacts.push_back(createArtifact(FE));

return json::Object{{"uri", FileURI}, {"fileIndex", Index}};
return json::Object{{"uri", FileURI}, {"index", Index}};
}

static json::Object createTextRegion(SourceRange R, const SourceManager &SM) {
Expand All @@ -158,9 +158,10 @@ static json::Object createTextRegion(SourceRange R, const SourceManager &SM) {

static json::Object createPhysicalLocation(SourceRange R, const FileEntry &FE,
const SourceManager &SMgr,
json::Array &Files) {
return json::Object{{{"fileLocation", createFileLocation(FE, Files)},
{"region", createTextRegion(R, SMgr)}}};
json::Array &Artifacts) {
return json::Object{
{{"artifactLocation", createArtifactLocation(FE, Artifacts)},
{"region", createTextRegion(R, SMgr)}}};
}

enum class Importance { Important, Essential, Unimportant };
Expand Down Expand Up @@ -213,7 +214,7 @@ static Importance calculateImportance(const PathDiagnosticPiece &Piece) {
}

static json::Object createThreadFlow(const PathPieces &Pieces,
json::Array &Files) {
json::Array &Artifacts) {
const SourceManager &SMgr = Pieces.front()->getLocation().getManager();
json::Array Locations;
for (const auto &Piece : Pieces) {
Expand All @@ -222,27 +223,21 @@ static json::Object createThreadFlow(const PathPieces &Pieces,
createLocation(createPhysicalLocation(
P.asRange(),
*P.asLocation().getExpansionLoc().getFileEntry(),
SMgr, Files),
SMgr, Artifacts),
Piece->getString()),
calculateImportance(*Piece)));
}
return json::Object{{"locations", std::move(Locations)}};
}

static json::Object createCodeFlow(const PathPieces &Pieces,
json::Array &Files) {
json::Array &Artifacts) {
return json::Object{
{"threadFlows", json::Array{createThreadFlow(Pieces, Files)}}};
}

static json::Object createTool() {
return json::Object{{"name", "clang"},
{"fullName", "clang static analyzer"},
{"language", "en-US"},
{"version", getClangFullVersion()}};
{"threadFlows", json::Array{createThreadFlow(Pieces, Artifacts)}}};
}

static json::Object createResult(const PathDiagnostic &Diag, json::Array &Files,
static json::Object createResult(const PathDiagnostic &Diag,
json::Array &Artifacts,
const StringMap<unsigned> &RuleMapping) {
const PathPieces &Path = Diag.path.flatten(false);
const SourceManager &SMgr = Path.front()->getLocation().getManager();
Expand All @@ -252,12 +247,12 @@ static json::Object createResult(const PathDiagnostic &Diag, json::Array &Files,

return json::Object{
{"message", createMessage(Diag.getVerboseDescription())},
{"codeFlows", json::Array{createCodeFlow(Path, Files)}},
{"codeFlows", json::Array{createCodeFlow(Path, Artifacts)}},
{"locations",
json::Array{createLocation(createPhysicalLocation(
Diag.getLocation().asRange(),
*Diag.getLocation().asLocation().getExpansionLoc().getFileEntry(),
SMgr, Files))}},
SMgr, Artifacts))}},
{"ruleIndex", Iter->getValue()},
{"ruleId", Diag.getCheckName()}};
}
Expand Down Expand Up @@ -288,7 +283,7 @@ static json::Object createRule(const PathDiagnostic &Diag) {
StringRef CheckName = Diag.getCheckName();
json::Object Ret{
{"fullDescription", createMessage(getRuleDescription(CheckName))},
{"name", createMessage(CheckName)},
{"name", CheckName},
{"id", CheckName}};

std::string RuleURI = getRuleHelpURIStr(CheckName);
Expand All @@ -315,24 +310,28 @@ static json::Array createRules(std::vector<const PathDiagnostic *> &Diags,
return Rules;
}

static json::Object createResources(std::vector<const PathDiagnostic *> &Diags,
StringMap<unsigned> &RuleMapping) {
return json::Object{{"rules", createRules(Diags, RuleMapping)}};
static json::Object createTool(std::vector<const PathDiagnostic *> &Diags,
StringMap<unsigned> &RuleMapping) {
return json::Object{
{"driver", json::Object{{"name", "clang"},
{"fullName", "clang static analyzer"},
{"language", "en-US"},
{"version", getClangFullVersion()},
{"rules", createRules(Diags, RuleMapping)}}}};
}

static json::Object createRun(std::vector<const PathDiagnostic *> &Diags) {
json::Array Results, Files;
json::Array Results, Artifacts;
StringMap<unsigned> RuleMapping;
json::Object Resources = createResources(Diags, RuleMapping);
json::Object Tool = createTool(Diags, RuleMapping);

llvm::for_each(Diags, [&](const PathDiagnostic *D) {
Results.push_back(createResult(*D, Files, RuleMapping));
Results.push_back(createResult(*D, Artifacts, RuleMapping));
});

return json::Object{{"tool", createTool()},
{"resources", std::move(Resources)},
return json::Object{{"tool", std::move(Tool)},
{"results", std::move(Results)},
{"files", std::move(Files)}};
{"artifacts", std::move(Artifacts)}};
}

void SarifDiagnostics::FlushDiagnosticsImpl(
Expand All @@ -350,8 +349,8 @@ void SarifDiagnostics::FlushDiagnosticsImpl(
}
json::Object Sarif{
{"$schema",
"http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-11-28"},
{"version", "2.0.0-csd.2.beta.2018-11-28"},
"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"},
{"version", "2.1.0"},
{"runs", json::Array{createRun(Diags)}}};
OS << llvm::formatv("{0:2}\n", json::Value(std::move(Sarif)));
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
{
"$schema": "http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-11-28",
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"runs": [
{
"files": [
"artifacts": [
{
"fileLocation": {
},
"length": 434,
"location": {
},
"mimeType": "text/plain",
"roles": [
"resultFile"
]
}
],
"resources": {
"rules": [
{
"fullDescription": {
"text": "Mark tainted symbols as such."
},
"id": "debug.TaintTest",
"name": {
"text": "debug.TaintTest"
}
}
]
},
"results": [
{
"codeFlows": [
Expand All @@ -40,8 +27,8 @@
"text": "Calling 'f'"
},
"physicalLocation": {
"fileLocation": {
"fileIndex": 0,
"artifactLocation": {
"index": 0,
},
"region": {
"endColumn": 6,
Expand All @@ -59,8 +46,8 @@
"text": "tainted"
},
"physicalLocation": {
"fileLocation": {
"fileIndex": 0,
"artifactLocation": {
"index": 0,
},
"region": {
"endColumn": 18,
Expand All @@ -79,8 +66,8 @@
"locations": [
{
"physicalLocation": {
"fileLocation": {
"fileIndex": 0,
"artifactLocation": {
"index": 0,
},
"region": {
"endColumn": 18,
Expand All @@ -99,9 +86,20 @@
}
],
"tool": {
"fullName": "clang static analyzer",
"language": "en-US",
"name": "clang",
"driver": {
"fullName": "clang static analyzer",
"language": "en-US",
"name": "clang",
"rules": [
{
"fullDescription": {
"text": "Mark tainted symbols as such."
},
"id": "debug.TaintTest",
"name": "debug.TaintTest"
}
],
}
}
}
],
Expand Down
Loading

0 comments on commit fce4324

Please sign in to comment.