Slice 4 of #94 (completes the epic). Quick-fixes are derived from the structured
schema completions, never by parsing a diagnostic message:
- TreeNode gains contentRange (the span between an element's start and end tags),
captured by the ranged reader, so an inserted attribute or child is placed
exactly.
- QuickFix and TextEdit model an editor edit (a replacement over a source range;
an insertion is a zero-width range).
- QuickFixEngine turns a Completions into fixes: a required-but-absent attribute
becomes an insertion before the start tag's >, and a still-expected required
child becomes an insertion before the end tag. Schema.Document.quickFixes(at:in:)
is the entry over a ranged tree.
Tests apply a fix and re-validate: adding the required id, or inserting the
required qty, yields XML the schema then accepts; a complete element offers none.
#94 (editor integration) is complete: ranged recovering read, unified lint,
schema completions, and quick-fixes.
Slice 1 of #94 (editor integration). The keystone: a located validation finding
can now be mapped back to a source range.
- TreeNode gains a sourceRange (start/end Mark); SourceRange is a half-open span.
- PureXML.readTree builds a mutable, parent-aware, best-effort tree whose every
node carries its span (an element from the < of its start tag to past its end
tag; leaves over the text they consumed). Never throws, recovers in place,
returns located diagnostics.
- TreeNode.node(at:) navigates a validation coding path to its node using the
same canonical convention the validators build paths with (a sibling index
only when a name repeats), and sourceRange(at:) returns the span. So
Document.validate's ValidationError.codingPath resolves to characters in the
document.
Tests prove the spans, the navigation, the end-to-end bridge (an XSD finding to
a source range), and that ranged reading of invalid input never crashes.
Add PureXML.Model.TreeNode, a reference-type document tree that knows its
parent and siblings. Navigation goes up and sideways (parent, nextSibling,
previousSibling, ancestors, root, elementChildren, stringValue) and editing
is in place (append, insert before/after, removeFromParent, replace, copy).
Children are held strongly and the parent weakly; attaching a node detaches
it from any prior parent and a node can never become its own ancestor.
parseTree builds one from XML; TreeNode.node converts back for serialization.
Closes#31