Skip to main content

SourceInfo

Enum SourceInfo 

Source
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. by records the producer; from records source-side anchors (empty for pure synthesis, Invocation for 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.

Fields

§file_id: FileId
§start_offset: usize
§end_offset: usize
§

Substring

Substring extraction from a parent source

Offsets are relative to the parent’s text. The chain of Substrings always resolves to an Original.

Fields

§parent: Arc<SourceInfo>
§start_offset: usize
§end_offset: usize
§

Concat

Concatenation of multiple sources

Used when coalescing adjacent text nodes while preserving the fact that they came from different source locations.

Fields

§

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).

Fields

§by: By
§from: SmallVec<[Anchor; 2]>

Implementations§

Source§

impl SourceInfo

Source

pub fn map_offset( &self, offset: usize, ctx: &SourceContext, ) -> Option<MappedLocation>

Map an offset in the current text back to original source

Source

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

Source

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)

Source

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.

Source

pub fn substring(parent: SourceInfo, start: usize, end: usize) -> Self

Create source info for a substring extraction

Source

pub fn concat(pieces: Vec<(SourceInfo, usize)>) -> Self

Create source info for concatenated sources

Source

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 }.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn length(&self) -> usize

Get the length (in bytes) represented by this SourceInfo

Source

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.

Source

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.

Source

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.

Source

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:

  • OriginalSome(start..end) iff the file matches target, else None.
  • Substring → recurse the parent; offsets compose additively.
  • Concat → every piece must resolve into target AND the resolved ranges must be byte-contiguous (no gaps, no overlaps). A gappy Concat returns None — the writer can’t Verbatim-copy a non-contiguous span.
  • Generated → walk the Invocation anchor only via invocation_anchor. No other anchor role is consulted — not ValueSource (Plan 9), not future Dispatch (Plan 10), not AnchorRole::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.

Source

pub fn remap_file_ids<F>(&mut self, map: &F)
where F: Fn(FileId) -> FileId,

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.

Source

pub fn root_file_id(&self) -> Option<FileId>

First FileId reachable from this SourceInfo’s root.

  • OriginalSome(file_id).
  • Substring → recurse parent.
  • Concatpieces.iter().find_map(|p| p.source_info.root_file_id()) (find_map semantics — skips Generated holes and empty pieces).
  • Generatedinvocation_anchor().and_then(|si| si.root_file_id()); None when no Invocation anchor is present.
Source

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

Source§

fn clone(&self) -> SourceInfo

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SourceInfo

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for SourceInfo

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for SourceInfo

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for SourceInfo

Source§

fn eq(&self, other: &SourceInfo) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for SourceInfo

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for SourceInfo

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.