aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/hover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/hover.rs')
-rw-r--r--crates/ra_ide/src/hover.rs3454
1 files changed, 1709 insertions, 1745 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index f36b9de7e..ad68bc43c 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -16,18 +16,18 @@ use ra_ide_db::{
16 defs::{classify_name, classify_name_ref, Definition}, 16 defs::{classify_name, classify_name_ref, Definition},
17 RootDatabase, 17 RootDatabase,
18}; 18};
19use ra_syntax::{ast, ast::Path, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; 19use ra_syntax::{ast, ast::Path, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
20use ra_tt::{Ident, Leaf, Literal, TokenTree}; 20use ra_tt::{Ident, Leaf, Literal, TokenTree};
21use stdx::format_to;
22use test_utils::mark;
21use url::Url; 23use url::Url;
22 24
23use crate::{ 25use crate::{
24 display::{ 26 display::{macro_label, ShortLabel, ToNav, TryToNav},
25 macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav, 27 markup::Markup,
26 },
27 runnables::runnable, 28 runnables::runnable,
28 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, 29 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
29}; 30};
30use test_utils::mark;
31 31
32#[derive(Clone, Debug, PartialEq, Eq)] 32#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct HoverConfig { 33pub struct HoverConfig {
@@ -76,50 +76,8 @@ pub struct HoverGotoTypeData {
76/// Contains the results when hovering over an item 76/// Contains the results when hovering over an item
77#[derive(Debug, Default)] 77#[derive(Debug, Default)]
78pub struct HoverResult { 78pub struct HoverResult {
79 results: Vec<String>, 79 pub markup: Markup,
80 actions: Vec<HoverAction>, 80 pub actions: Vec<HoverAction>,
81}
82
83impl HoverResult {
84 pub fn new() -> HoverResult {
85 Self::default()
86 }
87
88 pub fn extend(&mut self, item: Option<String>) {
89 self.results.extend(item);
90 }
91
92 pub fn is_empty(&self) -> bool {
93 self.results.is_empty()
94 }
95
96 pub fn len(&self) -> usize {
97 self.results.len()
98 }
99
100 pub fn first(&self) -> Option<&str> {
101 self.results.first().map(String::as_str)
102 }
103
104 pub fn results(&self) -> &[String] {
105 &self.results
106 }
107
108 pub fn actions(&self) -> &[HoverAction] {
109 &self.actions
110 }
111
112 pub fn push_action(&mut self, action: HoverAction) {
113 self.actions.push(action);
114 }
115
116 /// Returns the results converted into markup
117 /// for displaying in a UI
118 ///
119 /// Does not process actions!
120 pub fn to_markup(&self) -> String {
121 self.results.join("\n\n___\n")
122 }
123} 81}
124 82
125// Feature: Hover 83// Feature: Hover
@@ -132,37 +90,33 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
132 let token = pick_best(file.token_at_offset(position.offset))?; 90 let token = pick_best(file.token_at_offset(position.offset))?;
133 let token = sema.descend_into_macros(token); 91 let token = sema.descend_into_macros(token);
134 92
135 let mut res = HoverResult::new(); 93 let mut res = HoverResult::default();
136 94
137 if let Some((node, name_kind)) = match_ast! { 95 let node = token.parent();
138 match (token.parent()) { 96 let definition = match_ast! {
139 ast::NameRef(name_ref) => { 97 match node {
140 classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d.definition())) 98 ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition()),
141 }, 99 ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition()),
142 ast::Name(name) => {
143 classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition()))
144 },
145 _ => None, 100 _ => None,
146 } 101 }
147 } { 102 };
148 let range = sema.original_range(&node).range; 103 if let Some(definition) = definition {
149 let text = hover_text_from_name_kind(db, name_kind.clone()); 104 if let Some(markup) = hover_for_definition(db, definition) {
150 let text = text.map(|text| rewrite_links(db, &text, &name_kind).unwrap_or(text)); 105 let markup = rewrite_links(db, &markup.as_str(), &definition);
151 res.extend(text); 106 res.markup = Markup::from(markup);
152 107 if let Some(action) = show_implementations_action(db, definition) {
153 if !res.is_empty() { 108 res.actions.push(action);
154 if let Some(action) = show_implementations_action(db, name_kind) {
155 res.push_action(action);
156 } 109 }
157 110
158 if let Some(action) = runnable_action(&sema, name_kind, position.file_id) { 111 if let Some(action) = runnable_action(&sema, definition, position.file_id) {
159 res.push_action(action); 112 res.actions.push(action);
160 } 113 }
161 114
162 if let Some(action) = goto_type_action(db, name_kind) { 115 if let Some(action) = goto_type_action(db, definition) {
163 res.push_action(action); 116 res.actions.push(action);
164 } 117 }
165 118
119 let range = sema.original_range(&node).range;
166 return Some(RangeInfo::new(range, res)); 120 return Some(RangeInfo::new(range, res));
167 } 121 }
168 } 122 }
@@ -173,22 +127,16 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
173 127
174 let ty = match_ast! { 128 let ty = match_ast! {
175 match node { 129 match node {
176 ast::MacroCall(_it) => { 130 ast::Expr(it) => sema.type_of_expr(&it)?,
177 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. 131 ast::Pat(it) => sema.type_of_pat(&it)?,
178 // (e.g expanding a builtin macro). So we give up here. 132 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
179 return None; 133 // (e.g expanding a builtin macro). So we give up here.
180 }, 134 ast::MacroCall(_it) => return None,
181 ast::Expr(it) => { 135 _ => return None,
182 sema.type_of_expr(&it)
183 },
184 ast::Pat(it) => {
185 sema.type_of_pat(&it)
186 },
187 _ => None,
188 } 136 }
189 }?; 137 };
190 138
191 res.extend(Some(rust_code_markup(&ty.display(db)))); 139 res.markup = Markup::fenced_block(&ty.display(db));
192 let range = sema.original_range(&node).range; 140 let range = sema.original_range(&node).range;
193 Some(RangeInfo::new(range, res)) 141 Some(RangeInfo::new(range, res))
194} 142}
@@ -196,8 +144,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
196fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { 144fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
197 fn to_action(nav_target: NavigationTarget) -> HoverAction { 145 fn to_action(nav_target: NavigationTarget) -> HoverAction {
198 HoverAction::Implementaion(FilePosition { 146 HoverAction::Implementaion(FilePosition {
199 file_id: nav_target.file_id(), 147 file_id: nav_target.file_id,
200 offset: nav_target.range().start(), 148 offset: nav_target.focus_or_full_range().start(),
201 }) 149 })
202 } 150 }
203 151
@@ -269,7 +217,11 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
269 .into_iter() 217 .into_iter()
270 .filter_map(|it| { 218 .filter_map(|it| {
271 Some(HoverGotoTypeData { 219 Some(HoverGotoTypeData {
272 mod_path: mod_path(db, &it)?, 220 mod_path: render_path(
221 db,
222 it.module(db)?,
223 it.name(db).map(|name| name.to_string()),
224 ),
273 nav: it.try_to_nav(db)?, 225 nav: it.try_to_nav(db)?,
274 }) 226 })
275 }) 227 })
@@ -281,15 +233,28 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
281 } 233 }
282} 234}
283 235
284fn hover_text( 236fn hover_markup(
285 docs: Option<String>, 237 docs: Option<String>,
286 desc: Option<String>, 238 desc: Option<String>,
287 mod_path: Option<String>, 239 mod_path: Option<String>,
288) -> Option<String> { 240) -> Option<Markup> {
289 if let Some(desc) = desc { 241 match desc {
290 Some(rust_code_markup_with_doc(&desc, docs.as_deref(), mod_path.as_deref())) 242 Some(desc) => {
291 } else { 243 let mut buf = String::new();
292 docs 244
245 if let Some(mod_path) = mod_path {
246 if !mod_path.is_empty() {
247 format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
248 }
249 }
250 format_to!(buf, "```rust\n{}\n```", desc);
251
252 if let Some(doc) = docs {
253 format_to!(buf, "\n___\n\n{}", doc);
254 }
255 Some(buf.into())
256 }
257 None => docs.map(Markup::from),
293 } 258 }
294} 259}
295 260
@@ -311,43 +276,35 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
311 .map(|name| name.to_string()) 276 .map(|name| name.to_string())
312} 277}
313 278
314fn determine_mod_path(db: &RootDatabase, module: Module, name: Option<String>) -> String { 279fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
315 once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string)) 280 let crate_name =
316 .chain( 281 db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string);
317 module 282 let module_path = module
318 .path_to_root(db) 283 .path_to_root(db)
319 .into_iter() 284 .into_iter()
320 .rev() 285 .rev()
321 .map(|it| it.name(db).map(|name| name.to_string())), 286 .flat_map(|it| it.name(db).map(|name| name.to_string()));
322 ) 287 crate_name.into_iter().chain(module_path).chain(item_name).join("::")
323 .chain(once(name))
324 .flatten()
325 .join("::")
326}
327
328// returns None only for ModuleDef::BuiltinType
329fn mod_path(db: &RootDatabase, item: &ModuleDef) -> Option<String> {
330 Some(determine_mod_path(db, item.module(db)?, item.name(db).map(|name| name.to_string())))
331} 288}
332 289
333fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { 290fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
334 def.module(db).map(|module| determine_mod_path(db, module, definition_owner_name(db, def))) 291 def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
335} 292}
336 293
337fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { 294fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
338 let mod_path = definition_mod_path(db, &def); 295 let mod_path = definition_mod_path(db, &def);
339 return match def { 296 return match def {
340 Definition::Macro(it) => { 297 Definition::Macro(it) => {
341 let src = it.source(db); 298 let src = it.source(db);
342 let docs = Documentation::from_ast(&src.value).map(Into::into); 299 let docs = Documentation::from_ast(&src.value).map(Into::into);
343 hover_text(docs, Some(macro_label(&src.value)), mod_path) 300 hover_markup(docs, Some(macro_label(&src.value)), mod_path)
344 } 301 }
345 Definition::Field(it) => { 302 Definition::Field(it) => {
346 let src = it.source(db); 303 let src = it.source(db);
347 match src.value { 304 match src.value {
348 FieldSource::Named(it) => { 305 FieldSource::Named(it) => {
349 let docs = Documentation::from_ast(&it).map(Into::into); 306 let docs = Documentation::from_ast(&it).map(Into::into);
350 hover_text(docs, it.short_label(), mod_path) 307 hover_markup(docs, it.short_label(), mod_path)
351 } 308 }
352 _ => None, 309 _ => None,
353 } 310 }
@@ -356,7 +313,7 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
356 ModuleDef::Module(it) => match it.definition_source(db).value { 313 ModuleDef::Module(it) => match it.definition_source(db).value {
357 ModuleSource::Module(it) => { 314 ModuleSource::Module(it) => {
358 let docs = Documentation::from_ast(&it).map(Into::into); 315 let docs = Documentation::from_ast(&it).map(Into::into);
359 hover_text(docs, it.short_label(), mod_path) 316 hover_markup(docs, it.short_label(), mod_path)
360 } 317 }
361 _ => None, 318 _ => None,
362 }, 319 },
@@ -369,23 +326,23 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
369 ModuleDef::Static(it) => from_def_source(db, it, mod_path), 326 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
370 ModuleDef::Trait(it) => from_def_source(db, it, mod_path), 327 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
371 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 328 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
372 ModuleDef::BuiltinType(it) => Some(it.to_string()), 329 ModuleDef::BuiltinType(it) => return Some(it.to_string().into()),
373 }, 330 },
374 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display(db))), 331 Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))),
375 Definition::TypeParam(_) | Definition::SelfType(_) => { 332 Definition::TypeParam(_) | Definition::SelfType(_) => {
376 // FIXME: Hover for generic param 333 // FIXME: Hover for generic param
377 None 334 None
378 } 335 }
379 }; 336 };
380 337
381 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<String> 338 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
382 where 339 where
383 D: HasSource<Ast = A>, 340 D: HasSource<Ast = A>,
384 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner, 341 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner,
385 { 342 {
386 let src = def.source(db); 343 let src = def.source(db);
387 let docs = Documentation::from_ast(&src.value).map(Into::into); 344 let docs = Documentation::from_ast(&src.value).map(Into::into);
388 hover_text(docs, src.value.short_label(), mod_path) 345 hover_markup(docs, src.value.short_label(), mod_path)
389 } 346 }
390} 347}
391 348
@@ -422,7 +379,7 @@ fn map_links<'e>(
422} 379}
423 380
424/// Rewrite documentation links in markdown to point to an online host (e.g. docs.rs) 381/// Rewrite documentation links in markdown to point to an online host (e.g. docs.rs)
425fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition) -> Option<String> { 382fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition) -> String {
426 let doc = Parser::new_with_broken_link_callback( 383 let doc = Parser::new_with_broken_link_callback(
427 markdown, 384 markdown,
428 Options::empty(), 385 Options::empty(),
@@ -452,7 +409,7 @@ fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition) ->
452 }); 409 });
453 let mut out = String::new(); 410 let mut out = String::new();
454 cmark(doc, &mut out, None).ok(); 411 cmark(doc, &mut out, None).ok();
455 Some(out) 412 out
456} 413}
457 414
458#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] 415#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
@@ -665,7 +622,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
665 fn priority(n: &SyntaxToken) -> usize { 622 fn priority(n: &SyntaxToken) -> usize {
666 match n.kind() { 623 match n.kind() {
667 IDENT | INT_NUMBER => 3, 624 IDENT | INT_NUMBER => 3,
668 L_PAREN | R_PAREN => 2, 625 T!['('] | T![')'] => 2,
669 kind if kind.is_trivia() => 0, 626 kind if kind.is_trivia() => 0,
670 _ => 1, 627 _ => 1,
671 } 628 }
@@ -674,64 +631,38 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
674 631
675#[cfg(test)] 632#[cfg(test)]
676mod tests { 633mod tests {
677 use super::*; 634 use expect::{expect, Expect};
678 use insta::assert_debug_snapshot;
679
680 use ra_db::FileLoader; 635 use ra_db::FileLoader;
681 use ra_syntax::TextRange;
682 636
683 use crate::mock_analysis::analysis_and_position; 637 use crate::mock_analysis::analysis_and_position;
684 638
685 fn trim_markup(s: &str) -> String { 639 use super::*;
686 s.trim()
687 .replace("````", "```")
688 .replace("---", "___")
689 .replace("\\<-", "<-")
690 .replace("```\n\n___", "```\n___")
691 .trim_start_matches("```rust\n")
692 .trim_start_matches("test\n```\n\n```rust\n")
693 .trim_end_matches("\n```")
694 .to_string()
695 }
696
697 fn trim_markup_opt(s: Option<&str>) -> Option<String> {
698 s.map(trim_markup)
699 }
700 640
701 fn assert_impl_action(action: &HoverAction, position: u32) { 641 fn check_hover_no_result(ra_fixture: &str) {
702 let offset = match action { 642 let (analysis, position) = analysis_and_position(ra_fixture);
703 HoverAction::Implementaion(pos) => pos.offset, 643 assert!(analysis.hover(position).unwrap().is_none());
704 it => panic!("Unexpected hover action: {:#?}", it),
705 };
706 assert_eq!(offset, position.into());
707 } 644 }
708 645
709 fn check_hover_result(fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) { 646 fn check(ra_fixture: &str, expect: Expect) {
710 let (analysis, position) = analysis_and_position(fixture); 647 let (analysis, position) = analysis_and_position(ra_fixture);
711 let hover = analysis.hover(position).unwrap().unwrap(); 648 let hover = analysis.hover(position).unwrap().unwrap();
712 let mut results = Vec::from(hover.info.results());
713 results.sort();
714
715 for (markup, expected) in
716 results.iter().zip(expected.iter().chain(std::iter::repeat(&"<missing>")))
717 {
718 assert_eq!(trim_markup(&markup), *expected);
719 }
720
721 assert_eq!(hover.info.len(), expected.len());
722 649
723 let content = analysis.db.file_text(position.file_id); 650 let content = analysis.db.file_text(position.file_id);
724 (content[hover.range].to_string(), hover.info.actions().to_vec()) 651 let hovered_element = &content[hover.range];
652
653 let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
654 expect.assert_eq(&actual)
725 } 655 }
726 656
727 fn check_hover_no_result(fixture: &str) { 657 fn check_actions(ra_fixture: &str, expect: Expect) {
728 let (analysis, position) = analysis_and_position(fixture); 658 let (analysis, position) = analysis_and_position(ra_fixture);
729 assert!(analysis.hover(position).unwrap().is_none()); 659 let hover = analysis.hover(position).unwrap().unwrap();
660 expect.assert_debug_eq(&hover.info.actions)
730 } 661 }
731 662
732 #[test] 663 #[test]
733 fn hover_shows_type_of_an_expression() { 664 fn hover_shows_type_of_an_expression() {
734 let (analysis, position) = analysis_and_position( 665 check(
735 r#" 666 r#"
736pub fn foo() -> u32 { 1 } 667pub fn foo() -> u32 { 1 }
737 668
@@ -739,606 +670,643 @@ fn main() {
739 let foo_test = foo()<|>; 670 let foo_test = foo()<|>;
740} 671}
741"#, 672"#,
673 expect![[r#"
674 *foo()*
675 ```rust
676 u32
677 ```
678 "#]],
742 ); 679 );
743 let hover = analysis.hover(position).unwrap().unwrap();
744 assert_eq!(hover.range, TextRange::new(58.into(), 63.into()));
745 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("u32"));
746 } 680 }
747 681
748 #[test] 682 #[test]
749 fn hover_shows_long_type_of_an_expression() { 683 fn hover_shows_long_type_of_an_expression() {
750 check_hover_result( 684 check(
751 r#" 685 r#"
752 //- /main.rs 686struct Scan<A, B, C> { a: A, b: B, c: C }
753 struct Scan<A, B, C> { 687struct Iter<I> { inner: I }
754 a: A, 688enum Option<T> { Some(T), None }
755 b: B,
756 c: C,
757 }
758 689
759 struct FakeIter<I> { 690struct OtherStruct<T> { i: T }
760 inner: I,
761 }
762
763 struct OtherStruct<T> {
764 i: T,
765 }
766 691
767 enum FakeOption<T> { 692fn scan<A, B, C>(a: A, b: B, c: C) -> Iter<Scan<OtherStruct<A>, B, C>> {
768 Some(T), 693 Iter { inner: Scan { a, b, c } }
769 None, 694}
770 }
771
772 fn scan<A, B, C>(a: A, b: B, c: C) -> FakeIter<Scan<OtherStruct<A>, B, C>> {
773 FakeIter { inner: Scan { a, b, c } }
774 }
775 695
776 fn main() { 696fn main() {
777 let num: i32 = 55; 697 let num: i32 = 55;
778 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> FakeOption<u32> { 698 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option<u32> {
779 FakeOption::Some(*memo + value) 699 Option::Some(*memo + value)
780 }; 700 };
781 let number = 5u32; 701 let number = 5u32;
782 let mut iter<|> = scan(OtherStruct { i: num }, closure, number); 702 let mut iter<|> = scan(OtherStruct { i: num }, closure, number);
783 } 703}
784 "#, 704"#,
785 &["FakeIter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> FakeOption<u32>, u32>>"], 705 expect![[r#"
706 *iter*
707 ```rust
708 Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
709 ```
710 "#]],
786 ); 711 );
787 } 712 }
788 713
789 #[test] 714 #[test]
790 fn hover_shows_fn_signature() { 715 fn hover_shows_fn_signature() {
791 // Single file with result 716 // Single file with result
792 check_hover_result( 717 check(
793 r#" 718 r#"
794 //- /main.rs 719pub fn foo() -> u32 { 1 }
795 pub fn foo() -> u32 { 1 }
796 720
797 fn main() { 721fn main() { let foo_test = fo<|>o(); }
798 let foo_test = fo<|>o(); 722"#,
799 } 723 expect![[r#"
800 "#, 724 *foo*
801 &["pub fn foo() -> u32"], 725 ```rust
726 pub fn foo() -> u32
727 ```
728 "#]],
802 ); 729 );
803 730
804 // Multiple candidates but results are ambiguous. 731 // Multiple candidates but results are ambiguous.
805 check_hover_result( 732 check(
806 r#" 733 r#"
807 //- /a.rs 734//- /a.rs
808 pub fn foo() -> u32 { 1 } 735pub fn foo() -> u32 { 1 }
809 736
810 //- /b.rs 737//- /b.rs
811 pub fn foo() -> &str { "" } 738pub fn foo() -> &str { "" }
812 739
813 //- /c.rs 740//- /c.rs
814 pub fn foo(a: u32, b: u32) {} 741pub fn foo(a: u32, b: u32) {}
815 742
816 //- /main.rs 743//- /main.rs
817 mod a; 744mod a;
818 mod b; 745mod b;
819 mod c; 746mod c;
820 747
821 fn main() { 748fn main() { let foo_test = fo<|>o(); }
822 let foo_test = fo<|>o();
823 }
824 "#, 749 "#,
825 &["{unknown}"], 750 expect![[r#"
751 *foo*
752 ```rust
753 {unknown}
754 ```
755 "#]],
826 ); 756 );
827 } 757 }
828 758
829 #[test] 759 #[test]
830 fn hover_shows_fn_signature_with_type_params() { 760 fn hover_shows_fn_signature_with_type_params() {
831 check_hover_result( 761 check(
832 r#" 762 r#"
833 //- /main.rs 763pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
834 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
835 764
836 fn main() { 765fn main() { let foo_test = fo<|>o(); }
837 let foo_test = fo<|>o();
838 }
839 "#, 766 "#,
840 &["pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str"], 767 expect![[r#"
768 *foo*
769 ```rust
770 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str
771 ```
772 "#]],
841 ); 773 );
842 } 774 }
843 775
844 #[test] 776 #[test]
845 fn hover_shows_fn_signature_on_fn_name() { 777 fn hover_shows_fn_signature_on_fn_name() {
846 check_hover_result( 778 check(
847 r#" 779 r#"
848 //- /main.rs 780pub fn foo<|>(a: u32, b: u32) -> u32 {}
849 pub fn foo<|>(a: u32, b: u32) -> u32 {}
850 781
851 fn main() { 782fn main() { }
852 } 783"#,
853 "#, 784 expect![[r#"
854 &["pub fn foo(a: u32, b: u32) -> u32"], 785 *foo*
786 ```rust
787 pub fn foo(a: u32, b: u32) -> u32
788 ```
789 "#]],
855 ); 790 );
856 } 791 }
857 792
858 #[test] 793 #[test]
859 fn hover_shows_struct_field_info() { 794 fn hover_shows_struct_field_info() {
860 // Hovering over the field when instantiating 795 // Hovering over the field when instantiating
861 check_hover_result( 796 check(
862 r#" 797 r#"
863 //- /main.rs 798struct Foo { field_a: u32 }
864 struct Foo {
865 field_a: u32,
866 }
867 799
868 fn main() { 800fn main() {
869 let foo = Foo { 801 let foo = Foo { field_a<|>: 0, };
870 field_a<|>: 0, 802}
871 }; 803"#,
872 } 804 expect![[r#"
873 "#, 805 *field_a*
874 &["test::Foo\n```\n\n```rust\nfield_a: u32"], 806 ```rust
807 Foo
808 ```
809
810 ```rust
811 field_a: u32
812 ```
813 "#]],
875 ); 814 );
876 815
877 // Hovering over the field in the definition 816 // Hovering over the field in the definition
878 check_hover_result( 817 check(
879 r#" 818 r#"
880 //- /main.rs 819struct Foo { field_a<|>: u32 }
881 struct Foo {
882 field_a<|>: u32,
883 }
884 820
885 fn main() { 821fn main() {
886 let foo = Foo { 822 let foo = Foo { field_a: 0 };
887 field_a: 0, 823}
888 }; 824"#,
889 } 825 expect![[r#"
890 "#, 826 *field_a*
891 &["test::Foo\n```\n\n```rust\nfield_a: u32"], 827 ```rust
828 Foo
829 ```
830
831 ```rust
832 field_a: u32
833 ```
834 "#]],
892 ); 835 );
893 } 836 }
894 837
895 #[test] 838 #[test]
896 fn hover_const_static() { 839 fn hover_const_static() {
897 check_hover_result( 840 check(
898 r#" 841 r#"const foo<|>: u32 = 0;"#,
899 //- /main.rs 842 expect![[r#"
900 const foo<|>: u32 = 0; 843 *foo*
901 "#, 844 ```rust
902 &["const foo: u32"], 845 const foo: u32
846 ```
847 "#]],
903 ); 848 );
904 849 check(
905 check_hover_result( 850 r#"static foo<|>: u32 = 0;"#,
906 r#" 851 expect![[r#"
907 //- /main.rs 852 *foo*
908 static foo<|>: u32 = 0; 853 ```rust
909 "#, 854 static foo: u32
910 &["static foo: u32"], 855 ```
856 "#]],
911 ); 857 );
912 } 858 }
913 859
914 #[test] 860 #[test]
915 fn hover_default_generic_types() { 861 fn hover_default_generic_types() {
916 check_hover_result( 862 check(
917 r#" 863 r#"
918//- /main.rs 864struct Test<K, T = u8> { k: K, t: T }
919struct Test<K, T = u8> {
920 k: K,
921 t: T,
922}
923 865
924fn main() { 866fn main() {
925 let zz<|> = Test { t: 23u8, k: 33 }; 867 let zz<|> = Test { t: 23u8, k: 33 };
926}"#, 868}"#,
927 &["Test<i32, u8>"], 869 expect![[r#"
870 *zz*
871 ```rust
872 Test<i32, u8>
873 ```
874 "#]],
928 ); 875 );
929 } 876 }
930 877
931 #[test] 878 #[test]
932 fn hover_some() { 879 fn hover_some() {
933 let (analysis, position) = analysis_and_position( 880 check(
934 " 881 r#"
935 enum Option<T> { Some(T) } 882enum Option<T> { Some(T) }
936 use Option::Some; 883use Option::Some;
937 884
938 fn main() { 885fn main() { So<|>me(12); }
939 So<|>me(12); 886"#,
940 } 887 expect![[r#"
941 ", 888 *Some*
942 ); 889 ```rust
943 let hover = analysis.hover(position).unwrap().unwrap(); 890 Option
944 assert_eq!( 891 ```
945 trim_markup_opt(hover.info.first()).as_deref(), 892
946 Some("test::Option\n```\n\n```rust\nSome") 893 ```rust
894 Some
895 ```
896 "#]],
947 ); 897 );
948 898
949 let (analysis, position) = analysis_and_position( 899 check(
950 " 900 r#"
951 enum Option<T> { Some(T) } 901enum Option<T> { Some(T) }
952 use Option::Some; 902use Option::Some;
953 903
954 fn main() { 904fn main() { let b<|>ar = Some(12); }
955 let b<|>ar = Some(12); 905"#,
956 } 906 expect![[r#"
957 ", 907 *bar*
908 ```rust
909 Option<i32>
910 ```
911 "#]],
958 ); 912 );
959 let hover = analysis.hover(position).unwrap().unwrap();
960 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("Option<i32>"));
961 } 913 }
962 914
963 #[test] 915 #[test]
964 fn hover_enum_variant() { 916 fn hover_enum_variant() {
965 check_hover_result( 917 check(
966 r#" 918 r#"
967 //- /main.rs 919enum Option<T> {
968 enum Option<T> { 920 /// The None variant
969 /// The None variant 921 Non<|>e
970 Non<|>e 922}
971 } 923"#,
972 "#, 924 expect![[r#"
973 &[" 925 *None*
974test::Option 926 ```rust
975``` 927 Option
928 ```
976 929
977```rust 930 ```rust
978None 931 None
979``` 932 ```
980___ 933 ___
981 934
982The None variant 935 The None variant
983 " 936 "#]],
984 .trim()],
985 ); 937 );
986 938
987 check_hover_result( 939 check(
988 r#" 940 r#"
989 //- /main.rs 941enum Option<T> {
990 enum Option<T> { 942 /// The Some variant
991 /// The Some variant 943 Some(T)
992 Some(T) 944}
993 } 945fn main() {
994 fn main() { 946 let s = Option::Som<|>e(12);
995 let s = Option::Som<|>e(12); 947}
996 } 948"#,
997 "#, 949 expect![[r#"
998 &[" 950 *Some*
999test::Option 951 ```rust
1000``` 952 Option
953 ```
1001 954
1002```rust 955 ```rust
1003Some 956 Some
1004``` 957 ```
1005___ 958 ___
1006 959
1007The Some variant 960 The Some variant
1008 " 961 "#]],
1009 .trim()],
1010 ); 962 );
1011 } 963 }
1012 964
1013 #[test] 965 #[test]
1014 fn hover_for_local_variable() { 966 fn hover_for_local_variable() {
1015 let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); 967 check(
1016 let hover = analysis.hover(position).unwrap().unwrap(); 968 r#"fn func(foo: i32) { fo<|>o; }"#,
1017 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("i32")); 969 expect![[r#"
970 *foo*
971 ```rust
972 i32
973 ```
974 "#]],
975 )
1018 } 976 }
1019 977
1020 #[test] 978 #[test]
1021 fn hover_for_local_variable_pat() { 979 fn hover_for_local_variable_pat() {
1022 let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); 980 check(
1023 let hover = analysis.hover(position).unwrap().unwrap(); 981 r#"fn func(fo<|>o: i32) {}"#,
1024 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("i32")); 982 expect![[r#"
983 *foo*
984 ```rust
985 i32
986 ```
987 "#]],
988 )
1025 } 989 }
1026 990
1027 #[test] 991 #[test]
1028 fn hover_local_var_edge() { 992 fn hover_local_var_edge() {
1029 let (analysis, position) = analysis_and_position( 993 check(
1030 " 994 r#"fn func(foo: i32) { if true { <|>foo; }; }"#,
1031fn func(foo: i32) { if true { <|>foo; }; } 995 expect![[r#"
1032", 996 *foo*
1033 ); 997 ```rust
1034 let hover = analysis.hover(position).unwrap().unwrap(); 998 i32
1035 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("i32")); 999 ```
1000 "#]],
1001 )
1036 } 1002 }
1037 1003
1038 #[test] 1004 #[test]
1039 fn hover_for_param_edge() { 1005 fn hover_for_param_edge() {
1040 let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); 1006 check(
1041 let hover = analysis.hover(position).unwrap().unwrap(); 1007 r#"fn func(<|>foo: i32) {}"#,
1042 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("i32")); 1008 expect![[r#"
1009 *foo*
1010 ```rust
1011 i32
1012 ```
1013 "#]],
1014 )
1043 } 1015 }
1044 1016
1045 #[test] 1017 #[test]
1046 fn test_hover_infer_associated_method_result() { 1018 fn test_hover_infer_associated_method_result() {
1047 let (analysis, position) = analysis_and_position( 1019 check(
1048 " 1020 r#"
1049 struct Thing { x: u32 } 1021struct Thing { x: u32 }
1050 1022
1051 impl Thing { 1023impl Thing {
1052 fn new() -> Thing { 1024 fn new() -> Thing { Thing { x: 0 } }
1053 Thing { x: 0 } 1025}
1054 }
1055 }
1056 1026
1057 fn main() { 1027fn main() { let foo_<|>test = Thing::new(); }
1058 let foo_<|>test = Thing::new(); 1028 "#,
1059 } 1029 expect![[r#"
1060 ", 1030 *foo_test*
1061 ); 1031 ```rust
1062 let hover = analysis.hover(position).unwrap().unwrap(); 1032 Thing
1063 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("Thing")); 1033 ```
1034 "#]],
1035 )
1064 } 1036 }
1065 1037
1066 #[test] 1038 #[test]
1067 fn test_hover_infer_associated_method_exact() { 1039 fn test_hover_infer_associated_method_exact() {
1068 let (analysis, position) = analysis_and_position( 1040 check(
1069 " 1041 r#"
1070 mod wrapper { 1042mod wrapper {
1071 struct Thing { x: u32 } 1043 struct Thing { x: u32 }
1072 1044
1073 impl Thing { 1045 impl Thing {
1074 fn new() -> Thing { 1046 fn new() -> Thing { Thing { x: 0 } }
1075 Thing { x: 0 } 1047 }
1076 } 1048}
1077 }
1078 }
1079 1049
1080 fn main() { 1050fn main() { let foo_test = wrapper::Thing::new<|>(); }
1081 let foo_test = wrapper::Thing::new<|>(); 1051"#,
1082 } 1052 expect![[r#"
1083 ", 1053 *new*
1084 ); 1054 ```rust
1085 let hover = analysis.hover(position).unwrap().unwrap(); 1055 wrapper::Thing
1086 assert_eq!( 1056 ```
1087 trim_markup_opt(hover.info.first()).as_deref(), 1057
1088 Some("test::wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") 1058 ```rust
1089 ); 1059 fn new() -> Thing
1060 ```
1061 "#]],
1062 )
1090 } 1063 }
1091 1064
1092 #[test] 1065 #[test]
1093 fn test_hover_infer_associated_const_in_pattern() { 1066 fn test_hover_infer_associated_const_in_pattern() {
1094 let (analysis, position) = analysis_and_position( 1067 check(
1095 " 1068 r#"
1096 struct X; 1069struct X;
1097 impl X { 1070impl X {
1098 const C: u32 = 1; 1071 const C: u32 = 1;
1099 } 1072}
1100 1073
1101 fn main() { 1074fn main() {
1102 match 1 { 1075 match 1 {
1103 X::C<|> => {}, 1076 X::C<|> => {},
1104 2 => {}, 1077 2 => {},
1105 _ => {} 1078 _ => {}
1106 }; 1079 };
1107 } 1080}
1108 ", 1081"#,
1109 ); 1082 expect![[r#"
1110 let hover = analysis.hover(position).unwrap().unwrap(); 1083 *C*
1111 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("const C: u32")); 1084 ```rust
1085 const C: u32
1086 ```
1087 "#]],
1088 )
1112 } 1089 }
1113 1090
1114 #[test] 1091 #[test]
1115 fn test_hover_self() { 1092 fn test_hover_self() {
1116 let (analysis, position) = analysis_and_position( 1093 check(
1117 " 1094 r#"
1118 struct Thing { x: u32 } 1095struct Thing { x: u32 }
1119 impl Thing { 1096impl Thing {
1120 fn new() -> Self { 1097 fn new() -> Self { Self<|> { x: 0 } }
1121 Self<|> { x: 0 } 1098}
1122 } 1099"#,
1123 } 1100 expect![[r#"
1124 ", 1101 *Self { x: 0 }*
1125 ); 1102 ```rust
1126 let hover = analysis.hover(position).unwrap().unwrap(); 1103 Thing
1127 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("Thing")); 1104 ```
1128 1105 "#]],
1129 /* FIXME: revive these tests 1106 )
1130 let (analysis, position) = analysis_and_position( 1107 } /* FIXME: revive these tests
1131 " 1108 let (analysis, position) = analysis_and_position(
1132 struct Thing { x: u32 } 1109 "
1133 impl Thing { 1110 struct Thing { x: u32 }
1134 fn new() -> Self<|> { 1111 impl Thing {
1135 Self { x: 0 } 1112 fn new() -> Self<|> {
1136 } 1113 Self { x: 0 }
1137 } 1114 }
1138 ", 1115 }
1139 ); 1116 ",
1140 1117 );
1141 let hover = analysis.hover(position).unwrap().unwrap(); 1118
1142 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); 1119 let hover = analysis.hover(position).unwrap().unwrap();
1143 1120 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing"));
1144 let (analysis, position) = analysis_and_position( 1121
1145 " 1122 let (analysis, position) = analysis_and_position(
1146 enum Thing { A } 1123 "
1147 impl Thing { 1124 enum Thing { A }
1148 pub fn new() -> Self<|> { 1125 impl Thing {
1149 Thing::A 1126 pub fn new() -> Self<|> {
1150 } 1127 Thing::A
1151 } 1128 }
1152 ", 1129 }
1153 ); 1130 ",
1154 let hover = analysis.hover(position).unwrap().unwrap(); 1131 );
1155 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); 1132 let hover = analysis.hover(position).unwrap().unwrap();
1156 1133 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
1157 let (analysis, position) = analysis_and_position( 1134
1158 " 1135 let (analysis, position) = analysis_and_position(
1159 enum Thing { A } 1136 "
1160 impl Thing { 1137 enum Thing { A }
1161 pub fn thing(a: Self<|>) { 1138 impl Thing {
1162 } 1139 pub fn thing(a: Self<|>) {
1163 } 1140 }
1164 ", 1141 }
1165 ); 1142 ",
1166 let hover = analysis.hover(position).unwrap().unwrap(); 1143 );
1167 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); 1144 let hover = analysis.hover(position).unwrap().unwrap();
1168 */ 1145 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
1169 } 1146 */
1170 1147
1171 #[test] 1148 #[test]
1172 fn test_hover_shadowing_pat() { 1149 fn test_hover_shadowing_pat() {
1173 let (analysis, position) = analysis_and_position( 1150 check(
1174 " 1151 r#"
1175 fn x() {} 1152fn x() {}
1176 1153
1177 fn y() { 1154fn y() {
1178 let x = 0i32; 1155 let x = 0i32;
1179 x<|>; 1156 x<|>;
1180 } 1157}
1181 ", 1158"#,
1182 ); 1159 expect![[r#"
1183 let hover = analysis.hover(position).unwrap().unwrap(); 1160 *x*
1184 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("i32")); 1161 ```rust
1162 i32
1163 ```
1164 "#]],
1165 )
1185 } 1166 }
1186 1167
1187 #[test] 1168 #[test]
1188 fn test_hover_macro_invocation() { 1169 fn test_hover_macro_invocation() {
1189 let (analysis, position) = analysis_and_position( 1170 check(
1190 " 1171 r#"
1191 macro_rules! foo { 1172macro_rules! foo { () => {} }
1192 () => {}
1193 }
1194 1173
1195 fn f() { 1174fn f() { fo<|>o!(); }
1196 fo<|>o!(); 1175"#,
1197 } 1176 expect![[r#"
1198 ", 1177 *foo*
1199 ); 1178 ```rust
1200 let hover = analysis.hover(position).unwrap().unwrap(); 1179 macro_rules! foo
1201 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("macro_rules! foo")); 1180 ```
1181 "#]],
1182 )
1202 } 1183 }
1203 1184
1204 #[test] 1185 #[test]
1205 fn test_hover_tuple_field() { 1186 fn test_hover_tuple_field() {
1206 let (analysis, position) = analysis_and_position( 1187 check(
1207 " 1188 r#"struct TS(String, i32<|>);"#,
1208 struct TS(String, i32<|>); 1189 expect![[r#"
1209 ", 1190 *i32*
1210 ); 1191 i32
1211 let hover = analysis.hover(position).unwrap().unwrap(); 1192 "#]],
1212 assert_eq!(trim_markup_opt(hover.info.first()).as_deref(), Some("i32")); 1193 )
1213 } 1194 }
1214 1195
1215 #[test] 1196 #[test]
1216 fn test_hover_through_macro() { 1197 fn test_hover_through_macro() {
1217 let (hover_on, _) = check_hover_result( 1198 check(
1218 " 1199 r#"
1219 //- /lib.rs 1200macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1220 macro_rules! id { 1201fn foo() {}
1221 ($($tt:tt)*) => { $($tt)* } 1202id! {
1222 } 1203 fn bar() { fo<|>o(); }
1223 fn foo() {} 1204}
1224 id! { 1205"#,
1225 fn bar() { 1206 expect![[r#"
1226 fo<|>o(); 1207 *foo*
1227 } 1208 ```rust
1228 } 1209 fn foo()
1229 ", 1210 ```
1230 &["fn foo()"], 1211 "#]],
1231 ); 1212 );
1232
1233 assert_eq!(hover_on, "foo")
1234 } 1213 }
1235 1214
1236 #[test] 1215 #[test]
1237 fn test_hover_through_expr_in_macro() { 1216 fn test_hover_through_expr_in_macro() {
1238 let (hover_on, _) = check_hover_result( 1217 check(
1239 " 1218 r#"
1240 //- /lib.rs 1219macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1241 macro_rules! id { 1220fn foo(bar:u32) { let a = id!(ba<|>r); }
1242 ($($tt:tt)*) => { $($tt)* } 1221"#,
1243 } 1222 expect![[r#"
1244 fn foo(bar:u32) { 1223 *bar*
1245 let a = id!(ba<|>r); 1224 ```rust
1246 } 1225 u32
1247 ", 1226 ```
1248 &["u32"], 1227 "#]],
1249 ); 1228 );
1250
1251 assert_eq!(hover_on, "bar")
1252 } 1229 }
1253 1230
1254 #[test] 1231 #[test]
1255 fn test_hover_through_expr_in_macro_recursive() { 1232 fn test_hover_through_expr_in_macro_recursive() {
1256 let (hover_on, _) = check_hover_result( 1233 check(
1257 " 1234 r#"
1258 //- /lib.rs 1235macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1259 macro_rules! id_deep { 1236macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1260 ($($tt:tt)*) => { $($tt)* } 1237fn foo(bar:u32) { let a = id!(ba<|>r); }
1261 } 1238"#,
1262 macro_rules! id { 1239 expect![[r#"
1263 ($($tt:tt)*) => { id_deep!($($tt)*) } 1240 *bar*
1264 } 1241 ```rust
1265 fn foo(bar:u32) { 1242 u32
1266 let a = id!(ba<|>r); 1243 ```
1267 } 1244 "#]],
1268 ",
1269 &["u32"],
1270 ); 1245 );
1271
1272 assert_eq!(hover_on, "bar")
1273 } 1246 }
1274 1247
1275 #[test] 1248 #[test]
1276 fn test_hover_through_func_in_macro_recursive() { 1249 fn test_hover_through_func_in_macro_recursive() {
1277 let (hover_on, _) = check_hover_result( 1250 check(
1278 " 1251 r#"
1279 //- /lib.rs 1252macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1280 macro_rules! id_deep { 1253macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1281 ($($tt:tt)*) => { $($tt)* } 1254fn bar() -> u32 { 0 }
1282 } 1255fn foo() { let a = id!([0u32, bar(<|>)] ); }
1283 macro_rules! id { 1256"#,
1284 ($($tt:tt)*) => { id_deep!($($tt)*) } 1257 expect![[r#"
1285 } 1258 *bar()*
1286 fn bar() -> u32 { 1259 ```rust
1287 0 1260 u32
1288 } 1261 ```
1289 fn foo() { 1262 "#]],
1290 let a = id!([0u32, bar(<|>)] );
1291 }
1292 ",
1293 &["u32"],
1294 ); 1263 );
1295
1296 assert_eq!(hover_on, "bar()")
1297 } 1264 }
1298 1265
1299 #[test] 1266 #[test]
1300 fn test_hover_through_literal_string_in_macro() { 1267 fn test_hover_through_literal_string_in_macro() {
1301 let (hover_on, _) = check_hover_result( 1268 check(
1302 r#" 1269 r#"
1303 //- /lib.rs 1270macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } }
1304 macro_rules! arr { 1271fn foo() {
1305 ($($tt:tt)*) => { [$($tt)*)] } 1272 let mastered_for_itunes = "";
1306 } 1273 let _ = arr!("Tr<|>acks", &mastered_for_itunes);
1307 fn foo() { 1274}
1308 let mastered_for_itunes = ""; 1275"#,
1309 let _ = arr!("Tr<|>acks", &mastered_for_itunes); 1276 expect![[r#"
1310 } 1277 *"Tracks"*
1311 "#, 1278 ```rust
1312 &["&str"], 1279 &str
1280 ```
1281 "#]],
1313 ); 1282 );
1314
1315 assert_eq!(hover_on, "\"Tracks\"");
1316 } 1283 }
1317 1284
1318 #[test] 1285 #[test]
1319 fn test_hover_through_assert_macro() { 1286 fn test_hover_through_assert_macro() {
1320 let (hover_on, _) = check_hover_result( 1287 check(
1321 r#" 1288 r#"
1322 //- /lib.rs 1289#[rustc_builtin_macro]
1323 #[rustc_builtin_macro] 1290macro_rules! assert {}
1324 macro_rules! assert {}
1325 1291
1326 fn bar() -> bool { true } 1292fn bar() -> bool { true }
1327 fn foo() { 1293fn foo() {
1328 assert!(ba<|>r()); 1294 assert!(ba<|>r());
1329 } 1295}
1330 "#, 1296"#,
1331 &["fn bar() -> bool"], 1297 expect![[r#"
1298 *bar*
1299 ```rust
1300 fn bar() -> bool
1301 ```
1302 "#]],
1332 ); 1303 );
1333
1334 assert_eq!(hover_on, "bar");
1335 } 1304 }
1336 1305
1337 #[test] 1306 #[test]
1338 fn test_hover_through_literal_string_in_builtin_macro() { 1307 fn test_hover_through_literal_string_in_builtin_macro() {
1339 check_hover_no_result( 1308 check_hover_no_result(
1340 r#" 1309 r#"
1341 //- /lib.rs
1342 #[rustc_builtin_macro] 1310 #[rustc_builtin_macro]
1343 macro_rules! format {} 1311 macro_rules! format {}
1344 1312
@@ -1351,122 +1319,159 @@ fn func(foo: i32) { if true { <|>foo; }; }
1351 1319
1352 #[test] 1320 #[test]
1353 fn test_hover_non_ascii_space_doc() { 1321 fn test_hover_non_ascii_space_doc() {
1354 check_hover_result( 1322 check(
1355 " 1323 "
1356 //- /lib.rs 1324/// <- `\u{3000}` here
1357 /// <- `\u{3000}` here 1325fn foo() { }
1358 fn foo() {
1359 }
1360 1326
1361 fn bar() { 1327fn bar() { fo<|>o(); }
1362 fo<|>o(); 1328",
1363 } 1329 expect![[r#"
1364 ", 1330 *foo*
1365 &["fn foo()\n```\n___\n\n<- `\u{3000}` here"], 1331 ```rust
1332 fn foo()
1333 ```
1334 ___
1335
1336 <- ` ` here
1337 "#]],
1366 ); 1338 );
1367 } 1339 }
1368 1340
1369 #[test] 1341 #[test]
1370 fn test_hover_function_show_qualifiers() { 1342 fn test_hover_function_show_qualifiers() {
1371 check_hover_result( 1343 check(
1372 " 1344 r#"async fn foo<|>() {}"#,
1373 //- /lib.rs 1345 expect![[r#"
1374 async fn foo<|>() {} 1346 *foo*
1375 ", 1347 ```rust
1376 &["async fn foo()"], 1348 async fn foo()
1377 ); 1349 ```
1378 check_hover_result( 1350 "#]],
1379 " 1351 );
1380 //- /lib.rs 1352 check(
1381 pub const unsafe fn foo<|>() {} 1353 r#"pub const unsafe fn foo<|>() {}"#,
1382 ", 1354 expect![[r#"
1383 &["pub const unsafe fn foo()"], 1355 *foo*
1384 ); 1356 ```rust
1385 check_hover_result( 1357 pub const unsafe fn foo()
1386 r#" 1358 ```
1387 //- /lib.rs 1359 "#]],
1388 pub(crate) async unsafe extern "C" fn foo<|>() {} 1360 );
1389 "#, 1361 check(
1390 &[r#"pub(crate) async unsafe extern "C" fn foo()"#], 1362 r#"pub(crate) async unsafe extern "C" fn foo<|>() {}"#,
1363 expect![[r#"
1364 *foo*
1365 ```rust
1366 pub(crate) async unsafe extern "C" fn foo()
1367 ```
1368 "#]],
1391 ); 1369 );
1392 } 1370 }
1393 1371
1394 #[test] 1372 #[test]
1395 fn test_hover_trait_show_qualifiers() { 1373 fn test_hover_trait_show_qualifiers() {
1396 let (_, actions) = check_hover_result( 1374 check_actions(
1397 " 1375 r"unsafe trait foo<|>() {}",
1398 //- /lib.rs 1376 expect![[r#"
1399 unsafe trait foo<|>() {} 1377 [
1400 ", 1378 Implementaion(
1401 &["unsafe trait foo"], 1379 FilePosition {
1380 file_id: FileId(
1381 1,
1382 ),
1383 offset: 13,
1384 },
1385 ),
1386 ]
1387 "#]],
1402 ); 1388 );
1403 assert_impl_action(&actions[0], 13);
1404 } 1389 }
1405 1390
1406 #[test] 1391 #[test]
1407 fn test_hover_mod_with_same_name_as_function() { 1392 fn test_hover_mod_with_same_name_as_function() {
1408 check_hover_result( 1393 check(
1409 " 1394 r#"
1410 //- /lib.rs 1395use self::m<|>y::Bar;
1411 use self::m<|>y::Bar; 1396mod my { pub struct Bar; }
1412
1413 mod my {
1414 pub struct Bar;
1415 }
1416 1397
1417 fn my() {} 1398fn my() {}
1418 ", 1399"#,
1419 &["mod my"], 1400 expect![[r#"
1401 *my*
1402 ```rust
1403 mod my
1404 ```
1405 "#]],
1420 ); 1406 );
1421 } 1407 }
1422 1408
1423 #[test] 1409 #[test]
1424 fn test_hover_struct_doc_comment() { 1410 fn test_hover_struct_doc_comment() {
1425 check_hover_result( 1411 check(
1426 r#" 1412 r#"
1427 //- /lib.rs 1413/// bar docs
1428 /// bar docs 1414struct Bar;
1429 struct Bar;
1430 1415
1431 fn foo() { 1416fn foo() { let bar = Ba<|>r; }
1432 let bar = Ba<|>r; 1417"#,
1433 } 1418 expect![[r#"
1434 "#, 1419 *Bar*
1435 &["struct Bar\n```\n___\n\nbar docs"], 1420 ```rust
1421 struct Bar
1422 ```
1423 ___
1424
1425 bar docs
1426 "#]],
1436 ); 1427 );
1437 } 1428 }
1438 1429
1439 #[test] 1430 #[test]
1440 fn test_hover_struct_doc_attr() { 1431 fn test_hover_struct_doc_attr() {
1441 check_hover_result( 1432 check(
1442 r#" 1433 r#"
1443 //- /lib.rs 1434#[doc = "bar docs"]
1444 #[doc = "bar docs"] 1435struct Bar;
1445 struct Bar;
1446 1436
1447 fn foo() { 1437fn foo() { let bar = Ba<|>r; }
1448 let bar = Ba<|>r; 1438"#,
1449 } 1439 expect![[r#"
1450 "#, 1440 *Bar*
1451 &["struct Bar\n```\n___\n\nbar docs"], 1441 ```rust
1442 struct Bar
1443 ```
1444 ___
1445
1446 bar docs
1447 "#]],
1452 ); 1448 );
1453 } 1449 }
1454 1450
1455 #[test] 1451 #[test]
1456 fn test_hover_struct_doc_attr_multiple_and_mixed() { 1452 fn test_hover_struct_doc_attr_multiple_and_mixed() {
1457 check_hover_result( 1453 check(
1458 r#" 1454 r#"
1459 //- /lib.rs 1455/// bar docs 0
1460 /// bar docs 0 1456#[doc = "bar docs 1"]
1461 #[doc = "bar docs 1"] 1457#[doc = "bar docs 2"]
1462 #[doc = "bar docs 2"] 1458struct Bar;
1463 struct Bar;
1464 1459
1465 fn foo() { 1460fn foo() { let bar = Ba<|>r; }
1466 let bar = Ba<|>r; 1461"#,
1467 } 1462 expect![[r#"
1468 "#, 1463 *Bar*
1469 &["struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2"], 1464 ```rust
1465 struct Bar
1466 ```
1467 ___
1468
1469 bar docs 0
1470
1471 bar docs 1
1472
1473 bar docs 2
1474 "#]],
1470 ); 1475 );
1471 } 1476 }
1472 1477
@@ -1623,27 +1628,35 @@ fn func(foo: i32) { if true { <|>foo; }; }
1623 fn test_hover_macro_generated_struct_fn_doc_comment() { 1628 fn test_hover_macro_generated_struct_fn_doc_comment() {
1624 mark::check!(hover_macro_generated_struct_fn_doc_comment); 1629 mark::check!(hover_macro_generated_struct_fn_doc_comment);
1625 1630
1626 check_hover_result( 1631 check(
1627 r#" 1632 r#"
1628 //- /lib.rs 1633macro_rules! bar {
1629 macro_rules! bar { 1634 () => {
1630 () => { 1635 struct Bar;
1631 struct Bar; 1636 impl Bar {
1632 impl Bar { 1637 /// Do the foo
1633 /// Do the foo 1638 fn foo(&self) {}
1634 fn foo(&self) {} 1639 }
1635 } 1640 }
1636 } 1641}
1637 }
1638 1642
1639 bar!(); 1643bar!();
1640 1644
1641 fn foo() { 1645fn foo() { let bar = Bar; bar.fo<|>o(); }
1642 let bar = Bar; 1646"#,
1643 bar.fo<|>o(); 1647 expect![[r#"
1644 } 1648 *foo*
1645 "#, 1649 ```rust
1646 &["test::Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"], 1650 Bar
1651 ```
1652
1653 ```rust
1654 fn foo(&self)
1655 ```
1656 ___
1657
1658 Do the foo
1659 "#]],
1647 ); 1660 );
1648 } 1661 }
1649 1662
@@ -1651,1204 +1664,1155 @@ fn func(foo: i32) { if true { <|>foo; }; }
1651 fn test_hover_macro_generated_struct_fn_doc_attr() { 1664 fn test_hover_macro_generated_struct_fn_doc_attr() {
1652 mark::check!(hover_macro_generated_struct_fn_doc_attr); 1665 mark::check!(hover_macro_generated_struct_fn_doc_attr);
1653 1666
1654 check_hover_result( 1667 check(
1655 r#" 1668 r#"
1656 //- /lib.rs 1669macro_rules! bar {
1657 macro_rules! bar { 1670 () => {
1658 () => { 1671 struct Bar;
1659 struct Bar; 1672 impl Bar {
1660 impl Bar { 1673 #[doc = "Do the foo"]
1661 #[doc = "Do the foo"] 1674 fn foo(&self) {}
1662 fn foo(&self) {} 1675 }
1663 } 1676 }
1664 } 1677}
1665 }
1666 1678
1667 bar!(); 1679bar!();
1668 1680
1669 fn foo() { 1681fn foo() { let bar = Bar; bar.fo<|>o(); }
1670 let bar = Bar; 1682"#,
1671 bar.fo<|>o(); 1683 expect![[r#"
1672 } 1684 *foo*
1673 "#, 1685 ```rust
1674 &["test::Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"], 1686 Bar
1687 ```
1688
1689 ```rust
1690 fn foo(&self)
1691 ```
1692 ___
1693
1694 Do the foo
1695 "#]],
1675 ); 1696 );
1676 } 1697 }
1677 1698
1678 #[test] 1699 #[test]
1679 fn test_hover_trait_has_impl_action() { 1700 fn test_hover_trait_has_impl_action() {
1680 let (_, actions) = check_hover_result( 1701 check_actions(
1681 " 1702 r#"trait foo<|>() {}"#,
1682 //- /lib.rs 1703 expect![[r#"
1683 trait foo<|>() {} 1704 [
1684 ", 1705 Implementaion(
1685 &["trait foo"], 1706 FilePosition {
1707 file_id: FileId(
1708 1,
1709 ),
1710 offset: 6,
1711 },
1712 ),
1713 ]
1714 "#]],
1686 ); 1715 );
1687 assert_impl_action(&actions[0], 6);
1688 } 1716 }
1689 1717
1690 #[test] 1718 #[test]
1691 fn test_hover_struct_has_impl_action() { 1719 fn test_hover_struct_has_impl_action() {
1692 let (_, actions) = check_hover_result( 1720 check_actions(
1693 " 1721 r"struct foo<|>() {}",
1694 //- /lib.rs 1722 expect![[r#"
1695 struct foo<|>() {} 1723 [
1696 ", 1724 Implementaion(
1697 &["struct foo"], 1725 FilePosition {
1726 file_id: FileId(
1727 1,
1728 ),
1729 offset: 7,
1730 },
1731 ),
1732 ]
1733 "#]],
1698 ); 1734 );
1699 assert_impl_action(&actions[0], 7);
1700 } 1735 }
1701 1736
1702 #[test] 1737 #[test]
1703 fn test_hover_union_has_impl_action() { 1738 fn test_hover_union_has_impl_action() {
1704 let (_, actions) = check_hover_result( 1739 check_actions(
1705 " 1740 r#"union foo<|>() {}"#,
1706 //- /lib.rs 1741 expect![[r#"
1707 union foo<|>() {} 1742 [
1708 ", 1743 Implementaion(
1709 &["union foo"], 1744 FilePosition {
1745 file_id: FileId(
1746 1,
1747 ),
1748 offset: 6,
1749 },
1750 ),
1751 ]
1752 "#]],
1710 ); 1753 );
1711 assert_impl_action(&actions[0], 6);
1712 } 1754 }
1713 1755
1714 #[test] 1756 #[test]
1715 fn test_hover_enum_has_impl_action() { 1757 fn test_hover_enum_has_impl_action() {
1716 let (_, actions) = check_hover_result( 1758 check_actions(
1717 " 1759 r"enum foo<|>() { A, B }",
1718 //- /lib.rs 1760 expect![[r#"
1719 enum foo<|>() { 1761 [
1720 A, 1762 Implementaion(
1721 B 1763 FilePosition {
1722 } 1764 file_id: FileId(
1723 ", 1765 1,
1724 &["enum foo"], 1766 ),
1767 offset: 5,
1768 },
1769 ),
1770 ]
1771 "#]],
1725 ); 1772 );
1726 assert_impl_action(&actions[0], 5);
1727 } 1773 }
1728 1774
1729 #[test] 1775 #[test]
1730 fn test_hover_test_has_action() { 1776 fn test_hover_test_has_action() {
1731 let (_, actions) = check_hover_result( 1777 check_actions(
1732 " 1778 r#"
1733 //- /lib.rs 1779#[test]
1734 #[test] 1780fn foo_<|>test() {}
1735 fn foo_<|>test() {} 1781"#,
1736 ", 1782 expect![[r#"
1737 &["fn foo_test()"], 1783 [
1738 ); 1784 Runnable(
1739 assert_debug_snapshot!(actions, 1785 Runnable {
1740 @r###" 1786 nav: NavigationTarget {
1741 [ 1787 file_id: FileId(
1742 Runnable( 1788 1,
1743 Runnable { 1789 ),
1744 nav: NavigationTarget { 1790 full_range: 0..24,
1745 file_id: FileId( 1791 focus_range: Some(
1746 1, 1792 11..19,
1747 ), 1793 ),
1748 full_range: 0..24, 1794 name: "foo_test",
1749 name: "foo_test", 1795 kind: FN,
1750 kind: FN_DEF, 1796 container_name: None,
1751 focus_range: Some( 1797 description: None,
1752 11..19, 1798 docs: None,
1753 ), 1799 },
1754 container_name: None, 1800 kind: Test {
1755 description: None, 1801 test_id: Path(
1756 docs: None, 1802 "foo_test",
1757 }, 1803 ),
1758 kind: Test { 1804 attr: TestAttr {
1759 test_id: Path( 1805 ignore: false,
1760 "foo_test", 1806 },
1761 ),
1762 attr: TestAttr {
1763 ignore: false,
1764 }, 1807 },
1808 cfg_exprs: [],
1765 }, 1809 },
1766 cfg_exprs: [], 1810 ),
1767 }, 1811 ]
1768 ), 1812 "#]],
1769 ] 1813 );
1770 "###);
1771 } 1814 }
1772 1815
1773 #[test] 1816 #[test]
1774 fn test_hover_test_mod_has_action() { 1817 fn test_hover_test_mod_has_action() {
1775 let (_, actions) = check_hover_result( 1818 check_actions(
1776 " 1819 r#"
1777 //- /lib.rs 1820mod tests<|> {
1778 mod tests<|> { 1821 #[test]
1779 #[test] 1822 fn foo_test() {}
1780 fn foo_test() {} 1823}
1781 } 1824"#,
1782 ", 1825 expect![[r#"
1783 &["mod tests"], 1826 [
1784 ); 1827 Runnable(
1785 assert_debug_snapshot!(actions, 1828 Runnable {
1786 @r###" 1829 nav: NavigationTarget {
1787 [ 1830 file_id: FileId(
1788 Runnable( 1831 1,
1789 Runnable { 1832 ),
1790 nav: NavigationTarget { 1833 full_range: 0..46,
1791 file_id: FileId( 1834 focus_range: Some(
1792 1, 1835 4..9,
1793 ), 1836 ),
1794 full_range: 0..46, 1837 name: "tests",
1795 name: "tests", 1838 kind: MODULE,
1796 kind: MODULE, 1839 container_name: None,
1797 focus_range: Some( 1840 description: None,
1798 4..9, 1841 docs: None,
1799 ), 1842 },
1800 container_name: None, 1843 kind: TestMod {
1801 description: None, 1844 path: "tests",
1802 docs: None, 1845 },
1803 }, 1846 cfg_exprs: [],
1804 kind: TestMod {
1805 path: "tests",
1806 }, 1847 },
1807 cfg_exprs: [], 1848 ),
1808 }, 1849 ]
1809 ), 1850 "#]],
1810 ] 1851 );
1811 "###);
1812 } 1852 }
1813 1853
1814 #[test] 1854 #[test]
1815 fn test_hover_struct_has_goto_type_action() { 1855 fn test_hover_struct_has_goto_type_action() {
1816 let (_, actions) = check_hover_result( 1856 check_actions(
1817 " 1857 r#"
1818 //- /main.rs 1858struct S{ f1: u32 }
1819 struct S{ f1: u32 }
1820 1859
1821 fn main() { 1860fn main() { let s<|>t = S{ f1:0 }; }
1822 let s<|>t = S{ f1:0 }; 1861 "#,
1823 } 1862 expect![[r#"
1824 ",
1825 &["S"],
1826 );
1827 assert_debug_snapshot!(actions,
1828 @r###"
1829 [
1830 GoToType(
1831 [ 1863 [
1832 HoverGotoTypeData { 1864 GoToType(
1833 mod_path: "test::S", 1865 [
1834 nav: NavigationTarget { 1866 HoverGotoTypeData {
1835 file_id: FileId( 1867 mod_path: "S",
1836 1, 1868 nav: NavigationTarget {
1837 ), 1869 file_id: FileId(
1838 full_range: 0..19, 1870 1,
1839 name: "S", 1871 ),
1840 kind: STRUCT_DEF, 1872 full_range: 0..19,
1841 focus_range: Some( 1873 focus_range: Some(
1842 7..8, 1874 7..8,
1843 ), 1875 ),
1844 container_name: None, 1876 name: "S",
1845 description: Some( 1877 kind: STRUCT,
1846 "struct S", 1878 container_name: None,
1847 ), 1879 description: Some(
1848 docs: None, 1880 "struct S",
1849 }, 1881 ),
1850 }, 1882 docs: None,
1851 ], 1883 },
1852 ), 1884 },
1853 ] 1885 ],
1854 "###); 1886 ),
1887 ]
1888 "#]],
1889 );
1855 } 1890 }
1856 1891
1857 #[test] 1892 #[test]
1858 fn test_hover_generic_struct_has_goto_type_actions() { 1893 fn test_hover_generic_struct_has_goto_type_actions() {
1859 let (_, actions) = check_hover_result( 1894 check_actions(
1860 " 1895 r#"
1861 //- /main.rs 1896struct Arg(u32);
1862 struct Arg(u32); 1897struct S<T>{ f1: T }
1863 struct S<T>{ f1: T }
1864 1898
1865 fn main() { 1899fn main() { let s<|>t = S{ f1:Arg(0) }; }
1866 let s<|>t = S{ f1:Arg(0) }; 1900"#,
1867 } 1901 expect![[r#"
1868 ",
1869 &["S<Arg>"],
1870 );
1871 assert_debug_snapshot!(actions,
1872 @r###"
1873 [
1874 GoToType(
1875 [ 1902 [
1876 HoverGotoTypeData { 1903 GoToType(
1877 mod_path: "test::S", 1904 [
1878 nav: NavigationTarget { 1905 HoverGotoTypeData {
1879 file_id: FileId( 1906 mod_path: "S",
1880 1, 1907 nav: NavigationTarget {
1881 ), 1908 file_id: FileId(
1882 full_range: 17..37, 1909 1,
1883 name: "S", 1910 ),
1884 kind: STRUCT_DEF, 1911 full_range: 17..37,
1885 focus_range: Some( 1912 focus_range: Some(
1886 24..25, 1913 24..25,
1887 ), 1914 ),
1888 container_name: None, 1915 name: "S",
1889 description: Some( 1916 kind: STRUCT,
1890 "struct S", 1917 container_name: None,
1891 ), 1918 description: Some(
1892 docs: None, 1919 "struct S",
1893 }, 1920 ),
1894 }, 1921 docs: None,
1895 HoverGotoTypeData { 1922 },
1896 mod_path: "test::Arg", 1923 },
1897 nav: NavigationTarget { 1924 HoverGotoTypeData {
1898 file_id: FileId( 1925 mod_path: "Arg",
1899 1, 1926 nav: NavigationTarget {
1900 ), 1927 file_id: FileId(
1901 full_range: 0..16, 1928 1,
1902 name: "Arg", 1929 ),
1903 kind: STRUCT_DEF, 1930 full_range: 0..16,
1904 focus_range: Some( 1931 focus_range: Some(
1905 7..10, 1932 7..10,
1906 ), 1933 ),
1907 container_name: None, 1934 name: "Arg",
1908 description: Some( 1935 kind: STRUCT,
1909 "struct Arg", 1936 container_name: None,
1910 ), 1937 description: Some(
1911 docs: None, 1938 "struct Arg",
1912 }, 1939 ),
1913 }, 1940 docs: None,
1914 ], 1941 },
1915 ), 1942 },
1916 ] 1943 ],
1917 "###); 1944 ),
1945 ]
1946 "#]],
1947 );
1918 } 1948 }
1919 1949
1920 #[test] 1950 #[test]
1921 fn test_hover_generic_struct_has_flattened_goto_type_actions() { 1951 fn test_hover_generic_struct_has_flattened_goto_type_actions() {
1922 let (_, actions) = check_hover_result( 1952 check_actions(
1923 " 1953 r#"
1924 //- /main.rs 1954struct Arg(u32);
1925 struct Arg(u32); 1955struct S<T>{ f1: T }
1926 struct S<T>{ f1: T }
1927 1956
1928 fn main() { 1957fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
1929 let s<|>t = S{ f1: S{ f1: Arg(0) } }; 1958 "#,
1930 } 1959 expect![[r#"
1931 ",
1932 &["S<S<Arg>>"],
1933 );
1934 assert_debug_snapshot!(actions,
1935 @r###"
1936 [
1937 GoToType(
1938 [ 1960 [
1939 HoverGotoTypeData { 1961 GoToType(
1940 mod_path: "test::S", 1962 [
1941 nav: NavigationTarget { 1963 HoverGotoTypeData {
1942 file_id: FileId( 1964 mod_path: "S",
1943 1, 1965 nav: NavigationTarget {
1944 ), 1966 file_id: FileId(
1945 full_range: 17..37, 1967 1,
1946 name: "S", 1968 ),
1947 kind: STRUCT_DEF, 1969 full_range: 17..37,
1948 focus_range: Some( 1970 focus_range: Some(
1949 24..25, 1971 24..25,
1950 ), 1972 ),
1951 container_name: None, 1973 name: "S",
1952 description: Some( 1974 kind: STRUCT,
1953 "struct S", 1975 container_name: None,
1954 ), 1976 description: Some(
1955 docs: None, 1977 "struct S",
1956 }, 1978 ),
1957 }, 1979 docs: None,
1958 HoverGotoTypeData { 1980 },
1959 mod_path: "test::Arg", 1981 },
1960 nav: NavigationTarget { 1982 HoverGotoTypeData {
1961 file_id: FileId( 1983 mod_path: "Arg",
1962 1, 1984 nav: NavigationTarget {
1963 ), 1985 file_id: FileId(
1964 full_range: 0..16, 1986 1,
1965 name: "Arg", 1987 ),
1966 kind: STRUCT_DEF, 1988 full_range: 0..16,
1967 focus_range: Some( 1989 focus_range: Some(
1968 7..10, 1990 7..10,
1969 ), 1991 ),
1970 container_name: None, 1992 name: "Arg",
1971 description: Some( 1993 kind: STRUCT,
1972 "struct Arg", 1994 container_name: None,
1973 ), 1995 description: Some(
1974 docs: None, 1996 "struct Arg",
1975 }, 1997 ),
1976 }, 1998 docs: None,
1977 ], 1999 },
1978 ), 2000 },
1979 ] 2001 ],
1980 "###); 2002 ),
2003 ]
2004 "#]],
2005 );
1981 } 2006 }
1982 2007
1983 #[test] 2008 #[test]
1984 fn test_hover_tuple_has_goto_type_actions() { 2009 fn test_hover_tuple_has_goto_type_actions() {
1985 let (_, actions) = check_hover_result( 2010 check_actions(
1986 " 2011 r#"
1987 //- /main.rs 2012struct A(u32);
1988 struct A(u32); 2013struct B(u32);
1989 struct B(u32); 2014mod M {
1990 mod M { 2015 pub struct C(u32);
1991 pub struct C(u32); 2016}
1992 }
1993 2017
1994 fn main() { 2018fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
1995 let s<|>t = (A(1), B(2), M::C(3) ); 2019"#,
1996 } 2020 expect![[r#"
1997 ",
1998 &["(A, B, C)"],
1999 );
2000 assert_debug_snapshot!(actions,
2001 @r###"
2002 [
2003 GoToType(
2004 [ 2021 [
2005 HoverGotoTypeData { 2022 GoToType(
2006 mod_path: "test::A", 2023 [
2007 nav: NavigationTarget { 2024 HoverGotoTypeData {
2008 file_id: FileId( 2025 mod_path: "A",
2009 1, 2026 nav: NavigationTarget {
2010 ), 2027 file_id: FileId(
2011 full_range: 0..14, 2028 1,
2012 name: "A", 2029 ),
2013 kind: STRUCT_DEF, 2030 full_range: 0..14,
2014 focus_range: Some( 2031 focus_range: Some(
2015 7..8, 2032 7..8,
2016 ), 2033 ),
2017 container_name: None, 2034 name: "A",
2018 description: Some( 2035 kind: STRUCT,
2019 "struct A", 2036 container_name: None,
2020 ), 2037 description: Some(
2021 docs: None, 2038 "struct A",
2022 }, 2039 ),
2023 }, 2040 docs: None,
2024 HoverGotoTypeData { 2041 },
2025 mod_path: "test::B", 2042 },
2026 nav: NavigationTarget { 2043 HoverGotoTypeData {
2027 file_id: FileId( 2044 mod_path: "B",
2028 1, 2045 nav: NavigationTarget {
2029 ), 2046 file_id: FileId(
2030 full_range: 15..29, 2047 1,
2031 name: "B", 2048 ),
2032 kind: STRUCT_DEF, 2049 full_range: 15..29,
2033 focus_range: Some( 2050 focus_range: Some(
2034 22..23, 2051 22..23,
2035 ), 2052 ),
2036 container_name: None, 2053 name: "B",
2037 description: Some( 2054 kind: STRUCT,
2038 "struct B", 2055 container_name: None,
2039 ), 2056 description: Some(
2040 docs: None, 2057 "struct B",
2041 }, 2058 ),
2042 }, 2059 docs: None,
2043 HoverGotoTypeData { 2060 },
2044 mod_path: "test::M::C", 2061 },
2045 nav: NavigationTarget { 2062 HoverGotoTypeData {
2046 file_id: FileId( 2063 mod_path: "M::C",
2047 1, 2064 nav: NavigationTarget {
2048 ), 2065 file_id: FileId(
2049 full_range: 42..60, 2066 1,
2050 name: "C", 2067 ),
2051 kind: STRUCT_DEF, 2068 full_range: 42..60,
2052 focus_range: Some( 2069 focus_range: Some(
2053 53..54, 2070 53..54,
2054 ), 2071 ),
2055 container_name: None, 2072 name: "C",
2056 description: Some( 2073 kind: STRUCT,
2057 "pub struct C", 2074 container_name: None,
2058 ), 2075 description: Some(
2059 docs: None, 2076 "pub struct C",
2060 }, 2077 ),
2061 }, 2078 docs: None,
2062 ], 2079 },
2063 ), 2080 },
2064 ] 2081 ],
2065 "###); 2082 ),
2083 ]
2084 "#]],
2085 );
2066 } 2086 }
2067 2087
2068 #[test] 2088 #[test]
2069 fn test_hover_return_impl_trait_has_goto_type_action() { 2089 fn test_hover_return_impl_trait_has_goto_type_action() {
2070 let (_, actions) = check_hover_result( 2090 check_actions(
2071 " 2091 r#"
2072 //- /main.rs 2092trait Foo {}
2073 trait Foo {} 2093fn foo() -> impl Foo {}
2074
2075 fn foo() -> impl Foo {}
2076 2094
2077 fn main() { 2095fn main() { let s<|>t = foo(); }
2078 let s<|>t = foo(); 2096"#,
2079 } 2097 expect![[r#"
2080 ",
2081 &["impl Foo"],
2082 );
2083 assert_debug_snapshot!(actions,
2084 @r###"
2085 [
2086 GoToType(
2087 [ 2098 [
2088 HoverGotoTypeData { 2099 GoToType(
2089 mod_path: "test::Foo", 2100 [
2090 nav: NavigationTarget { 2101 HoverGotoTypeData {
2091 file_id: FileId( 2102 mod_path: "Foo",
2092 1, 2103 nav: NavigationTarget {
2093 ), 2104 file_id: FileId(
2094 full_range: 0..12, 2105 1,
2095 name: "Foo", 2106 ),
2096 kind: TRAIT_DEF, 2107 full_range: 0..12,
2097 focus_range: Some( 2108 focus_range: Some(
2098 6..9, 2109 6..9,
2099 ), 2110 ),
2100 container_name: None, 2111 name: "Foo",
2101 description: Some( 2112 kind: TRAIT,
2102 "trait Foo", 2113 container_name: None,
2103 ), 2114 description: Some(
2104 docs: None, 2115 "trait Foo",
2105 }, 2116 ),
2106 }, 2117 docs: None,
2107 ], 2118 },
2108 ), 2119 },
2109 ] 2120 ],
2110 "###); 2121 ),
2122 ]
2123 "#]],
2124 );
2111 } 2125 }
2112 2126
2113 #[test] 2127 #[test]
2114 fn test_hover_generic_return_impl_trait_has_goto_type_action() { 2128 fn test_hover_generic_return_impl_trait_has_goto_type_action() {
2115 let (_, actions) = check_hover_result( 2129 check_actions(
2116 " 2130 r#"
2117 //- /main.rs 2131trait Foo<T> {}
2118 trait Foo<T> {} 2132struct S;
2119 struct S; 2133fn foo() -> impl Foo<S> {}
2120
2121 fn foo() -> impl Foo<S> {}
2122 2134
2123 fn main() { 2135fn main() { let s<|>t = foo(); }
2124 let s<|>t = foo(); 2136"#,
2125 } 2137 expect![[r#"
2126 ",
2127 &["impl Foo<S>"],
2128 );
2129 assert_debug_snapshot!(actions,
2130 @r###"
2131 [
2132 GoToType(
2133 [ 2138 [
2134 HoverGotoTypeData { 2139 GoToType(
2135 mod_path: "test::Foo", 2140 [
2136 nav: NavigationTarget { 2141 HoverGotoTypeData {
2137 file_id: FileId( 2142 mod_path: "Foo",
2138 1, 2143 nav: NavigationTarget {
2139 ), 2144 file_id: FileId(
2140 full_range: 0..15, 2145 1,
2141 name: "Foo", 2146 ),
2142 kind: TRAIT_DEF, 2147 full_range: 0..15,
2143 focus_range: Some( 2148 focus_range: Some(
2144 6..9, 2149 6..9,
2145 ), 2150 ),
2146 container_name: None, 2151 name: "Foo",
2147 description: Some( 2152 kind: TRAIT,
2148 "trait Foo", 2153 container_name: None,
2149 ), 2154 description: Some(
2150 docs: None, 2155 "trait Foo",
2151 }, 2156 ),
2152 }, 2157 docs: None,
2153 HoverGotoTypeData { 2158 },
2154 mod_path: "test::S", 2159 },
2155 nav: NavigationTarget { 2160 HoverGotoTypeData {
2156 file_id: FileId( 2161 mod_path: "S",
2157 1, 2162 nav: NavigationTarget {
2158 ), 2163 file_id: FileId(
2159 full_range: 16..25, 2164 1,
2160 name: "S", 2165 ),
2161 kind: STRUCT_DEF, 2166 full_range: 16..25,
2162 focus_range: Some( 2167 focus_range: Some(
2163 23..24, 2168 23..24,
2164 ), 2169 ),
2165 container_name: None, 2170 name: "S",
2166 description: Some( 2171 kind: STRUCT,
2167 "struct S", 2172 container_name: None,
2168 ), 2173 description: Some(
2169 docs: None, 2174 "struct S",
2170 }, 2175 ),
2171 }, 2176 docs: None,
2172 ], 2177 },
2173 ), 2178 },
2174 ] 2179 ],
2175 "###); 2180 ),
2181 ]
2182 "#]],
2183 );
2176 } 2184 }
2177 2185
2178 #[test] 2186 #[test]
2179 fn test_hover_return_impl_traits_has_goto_type_action() { 2187 fn test_hover_return_impl_traits_has_goto_type_action() {
2180 let (_, actions) = check_hover_result( 2188 check_actions(
2181 " 2189 r#"
2182 //- /main.rs 2190trait Foo {}
2183 trait Foo {} 2191trait Bar {}
2184 trait Bar {} 2192fn foo() -> impl Foo + Bar {}
2185
2186 fn foo() -> impl Foo + Bar {}
2187 2193
2188 fn main() { 2194fn main() { let s<|>t = foo(); }
2189 let s<|>t = foo(); 2195 "#,
2190 } 2196 expect![[r#"
2191 ",
2192 &["impl Foo + Bar"],
2193 );
2194 assert_debug_snapshot!(actions,
2195 @r###"
2196 [
2197 GoToType(
2198 [ 2197 [
2199 HoverGotoTypeData { 2198 GoToType(
2200 mod_path: "test::Foo", 2199 [
2201 nav: NavigationTarget { 2200 HoverGotoTypeData {
2202 file_id: FileId( 2201 mod_path: "Foo",
2203 1, 2202 nav: NavigationTarget {
2204 ), 2203 file_id: FileId(
2205 full_range: 0..12, 2204 1,
2206 name: "Foo", 2205 ),
2207 kind: TRAIT_DEF, 2206 full_range: 0..12,
2208 focus_range: Some( 2207 focus_range: Some(
2209 6..9, 2208 6..9,
2210 ), 2209 ),
2211 container_name: None, 2210 name: "Foo",
2212 description: Some( 2211 kind: TRAIT,
2213 "trait Foo", 2212 container_name: None,
2214 ), 2213 description: Some(
2215 docs: None, 2214 "trait Foo",
2216 }, 2215 ),
2217 }, 2216 docs: None,
2218 HoverGotoTypeData { 2217 },
2219 mod_path: "test::Bar", 2218 },
2220 nav: NavigationTarget { 2219 HoverGotoTypeData {
2221 file_id: FileId( 2220 mod_path: "Bar",
2222 1, 2221 nav: NavigationTarget {
2223 ), 2222 file_id: FileId(
2224 full_range: 13..25, 2223 1,
2225 name: "Bar", 2224 ),
2226 kind: TRAIT_DEF, 2225 full_range: 13..25,
2227 focus_range: Some( 2226 focus_range: Some(
2228 19..22, 2227 19..22,
2229 ), 2228 ),
2230 container_name: None, 2229 name: "Bar",
2231 description: Some( 2230 kind: TRAIT,
2232 "trait Bar", 2231 container_name: None,
2233 ), 2232 description: Some(
2234 docs: None, 2233 "trait Bar",
2235 }, 2234 ),
2236 }, 2235 docs: None,
2237 ], 2236 },
2238 ), 2237 },
2239 ] 2238 ],
2240 "###); 2239 ),
2240 ]
2241 "#]],
2242 );
2241 } 2243 }
2242 2244
2243 #[test] 2245 #[test]
2244 fn test_hover_generic_return_impl_traits_has_goto_type_action() { 2246 fn test_hover_generic_return_impl_traits_has_goto_type_action() {
2245 let (_, actions) = check_hover_result( 2247 check_actions(
2246 " 2248 r#"
2247 //- /main.rs 2249trait Foo<T> {}
2248 trait Foo<T> {} 2250trait Bar<T> {}
2249 trait Bar<T> {} 2251struct S1 {}
2250 struct S1 {} 2252struct S2 {}
2251 struct S2 {}
2252 2253
2253 fn foo() -> impl Foo<S1> + Bar<S2> {} 2254fn foo() -> impl Foo<S1> + Bar<S2> {}
2254 2255
2255 fn main() { 2256fn main() { let s<|>t = foo(); }
2256 let s<|>t = foo(); 2257"#,
2257 } 2258 expect![[r#"
2258 ",
2259 &["impl Foo<S1> + Bar<S2>"],
2260 );
2261 assert_debug_snapshot!(actions,
2262 @r###"
2263 [
2264 GoToType(
2265 [ 2259 [
2266 HoverGotoTypeData { 2260 GoToType(
2267 mod_path: "test::Foo", 2261 [
2268 nav: NavigationTarget { 2262 HoverGotoTypeData {
2269 file_id: FileId( 2263 mod_path: "Foo",
2270 1, 2264 nav: NavigationTarget {
2271 ), 2265 file_id: FileId(
2272 full_range: 0..15, 2266 1,
2273 name: "Foo", 2267 ),
2274 kind: TRAIT_DEF, 2268 full_range: 0..15,
2275 focus_range: Some( 2269 focus_range: Some(
2276 6..9, 2270 6..9,
2277 ), 2271 ),
2278 container_name: None, 2272 name: "Foo",
2279 description: Some( 2273 kind: TRAIT,
2280 "trait Foo", 2274 container_name: None,
2281 ), 2275 description: Some(
2282 docs: None, 2276 "trait Foo",
2283 }, 2277 ),
2284 }, 2278 docs: None,
2285 HoverGotoTypeData { 2279 },
2286 mod_path: "test::Bar", 2280 },
2287 nav: NavigationTarget { 2281 HoverGotoTypeData {
2288 file_id: FileId( 2282 mod_path: "Bar",
2289 1, 2283 nav: NavigationTarget {
2290 ), 2284 file_id: FileId(
2291 full_range: 16..31, 2285 1,
2292 name: "Bar", 2286 ),
2293 kind: TRAIT_DEF, 2287 full_range: 16..31,
2294 focus_range: Some( 2288 focus_range: Some(
2295 22..25, 2289 22..25,
2296 ), 2290 ),
2297 container_name: None, 2291 name: "Bar",
2298 description: Some( 2292 kind: TRAIT,
2299 "trait Bar", 2293 container_name: None,
2300 ), 2294 description: Some(
2301 docs: None, 2295 "trait Bar",
2302 }, 2296 ),
2303 }, 2297 docs: None,
2304 HoverGotoTypeData { 2298 },
2305 mod_path: "test::S1", 2299 },
2306 nav: NavigationTarget { 2300 HoverGotoTypeData {
2307 file_id: FileId( 2301 mod_path: "S1",
2308 1, 2302 nav: NavigationTarget {
2309 ), 2303 file_id: FileId(
2310 full_range: 32..44, 2304 1,
2311 name: "S1", 2305 ),
2312 kind: STRUCT_DEF, 2306 full_range: 32..44,
2313 focus_range: Some( 2307 focus_range: Some(
2314 39..41, 2308 39..41,
2315 ), 2309 ),
2316 container_name: None, 2310 name: "S1",
2317 description: Some( 2311 kind: STRUCT,
2318 "struct S1", 2312 container_name: None,
2319 ), 2313 description: Some(
2320 docs: None, 2314 "struct S1",
2321 }, 2315 ),
2322 }, 2316 docs: None,
2323 HoverGotoTypeData { 2317 },
2324 mod_path: "test::S2", 2318 },
2325 nav: NavigationTarget { 2319 HoverGotoTypeData {
2326 file_id: FileId( 2320 mod_path: "S2",
2327 1, 2321 nav: NavigationTarget {
2328 ), 2322 file_id: FileId(
2329 full_range: 45..57, 2323 1,
2330 name: "S2", 2324 ),
2331 kind: STRUCT_DEF, 2325 full_range: 45..57,
2332 focus_range: Some( 2326 focus_range: Some(
2333 52..54, 2327 52..54,
2334 ), 2328 ),
2335 container_name: None, 2329 name: "S2",
2336 description: Some( 2330 kind: STRUCT,
2337 "struct S2", 2331 container_name: None,
2338 ), 2332 description: Some(
2339 docs: None, 2333 "struct S2",
2340 }, 2334 ),
2341 }, 2335 docs: None,
2342 ], 2336 },
2343 ), 2337 },
2344 ] 2338 ],
2345 "###); 2339 ),
2340 ]
2341 "#]],
2342 );
2346 } 2343 }
2347 2344
2348 #[test] 2345 #[test]
2349 fn test_hover_arg_impl_trait_has_goto_type_action() { 2346 fn test_hover_arg_impl_trait_has_goto_type_action() {
2350 let (_, actions) = check_hover_result( 2347 check_actions(
2351 " 2348 r#"
2352 //- /lib.rs 2349trait Foo {}
2353 trait Foo {} 2350fn foo(ar<|>g: &impl Foo) {}
2354 fn foo(ar<|>g: &impl Foo) {} 2351"#,
2355 ", 2352 expect![[r#"
2356 &["&impl Foo"],
2357 );
2358 assert_debug_snapshot!(actions,
2359 @r###"
2360 [
2361 GoToType(
2362 [ 2353 [
2363 HoverGotoTypeData { 2354 GoToType(
2364 mod_path: "test::Foo", 2355 [
2365 nav: NavigationTarget { 2356 HoverGotoTypeData {
2366 file_id: FileId( 2357 mod_path: "Foo",
2367 1, 2358 nav: NavigationTarget {
2368 ), 2359 file_id: FileId(
2369 full_range: 0..12, 2360 1,
2370 name: "Foo", 2361 ),
2371 kind: TRAIT_DEF, 2362 full_range: 0..12,
2372 focus_range: Some( 2363 focus_range: Some(
2373 6..9, 2364 6..9,
2374 ), 2365 ),
2375 container_name: None, 2366 name: "Foo",
2376 description: Some( 2367 kind: TRAIT,
2377 "trait Foo", 2368 container_name: None,
2378 ), 2369 description: Some(
2379 docs: None, 2370 "trait Foo",
2380 }, 2371 ),
2381 }, 2372 docs: None,
2382 ], 2373 },
2383 ), 2374 },
2384 ] 2375 ],
2385 "###); 2376 ),
2377 ]
2378 "#]],
2379 );
2386 } 2380 }
2387 2381
2388 #[test] 2382 #[test]
2389 fn test_hover_arg_impl_traits_has_goto_type_action() { 2383 fn test_hover_arg_impl_traits_has_goto_type_action() {
2390 let (_, actions) = check_hover_result( 2384 check_actions(
2391 " 2385 r#"
2392 //- /lib.rs 2386trait Foo {}
2393 trait Foo {} 2387trait Bar<T> {}
2394 trait Bar<T> {} 2388struct S{}
2395 struct S{}
2396 2389
2397 fn foo(ar<|>g: &impl Foo + Bar<S>) {} 2390fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2398 ", 2391"#,
2399 &["&impl Foo + Bar<S>"], 2392 expect![[r#"
2400 );
2401 assert_debug_snapshot!(actions,
2402 @r###"
2403 [
2404 GoToType(
2405 [ 2393 [
2406 HoverGotoTypeData { 2394 GoToType(
2407 mod_path: "test::Foo", 2395 [
2408 nav: NavigationTarget { 2396 HoverGotoTypeData {
2409 file_id: FileId( 2397 mod_path: "Foo",
2410 1, 2398 nav: NavigationTarget {
2411 ), 2399 file_id: FileId(
2412 full_range: 0..12, 2400 1,
2413 name: "Foo", 2401 ),
2414 kind: TRAIT_DEF, 2402 full_range: 0..12,
2415 focus_range: Some( 2403 focus_range: Some(
2416 6..9, 2404 6..9,
2417 ), 2405 ),
2418 container_name: None, 2406 name: "Foo",
2419 description: Some( 2407 kind: TRAIT,
2420 "trait Foo", 2408 container_name: None,
2421 ), 2409 description: Some(
2422 docs: None, 2410 "trait Foo",
2423 }, 2411 ),
2424 }, 2412 docs: None,
2425 HoverGotoTypeData { 2413 },
2426 mod_path: "test::Bar", 2414 },
2427 nav: NavigationTarget { 2415 HoverGotoTypeData {
2428 file_id: FileId( 2416 mod_path: "Bar",
2429 1, 2417 nav: NavigationTarget {
2430 ), 2418 file_id: FileId(
2431 full_range: 13..28, 2419 1,
2432 name: "Bar", 2420 ),
2433 kind: TRAIT_DEF, 2421 full_range: 13..28,
2434 focus_range: Some( 2422 focus_range: Some(
2435 19..22, 2423 19..22,
2436 ), 2424 ),
2437 container_name: None, 2425 name: "Bar",
2438 description: Some( 2426 kind: TRAIT,
2439 "trait Bar", 2427 container_name: None,
2440 ), 2428 description: Some(
2441 docs: None, 2429 "trait Bar",
2442 }, 2430 ),
2443 }, 2431 docs: None,
2444 HoverGotoTypeData { 2432 },
2445 mod_path: "test::S", 2433 },
2446 nav: NavigationTarget { 2434 HoverGotoTypeData {
2447 file_id: FileId( 2435 mod_path: "S",
2448 1, 2436 nav: NavigationTarget {
2449 ), 2437 file_id: FileId(
2450 full_range: 29..39, 2438 1,
2451 name: "S", 2439 ),
2452 kind: STRUCT_DEF, 2440 full_range: 29..39,
2453 focus_range: Some( 2441 focus_range: Some(
2454 36..37, 2442 36..37,
2455 ), 2443 ),
2456 container_name: None, 2444 name: "S",
2457 description: Some( 2445 kind: STRUCT,
2458 "struct S", 2446 container_name: None,
2459 ), 2447 description: Some(
2460 docs: None, 2448 "struct S",
2461 }, 2449 ),
2462 }, 2450 docs: None,
2463 ], 2451 },
2464 ), 2452 },
2465 ] 2453 ],
2466 "###); 2454 ),
2455 ]
2456 "#]],
2457 );
2467 } 2458 }
2468 2459
2469 #[test] 2460 #[test]
2470 fn test_hover_arg_generic_impl_trait_has_goto_type_action() { 2461 fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2471 let (_, actions) = check_hover_result( 2462 check_actions(
2472 " 2463 r#"
2473 //- /lib.rs 2464trait Foo<T> {}
2474 trait Foo<T> {} 2465struct S {}
2475 struct S {} 2466fn foo(ar<|>g: &impl Foo<S>) {}
2476 fn foo(ar<|>g: &impl Foo<S>) {} 2467"#,
2477 ", 2468 expect![[r#"
2478 &["&impl Foo<S>"],
2479 );
2480 assert_debug_snapshot!(actions,
2481 @r###"
2482 [
2483 GoToType(
2484 [ 2469 [
2485 HoverGotoTypeData { 2470 GoToType(
2486 mod_path: "test::Foo", 2471 [
2487 nav: NavigationTarget { 2472 HoverGotoTypeData {
2488 file_id: FileId( 2473 mod_path: "Foo",
2489 1, 2474 nav: NavigationTarget {
2490 ), 2475 file_id: FileId(
2491 full_range: 0..15, 2476 1,
2492 name: "Foo", 2477 ),
2493 kind: TRAIT_DEF, 2478 full_range: 0..15,
2494 focus_range: Some( 2479 focus_range: Some(
2495 6..9, 2480 6..9,
2496 ), 2481 ),
2497 container_name: None, 2482 name: "Foo",
2498 description: Some( 2483 kind: TRAIT,
2499 "trait Foo", 2484 container_name: None,
2500 ), 2485 description: Some(
2501 docs: None, 2486 "trait Foo",
2502 }, 2487 ),
2503 }, 2488 docs: None,
2504 HoverGotoTypeData { 2489 },
2505 mod_path: "test::S", 2490 },
2506 nav: NavigationTarget { 2491 HoverGotoTypeData {
2507 file_id: FileId( 2492 mod_path: "S",
2508 1, 2493 nav: NavigationTarget {
2509 ), 2494 file_id: FileId(
2510 full_range: 16..27, 2495 1,
2511 name: "S", 2496 ),
2512 kind: STRUCT_DEF, 2497 full_range: 16..27,
2513 focus_range: Some( 2498 focus_range: Some(
2514 23..24, 2499 23..24,
2515 ), 2500 ),
2516 container_name: None, 2501 name: "S",
2517 description: Some( 2502 kind: STRUCT,
2518 "struct S", 2503 container_name: None,
2519 ), 2504 description: Some(
2520 docs: None, 2505 "struct S",
2521 }, 2506 ),
2522 }, 2507 docs: None,
2523 ], 2508 },
2524 ), 2509 },
2525 ] 2510 ],
2526 "###); 2511 ),
2512 ]
2513 "#]],
2514 );
2527 } 2515 }
2528 2516
2529 #[test] 2517 #[test]
2530 fn test_hover_dyn_return_has_goto_type_action() { 2518 fn test_hover_dyn_return_has_goto_type_action() {
2531 let (_, actions) = check_hover_result( 2519 check_actions(
2532 " 2520 r#"
2533 //- /main.rs 2521trait Foo {}
2534 trait Foo {} 2522struct S;
2535 struct S; 2523impl Foo for S {}
2536 impl Foo for S {}
2537
2538 struct B<T>{}
2539 2524
2540 fn foo() -> B<dyn Foo> {} 2525struct B<T>{}
2526fn foo() -> B<dyn Foo> {}
2541 2527
2542 fn main() { 2528fn main() { let s<|>t = foo(); }
2543 let s<|>t = foo(); 2529"#,
2544 } 2530 expect![[r#"
2545 ",
2546 &["B<dyn Foo>"],
2547 );
2548 assert_debug_snapshot!(actions,
2549 @r###"
2550 [
2551 GoToType(
2552 [ 2531 [
2553 HoverGotoTypeData { 2532 GoToType(
2554 mod_path: "test::B", 2533 [
2555 nav: NavigationTarget { 2534 HoverGotoTypeData {
2556 file_id: FileId( 2535 mod_path: "B",
2557 1, 2536 nav: NavigationTarget {
2558 ), 2537 file_id: FileId(
2559 full_range: 42..55, 2538 1,
2560 name: "B", 2539 ),
2561 kind: STRUCT_DEF, 2540 full_range: 42..55,
2562 focus_range: Some( 2541 focus_range: Some(
2563 49..50, 2542 49..50,
2564 ), 2543 ),
2565 container_name: None, 2544 name: "B",
2566 description: Some( 2545 kind: STRUCT,
2567 "struct B", 2546 container_name: None,
2568 ), 2547 description: Some(
2569 docs: None, 2548 "struct B",
2570 }, 2549 ),
2571 }, 2550 docs: None,
2572 HoverGotoTypeData { 2551 },
2573 mod_path: "test::Foo", 2552 },
2574 nav: NavigationTarget { 2553 HoverGotoTypeData {
2575 file_id: FileId( 2554 mod_path: "Foo",
2576 1, 2555 nav: NavigationTarget {
2577 ), 2556 file_id: FileId(
2578 full_range: 0..12, 2557 1,
2579 name: "Foo", 2558 ),
2580 kind: TRAIT_DEF, 2559 full_range: 0..12,
2581 focus_range: Some( 2560 focus_range: Some(
2582 6..9, 2561 6..9,
2583 ), 2562 ),
2584 container_name: None, 2563 name: "Foo",
2585 description: Some( 2564 kind: TRAIT,
2586 "trait Foo", 2565 container_name: None,
2587 ), 2566 description: Some(
2588 docs: None, 2567 "trait Foo",
2589 }, 2568 ),
2590 }, 2569 docs: None,
2591 ], 2570 },
2592 ), 2571 },
2593 ] 2572 ],
2594 "###); 2573 ),
2574 ]
2575 "#]],
2576 );
2595 } 2577 }
2596 2578
2597 #[test] 2579 #[test]
2598 fn test_hover_dyn_arg_has_goto_type_action() { 2580 fn test_hover_dyn_arg_has_goto_type_action() {
2599 let (_, actions) = check_hover_result( 2581 check_actions(
2600 " 2582 r#"
2601 //- /lib.rs 2583trait Foo {}
2602 trait Foo {} 2584fn foo(ar<|>g: &dyn Foo) {}
2603 fn foo(ar<|>g: &dyn Foo) {} 2585"#,
2604 ", 2586 expect![[r#"
2605 &["&dyn Foo"],
2606 );
2607 assert_debug_snapshot!(actions,
2608 @r###"
2609 [
2610 GoToType(
2611 [ 2587 [
2612 HoverGotoTypeData { 2588 GoToType(
2613 mod_path: "test::Foo", 2589 [
2614 nav: NavigationTarget { 2590 HoverGotoTypeData {
2615 file_id: FileId( 2591 mod_path: "Foo",
2616 1, 2592 nav: NavigationTarget {
2617 ), 2593 file_id: FileId(
2618 full_range: 0..12, 2594 1,
2619 name: "Foo", 2595 ),
2620 kind: TRAIT_DEF, 2596 full_range: 0..12,
2621 focus_range: Some( 2597 focus_range: Some(
2622 6..9, 2598 6..9,
2623 ), 2599 ),
2624 container_name: None, 2600 name: "Foo",
2625 description: Some( 2601 kind: TRAIT,
2626 "trait Foo", 2602 container_name: None,
2627 ), 2603 description: Some(
2628 docs: None, 2604 "trait Foo",
2629 }, 2605 ),
2630 }, 2606 docs: None,
2631 ], 2607 },
2632 ), 2608 },
2633 ] 2609 ],
2634 "###); 2610 ),
2611 ]
2612 "#]],
2613 );
2635 } 2614 }
2636 2615
2637 #[test] 2616 #[test]
2638 fn test_hover_generic_dyn_arg_has_goto_type_action() { 2617 fn test_hover_generic_dyn_arg_has_goto_type_action() {
2639 let (_, actions) = check_hover_result( 2618 check_actions(
2640 " 2619 r#"
2641 //- /lib.rs 2620trait Foo<T> {}
2642 trait Foo<T> {} 2621struct S {}
2643 struct S {} 2622fn foo(ar<|>g: &dyn Foo<S>) {}
2644 fn foo(ar<|>g: &dyn Foo<S>) {} 2623"#,
2645 ", 2624 expect![[r#"
2646 &["&dyn Foo<S>"],
2647 );
2648 assert_debug_snapshot!(actions,
2649 @r###"
2650 [
2651 GoToType(
2652 [ 2625 [
2653 HoverGotoTypeData { 2626 GoToType(
2654 mod_path: "test::Foo", 2627 [
2655 nav: NavigationTarget { 2628 HoverGotoTypeData {
2656 file_id: FileId( 2629 mod_path: "Foo",
2657 1, 2630 nav: NavigationTarget {
2658 ), 2631 file_id: FileId(
2659 full_range: 0..15, 2632 1,
2660 name: "Foo", 2633 ),
2661 kind: TRAIT_DEF, 2634 full_range: 0..15,
2662 focus_range: Some( 2635 focus_range: Some(
2663 6..9, 2636 6..9,
2664 ), 2637 ),
2665 container_name: None, 2638 name: "Foo",
2666 description: Some( 2639 kind: TRAIT,
2667 "trait Foo", 2640 container_name: None,
2668 ), 2641 description: Some(
2669 docs: None, 2642 "trait Foo",
2670 }, 2643 ),
2671 }, 2644 docs: None,
2672 HoverGotoTypeData { 2645 },
2673 mod_path: "test::S", 2646 },
2674 nav: NavigationTarget { 2647 HoverGotoTypeData {
2675 file_id: FileId( 2648 mod_path: "S",
2676 1, 2649 nav: NavigationTarget {
2677 ), 2650 file_id: FileId(
2678 full_range: 16..27, 2651 1,
2679 name: "S", 2652 ),
2680 kind: STRUCT_DEF, 2653 full_range: 16..27,
2681 focus_range: Some( 2654 focus_range: Some(
2682 23..24, 2655 23..24,
2683 ), 2656 ),
2684 container_name: None, 2657 name: "S",
2685 description: Some( 2658 kind: STRUCT,
2686 "struct S", 2659 container_name: None,
2687 ), 2660 description: Some(
2688 docs: None, 2661 "struct S",
2689 }, 2662 ),
2690 }, 2663 docs: None,
2691 ], 2664 },
2692 ), 2665 },
2693 ] 2666 ],
2694 "###); 2667 ),
2668 ]
2669 "#]],
2670 );
2695 } 2671 }
2696 2672
2697 #[test] 2673 #[test]
2698 fn test_hover_goto_type_action_links_order() { 2674 fn test_hover_goto_type_action_links_order() {
2699 let (_, actions) = check_hover_result( 2675 check_actions(
2700 " 2676 r#"
2701 //- /lib.rs 2677trait ImplTrait<T> {}
2702 trait ImplTrait<T> {} 2678trait DynTrait<T> {}
2703 trait DynTrait<T> {} 2679struct B<T> {}
2704 struct B<T> {} 2680struct S {}
2705 struct S {}
2706 2681
2707 fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} 2682fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
2708 ", 2683 "#,
2709 &["&impl ImplTrait<B<dyn DynTrait<B<S>>>>"], 2684 expect![[r#"
2710 );
2711 assert_debug_snapshot!(actions,
2712 @r###"
2713 [
2714 GoToType(
2715 [ 2685 [
2716 HoverGotoTypeData { 2686 GoToType(
2717 mod_path: "test::ImplTrait", 2687 [
2718 nav: NavigationTarget { 2688 HoverGotoTypeData {
2719 file_id: FileId( 2689 mod_path: "ImplTrait",
2720 1, 2690 nav: NavigationTarget {
2721 ), 2691 file_id: FileId(
2722 full_range: 0..21, 2692 1,
2723 name: "ImplTrait", 2693 ),
2724 kind: TRAIT_DEF, 2694 full_range: 0..21,
2725 focus_range: Some( 2695 focus_range: Some(
2726 6..15, 2696 6..15,
2727 ), 2697 ),
2728 container_name: None, 2698 name: "ImplTrait",
2729 description: Some( 2699 kind: TRAIT,
2730 "trait ImplTrait", 2700 container_name: None,
2731 ), 2701 description: Some(
2732 docs: None, 2702 "trait ImplTrait",
2733 }, 2703 ),
2734 }, 2704 docs: None,
2735 HoverGotoTypeData { 2705 },
2736 mod_path: "test::B", 2706 },
2737 nav: NavigationTarget { 2707 HoverGotoTypeData {
2738 file_id: FileId( 2708 mod_path: "B",
2739 1, 2709 nav: NavigationTarget {
2740 ), 2710 file_id: FileId(
2741 full_range: 43..57, 2711 1,
2742 name: "B", 2712 ),
2743 kind: STRUCT_DEF, 2713 full_range: 43..57,
2744 focus_range: Some( 2714 focus_range: Some(
2745 50..51, 2715 50..51,
2746 ), 2716 ),
2747 container_name: None, 2717 name: "B",
2748 description: Some( 2718 kind: STRUCT,
2749 "struct B", 2719 container_name: None,
2750 ), 2720 description: Some(
2751 docs: None, 2721 "struct B",
2752 }, 2722 ),
2753 }, 2723 docs: None,
2754 HoverGotoTypeData { 2724 },
2755 mod_path: "test::DynTrait", 2725 },
2756 nav: NavigationTarget { 2726 HoverGotoTypeData {
2757 file_id: FileId( 2727 mod_path: "DynTrait",
2758 1, 2728 nav: NavigationTarget {
2759 ), 2729 file_id: FileId(
2760 full_range: 22..42, 2730 1,
2761 name: "DynTrait", 2731 ),
2762 kind: TRAIT_DEF, 2732 full_range: 22..42,
2763 focus_range: Some( 2733 focus_range: Some(
2764 28..36, 2734 28..36,
2765 ), 2735 ),
2766 container_name: None, 2736 name: "DynTrait",
2767 description: Some( 2737 kind: TRAIT,
2768 "trait DynTrait", 2738 container_name: None,
2769 ), 2739 description: Some(
2770 docs: None, 2740 "trait DynTrait",
2771 }, 2741 ),
2772 }, 2742 docs: None,
2773 HoverGotoTypeData { 2743 },
2774 mod_path: "test::S", 2744 },
2775 nav: NavigationTarget { 2745 HoverGotoTypeData {
2776 file_id: FileId( 2746 mod_path: "S",
2777 1, 2747 nav: NavigationTarget {
2778 ), 2748 file_id: FileId(
2779 full_range: 58..69, 2749 1,
2780 name: "S", 2750 ),
2781 kind: STRUCT_DEF, 2751 full_range: 58..69,
2782 focus_range: Some( 2752 focus_range: Some(
2783 65..66, 2753 65..66,
2784 ), 2754 ),
2785 container_name: None, 2755 name: "S",
2786 description: Some( 2756 kind: STRUCT,
2787 "struct S", 2757 container_name: None,
2788 ), 2758 description: Some(
2789 docs: None, 2759 "struct S",
2790 }, 2760 ),
2791 }, 2761 docs: None,
2792 ], 2762 },
2793 ), 2763 },
2794 ] 2764 ],
2795 "###); 2765 ),
2766 ]
2767 "#]],
2768 );
2796 } 2769 }
2797 2770
2798 #[test] 2771 #[test]
2799 fn test_hover_associated_type_has_goto_type_action() { 2772 fn test_hover_associated_type_has_goto_type_action() {
2800 let (_, actions) = check_hover_result( 2773 check_actions(
2801 " 2774 r#"
2802 //- /main.rs 2775trait Foo {
2803 trait Foo { 2776 type Item;
2804 type Item; 2777 fn get(self) -> Self::Item {}
2805 fn get(self) -> Self::Item {} 2778}
2806 }
2807 2779
2808 struct Bar{} 2780struct Bar{}
2809 struct S{} 2781struct S{}
2810 2782
2811 impl Foo for S{ 2783impl Foo for S { type Item = Bar; }
2812 type Item = Bar;
2813 }
2814 2784
2815 fn test() -> impl Foo { 2785fn test() -> impl Foo { S {} }
2816 S{}
2817 }
2818 2786
2819 fn main() { 2787fn main() { let s<|>t = test().get(); }
2820 let s<|>t = test().get(); 2788"#,
2821 } 2789 expect![[r#"
2822 ",
2823 &["Foo::Item<impl Foo>"],
2824 );
2825 assert_debug_snapshot!(actions,
2826 @r###"
2827 [
2828 GoToType(
2829 [ 2790 [
2830 HoverGotoTypeData { 2791 GoToType(
2831 mod_path: "test::Foo", 2792 [
2832 nav: NavigationTarget { 2793 HoverGotoTypeData {
2833 file_id: FileId( 2794 mod_path: "Foo",
2834 1, 2795 nav: NavigationTarget {
2835 ), 2796 file_id: FileId(
2836 full_range: 0..62, 2797 1,
2837 name: "Foo", 2798 ),
2838 kind: TRAIT_DEF, 2799 full_range: 0..62,
2839 focus_range: Some( 2800 focus_range: Some(
2840 6..9, 2801 6..9,
2841 ), 2802 ),
2842 container_name: None, 2803 name: "Foo",
2843 description: Some( 2804 kind: TRAIT,
2844 "trait Foo", 2805 container_name: None,
2845 ), 2806 description: Some(
2846 docs: None, 2807 "trait Foo",
2847 }, 2808 ),
2848 }, 2809 docs: None,
2849 ], 2810 },
2850 ), 2811 },
2851 ] 2812 ],
2852 "###); 2813 ),
2814 ]
2815 "#]],
2816 );
2853 } 2817 }
2854} 2818}