From f37eecfdac8fa95eaf3d3ade9c02a258a7879e42 Mon Sep 17 00:00:00 2001 From: MiniRML <134226498+MiniRML@users.noreply.github.com> Date: Mon, 12 Oct 2026 08:54:38 -0700 Subject: [PATCH] fix(progress): ignore C++ raw-string contents --- tools/progress.py | 15 ++++++++++----- tools/tests/test_progress.py | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/tools/progress.py b/tools/progress.py index c27199b01..4a15c8984 100644 --- a/tools/progress.py +++ b/tools/progress.py @@ -6,6 +6,11 @@ import sys from html import escape from pathlib import Path +try: + from tools.nid_names import CPP_TOKEN +except ImportError: + from nid_names import CPP_TOKEN + ROOT = Path(__file__).resolve().parent.parent PRX = ROOT / "core" / "libs" / "prx" OPCODES = ROOT / "core" / "shader" / "recompiler" / "RdnaDecoder" / "include" / "RdnaDecoder" / "RdnaOpcode.hpp" @@ -20,7 +25,6 @@ STUB_WRAPPER = re.compile( r"^[ \t]*(?:static\s+)?(?:\[\[noreturn\]\]\s+)?(?:(?!APS5_VABI)[\w:<>,\s*&])+?[\s*&]" r"(?!(?:if|while|for|switch|catch|return|else)\b)(\w+)\s*\([^;{]*\)\s*" r"(?:const\s*)?(?:noexcept\s*)?(?:->\s*[\w:<>*&\s]+?)?\{", re.M) -NON_CODE = re.compile(r'"(?:\\.|[^"\\\n])*"|\'(?:\\.|[^\'\\\n])*\'|//[^\n]*|/\*.*?\*/', re.S) DISCARD = re.compile(r"\(void\)\s*\w+\s*;") EMPTY_RETURN = re.compile(r"return\s*;") CONST_RETURN = re.compile(r"return\s+(?:[+-]?\s*(?:0[xX][0-9a-fA-F]+|\d+)[uUlL]*|\w+|\"(?:\\.|[^\"\\])*\")\s*;") @@ -73,14 +77,15 @@ DONE_COLOR, TODO_COLOR, BORDER, TEXT = "#2ea043", "#6e7681", "#0d1117", "#ffffff def blank(match): - if match.group(0).startswith(('"', "'")): + if match.group("code") is not None: + return match.group() + if match.group("comment") is None: return "LITERAL" - return re.sub(r"[^\n]", " ", match.group(0)) + return re.sub(r"[^\n]", " ", match.group()) def code(text): - return NON_CODE.sub(blank, text) - + return CPP_TOKEN.sub(blank, text.replace("\\\n", "").replace("\\\r\n", "")) def body_end(text, start): depth = 0 diff --git a/tools/tests/test_progress.py b/tools/tests/test_progress.py index d5ee4c87a..125de5c1e 100644 --- a/tools/tests/test_progress.py +++ b/tools/tests/test_progress.py @@ -9,6 +9,30 @@ import progress class ProgressTests(unittest.TestCase): + def test_raw_string_example_does_not_declare_an_export(self): + source = 'const char* example = R"help(\nint APS5_VABI Fake() { return 0; }\n)help";\n' + source += 'int APS5_VABI Real() { return 7; }\n' + with tempfile.TemporaryDirectory() as directory: + library = Path(directory) / "libSceExample" + library.mkdir() + (library / "Export.cpp").write_text(source, encoding="utf-8") + group = progress.scan_library(library) + self.assertEqual(group["done_names"], ["Real"]) + self.assertEqual(group["todo_names"], []) + + def test_stub_marker_inside_raw_literals_does_not_mark_implementation_as_stub(self): + for prefix in ("", "u8", "u", "U", "L"): + source = ('int APS5_VABI Ready(int value) {\n' + 'auto message = ' + prefix + 'R"help(\n"quoted" NotImplemented_nid_no_patch(); } {\n)help";\n' + 'return value + 1;\n}\n') + with self.subTest(prefix=prefix), tempfile.TemporaryDirectory() as directory: + library = Path(directory) / "libSceExample" + library.mkdir() + (library / "Export.cpp").write_text(source, encoding="utf-8") + group = progress.scan_library(library) + self.assertEqual(group["done_names"], ["Ready"]) + self.assertEqual(group["todo_names"], []) + def test_nonvoid_stub_wrappers_keep_callers_unimplemented(self): with tempfile.TemporaryDirectory() as directory: library = Path(directory) / "libSceExample"