fix(tools): keep source lines when the guest pointer audit blanks comments and literals

Main's progress.code now drops blank lines, so the audit reported
lines from a shorter text (Export.cpp:145 for an access on line 172).
The audit blanks comments and literals itself, keeping every line,
including spliced ones.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
LeandroLP23andClaude Opus 5.5 committed 2026-11-05 22:08:27 +01:00
1 parent 0fa9337b21
commit 6f4a93d0e4
2 files changed
+39 -4

No files matched your search

+30 -1
View File
@@ -103,6 +103,35 @@ def accesses(body, name):
return sorted(found)
def splice_lines(text):
lines = []
pending = ""
joined = 0
for line in text.replace("\r\n", "\n").split("\n"):
if line.endswith("\\"):
pending += line[:-1]
joined += 1
continue
lines.append(pending + line + "\n" * joined)
pending = ""
joined = 0
if joined:
lines.append(pending + "\n" * joined)
return "\n".join(lines)
def keep_lines(match):
if match.group("code") is not None:
return match.group()
if match.group("comment") is None:
return "LITERAL" + "\n" * match.group().count("\n")
return re.sub(r"[^\n]", " ", match.group())
def source_code(text):
return progress.CPP_TOKEN.sub(keep_lines, splice_lines(text))
def audit_text(text):
results = []
for match in progress.DEFINITION.finditer(text):
@@ -124,7 +153,7 @@ def audit(libraries):
for source in sorted(library.rglob("*.cpp")):
if "tests" in source.relative_to(library).parts:
continue
text = progress.code(source.read_text(encoding="utf-8", errors="ignore"))
text = source_code(source.read_text(encoding="utf-8", errors="ignore"))
for entry in audit_text(text):
report.append({"library": library.name, "file": source.relative_to(ROOT).as_posix(), **entry})
return report
+9 -3
View File
@@ -13,7 +13,7 @@ import progress
def findings(source):
return [(entry["function"], entry["parameter"], entry["kinds"]) for entry in guest_pointer_audit.audit_text(progress.code(source))]
return [(entry["function"], entry["parameter"], entry["kinds"]) for entry in guest_pointer_audit.audit_text(guest_pointer_audit.source_code(source))]
class AccessTests(unittest.TestCase):
@@ -101,15 +101,21 @@ class AccessTests(unittest.TestCase):
self.assertEqual(findings(source), [("sceExampleSn", "p", ["library call"]), ("sceExampleS", "p", ["library call"])])
def test_line_is_the_earliest_access_of_any_kind(self):
entry, = guest_pointer_audit.audit_text(progress.code("int APS5_VABI sceExampleEarly(Info* p)\n{\n p[0] = {};\n p->field = 1;\n return 0;\n}\n"))
entry, = guest_pointer_audit.audit_text(guest_pointer_audit.source_code("int APS5_VABI sceExampleEarly(Info* p)\n{\n p[0] = {};\n p->field = 1;\n return 0;\n}\n"))
self.assertEqual((entry["line"], entry["kinds"]), (3, ["index", "member"]))
def test_comments_and_literals_are_ignored(self):
source = "int APS5_VABI sceExampleText(Info* info) { // info->size = 4;\n return Log(\"info->size *info info[0]\"); }\n"
self.assertEqual(findings(source), [])
def test_line_counts_blank_spliced_and_commented_lines(self):
source = ("int APS5_VABI sceExampleBlank(int* out)\n{\n\n\n /* one\n two */\n const char* s = R\"(a\nb)\";\n"
" int wide = 1 + \\\n 2;\n\n *out = wide;\n return 0;\n}\n")
entry, = guest_pointer_audit.audit_text(guest_pointer_audit.source_code(source))
self.assertEqual(entry["line"], 12)
def test_line_points_at_the_first_access(self):
entry, = guest_pointer_audit.audit_text(progress.code("int APS5_VABI sceExampleLine(int* out)\n{\n int a = 0;\n *out = a;\n return 0;\n}\n"))
entry, = guest_pointer_audit.audit_text(guest_pointer_audit.source_code("int APS5_VABI sceExampleLine(int* out)\n{\n int a = 0;\n *out = a;\n return 0;\n}\n"))
self.assertEqual(entry["line"], 4)