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_definitionchain 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’stests/dom/basictests.cppthe collapsednamespace type_tests {on line 1467 closes on line 1811, and recovery put that}inside apreproc_elsethat runs to line 2505: the region that restorestype_testscovers the wholepreproc_else, and without this check every namespace written after the close inheritedtype_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
impl OrphanedNamespaceScopeIndex
pub fn build(root: Node<'_>, source: &str) -> Self
Sourcepub fn matching_close_brace(&self, open: usize) -> Option<Range>
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).
pub fn is_empty(&self) -> bool
Sourcepub fn approximate_size(&self) -> usize
pub fn approximate_size(&self) -> usize
The bytes this index holds, for the analyzer cache’s weight.
Sourcepub fn region_at(&self, byte: usize) -> Option<&RecoveredNamespaceRegion>
pub fn region_at(&self, byte: usize) -> Option<&RecoveredNamespaceRegion>
The innermost recovered region containing byte.
Sourcepub fn enclosing_namespace_components(
&self,
node: Node<'_>,
source: &str,
) -> Vec<String>
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).
Sourcepub fn enclosing_namespace_levels(
&self,
node: Node<'_>,
source: &str,
) -> Vec<(String, Range, Range)>
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.
Sourcepub fn restore_enclosing_namespaces(
&self,
parsed: Vec<(usize, Vec<String>, bool)>,
node_start: usize,
) -> Vec<String>
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
impl Clone for OrphanedNamespaceScopeIndex
Source§impl Debug for OrphanedNamespaceScopeIndex
impl Debug for OrphanedNamespaceScopeIndex
Auto Trait Implementations§
impl Forget for OrphanedNamespaceScopeIndex
impl Freeze for OrphanedNamespaceScopeIndex
impl Move for OrphanedNamespaceScopeIndex
impl RefUnwindSafe for OrphanedNamespaceScopeIndex
impl Send for OrphanedNamespaceScopeIndex
impl Sync for OrphanedNamespaceScopeIndex
impl Unpin for OrphanedNamespaceScopeIndex
impl UnsafeUnpin for OrphanedNamespaceScopeIndex
impl UnwindSafe for OrphanedNamespaceScopeIndex
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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