pub enum SourceInfo {
Original {
file_id: FileId,
start_offset: usize,
end_offset: usize,
},
Substring {
parent: Arc<SourceInfo>,
start_offset: usize,
end_offset: usize,
},
Concat {
pieces: Vec<SourcePiece>,
},
Generated {
by: By,
from: SmallVec<[Anchor; 2]>,
},
}Expand description
Source information tracking a location and its transformation history
This enum stores only byte offsets. Row and column information is computed
on-demand via map_offset() using the FileInformation line break index.
Design notes:
- Original: Points directly to a file with byte offsets
- Substring: Points to a range within a parent SourceInfo (offsets are relative to parent)
- Concat: Combines multiple SourceInfo pieces (preserves provenance when coalescing text)
- Generated: Produced by a pipeline transform.
byrecords the producer;fromrecords source-side anchors (empty for pure synthesis,Invocationfor shortcode-style resolutions).
The Transformed variant was removed because it’s not used in production code. Text transformations (smart quotes, em-dashes) use Original SourceInfo pointing to the pre-transformation text, accepting that the byte offsets are approximate.
Variants§
Original
Direct position in an original file
Stores only byte offsets. Use map_offset() to get row/column information.
Substring
Substring extraction from a parent source
Offsets are relative to the parent’s text. The chain of Substrings always resolves to an Original.
Concat
Concatenation of multiple sources
Used when coalescing adjacent text nodes while preserving the fact that they came from different source locations.
Fields
pieces: Vec<SourcePiece>Generated
Node produced by a pipeline transform
by records the producer (“which transform made me”); from is a
list of typed, role-labeled source-info pointers (“which source
bytes contributed to me”). Empty from means pure synthesis
(sectionize wrappers, filter constructions, title-block h1).
An Invocation anchor present means there is a source-side
preimage (every shortcode resolution).
Implementations§
Source§impl SourceInfo
impl SourceInfo
Sourcepub fn map_offset(
&self,
offset: usize,
ctx: &SourceContext,
) -> Option<MappedLocation>
pub fn map_offset( &self, offset: usize, ctx: &SourceContext, ) -> Option<MappedLocation>
Map an offset in the current text back to original source
Sourcepub fn map_range(
&self,
start: usize,
end: usize,
ctx: &SourceContext,
) -> Option<(MappedLocation, MappedLocation)>
pub fn map_range( &self, start: usize, end: usize, ctx: &SourceContext, ) -> Option<(MappedLocation, MappedLocation)>
Map a range in the current text back to original source
Source§impl SourceInfo
impl SourceInfo
Sourcepub fn original(file_id: FileId, start_offset: usize, end_offset: usize) -> Self
pub fn original(file_id: FileId, start_offset: usize, end_offset: usize) -> Self
Create source info for a position in an original file (from offsets)
Sourcepub fn from_range(file_id: FileId, range: Range) -> Self
pub fn from_range(file_id: FileId, range: Range) -> Self
Create source info for a position in an original file (from Range)
This is a compatibility helper for code that still uses Range. The row and column information in the Range is ignored; only offsets are stored.
Sourcepub fn substring(parent: SourceInfo, start: usize, end: usize) -> Self
pub fn substring(parent: SourceInfo, start: usize, end: usize) -> Self
Create source info for a substring extraction
Sourcepub fn concat(pieces: Vec<(SourceInfo, usize)>) -> Self
pub fn concat(pieces: Vec<(SourceInfo, usize)>) -> Self
Create source info for concatenated sources
Sourcepub fn generated(by: By) -> Self
pub fn generated(by: By) -> Self
Create a SourceInfo::Generated with an empty anchor list.
Use SourceInfo::append_anchor to add anchors after construction.
For Generated nodes that need to carry anchors at construction
time, build the variant directly: SourceInfo::Generated { by, from }.
Sourcepub fn for_test() -> Self
pub fn for_test() -> Self
Convenience for tests: produce a non-atomic Generated source_info
with By::test_scaffold() and no anchors. Use this in test code
where a constructor requires a SourceInfo but there’s no real
provenance to record. Replaces the historical
SourceInfo::default() pattern in tests.
Sourcepub fn invocation_anchor(&self) -> Option<&Arc<SourceInfo>>
pub fn invocation_anchor(&self) -> Option<&Arc<SourceInfo>>
If this is a SourceInfo::Generated, return the first anchor whose
role is AnchorRole::Invocation.
Returns None otherwise (including for non-Generated variants).
By convention there is at most one Invocation anchor per node.
Sourcepub fn value_source_anchor(&self) -> Option<&Arc<SourceInfo>>
pub fn value_source_anchor(&self) -> Option<&Arc<SourceInfo>>
If this is a SourceInfo::Generated, return the first anchor whose
role is AnchorRole::ValueSource.
Returns None otherwise. By convention there is at most one
ValueSource anchor per node.
Sourcepub fn anchors_with_role<'a>(
&'a self,
role: &'a AnchorRole,
) -> Box<dyn Iterator<Item = &'a Arc<SourceInfo>> + 'a>
pub fn anchors_with_role<'a>( &'a self, role: &'a AnchorRole, ) -> Box<dyn Iterator<Item = &'a Arc<SourceInfo>> + 'a>
Iterate over every anchor in this SourceInfo::Generated whose role
equals role.
Returns an empty iterator for non-Generated variants. Iteration order
is the append order.
Sourcepub fn append_anchor(&mut self, role: AnchorRole, source_info: Arc<SourceInfo>)
pub fn append_anchor(&mut self, role: AnchorRole, source_info: Arc<SourceInfo>)
Append (role, source_info) to this SourceInfo::Generated’s
anchor list.
Panics if self is not SourceInfo::Generated. By convention there
is at most one anchor per known role; appending a second anchor with
the same role does not replace the first — accessors that find by
role return the earliest match.
Sourcepub fn combine(&self, other: &SourceInfo) -> Self
pub fn combine(&self, other: &SourceInfo) -> Self
Combine two SourceInfo objects representing adjacent text
This creates a Concat mapping that preserves both sources. The resulting SourceInfo spans from the start of self to the end of other.
Sourcepub fn start_offset(&self) -> usize
pub fn start_offset(&self) -> usize
Get the start offset for this SourceInfo
For Original and Substring, returns the start_offset field. For Concat, returns 0 (the concat represents a new text starting at 0). For Generated, returns 0.
Sourcepub fn end_offset(&self) -> usize
pub fn end_offset(&self) -> usize
Get the end offset for this SourceInfo
For Original and Substring, returns the end_offset field. For Concat, returns the total length. For Generated, returns 0.
Sourcepub fn resolve_byte_range(&self) -> Option<(usize, usize, usize)>
pub fn resolve_byte_range(&self) -> Option<(usize, usize, usize)>
Chain-resolve to (file_id, start_offset, end_offset) in the
root source file.
Returns None for Concat — Concat doesn’t map cleanly to a
single contiguous byte range. For Generated, delegates to the
first Invocation anchor and recurses (None when no
Invocation anchor is present). The attribution v1 sidecar
relies on this contract; project-scoped (v2) features that need
the full chain resolver should use map_offset against a
SourceContext instead.
Sourcepub fn preimage_in(&self, target: FileId) -> Option<Range<usize>>
pub fn preimage_in(&self, target: FileId) -> Option<Range<usize>>
Byte range in target that this SourceInfo’s preimage covers, if any.
This is the writer’s “can I Verbatim-copy bytes from target for the
node carrying this source_info?” check.
Semantics by variant:
Original→Some(start..end)iff the file matchestarget, elseNone.Substring→ recurse the parent; offsets compose additively.Concat→ every piece must resolve intotargetAND the resolved ranges must be byte-contiguous (no gaps, no overlaps). A gappy Concat returnsNone— the writer can’t Verbatim-copy a non-contiguous span.Generated→ walk theInvocationanchor only viainvocation_anchor. No other anchor role is consulted — notValueSource(Plan 9), not futureDispatch(Plan 10), notAnchorRole::Other. See the role-asymmetry section below.
§Role asymmetry
preimage_in only walks AnchorRole::Invocation. This is load-bearing:
copying bytes from a ValueSource source range would emit raw YAML
metadata (or whatever the value lived in) into the body — a hard
correctness bug. The same applies to Dispatch (which points at Lua
source) and to any extension-defined Other role.
Future anchor roles default to non-walked. Extensions introducing
AnchorRole::Other("…") should treat this as a feature: their
attribution metadata is not accidentally consulted by the writer’s
byte-copying path. If a role does contribute to body-text preimage,
it must be explicitly added to this function’s Generated arm.
Sourcepub fn remap_file_ids<F>(&mut self, map: &F)
pub fn remap_file_ids<F>(&mut self, map: &F)
Remap every FileId referenced by this SourceInfo (including those
inside Substring parents and Concat pieces) using the provided
mapping function.
Used when merging ASTs that were parsed against different files into a
single ASTContext with a shared filename table — callers shift each
AST’s FileIds to their slot in the merged table before combining.
Sourcepub fn root_file_id(&self) -> Option<FileId>
pub fn root_file_id(&self) -> Option<FileId>
First FileId reachable from this SourceInfo’s root.
Original→Some(file_id).Substring→ recurse parent.Concat→pieces.iter().find_map(|p| p.source_info.root_file_id())(find_mapsemantics — skips Generated holes and empty pieces).Generated→invocation_anchor().and_then(|si| si.root_file_id());Nonewhen noInvocationanchor is present.
Sourcepub fn collect_file_ids(&self, out: &mut HashSet<FileId>)
pub fn collect_file_ids(&self, out: &mut HashSet<FileId>)
Insert every FileId reachable from this SourceInfo into out.
Walks every Original, every Substring parent, every Concat
piece, and every Generated anchor (all roles — Invocation,
ValueSource, Other).
Trait Implementations§
Source§impl Clone for SourceInfo
impl Clone for SourceInfo
Source§fn clone(&self) -> SourceInfo
fn clone(&self) -> SourceInfo
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SourceInfo
impl Debug for SourceInfo
Source§impl Default for SourceInfo
impl Default for SourceInfo
Source§impl<'de> Deserialize<'de> for SourceInfo
impl<'de> Deserialize<'de> for SourceInfo
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for SourceInfo
impl PartialEq for SourceInfo
Source§fn eq(&self, other: &SourceInfo) -> bool
fn eq(&self, other: &SourceInfo) -> bool
self and other values to be equal, and is used by ==.