Render until the output stops changing - #597
Open
faresrafat3 wants to merge 1 commit into
Open
faresrafat3 wants to merge 1 commit into
faresrafat3 wants to merge 1 commit into
Conversation
Escaping can depend on where word wrapping split a paragraph, so a
single render pass may produce text that the next pass formats
differently. With a small --wrap, three passes are sometimes needed,
but only two were performed. The result was that a file mdformat had
just written failed --check, and a second mdformat run changed it again:
$ printf 'A * * b\n' > test.md
$ mdformat --wrap 5 test.md && cat test.md
A *
\* b
$ mdformat --check --wrap 5 test.md
Error: File "test.md" is not formatted.
Rendering now repeats until the output is unchanged (bounded, so a
pathological input cannot loop forever). Two passes still cover almost
every input; across the CommonMark spec fixtures with --wrap=5, four
cases need three.
Author
|
Hi @hukkin — following up on this PR. It fixes the fixed-point rendering issue where |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #588.
Escaping can depend on where word wrapping split a paragraph, so a single
render pass may produce text that the next pass formats differently. With a
small
--wrap, three passes are sometimes needed, but only two wereperformed, so a file mdformat had just written failed
--checkand a secondrun changed it again:
Root cause
For that input the render passes are:
Pass 1 breaks the line after
A * *, so on pass 2 the second asterisk is atthe end of a text token and loses the whitespace neighbour that had kept it
unescaped. Pass 2 then escapes it, and pass 3 escapes the first one too
because it is now adjacent to the backslash.
mdformat.text()only ran twopasses, so it returned the pass-2 output, which is not a fixed point.
Changes
_api.text()now renders repeatedly until the output is unchanged, with abound of 9 iterations so a pathological input cannot loop forever. This makes
"what mdformat writes" and "what
--checkaccepts" the same thing.Verification
The reported command sequence now settles on the first run and
--checkpasses:
A regression test covers exactly this (
test_check__after_format_with_small_wrap).I measured how many passes the CommonMark spec fixtures actually need, to check
that the loop is not papering over a deeper problem:
keepno605So two passes cover everything except one case at
--wrap=5, which is why thebug only shows up at small wrap widths.
Full suite:
4283 passed, 5 skipped(4282 before, plus the new test).