Skip to main content

OrphanedNamespaceScopeIndex

Struct OrphanedNamespaceScopeIndex 

Source
pub struct OrphanedNamespaceScopeIndex { /* private fields */ }
Expand description

The namespaces C++ parse recovery drops from a file’s tree.

When tree-sitter cannot parse a construct inside a namespace body it closes an inner scope with a MISSING brace, or skips an opening brace into an ERROR node. Every real } after that then closes one scope too early: a class body’s } closes the namespace, the namespace’s own } closes its parent, and the outermost real closes land in a trailing ERROR node. The declarations between a stolen close and the real one keep their byte positions but lose their namespace_definition ancestors (Catch2’s catch_matchers_templated.hpp, issue #1537).

A file-global stack over real AST brace tokens restores both lost and overextended namespaces. Missing braces do nothing; error-free subtrees are balanced and can be skipped. For each child of a damaged container, compare the namespaces still open on that stack with the parsed ancestor path. A difference yields a region carrying the complete lexical path, including an empty path when recovery swallowed file-scope declarations. Consecutive children sharing that path form one RecoveredNamespaceRegion. The same pass retains matching brace positions for declaration partitioning (#3087). A file without parse errors needs neither correction nor a brace index.

The stack restores the source’s nesting only while the tree’s brace tokens are the source’s braces. Severe recovery can break that even when the real brace counts balance: in simdjson’s compile_time_json-inl.h, ABI 15 keeps the reflection case labels as character nodes but loses the outer namespace’s closing token. The global stack then cascades the function and inner namespace closes into the wrong owners. A surviving namespace_definition can supply stronger provenance when its body has a genuine declaration boundary: its direct real } belongs to that namespace, while a missing direct close proves that the namespace has no close to claim. A body whose direct boundary is itself recovered from a class/member error stays with the global fallback. The proven boundaries override the global stack only when the file has no unpaired real close. An unpaired close proves the stream lost an open at a position the stack cannot recover, so all pairing in that file remains invalid: Self::matching_close_brace then answers nothing and each restored level keeps the head that writes it. The namespace paths remain, as the best-effort structure recovery they are.

Every consumer reads a node’s namespace path through one authority rule, shared by Self::enclosing_namespace_levels and Self::restore_enclosing_namespaces, so declaration collection and both lookup directions agree:

  • Outside every region, the node’s parsed namespace_definition chain is the whole answer.
  • Inside a region, the region’s restored levels come first and only the parsed ancestors that start inside the region follow them. The region overrides a parsed ancestor that starts before it, which is how a namespace the tree kept open past its real close gives up the declarations after that close (#3087).
  • A restored level stops applying at the close the stack paired with its {, and so does every level inside it. The walk compares a child with the stack before it descends into that child, so a run can reach past a close inside its last child. In simdjson’s tests/dom/basictests.cpp the collapsed namespace type_tests { on line 1467 closes on line 1811, and recovery put that } inside a preproc_else that runs to line 2505: the region that restores type_tests covers the whole preproc_else, and without this check every namespace written after the close inherited type_tests (#3633). A level whose close the stack did not prove applies to the whole region, the best-effort answer #3328 leaves.
  • A region whose restored path is empty keeps exactly the parsed ancestors whose own { and } are both real tokens, wherever they start, and drops the others. This holds whether or not the file’s pairing is proven.

Implementations§

Source§

impl OrphanedNamespaceScopeIndex

Source

pub fn build(root: Node<'_>, source: &str) -> Self

Source

pub fn matching_close_brace(&self, open: usize) -> Option<Range>

The real AST brace matching an opening brace in a damaged subtree. Missing tokens and braces inside comments or literals do not participate.

None when this open has no close in the file, and for every open in a file whose brace token stream lost an opening token: a caller cannot treat a pairing the walk could not prove as an enclosing extent (#3328).

Source

pub fn is_empty(&self) -> bool

Source

pub fn approximate_size(&self) -> usize

The bytes this index holds, for the analyzer cache’s weight.

Source

pub fn region_at(&self, byte: usize) -> Option<&RecoveredNamespaceRegion>

The innermost recovered region containing byte.

Source

pub fn enclosing_namespace_components( &self, node: Node<'_>, source: &str, ) -> Vec<String>

The enclosing namespaces of node, outermost first, restoring the ones parse recovery dropped from its ancestor chain. The one answer both lookup directions and declaration collection use (issue #1537).

Source

pub fn enclosing_namespace_levels( &self, node: Node<'_>, source: &str, ) -> Vec<(String, Range, Range)>

Self::enclosing_namespace_components with the construct that writes each level and the level’s own name token, for the declaration walk that has to record both ranges.

A level the brace stack restored carries the ranges this index recorded for its head and name; a surviving namespace_definition ancestor carries its own node range and name token, which is what the ordinary namespace visit records.

Source

pub fn restore_enclosing_namespaces( &self, parsed: Vec<(usize, Vec<String>, bool)>, node_start: usize, ) -> Vec<String>

Self::enclosing_namespace_components for a caller that has already climbed the ancestor chain: parsed lists the node’s named namespace_definition ancestors outermost first, each with its start byte and whether its own opening and closing braces survived parsing. The answer follows the authority rule on OrphanedNamespaceScopeIndex.

Trait Implementations§

Source§

impl Clone for OrphanedNamespaceScopeIndex

Source§

fn clone(&self) -> Self

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 OrphanedNamespaceScopeIndex

Source§

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

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

impl Default for OrphanedNamespaceScopeIndex

Source§

fn default() -> Self

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

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> CapabilityProvider for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

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> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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 = !

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

fn try_from(value: U) -> Result<T, !>

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.