Skip to content

Commit 6d4e9c0

Browse files
committed
Account for frozen datatypes when updating finding metadata
1 parent a77025c commit 6d4e9c0

File tree

3 files changed

+87
-7
lines changed

3 files changed

+87
-7
lines changed

src/codemodder/codetf.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ def validate_description(self):
7676
raise ValueError("description must not be empty")
7777
return self
7878

79+
def with_findings(self, findings: list[Finding] | None) -> Change:
80+
return Change(
81+
lineNumber=self.lineNumber,
82+
description=self.description,
83+
diffSide=self.diffSide,
84+
properties=self.properties,
85+
packageActions=self.packageActions,
86+
findings=findings,
87+
)
88+
7989

8090
class AIMetadata(BaseModel):
8191
provider: Optional[str] = None
@@ -99,6 +109,16 @@ class ChangeSet(BaseModel):
99109
strategy: Optional[Strategy] = None
100110
provisional: Optional[bool] = False
101111

112+
def with_changes(self, changes: list[Change]) -> ChangeSet:
113+
return ChangeSet(
114+
path=self.path,
115+
diff=self.diff,
116+
changes=changes,
117+
ai=self.ai,
118+
strategy=self.strategy,
119+
provisional=self.provisional,
120+
)
121+
102122

103123
class Reference(BaseModel):
104124
url: str
@@ -141,6 +161,12 @@ def to_unfixed_finding(
141161
reason=reason,
142162
)
143163

164+
def with_rule(self, name: str, url: Optional[str]) -> Finding:
165+
return Finding(
166+
id=self.id,
167+
rule=Rule(id=self.rule.id, name=name, url=url),
168+
)
169+
144170

145171
class UnfixedFinding(Finding):
146172
path: str

src/codemodder/utils/update_finding_metadata.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
if typing.TYPE_CHECKING:
66
from codemodder.codemods.base_codemod import ToolRule
77

8-
from codemodder.codetf import ChangeSet
8+
from codemodder.codetf import Change, ChangeSet
99

1010

1111
def update_finding_metadata(
@@ -15,12 +15,23 @@ def update_finding_metadata(
1515
if not (tool_rule_map := {rule.id: (rule.name, rule.url) for rule in tool_rules}):
1616
return changesets
1717

18+
new_changesets: list[ChangeSet] = []
1819
for changeset in changesets:
20+
new_changes: list[Change] = []
1921
for change in changeset.changes:
20-
for finding in change.findings or []:
21-
if finding.id in tool_rule_map:
22-
finding.rule.name = tool_rule_map[finding.id][0]
23-
finding.rule.url = tool_rule_map[finding.id][1]
22+
new_changes.append(
23+
change.with_findings(
24+
[
25+
(
26+
finding.with_rule(*tool_rule_map[finding.rule.id])
27+
if finding.rule.id in tool_rule_map
28+
else finding
29+
)
30+
for finding in change.findings or []
31+
]
32+
or None
33+
)
34+
)
35+
new_changesets.append(changeset.with_changes(new_changes))
2436

25-
# TODO: eventually make this functional and return a new list
26-
return changesets
37+
return new_changesets
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from codemodder.codemods.base_codemod import ToolRule
2+
from codemodder.codetf import Change, ChangeSet, Finding, Rule
3+
from codemodder.utils.update_finding_metadata import update_finding_metadata
4+
5+
6+
def test_update_finding_metdata():
7+
tool_rule = ToolRule(id="rule_id", name="rule_name", url="rule_url")
8+
changeset = ChangeSet(
9+
path="",
10+
diff="",
11+
changes=[
12+
Change(
13+
lineNumber=1,
14+
description="foo",
15+
findings=[
16+
Finding(id="rule_id", rule=Rule(id="rule_id", name="other_name"))
17+
],
18+
),
19+
Change(
20+
lineNumber=2,
21+
description="bar",
22+
findings=[
23+
Finding(id="other_id", rule=Rule(id="other_id", name="other_name"))
24+
],
25+
),
26+
Change(
27+
lineNumber=3,
28+
description="baz",
29+
),
30+
],
31+
)
32+
33+
new_changesets = update_finding_metadata(
34+
tool_rules=[tool_rule], changesets=[changeset]
35+
)
36+
37+
assert new_changesets[0].changes[0].findings
38+
assert new_changesets[0].changes[0].findings[0].rule.name == "rule_name"
39+
assert new_changesets[0].changes[0].findings[0].rule.url == "rule_url"
40+
assert new_changesets[0].changes[1].findings
41+
assert new_changesets[0].changes[1].findings[0].rule.name == "other_name"
42+
assert new_changesets[0].changes[1].findings[0].rule.url is None
43+
assert new_changesets[0].changes[2] == changeset.changes[2]

0 commit comments

Comments
 (0)