Skip to content

Commit 99daf23

Browse files
committed
Auto merge of #13671 - Veykril:goto-decl, r=Veykril
Improve goto declaration Closes #13599 - goto decl now goes to assoc items of trait declarations over the items of trait implementations - goto decl now goes to the field declaration (opposed to goto def which shows both the field decl and binding created/local being used) - also adds back the goto definition fallback that seems to have been dropped at some point.
2 parents 6918009 + ae0bdff commit 99daf23

File tree

1 file changed

+112
-11
lines changed

1 file changed

+112
-11
lines changed

crates/ide/src/goto_declaration.rs

Lines changed: 112 additions & 11 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,
@@ -32,25 +36,37 @@ pub(crate) fn goto_declaration(
3236
match parent {
3337
ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
3438
NameRefClass::Definition(it) => Some(it),
35-
_ => None
39+
NameRefClass::FieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db),
3640
},
3741
ast::Name(name) => match NameClass::classify(&sema, &name)? {
38-
NameClass::Definition(it) => Some(it),
39-
_ => None
42+
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
43+
NameClass::PatFieldShorthand { field_ref, .. } => return field_ref.try_to_nav(db),
4044
},
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,89 @@ 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+
}
186+
187+
#[test]
188+
fn goto_decl_field_pat_shorthand() {
189+
check(
190+
r#"
191+
struct Foo { field: u32 }
192+
//^^^^^
193+
fn main() {
194+
let Foo { field$0 };
195+
}
196+
"#,
197+
);
198+
}
199+
200+
#[test]
201+
fn goto_decl_constructor_shorthand() {
202+
check(
203+
r#"
204+
struct Foo { field: u32 }
205+
//^^^^^
206+
fn main() {
207+
let field = 0;
208+
Foo { field$0 };
209+
}
210+
"#,
211+
);
212+
}
112213
}

0 commit comments

Comments
 (0)