Skip to content

Commit 5f4f575

Browse files
authored
All places when a Change() is created should report findings (#734)
* wip asserting findings * report findings
1 parent df0afef commit 5f4f575

File tree

8 files changed

+49
-9
lines changed

8 files changed

+49
-9
lines changed

src/codemodder/codemods/libcst_transformer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def add_change_from_position(
109109
Change(
110110
lineNumber=lineno,
111111
description=description,
112+
findings=self.file_context.get_findings_for_location(lineno),
112113
)
113114
)
114115

src/codemodder/codemods/test/utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from codemodder import registry
99
from codemodder.codemods.api import BaseCodemod
10+
from codemodder.codetf import Change
1011
from codemodder.context import CodemodExecutionContext
1112
from codemodder.diff import create_diff
1213
from codemodder.providers import load_providers
@@ -210,6 +211,8 @@ def run_and_assert(
210211

211212
self.assert_num_changes(changes, num_changes, min_num_changes)
212213

214+
self.assert_findings(changes[0].changes)
215+
213216
self.assert_changes(
214217
tmpdir,
215218
tmp_file_path,
@@ -219,3 +222,8 @@ def run_and_assert(
219222
)
220223

221224
return changes
225+
226+
def assert_findings(self, changes: list[Change]):
227+
assert all(
228+
x.findings is not None for x in changes
229+
), f"Expected all changes to have findings: {changes}"

src/codemodder/codemods/xml_transformer.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ class XMLTransformer(XMLGenerator, LexicalHandler):
2626
def __init__(
2727
self,
2828
out,
29+
file_context: FileContext,
2930
encoding: str = "utf-8",
3031
short_empty_elements: bool = False,
3132
results: list[Result] | None = None,
3233
) -> None:
34+
self.file_context = file_context
3335
self.results = results
3436
self.changes: list[Change] = []
3537
self._my_locator = Locator()
@@ -87,7 +89,11 @@ def match_result(self, line, column) -> bool:
8789

8890
def add_change(self, line):
8991
self.changes.append(
90-
Change(lineNumber=line, description=self.change_description)
92+
Change(
93+
lineNumber=line,
94+
description=self.change_description,
95+
findings=self.file_context.get_findings_for_location(line),
96+
)
9197
)
9298

9399

@@ -99,13 +105,14 @@ class ElementAttributeXMLTransformer(XMLTransformer):
99105
def __init__(
100106
self,
101107
out,
108+
file_context: FileContext,
102109
name_attributes_map: dict[str, dict[str, str]],
103110
encoding: str = "utf-8",
104111
short_empty_elements: bool = False,
105112
results: list[Result] | None = None,
106113
) -> None:
107114
self.name_attributes_map = name_attributes_map
108-
super().__init__(out, encoding, short_empty_elements, results)
115+
super().__init__(out, file_context, encoding, short_empty_elements, results)
109116

110117
def startElement(self, name, attrs):
111118
new_attrs: AttributesImpl = attrs
@@ -131,12 +138,13 @@ class NewElementXMLTransformer(XMLTransformer):
131138
def __init__(
132139
self,
133140
out,
141+
file_context: FileContext,
134142
encoding: str = "utf-8",
135143
short_empty_elements: bool = False,
136144
results: list[Result] | None = None,
137145
new_elements: list[NewElement] | None = None,
138146
) -> None:
139-
super().__init__(out, encoding, short_empty_elements, results)
147+
super().__init__(out, file_context, encoding, short_empty_elements, results)
140148
self.new_elements = new_elements or []
141149

142150
def startElement(self, name, attrs):
@@ -175,7 +183,9 @@ def apply(
175183
# this will fail fast for files that are not XML
176184
try:
177185
transformer_instance = self.xml_transformer(
178-
out=output_file, results=results
186+
out=output_file,
187+
file_context=file_context,
188+
results=results,
179189
)
180190
parser = make_parser()
181191
parser.setContentHandler(transformer_instance)

src/core_codemods/file_resource_leak.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ def line_filter(x):
5959

6060
for k, v in fr.assigned_resources.items():
6161
fr.assigned_resources[k] = [t for t in v if line_filter(t)]
62-
fixer = ResourceLeakFixer(self.context, fr.assigned_resources)
62+
fixer = ResourceLeakFixer(
63+
self.context, self.file_context, fr.assigned_resources
64+
)
6365
result = tree.visit(fixer)
6466
self.file_context.codemod_changes.extend(fixer.changes)
6567
return result
@@ -168,6 +170,7 @@ class ResourceLeakFixer(MetadataPreservingTransformer, NameAndAncestorResolution
168170
def __init__(
169171
self,
170172
context: CodemodContext,
173+
file_context: FileContext,
171174
leaked_assigned_resources: dict[
172175
cst.IndentedBlock | cst.Module,
173176
list[
@@ -182,6 +185,7 @@ def __init__(
182185
super().__init__(context)
183186
self.leaked_assigned_resources = leaked_assigned_resources
184187
self.changes: list[Change] = []
188+
self.file_context = file_context
185189

186190
def _is_fixable(self, block, index, named_targets, other_targets) -> bool:
187191
# assigned to something that is not a Name?
@@ -225,6 +229,9 @@ def _handle_block(
225229
Change(
226230
lineNumber=line_number,
227231
description=FileResourceLeakTransformer.change_description,
232+
findings=self.file_context.get_findings_for_location(
233+
line_number
234+
),
228235
)
229236
)
230237

src/core_codemods/fix_assert_tuple.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ def _report_new_lines(
4949
for idx in range(newlines_count):
5050
self.file_context.codemod_changes.append(
5151
Change(
52-
lineNumber=start_line + idx,
52+
lineNumber=(line_number := start_line + idx),
5353
description=self.change_description,
54+
findings=self.file_context.get_findings_for_location(line_number),
5455
)
5556
)
5657

src/core_codemods/sql_parameterization.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ def transform_module_impl(self, tree: cst.Module) -> cst.Module:
253253
Change(
254254
lineNumber=line_number,
255255
description=SQLQueryParameterizationTransformer.change_description,
256+
findings=self.file_context.get_findings_for_location(
257+
line_number
258+
),
256259
)
257260
)
258261
# Normalization and cleanup

src/core_codemods/url_sandbox.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def __init__(
7171
cst.CSTNode, Union[cst.CSTNode, cst.FlattenSentinel, cst.RemovalSentinel]
7272
] = {}
7373
self.changes_in_file: List[Change] = []
74+
self.file_context = file_context
7475
ContextAwareVisitor.__init__(self, codemod_context)
7576
UtilsMixin.__init__(
7677
self,
@@ -109,6 +110,9 @@ def leave_Call(self, original_node: cst.Call):
109110
Change(
110111
lineNumber=line_number,
111112
description=UrlSandboxTransformer.change_description,
113+
findings=self.file_context.get_findings_for_location(
114+
line_number
115+
),
112116
)
113117
)
114118

@@ -126,6 +130,9 @@ def leave_Call(self, original_node: cst.Call):
126130
Change(
127131
lineNumber=line_number,
128132
description=UrlSandboxTransformer.change_description,
133+
findings=self.file_context.get_findings_for_location(
134+
line_number
135+
),
129136
)
130137
)
131138

tests/test_xml_transformer.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from textwrap import dedent
33
from xml.sax import handler
44

5+
import mock
56
import pytest
67
from defusedxml import ExternalReferenceForbidden
78
from defusedxml.sax import make_parser
@@ -19,7 +20,7 @@ class TestXMLTransformer:
1920
def run_and_assert(self, input_code, expected_output):
2021
with StringIO() as result, StringIO(dedent(input_code)) as input_stream:
2122
result = StringIO()
22-
transformer = XMLTransformer(result)
23+
transformer = XMLTransformer(result, mock.MagicMock())
2324
parser = make_parser()
2425
parser.setContentHandler(transformer)
2526
parser.setProperty(handler.property_lexical_handler, transformer)
@@ -58,7 +59,7 @@ class TestElementAttributeXMLTransformer:
5859
def run_and_assert(self, name_attr_map, input_code, expected_output):
5960
with StringIO() as result, StringIO(dedent(input_code)) as input_stream:
6061
transformer = ElementAttributeXMLTransformer(
61-
result, name_attributes_map=name_attr_map
62+
result, mock.MagicMock(), name_attributes_map=name_attr_map
6263
)
6364
parser = make_parser()
6465
parser.setContentHandler(transformer)
@@ -101,7 +102,9 @@ class TestNewElementXMLTransformer:
101102

102103
def run_and_assert(self, new_elements, input_code, expected_output):
103104
with StringIO() as result, StringIO(dedent(input_code)) as input_stream:
104-
transformer = NewElementXMLTransformer(result, new_elements=new_elements)
105+
transformer = NewElementXMLTransformer(
106+
result, mock.MagicMock(), new_elements=new_elements
107+
)
105108
parser = make_parser()
106109
parser.setContentHandler(transformer)
107110
parser.setProperty(handler.property_lexical_handler, transformer)

0 commit comments

Comments
 (0)