Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions scripts/pr_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,10 @@
FENCE = re.compile(r"^ {0,3}```.*?^ {0,3}```[^\n]*", re.DOTALL | re.MULTILINE)
# An inline code span is a quotation for the same reason a fenced block is.
# A reviewer naming `<summary>` in prose was read as opening one.
# That swallowed the body from there to the next real close tag.
# The backreference between two boundary guards matches the run length exactly.
# So a one-backtick span carrying a two-backtick run closes on its own run.
# A span cannot cross a blank line, per CommonMark.
# Unbounded it paired two stray backticks and masked every marker between them.
# Replaced by a space rather than deleted, since deleting joins the text on either side.
# ``<summary`x`>`` would otherwise become an opening tag the body never carried.
# A space also leaves nothing unprintable in a marker this script quotes to a reader.
CODE_SPAN = re.compile(r"(?<!`)(`+)(?!`)(?:[^\n]|\n(?!\s*\n))*?(?<!`)\1(?!`)")
# Bounded to a paragraph, and an escaped tick opens nothing, since either masks a section.
# Only the opener takes that guard, a backslash being literal inside a span rather than an escape.
# Replaced by a space, since deleting joins the sides into a tag the body never carried.
CODE_SPAN = re.compile(r"(?<![\\`])(`+)(?!`)(?:[^\n]|\n(?!\s*\n))*?(?<!`)\1(?!`)")


# The round's own file summary table, whose first column is a path and whose second is prose.
Expand Down
36 changes: 36 additions & 0 deletions scripts/tests/test_pr_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -1700,6 +1700,42 @@ def test_a_real_coverage_line_survives_the_code_span_mask(self) -> None:
line = "- **Files reviewed:** 31/31 changed files"
self.assertEqual([line], pr_review.coverage_statements(OVERVIEW + "\n" + line + "\n"))

def test_an_escaped_backtick_does_not_open_a_span(self) -> None:
"""A backslash-escaped backtick is a literal, so it delimits nothing.

Reading one as an opener pairs it with the next real tick and masks everything between,
which is the silent direction: a genuine unknown section disappears and the loop closes
on a body nobody read.
"""
body = (
OVERVIEW
+ "\nEscaped \\` then <details><summary>Bogus</summary></details> then ` a span `."
)
self.assertEqual(["summary: Bogus"], pr_review.unrecognized_in(body))

def test_a_span_ending_in_a_backslash_still_closes(self) -> None:
"""A backslash inside a code span is literal, so it does not escape the closing run.

Guarding the closer the same way as the opener skips a valid close, so the span runs on
and masks the section after it, which is the failure the opener guard exists to prevent
rather than to cause.
"""
body = (
OVERVIEW
+ "\nA span `a\\` then <details><summary>Hidden</summary></details> and ` more."
)
self.assertEqual(["summary: Hidden"], pr_review.unrecognized_in(body))

def test_a_quoted_marker_stays_masked_when_the_span_ends_in_a_backslash(self) -> None:
"""The other side of the close guard: a quoted marker must not escape through it.

Where the span both carries a marker and ends in a backslash, failing to recognize the
close reports the quoted marker as a real section, which is what the masking exists to
prevent.
"""
body = OVERVIEW + "\nQuoting `<details><summary>Quoted</summary></details>\\` here."
self.assertEqual([], pr_review.unrecognized_in(body))

def test_every_vetted_marker_together_reads_as_recognized(self) -> None:
"""The corpus shape in one body, so the lists are held against what they were built from."""
self.assertEqual([], pr_review.unrecognized_in(nested()))
Expand Down