fix: preserve nested code fences in review snippets - #3418
kevin-lozada-santos wants to merge 8 commits into
Conversation
When a file's extracted lines contain their own fenced code blocks (e.g. a README with a ```bash section), wrapping them in the standard triple-backtick fence caused the Markdown parser to misinterpret the inner ``` as a closing fence. This broke rendering inside GitHub <details> collapsible blocks, producing a stray ``` before </details>. Introduce _get_fence(content) in pr_agent/algo/utils.py. The helper scans the content for the longest consecutive run of backticks and returns a fence that is one backtick longer (minimum three). This guarantees the outer fence can never be prematurely closed by any backtick sequence inside the content. Update extract_relevant_lines_str to call _get_fence instead of hard-coding ``` . The guard "if relevant_lines_str" that now wraps the fence assignment also prevents building a fence string around an empty result, which was a latent bug. Add tests/unittest/test_extract_relevant_lines_str.py covering: - Empty/missing file list returns an empty string. - Single-line and multi-line extraction with correct fences. - Language identifier propagated into the opening fence. - Optional dedent of common leading whitespace. - Fallback path that mines lines from the patch when head_file is None. - Filename with leading/trailing spaces is matched correctly. - Content containing ``` triggers a 4-backtick outer fence, and the inner block is preserved verbatim. - End-to-end check via convert_to_markdown_v2 with a real README containing a ```bash block: the <details> body uses ````markdown and the inner ```bash is kept intact.
Updated the content construction in the _test_make_file method for better readability by using parentheses for multiline strings. Also improved the assertion message in the test case to enhance clarity when the expected output does not match.
The `_get_fence` utility previously only considered backtick sequences when computing a safe outer fence for Markdown code blocks. When content (such as a README) contained triple-backtick fenced blocks, the function would produce a four-backtick fence. For content with even longer backtick runs, the fence could grow arbitrarily long, risking truncation by LLM providers or Markdown renderers with line-length limits. The updated algorithm evaluates both backtick and tilde fence candidates independently, then selects whichever yields the shorter safe fence. Since most real-world Markdown content uses backtick fences and rarely contains tilde sequences, a triple-backtick block in the content now triggers a three-tilde fence rather than a four-backtick fence. This keeps the outer fence at the minimum safe length in the common case. The tie-breaking rule preserves the previous default: when both candidates produce the same length, backticks are returned, so plain content without either character still produces the familiar ``` fence. All affected unit tests are updated to assert tilde fences where the old logic would have produced four-backtick fences, and a new dedicated test suite for `_get_fence` covers empty input, single-character runs, long runs of each character, mixed content, tie-breaking, and the invariant that the returned fence never appears verbatim inside the content. Reduces the risk of provider-side truncation caused by unexpectedly long fence lines when wrapping Markdown content that itself contains fenced code blocks.
… double quotes Updated string literals in the test file to use double quotes for consistency and improved readability. This change affects various sections of the code, including the definition of Python code blocks and the construction of synthetic files for testing. The adjustments ensure uniformity in string formatting across the test cases.
…unction The change updates string literals in the `_get_fence` function from single quotes to double quotes. This is a purely cosmetic, style-consistency change with no behavioral impact. Python projects often enforce a single quoting style across the codebase to maintain readability and reduce cognitive overhead when reading code. Tools like `black`, the widely adopted Python formatter, default to double quotes. Aligning with this convention ensures the codebase remains consistent and passes automated style checks without requiring exceptions or suppressions. Standardizing quote style reduces noise in future diffs, making it easier to spot meaningful changes rather than stylistic ones.
PR Summary by QodoPreserve nested code fences in review snippets
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1. Issue fences can still break reviews
|
|
Code review by qodo was updated up to the latest commit 54d3f63 |
Signed-off-by: kevin-lozada-santos <kevinolozadasantos@gmail.com>
|
Code review by qodo was updated up to the latest commit 6c4549f |
|
Updated the two nested-fence comments to imperative phrasing in 6c4549f. All 33 focused tests, Ruff, and applicable local pre-commit hooks pass. An exact Python AST comparison against the parent confirms that executable code, assertions, test names, and docstrings are unchanged. The separate |
Review follow-up at 54d3f63: clarified two test names and corrected test documentation. Executable AST is unchanged after excluding docstrings and those names; all 33 focused tests, Ruff and applicable pre-commit hooks pass. The full-suite and six successful CI results below are from the earlier 7f24014 revision; fresh CI for this follow-up is pending.
Fixes #3415. Restores @evandrocoan's fix from #2312 against current main, preserving all five original commits and their authorship. Adds four regression cases for nested fences in patch-derived snippets, with and without dedenting.
Extracted lines containing a closing triple-backtick fence currently close their own wrapper: GitHub then renders the review footer inside a second code block. The restored helper selects the shortest safe backtick or tilde fence, preserving the snippet and keeping the surrounding review intact. This does not change the separately identified issue_content interpolation.
Validation (Windows Python 3.12.13 and Linux Python 3.12.3):
Terminal excerpts:
I used Brain Scanner to organize a focused map of the review-formatting path and its test evidence. The diagnosis and repair are verified by the tests and renderer comparison above. Try it now: https://brainscanner.dev/