Skip to content

Commit

Permalink
Gather results by rules (#881)
Browse files Browse the repository at this point in the history
  • Loading branch information
drdavella authored Oct 16, 2024
1 parent 1361e68 commit 79aac2e
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/codemodder/result.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import itertools
from abc import abstractmethod
from dataclasses import dataclass, field
from pathlib import Path
Expand Down Expand Up @@ -139,7 +140,14 @@ def fuzzy_column_match(pos: CodeRange, location: Location) -> bool:


class ResultSet(dict[str, dict[Path, list[Result]]]):
results_for_rule: dict[str, list[Result]]

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.results_for_rule = {}

def add_result(self, result: Result):
self.results_for_rule.setdefault(result.rule_id, []).append(result)
for loc in result.locations:
self.setdefault(result.rule_id, {}).setdefault(loc.file, []).append(result)

Expand All @@ -157,23 +165,39 @@ def results_for_rule_and_file(
"""
return self.get(rule_id, {}).get(file.relative_to(context.directory), [])

def results_for_rules(self, rule_ids: list[str]) -> list[Result]:
"""
Returns flat list of all results that match any of the given rule IDs.
"""
return list(
itertools.chain.from_iterable(
self.results_for_rule.get(rule_id, []) for rule_id in rule_ids
)
)

def files_for_rule(self, rule_id: str) -> list[Path]:
return list(self.get(rule_id, {}).keys())

def all_rule_ids(self) -> list[str]:
return list(self.keys())

def __or__(self, other):
result = ResultSet(super().__or__(other))
result = self.__class__()
for k in self.keys() | other.keys():
result[k] = list_dict_or(self[k], other[k])
result[k] = list_dict_or(self.get(k, {}), other.get(k, {}))
result.results_for_rule = list_dict_or(
self.results_for_rule, other.results_for_rule
)
return result

def __ior__(self, other):
return self | other


def list_dict_or(
dictionary: dict[Any, list[Any]], other: dict[Any, list[Any]]
) -> dict[Path, list[Any]]:
result_dict = other | dictionary
) -> dict[Any, list[Any]]:
result_dict = {}
for k in other.keys() | dictionary.keys():
result_dict[k] = dictionary[k] + other[k]
result_dict[k] = dictionary.get(k, []) + other.get(k, [])
return result_dict
5 changes: 5 additions & 0 deletions tests/test_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ def test_or(self, tmpdir):
in combined["python:S5659"][Path("code.py")]
)

assert combined.results_for_rules(["python:S5659"]) == [
result1["python:S5659"][Path("code.py")][0],
result2["python:S5659"][Path("code.py")][0],
]

def test_sonar_only_open_issues(self, tmpdir):
issues = {
"issues": [
Expand Down

0 comments on commit 79aac2e

Please sign in to comment.