Skip to content

Commit

Permalink
Find definition for member declarations, fix definition nodes, add Sy…
Browse files Browse the repository at this point in the history
…ntaxNodeExt::cast

commit-id:c6ff00b1
  • Loading branch information
mkaput committed Feb 5, 2025
1 parent 270d503 commit 3cd27f5
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 12 deletions.
28 changes: 25 additions & 3 deletions src/lang/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::iter;
use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::{
GenericTypeId, LanguageElementId, LocalVarLongId, LookupItemId, MemberId, ModuleId,
ModuleItemId, NamedLanguageElementId, SubmoduleLongId, TopLevelLanguageElementId, TraitItemId,
VarId,
ModuleItemId, NamedLanguageElementId, StructLongId, SubmoduleLongId, TopLevelLanguageElementId,
TraitItemId, VarId,
};
use cairo_lang_diagnostics::ToOption;
use cairo_lang_doc::db::DocGroup;
Expand Down Expand Up @@ -445,8 +445,12 @@ fn find_definition(

if let Some(member_id) = try_extract_member(db, identifier, lookup_items)
.or_else(|| try_extract_member_from_constructor(db, identifier, lookup_items))
.or_else(|| try_extract_member_declaration(db, identifier))
{
return Some((ResolvedItem::Member(member_id), member_id.untyped_stable_ptr(db)));
return Some((
ResolvedItem::Member(member_id),
member_id.stable_ptr(db).lookup(db).name(db).stable_ptr().untyped(),
));
}

if let Some(var_id) = try_extract_variable_declaration(db, identifier, lookup_items) {
Expand Down Expand Up @@ -572,6 +576,24 @@ fn try_extract_member(
}
}

/// Extracts [`MemberId`] if the [`TerminalIdentifier`] is a name of member in struct declaration.
fn try_extract_member_declaration(
db: &AnalysisDatabase,
identifier: &ast::TerminalIdentifier,
) -> Option<MemberId> {
let member = identifier.as_syntax_node().parent()?.cast::<ast::Member>(db)?;
assert_eq!(member.name(db), *identifier);
let item_struct = member.as_syntax_node().parent_of_type::<ast::ItemStruct>(db)?;
let struct_id = StructLongId(
db.find_module_file_containing_node(&item_struct.as_syntax_node())?,
item_struct.stable_ptr(),
)
.intern(db);
let struct_members = db.struct_members(struct_id).ok()?;
let member_semantic = struct_members.get(&member.name(db).text(db))?;
Some(member_semantic.id)
}

/// Lookups if the identifier is a declaration of a variable/param in one of the lookup items.
///
/// Declaration identifiers aren't kept in `ResolvedData`, which is searched for by
Expand Down
7 changes: 7 additions & 0 deletions src/lang/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode};

pub trait SyntaxNodeExt {
/// Mirror of [`TypedSyntaxNode::cast`].
fn cast<T: TypedSyntaxNode>(self, db: &dyn SyntaxGroup) -> Option<T>;

/// Creates an iterator that yields ancestors of this syntax node.
fn ancestors(&self) -> impl Iterator<Item = SyntaxNode>;

Expand Down Expand Up @@ -40,6 +43,10 @@ pub trait SyntaxNodeExt {
}

impl SyntaxNodeExt for SyntaxNode {
fn cast<T: TypedSyntaxNode>(self, db: &dyn SyntaxGroup) -> Option<T> {
T::cast(db, self)
}

fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
// We aren't reusing `ancestors_with_self` here to avoid cloning this node.
iter::successors(self.parent(), SyntaxNode::parent)
Expand Down
11 changes: 5 additions & 6 deletions tests/e2e/find_references/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ fn struct_by_name() {
")
}

// FIXME(#129): The results for this are very off.
#[test]
fn struct_member_via_definition() {
test_transform!(find_references, r#"
Expand All @@ -38,10 +37,10 @@ fn struct_member_via_definition() {
}
"#, @r"
#[derive(Drop)]
struct <sel=declaration>Foo</sel> { width: u64 }
struct Foo { <sel=declaration>width</sel>: u64 }
fn main() {
let foo = <sel>Foo</sel> { width: 0 };
let x = foo.width * 2;
let foo = Foo { <sel>width</sel>: 0 };
let x = foo.<sel>width</sel> * 2;
}
")
}
Expand All @@ -57,7 +56,7 @@ fn struct_member_via_constructor() {
}
"#, @r"
#[derive(Drop)]
struct Foo { <sel=declaration>width: u64</sel> }
struct Foo { <sel=declaration>width</sel>: u64 }
fn main() {
let foo = Foo { <sel>width</sel>: 0 };
let x = foo.<sel>width</sel> * 2;
Expand All @@ -76,7 +75,7 @@ fn struct_member_via_field_access() {
}
"#, @r"
#[derive(Drop)]
struct Foo { <sel=declaration>width: u64</sel> }
struct Foo { <sel=declaration>width</sel>: u64 }
fn main() {
let foo = Foo { <sel>width</sel>: 0 };
let x = foo.<sel>width</sel> * 2;
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/goto_definition/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn struct_member_via_field_access() {
}
", @r"
#[derive(Drop)]
struct Circle { <sel>radius: u64</sel> }
struct Circle { <sel>radius</sel>: u64 }
fn foo(circle: Circle) -> u64 {
circle.radius
}
Expand All @@ -54,7 +54,7 @@ fn struct_member_in_constructor() {
}
", @r"
#[derive(Drop)]
struct Circle { <sel>radius: u64</sel> }
struct Circle { <sel>radius</sel>: u64 }
fn main() {
let circle = Circle { radius: 42 };
}
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/hover/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn member_definition_name() {
}
```
---
Docstring of Struct."""
Docstring of member1."""
"#)
}

Expand Down

0 comments on commit 3cd27f5

Please sign in to comment.