1
- use hir:: { Crate , Impl , Semantics } ;
2
- use ide_db:: RootDatabase ;
3
- use syntax:: { algo:: find_node_at_offset, ast, AstNode } ;
1
+ use hir:: { Impl , Semantics } ;
2
+ use ide_db:: {
3
+ defs:: { Definition , NameClass , NameRefClass } ,
4
+ RootDatabase ,
5
+ } ;
6
+ use syntax:: { ast, AstNode } ;
4
7
5
8
use crate :: { display:: TryToNav , FilePosition , NavigationTarget , RangeInfo } ;
6
9
@@ -21,55 +24,42 @@ pub(crate) fn goto_implementation(
21
24
let source_file = sema. parse ( position. file_id ) ;
22
25
let syntax = source_file. syntax ( ) . clone ( ) ;
23
26
24
- let krate = sema. to_module_def ( position. file_id ) ?. krate ( ) ;
25
-
26
- if let Some ( nominal_def) = find_node_at_offset :: < ast:: Adt > ( & syntax, position. offset ) {
27
- return Some ( RangeInfo :: new (
28
- nominal_def. syntax ( ) . text_range ( ) ,
29
- impls_for_def ( & sema, & nominal_def, krate) ?,
30
- ) ) ;
31
- } else if let Some ( trait_def) = find_node_at_offset :: < ast:: Trait > ( & syntax, position. offset ) {
32
- return Some ( RangeInfo :: new (
33
- trait_def. syntax ( ) . text_range ( ) ,
34
- impls_for_trait ( & sema, & trait_def, krate) ?,
35
- ) ) ;
36
- }
37
-
38
- None
39
- }
40
-
41
- fn impls_for_def (
42
- sema : & Semantics < RootDatabase > ,
43
- node : & ast:: Adt ,
44
- krate : Crate ,
45
- ) -> Option < Vec < NavigationTarget > > {
46
- let ty = match node {
47
- ast:: Adt :: Struct ( def) => sema. to_def ( def) ?. ty ( sema. db ) ,
48
- ast:: Adt :: Enum ( def) => sema. to_def ( def) ?. ty ( sema. db ) ,
49
- ast:: Adt :: Union ( def) => sema. to_def ( def) ?. ty ( sema. db ) ,
27
+ let node = sema. find_node_at_offset_with_descend ( & syntax, position. offset ) ?;
28
+ let def = match & node {
29
+ ast:: NameLike :: Name ( name) => {
30
+ NameClass :: classify ( & sema, name) . map ( |class| class. referenced_or_defined ( sema. db ) )
31
+ }
32
+ ast:: NameLike :: NameRef ( name_ref) => {
33
+ NameRefClass :: classify ( & sema, name_ref) . map ( |class| class. referenced ( sema. db ) )
34
+ }
35
+ ast:: NameLike :: Lifetime ( _) => None ,
36
+ } ?;
37
+ let def = match def {
38
+ Definition :: ModuleDef ( def) => def,
39
+ _ => return None ,
50
40
} ;
51
-
52
- let impls = Impl :: all_in_crate ( sema. db , krate) ;
53
-
54
- Some (
55
- impls
56
- . into_iter ( )
57
- . filter ( |impl_def| ty. is_equal_for_find_impls ( & impl_def. target_ty ( sema. db ) ) )
58
- . filter_map ( |imp| imp. try_to_nav ( sema. db ) )
59
- . collect ( ) ,
60
- )
41
+ let navs = match def {
42
+ hir:: ModuleDef :: Trait ( trait_) => impls_for_trait ( & sema, trait_) ,
43
+ hir:: ModuleDef :: Adt ( adt) => impls_for_ty ( & sema, adt. ty ( sema. db ) ) ,
44
+ hir:: ModuleDef :: TypeAlias ( alias) => impls_for_ty ( & sema, alias. ty ( sema. db ) ) ,
45
+ hir:: ModuleDef :: BuiltinType ( builtin) => {
46
+ let module = sema. to_module_def ( position. file_id ) ?;
47
+ impls_for_ty ( & sema, builtin. ty ( sema. db , module) )
48
+ }
49
+ _ => return None ,
50
+ } ;
51
+ Some ( RangeInfo { range : node. syntax ( ) . text_range ( ) , info : navs } )
61
52
}
62
53
63
- fn impls_for_trait (
64
- sema : & Semantics < RootDatabase > ,
65
- node : & ast:: Trait ,
66
- krate : Crate ,
67
- ) -> Option < Vec < NavigationTarget > > {
68
- let tr = sema. to_def ( node) ?;
69
-
70
- let impls = Impl :: for_trait ( sema. db , krate, tr) ;
54
+ fn impls_for_ty ( sema : & Semantics < RootDatabase > , ty : hir:: Type ) -> Vec < NavigationTarget > {
55
+ Impl :: all_for_type ( sema. db , ty) . into_iter ( ) . filter_map ( |imp| imp. try_to_nav ( sema. db ) ) . collect ( )
56
+ }
71
57
72
- Some ( impls. into_iter ( ) . filter_map ( |imp| imp. try_to_nav ( sema. db ) ) . collect ( ) )
58
+ fn impls_for_trait ( sema : & Semantics < RootDatabase > , trait_ : hir:: Trait ) -> Vec < NavigationTarget > {
59
+ Impl :: all_for_trait ( sema. db , trait_)
60
+ . into_iter ( )
61
+ . filter_map ( |imp| imp. try_to_nav ( sema. db ) )
62
+ . collect ( )
73
63
}
74
64
75
65
#[ cfg( test) ]
@@ -223,6 +213,50 @@ mod marker {
223
213
}
224
214
#[rustc_builtin_macro]
225
215
macro Copy {}
216
+ "# ,
217
+ ) ;
218
+ }
219
+
220
+ #[ test]
221
+ fn goto_implementation_type_alias ( ) {
222
+ check (
223
+ r#"
224
+ struct Foo;
225
+
226
+ type Bar$0 = Foo;
227
+
228
+ impl Foo {}
229
+ //^^^
230
+ impl Bar {}
231
+ //^^^
232
+ "# ,
233
+ ) ;
234
+ }
235
+
236
+ #[ test]
237
+ fn goto_implementation_adt_generic ( ) {
238
+ check (
239
+ r#"
240
+ struct Foo$0<T>;
241
+
242
+ impl<T> Foo<T> {}
243
+ //^^^^^^
244
+ impl Foo<str> {}
245
+ //^^^^^^^^
246
+ "# ,
247
+ ) ;
248
+ }
249
+
250
+ #[ test]
251
+ fn goto_implementation_builtin ( ) {
252
+ check (
253
+ r#"
254
+ //- /lib.rs crate:main deps:core
255
+ fn foo(_: bool$0) {{}}
256
+ //- /libcore.rs crate:core
257
+ #[lang = "bool"]
258
+ impl bool {}
259
+ //^^^^
226
260
"# ,
227
261
) ;
228
262
}
0 commit comments