Skip to content

Commit 3c794a3

Browse files
committed
Go to declaration goes to assoc items of trait declarations
1 parent 9fba39f commit 3c794a3

File tree

1 file changed

+82
-8
lines changed

1 file changed

+82
-8
lines changed

crates/ide/src/goto_declaration.rs

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
use hir::Semantics;
1+
use hir::{AsAssocItem, Semantics};
22
use ide_db::{
33
defs::{Definition, NameClass, NameRefClass},
44
RootDatabase,
55
};
66
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, T};
77

8-
use crate::{FilePosition, NavigationTarget, RangeInfo};
8+
use crate::{
9+
goto_definition::goto_definition, navigation_target::TryToNav, FilePosition, NavigationTarget,
10+
RangeInfo,
11+
};
912

1013
// Feature: Go to Declaration
1114
//
1215
// Navigates to the declaration of an identifier.
1316
//
14-
// This is currently the same as `Go to Definition` with the exception of outline modules where it
15-
// will navigate to the `mod name;` item declaration.
17+
// This is the same as `Go to Definition` with the following exceptions:
18+
// - outline modules will navigate to the `mod name;` item declaration
19+
// - trait assoc items will navigate to the assoc item of the trait declaration opposed to the trait impl
1620
pub(crate) fn goto_declaration(
1721
db: &RootDatabase,
1822
position: FilePosition,
@@ -41,16 +45,28 @@ pub(crate) fn goto_declaration(
4145
_ => None
4246
}
4347
};
44-
match def? {
48+
let assoc = match def? {
4549
Definition::Module(module) => {
46-
Some(NavigationTarget::from_module_to_decl(db, module))
50+
return Some(NavigationTarget::from_module_to_decl(db, module))
4751
}
52+
Definition::Const(c) => c.as_assoc_item(db),
53+
Definition::TypeAlias(ta) => ta.as_assoc_item(db),
54+
Definition::Function(f) => f.as_assoc_item(db),
4855
_ => None,
49-
}
56+
}?;
57+
58+
let trait_ = assoc.containing_trait_impl(db)?;
59+
let name = Some(assoc.name(db)?);
60+
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
61+
item.try_to_nav(db)
5062
})
5163
.collect();
5264

53-
Some(RangeInfo::new(range, info))
65+
if info.is_empty() {
66+
goto_definition(db, position)
67+
} else {
68+
Some(RangeInfo::new(range, info))
69+
}
5470
}
5571

5672
#[cfg(test)]
@@ -109,4 +125,62 @@ mod foo {
109125
"#,
110126
)
111127
}
128+
129+
#[test]
130+
fn goto_decl_goto_def_fallback() {
131+
check(
132+
r#"
133+
struct Foo;
134+
// ^^^
135+
impl Foo$0 {}
136+
"#,
137+
);
138+
}
139+
140+
#[test]
141+
fn goto_decl_assoc_item_no_impl_item() {
142+
check(
143+
r#"
144+
trait Trait {
145+
const C: () = ();
146+
// ^
147+
}
148+
impl Trait for () {}
149+
150+
fn main() {
151+
<()>::C$0;
152+
}
153+
"#,
154+
);
155+
}
156+
157+
#[test]
158+
fn goto_decl_assoc_item() {
159+
check(
160+
r#"
161+
trait Trait {
162+
const C: () = ();
163+
// ^
164+
}
165+
impl Trait for () {
166+
const C: () = ();
167+
}
168+
169+
fn main() {
170+
<()>::C$0;
171+
}
172+
"#,
173+
);
174+
check(
175+
r#"
176+
trait Trait {
177+
const C: () = ();
178+
// ^
179+
}
180+
impl Trait for () {
181+
const C$0: () = ();
182+
}
183+
"#,
184+
);
185+
}
112186
}

0 commit comments

Comments
 (0)