Skip to content

Commit e82af12

Browse files
committed
csgrep --warning-rate-limit: preserve location
... and other metadata from the warning instance that exceeded the limit Resolves: #119
1 parent 36c490c commit e82af12

File tree

2 files changed

+56
-30
lines changed

2 files changed

+56
-30
lines changed

src/lib/filter.cc

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <fstream>
2525
#include <iomanip>
26+
#include <queue>
2627
#include <set>
2728
#include <sstream>
2829

@@ -209,10 +210,17 @@ bool DuplicateFilter::matchDef(const Defect &def)
209210
// implementation of RateLimitter
210211

211212
struct RateLimitter::Private {
213+
// counter of checker/key-event pairs
212214
using TKey = std::pair<std::string, std::string>;
213215
using TCnt = int;
214216
using TMap = std::map<TKey, TCnt>;
215217
TMap counter;
218+
219+
// list of defects where the limit was exceeded
220+
using TErrorList = std::queue<Defect>;
221+
TErrorList errors;
222+
223+
// rate limit set during initialization
216224
TCnt rateLimit;
217225
};
218226

@@ -226,50 +234,59 @@ RateLimitter::RateLimitter(AbstractWriter *agent, int rateLimit):
226234
bool RateLimitter::matchDef(const Defect &def)
227235
{
228236
// resolve the checker/event pair for the key event
229-
const DefEvent &evt = def.events[def.keyEventIdx];
237+
DefEvent evt = def.events[def.keyEventIdx];
230238
const Private::TKey key(def.checker, evt.event);
231239

232240
// increment the counter and get the current value
233241
const Private::TCnt cnt = ++d->counter[key];
234242

235243
// check whether the specified limit is exceeded
236-
return (cnt < d->rateLimit);
244+
if (cnt < d->rateLimit)
245+
return true;
246+
247+
if (cnt == d->rateLimit) {
248+
// record defect prototype containing the key event only (without msg)
249+
evt.msg.clear();
250+
251+
Defect defProto = def;
252+
defProto.events.clear();
253+
defProto.events.push_back(std::move(evt));
254+
d->errors.push(std::move(defProto));
255+
}
256+
257+
// limit exceeded
258+
return false;
237259
}
238260

239261
void RateLimitter::flush()
240262
{
241-
for (const auto &item : d->counter) {
242-
const Private::TCnt cnt = item.second;
243-
if (cnt < d->rateLimit)
244-
// limit not exceeded for this checker/event pair
245-
continue;
263+
for (; !d->errors.empty(); d->errors.pop()) {
264+
Defect &def = d->errors.front();
246265

247-
// resolve the checker/event pair
248-
const Private::TKey &key = item.first;
249-
const std::string &checker = key.first;
250-
const std::string &keyEvtName = key.second;
266+
// resolve the count of occurrences for this checker/event pair
267+
const DefEvent &keyEvt = def.events[def.keyEventIdx];
268+
const Private::TKey key(def.checker, keyEvt.event);
269+
const Private::TCnt cnt = d->counter[key];
251270

252271
// construct an error event
253272
std::ostringstream err, note;
254-
err << cnt << " occurrences of " << keyEvtName
273+
err << cnt << " occurrences of " << keyEvt.event
255274
<< " exceeded the specified limit "
256275
<< d->rateLimit;
257276

258-
DefEvent evtErr("error[too-many]");
277+
DefEvent &evtErr = def.events.back();
278+
evtErr.event = "error[too-many]";
259279
evtErr.msg = err.str();
260280

261281
// construct a note event
262282
note << (cnt - d->rateLimit) << " occurrences of "
263-
<< keyEvtName << " were discarded because of this";
283+
<< keyEvt.event << " were discarded because of this";
264284

265-
DefEvent evtNote("note");
285+
DefEvent evtNote = evtErr;
286+
evtNote.event = "note";
266287
evtNote.msg = note.str();
267288
evtNote.verbosityLevel = /* info */ 1;
268-
269-
// construct a defect containing the above events
270-
Defect def(checker);
271-
def.events.push_back(evtErr);
272-
def.events.push_back(evtNote);
289+
def.events.push_back(std::move(evtNote));
273290

274291
// process the newly constructed defect by the chain of writers
275292
GenericAbstractFilter::handleDef(def);

tests/csgrep/0110-warning-rate-limit-stdout.txt

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,40 +1875,49 @@
18751875
},
18761876
{
18771877
"checker": "SHELLCHECK_WARNING",
1878+
"language": "shell",
1879+
"tool": "shellcheck",
18781880
"key_event_idx": 0,
18791881
"events": [
18801882
{
1881-
"file_name": "",
1882-
"line": 0,
1883+
"file_name": "./doc/example/compiler-etc-dependencies/example-sessions/ompi-defaults.sh",
1884+
"line": 3,
1885+
"column": 8,
18831886
"event": "error[too-many]",
18841887
"message": "115 occurrences of note[SC2086] exceeded the specified limit 16",
18851888
"verbosity_level": 0
18861889
},
18871890
{
1888-
"file_name": "",
1889-
"line": 0,
1891+
"file_name": "./doc/example/compiler-etc-dependencies/example-sessions/ompi-defaults.sh",
1892+
"line": 3,
1893+
"column": 8,
18901894
"event": "note",
1891-
"message": "99 occurrences of note[SC2086] were discarded because of this",
1895+
"message": "99 occurrences of error[too-many] were discarded because of this",
18921896
"verbosity_level": 1
18931897
}
18941898
]
18951899
},
18961900
{
18971901
"checker": "SHELLCHECK_WARNING",
1902+
"cwe": 140,
1903+
"language": "shell",
1904+
"tool": "shellcheck",
18981905
"key_event_idx": 0,
18991906
"events": [
19001907
{
1901-
"file_name": "",
1902-
"line": 0,
1908+
"file_name": "./init/bash_completion.in",
1909+
"line": 128,
1910+
"column": 37,
19031911
"event": "error[too-many]",
19041912
"message": "29 occurrences of warning[SC2207] exceeded the specified limit 16",
19051913
"verbosity_level": 0
19061914
},
19071915
{
1908-
"file_name": "",
1909-
"line": 0,
1916+
"file_name": "./init/bash_completion.in",
1917+
"line": 128,
1918+
"column": 37,
19101919
"event": "note",
1911-
"message": "13 occurrences of warning[SC2207] were discarded because of this",
1920+
"message": "13 occurrences of error[too-many] were discarded because of this",
19121921
"verbosity_level": 1
19131922
}
19141923
]

0 commit comments

Comments
 (0)