-
Notifications
You must be signed in to change notification settings - Fork 0
docs: document ProcessBuffer and continuation-state helper invariants (#366) #414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,6 +65,16 @@ impl ProcessBuffer { | |
| /// lines into the output. | ||
| pub(super) fn into_out(self) -> Vec<String> { self.out } | ||
|
|
||
| /// Drains any buffered lines into `out`, reflowing them as a table when | ||
| /// the run was recognised as one. | ||
| /// | ||
| /// Upholds the buffer invariant that `buf` is empty and `in_table` is | ||
| /// `false` on return, so the next line starts a fresh detection window. | ||
| /// Ellipsis replacement is applied here, *before* [`reflow_table`], because | ||
| /// the substitution must reach the cell text while it is still row-shaped; | ||
| /// running it after reflow would have to re-parse the emitted table. An | ||
| /// empty buffer short-circuits so ordering against [`push_out`](Self::push_out) | ||
| /// is preserved without emitting a spurious blank flush. | ||
| pub(super) fn flush(&mut self) { | ||
| debug!( | ||
| in_table = self.in_table, | ||
|
|
@@ -88,11 +98,26 @@ impl ProcessBuffer { | |
| self.in_table = false; | ||
| } | ||
|
|
||
| /// Emits `line` verbatim after first flushing any pending table. | ||
| /// | ||
| /// The flush is mandatory: a verbatim line (a code fence, for instance) | ||
| /// closes whatever table run preceded it, and appending it directly to | ||
| /// `out` without flushing would let it jump ahead of buffered rows that | ||
| /// belong earlier in the document. Flushing first keeps source ordering | ||
| /// intact. | ||
| pub(super) fn push_verbatim(&mut self, line: &str) { | ||
| self.flush(); | ||
| self.out.push(line.to_string()); | ||
| } | ||
|
|
||
| /// Consumes a code-fence marker line, returning `true` when it was handled. | ||
| /// | ||
| /// A fence marker can never be part of a table, so it must terminate the | ||
| /// current run; the line is emitted through [`push_verbatim`](Self::push_verbatim) | ||
| /// so the pending table flushes first and ordering is preserved. Non-marker | ||
| /// lines return `false` immediately, signalling the caller to fall through | ||
| /// to its in-fence and table-detection handling; this method deliberately | ||
| /// makes no decision about lines *inside* a fence. | ||
| pub(super) fn handle_fence_line(&mut self, line: &str, is_fence_marker: bool) -> bool { | ||
| if !is_fence_marker { | ||
| return false; | ||
|
|
@@ -102,6 +127,19 @@ impl ProcessBuffer { | |
| true | ||
| } | ||
|
|
||
| /// Routes a non-fence line through table detection, buffering it or handing | ||
| /// it back for verbatim emission. | ||
| /// | ||
| /// Returns `None` when the line has been absorbed into the pending table | ||
| /// run (`buf`), and `Some(line)` when the caller should emit it after the | ||
| /// buffer has been flushed. The invariant is that `buf` only ever holds | ||
| /// genuine table rows: every path that meets a line which cannot belong to | ||
| /// the current table flushes before yielding it, so a stray row can never | ||
| /// make [`reflow_table`] bail on an otherwise valid table. The ordering of | ||
|
Comment on lines
+135
to
+140
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Narrow the The code uses permissive heuristics. It buffers non-indented lines that start with Proposed wording- /// The invariant is that `buf` only ever holds genuine table rows: every path that meets a line which cannot belong to the current table flushes before yielding it, so a stray row can never make [`reflow_table`] bail on an otherwise valid table.
+ /// The buffer holds lines accepted by the table-detection heuristics.
+ /// Lines that fail those heuristics flush the current run before the
+ /// caller emits them; the heuristics do not prove that every buffered
+ /// line is a valid table row.🤖 Prompt for AI Agents |
||
| /// the guards is load-bearing — indented code blocks and block boundaries | ||
| /// (see the inline comments) must be recognised *before* the permissive | ||
| /// pipe heuristic, which would otherwise swallow lines that merely happen | ||
| /// to contain a `|`. | ||
| pub(super) fn handle_table_line(&mut self, line: String) -> Option<String> { | ||
| // A leading indent of four or more columns marks a Markdown indented | ||
| // code block, so such a line must stay verbatim and never enter table | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
bufis empty andin_tableistrue, the guard at the start offlushreturns without clearingin_table, so this newly documented unconditional postcondition is false. The existingflush_empty_buffer_is_noopunit test explicitly constructs that state and asserts thatin_tableremains true; qualify the invariant for non-empty buffers or reset the flag before returning.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coderabbitai Has this now been resolved in the latest commit?
Use codegraph analysis to determine your answer.
If this comment is now resolved, please mark it as such using the API. Otherwise, please provide an AI agent prompt for the remaining work to be done to address this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Length of output: 10181
@leynos, treat this comment as resolved.Codegraph analysis confirms that
ProcessBuffer::flushnow documents the empty-buffer exception at Lines 71-76. The empty-buffer guard still returns at Lines 86-88. The regression testflush_empty_buffer_is_noopconfirms thatin_tableremainstruefor this case.The checked-out commit matches the latest PR head:
9a0f5c309163398dda8f1df5e62edcab698188c6.Resolve the thread manually. I cannot use the API to resolve it because
chatgpt-codex-connectorcreated the original review comment, and I can resolve only comments created by this assistant identity.🧬 Code Graph Analysis Results
src/wrap/block.rs:11-28Returns indentation width and byte length, counting tabs as four columns.
src/wrap/block.rs:91-122classify_block(line, link_matcher)returns an optionalBlockKind. It recognizes unindented headings, bullets, blockquotes, footnote definitions, link-reference definitions, Markdownlint directives, and digit-prefixed blocks. Lines indented four or more columns are not classified by these checks.src/ellipsis.rs:130-177replace_ellipsis(lines)processes each line while tracking fences, indented code, link-reference definitions, and link-title continuations. It preserves fence lines, code, and link-reference-related lines verbatim; other prose lines are passed to ellipsis replacement.You are interacting with an AI system.