Skip to content

Commit

Permalink
Symbol path builder and UNL handling for annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
SpontanCombust committed Jun 13, 2024
1 parent 2c1f1eb commit 34df2cf
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 21 deletions.
82 changes: 64 additions & 18 deletions crates/analysis/src/symbol_analysis/unqualified_name_lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,22 +182,11 @@ impl<'a> UnqualifiedNameLookupBuilder<'a> {
let (self_, payload) = Self::new(doc, sympath_ctx, symtab_marcher);
(Rc::new(RefCell::new(self_)), payload)
}
}

impl SyntaxNodeVisitor for UnqualifiedNameLookupBuilder<'_> {
fn traversal_policy_default(&self) -> bool {
true
}


fn visit_class_decl(&mut self, _: &ClassDeclarationNode) -> ClassDeclarationTraversalPolicy {
let mut unl = self.payload.borrow_mut();
let sympath_ctx = self.sympath_ctx.borrow();

unl.push_scope();

fn build_for_class(&self, unl: &mut UnqualifiedNameLookup, class_path: &SymbolPath) {
let mut inherit_chain = self.symtab_marcher
.class_hierarchy(&sympath_ctx.current_sympath)
.class_hierarchy(class_path)
.collect::<Vec<_>>();

// we want to iterate classes starting from the most base class
Expand All @@ -210,17 +199,17 @@ impl SyntaxNodeVisitor for UnqualifiedNameLookupBuilder<'_> {
for ch in class_symtab.get_symbol_children_filtered(class) {
match ch {
ClassSymbolChild::Var(s) => {
if class.path() == &sympath_ctx.current_sympath || !s.specifiers.contains(AccessModifier::Private.into()) {
if class.path() == class_path || !s.specifiers.contains(AccessModifier::Private.into()) {
unl.insert(s.path().to_owned());
}
},
ClassSymbolChild::Autobind(s) => {
if class.path() == &sympath_ctx.current_sympath || !s.specifiers.contains(AccessModifier::Private.into()) {
if class.path() == class_path || !s.specifiers.contains(AccessModifier::Private.into()) {
unl.insert(s.path().to_owned());
}
},
ClassSymbolChild::Method(s) => {
if class.path() == &sympath_ctx.current_sympath || !s.specifiers.contains(AccessModifier::Private.into()) {
if class.path() == class_path || !s.specifiers.contains(AccessModifier::Private.into()) {
unl.insert(s.path().to_owned());
}
},
Expand All @@ -231,6 +220,21 @@ impl SyntaxNodeVisitor for UnqualifiedNameLookupBuilder<'_> {
}
}
}
}
}

impl SyntaxNodeVisitor for UnqualifiedNameLookupBuilder<'_> {
fn traversal_policy_default(&self) -> bool {
true
}


fn visit_class_decl(&mut self, _: &ClassDeclarationNode) -> ClassDeclarationTraversalPolicy {
let mut unl = self.payload.borrow_mut();
let sympath_ctx = self.sympath_ctx.borrow();

unl.push_scope();
self.build_for_class(&mut unl, &sympath_ctx.current_sympath);

TraversalPolicy::default_to(true)
}
Expand Down Expand Up @@ -351,8 +355,6 @@ impl SyntaxNodeVisitor for UnqualifiedNameLookupBuilder<'_> {

unl.push_scope();

//TODO handle annotated functions

if let Some((func_symtab, func_symvar)) = self.symtab_marcher.get_symbol_with_containing_table(&sympath_ctx.current_sympath) {
if let Some(func) = func_symvar.try_as_global_func_ref() {
for ch in func_symtab.get_symbol_children_filtered(func) {
Expand All @@ -362,6 +364,50 @@ impl SyntaxNodeVisitor for UnqualifiedNameLookupBuilder<'_> {
// local vars will be pushed dynamically as a function will go on
}
}
else if let Some(func) = func_symvar.try_as_member_func_injector_ref() {
let class_path = func.path().parent().unwrap_or_default();
self.build_for_class(&mut unl, class_path);

for ch in func_symtab.get_symbol_children_filtered(func) {
if let CallableSymbolChild::Param(s) = ch {
unl.insert(s.path().to_owned());
}
}
}
else if let Some(func) = func_symvar.try_as_member_func_replacer_ref() {
let class_path = func.path().parent().unwrap_or_default();
self.build_for_class(&mut unl, class_path);

for ch in func_symtab.get_symbol_children_filtered(func) {
if let CallableSymbolChild::Param(s) = ch {
unl.insert(s.path().to_owned());
}
}
}
else if let Some(func) = func_symvar.try_as_global_func_replacer_ref() {
for ch in func_symtab.get_symbol_children_filtered(func) {
if let CallableSymbolChild::Param(s) = ch {
unl.insert(s.path().to_owned());
}
}
}
else if let Some(func) = func_symvar.try_as_member_func_wrapper_ref() {
let class_path = func.path().parent().unwrap_or_default();
self.build_for_class(&mut unl, class_path);

for ch in func_symtab.get_symbol_children_filtered(func) {
match ch {
FunctionWrapperSymbolChild::Param(s) => {
unl.insert(s.path().to_owned())
},
FunctionWrapperSymbolChild::WrappedMethod(s) => {
unl.insert(s.path().to_owned())
},
_ => {}
}

}
}
}

TraversalPolicy::default_to(true)
Expand Down
12 changes: 9 additions & 3 deletions crates/analysis/src/utils/visitors/sympath_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,17 @@ impl SyntaxNodeVisitor for SymbolPathBuilder<'_> {


fn visit_global_func_decl(&mut self, n: &FunctionDeclarationNode) -> FunctionDeclarationTraversalPolicy {
let mut payload = self.payload.borrow_mut();
payload.current_sympath.clear();

if let Some(class_name) = n.annotation().and_then(|annot| annot.arg()) {
payload.current_sympath.push(&class_name.value(self.doc), SymbolCategory::Type);
}

let name = n.name().value(self.doc);
self.payload.borrow_mut().current_sympath = GlobalCallableSymbolPath::new(&name).into();
TraversalPolicy::default_to(true)
payload.current_sympath.push(&name, SymbolCategory::Callable);

//TODO handle annotated functions
TraversalPolicy::default_to(true)
}

fn exit_global_func_decl(&mut self, _: &FunctionDeclarationNode) {
Expand Down

0 comments on commit 34df2cf

Please sign in to comment.