review: the round-trip test could not see a merge that dropped the section

Adversarial review injected the other fault -- Some(_existing) => {}, which
drops the duplicate section outright -- and the whole improvise-io suite stayed
green at 2000 proptest cases while the fixture's item and its group line
vanished from the document. A test that compares two printed forms cannot tell
unstable-but-lossless from stable-and-lossy, because both sides of the equality
lose the same thing. Three contains assertions now run before the equality, and
they fail under that injection.

Two more from the same review. push_category destructures PCategory, so a fourth
field has to be named rather than silently dropped on the duplicate path only.
And design-principles.md's formula-tokenizer section described a tokenizer that
no longer exists -- a split_where pre-parse step and Token::Ident/Token::Str,
none of which are in the tree -- and claimed bare identifiers allow spaces,
which bare_ident forbids. This branch changes that production, so correcting the
sibling copy is the grep gotcha 48 asks for.

improvise-349m improvise-r08u

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
Edward Langley
2026-09-20 21:26:34 -07:00
parent e9b8b708c5
commit d5995814d1
3 changed files with 46 additions and 15 deletions
+19 -4
View File
@@ -54,12 +54,21 @@ impl ParsedFile {
/// Two `## Category:` sections naming one category are one category. The
/// merge concatenates, so the built order is the order a writer emits.
fn push_category(&mut self, pc: PCategory) {
match self.categories.iter_mut().find(|e| e.name == pc.name) {
let PCategory {
name,
items,
group_parents,
} = pc;
match self.categories.iter_mut().find(|e| e.name == name) {
Some(existing) => {
existing.items.extend(pc.items);
existing.group_parents.extend(pc.group_parents);
existing.items.extend(items);
existing.group_parents.extend(group_parents);
}
None => self.categories.push(pc),
None => self.categories.push(PCategory {
name,
items,
group_parents,
}),
}
}
}
@@ -1098,6 +1107,12 @@ mod parser_edge_cases {
## Category: C\n- X[G2]\n> G2[P2]\n";
let fmt = crate::persistence::format_md;
let printed = fmt(&parse_md(text).unwrap());
for owed in ["> G1[P1]", "> G2[P2]", "- X[G2]"] {
assert!(
printed.contains(owed),
"the merge dropped {owed}:\n{printed}"
);
}
assert_eq!(printed, fmt(&parse_md(&printed).unwrap()));
}