Skip to content

parser-json-cov: process nested events recursively #222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 85 additions & 27 deletions src/lib/parser-json-cov.cc
Original file line number Diff line number Diff line change
@@ -21,26 +21,104 @@

#include "parser-cov.hh" // for KeyEventDigger

#include <stack>

struct CovTreeDecoder::Private {
KeyEventDigger keDigger;
InStream &input;
const pt::ptree *pSrc;

Private(InStream &input_):
input(input_)
{
}

void readEvents(Defect *def);
};

CovTreeDecoder::CovTreeDecoder():
d(new Private)
CovTreeDecoder::CovTreeDecoder(InStream &input):
d(new Private(input))
{
}

CovTreeDecoder::~CovTreeDecoder() = default;

/// decode single event
static DefEvent covDecodeEvt(const pt::ptree &evtNode)
{
DefEvent evt;

evt.fileName = valueOf<std::string>(evtNode, "filePathname");
evt.line = valueOf<int> (evtNode, "lineNumber");
evt.column = valueOf<int> (evtNode, "columnNumber");
evt.event = valueOf<std::string>(evtNode, "eventTag");
evt.msg = valueOf<std::string>(evtNode, "eventDescription");

return evt;
}

struct CovEvtStackItem {
const pt::ptree &evts;
pt::ptree::const_iterator iter;

CovEvtStackItem(const pt::ptree &evts_):
evts(evts_),
iter(evts_.begin())
{
}
};

void CovTreeDecoder::Private::readEvents(Defect *def)
{
// stack to traverse events recursively (without recursive fnc call)
std::stack<CovEvtStackItem> todo;
todo.push(this->pSrc->get_child("events"));

do {
CovEvtStackItem &si = todo.top();
if (si.evts.end() == si.iter) {
// no more events at this level to iterate through
todo.pop();
continue;
}

// get current event and move to the next one
const pt::ptree &evtNode = (si.iter++)->second;

if (evtNode.get<bool>("main")) {
// this is a key event

if (def->keyEventIdx)
// key event redefinition (TODO: more detailed diagnostic msg)
std::cerr << this->input.fileName()
<< ": warning: key event redefinition detected"
<< std::endl;

// record key event index
def->keyEventIdx = def->events.size();
}

// push the event to the list of events
DefEvent evt = covDecodeEvt(evtNode);
def->events.push_back(std::move(evt));

// check for nested events and eventually process them recursively
const pt::ptree &nestedEvts = evtNode.get_child("events");
if (!nestedEvts.empty())
todo.push(nestedEvts);
}
while (!todo.empty());
}

bool CovTreeDecoder::readNode(Defect *def)
{
// move the iterator after we get the current position
const pt::ptree *pNode = this->nextNode();
if (!pNode)
d->pSrc = this->nextNode();
if (!d->pSrc)
// failed initialization or EOF
return false;

const pt::ptree &defNode = *pNode;
const pt::ptree &defNode = *d->pSrc;

// read per-defect properties
def->checker = defNode.get<std::string>("checkerName");
@@ -61,28 +139,8 @@ bool CovTreeDecoder::readNode(Defect *def)
def->imp = 1;
}

// count the events and allocate dst array
const pt::ptree &evtList = defNode.get_child("events");
def->events.resize(evtList.size());

// decode events one by one
unsigned idx = 0;
pt::ptree::const_iterator it;
for (it = evtList.begin(); it != evtList.end(); ++it, ++idx) {
const pt::ptree &evtNode = it->second;
DefEvent &evt = def->events[idx];

evt.fileName = valueOf<std::string>(evtNode, "filePathname");
evt.line = valueOf<int> (evtNode, "lineNumber");
evt.column = valueOf<int> (evtNode, "columnNumber");
evt.event = valueOf<std::string>(evtNode, "eventTag");
evt.msg = valueOf<std::string>(evtNode, "eventDescription");

if (evtNode.get<bool>("main"))
// this is a key event
// TODO: detect and report re-definitions of key events
def->keyEventIdx = idx;
}
// read all events
d->readEvents(def);

// initialize verbosity level of all events
d->keDigger.initVerbosity(def);
2 changes: 1 addition & 1 deletion src/lib/parser-json-cov.hh
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
/// tree decoder of the Coverity JSON format
class CovTreeDecoder: public AbstractTreeDecoder {
public:
CovTreeDecoder();
CovTreeDecoder(InStream &input);
~CovTreeDecoder() override;
bool readNode(Defect *def) override;

2 changes: 1 addition & 1 deletion src/lib/parser-json.cc
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ JsonParser::JsonParser(InStream &input):
d->decoder.reset(new SimpleTreeDecoder(d->input));
else if (findChildOf(&node, d->root, "issues"))
// Coverity JSON format
d->decoder.reset(new CovTreeDecoder);
d->decoder.reset(new CovTreeDecoder(d->input));
else if (findChildOf(&node, d->root, "runs"))
// SARIF format
d->decoder.reset(new SarifTreeDecoder);
Loading