From 5a5c5cb5f9e36cb754314489c9f4833b4c307bdf Mon Sep 17 00:00:00 2001 From: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com> Date: Sat, 21 Dec 2024 17:40:45 -0800 Subject: [PATCH] Fix cidentlist handling of single quotes in hex literals (#300) --- wpiformat/wpiformat/cidentlist.py | 23 ++++++++++++++------- wpiformat/wpiformat/test/test_cidentlist.py | 8 +++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/wpiformat/wpiformat/cidentlist.py b/wpiformat/wpiformat/cidentlist.py index b79bb65..c866141 100644 --- a/wpiformat/wpiformat/cidentlist.py +++ b/wpiformat/wpiformat/cidentlist.py @@ -18,6 +18,17 @@ def __print_failure(name): def should_process_file(config_file, name): return config_file.is_c_file(name) or config_file.is_cpp_file(name) + @staticmethod + def is_quote_in_number(lines, i): + if i == 0: + return False + c = lines[i - 1] + return ( + ord("0") <= ord(c) <= ord("9") + or ord("A") <= ord(c) <= ord("F") + or ord("a") <= ord(c) <= ord("f") + ) + def run_pipeline(self, config_file, name, lines): linesep = super().get_linesep(lines) @@ -46,7 +57,6 @@ def run_pipeline(self, config_file, name, lines): comment_str = r"/\*|\*/|//|" + linesep + r"|" string_str = r"\\\\|\\\"|\"|" char_str = r"\\'|'|" - digits_str = r"(?P\d+)|" extern_str = r"(?Pextern \"C(\+\+)?\")\s+(?P\{)?|" braces_str = r"\{|\}|;|def\s+\w+|\w+\**\s+\w+\s*(?P\(\))" postfix_str = r"(?=\s*(;|\{))" @@ -55,7 +65,6 @@ def run_pipeline(self, config_file, name, lines): + comment_str + string_str + char_str - + digits_str + extern_str + braces_str + postfix_str @@ -76,7 +85,6 @@ def run_pipeline(self, config_file, name, lines): in_singlecomment = False in_string = False in_char = False - last_digit_end = -1 for match in token_regex.finditer(lines): token = match.group() @@ -117,8 +125,11 @@ def run_pipeline(self, config_file, name, lines): elif token == "\\'": continue elif token == "'": - if not in_string and match.start() != last_digit_end: - in_char = not in_char + if in_string: + continue + if not in_char and self.is_quote_in_number(lines, match.start()): + continue + in_char = not in_char elif in_string or in_char: # Tokens processed after this branch are ignored if they are in # double or single quotes @@ -168,8 +179,6 @@ def run_pipeline(self, config_file, name, lines): # Replaces () with (void) output += lines[pos : match.span("paren")[0]] + "(void)" pos = match.span("paren")[0] + len("()") - elif match.group("digits"): - last_digit_end = match.end() # Write rest of file if it wasn't all processed if pos < len(lines): diff --git a/wpiformat/wpiformat/test/test_cidentlist.py b/wpiformat/wpiformat/test/test_cidentlist.py index e1b84cd..aaaf3b7 100644 --- a/wpiformat/wpiformat/test/test_cidentlist.py +++ b/wpiformat/wpiformat/test/test_cidentlist.py @@ -499,8 +499,16 @@ def test_cidentlist(): test.add_input("./Test.cpp", "void func() { int x = 1'000; }") test.add_latest_input_as_output(True) + # Ensure single quotes in hexadecimal literals are ignored + test.add_input("./Test.cpp", "void func() { int x = 0xffff'ffff; }") + test.add_latest_input_as_output(True) + # Ensure single quotes after numeric literals are not ignored test.add_input("./Test.cpp", "void func() { std::cout << 1 << '0'; }") test.add_latest_input_as_output(True) + # Ensure single quotes after hexadecimal characters are not ignored + test.add_input("./Test.cpp", "void func() { std::cout << 1 << 'a'; }") + test.add_latest_input_as_output(True) + test.run(OutputType.FILE)