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.rs3400
1 files changed, 1687 insertions, 1713 deletions
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index eaba2b61e..d067c339d 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -1,5 +1,3 @@
1use std::iter::once;
2
3use hir::{ 1use hir::{
4 Adt, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, HirDisplay, 2 Adt, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, HirDisplay,
5 Module, ModuleDef, ModuleSource, Semantics, 3 Module, ModuleDef, ModuleSource, Semantics,
@@ -10,16 +8,16 @@ use ra_ide_db::{
10 defs::{classify_name, classify_name_ref, Definition}, 8 defs::{classify_name, classify_name_ref, Definition},
11 RootDatabase, 9 RootDatabase,
12}; 10};
13use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; 11use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
12use stdx::format_to;
13use test_utils::mark;
14 14
15use crate::{ 15use crate::{
16 display::{ 16 display::{macro_label, ShortLabel, ToNav, TryToNav},
17 macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav, 17 markup::Markup,
18 },
19 runnables::runnable, 18 runnables::runnable,
20 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, 19 FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
21}; 20};
22use test_utils::mark;
23 21
24#[derive(Clone, Debug, PartialEq, Eq)] 22#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct HoverConfig { 23pub struct HoverConfig {
@@ -68,50 +66,8 @@ pub struct HoverGotoTypeData {
68/// Contains the results when hovering over an item 66/// Contains the results when hovering over an item
69#[derive(Debug, Default)] 67#[derive(Debug, Default)]
70pub struct HoverResult { 68pub struct HoverResult {
71 results: Vec<String>, 69 pub markup: Markup,
72 actions: Vec<HoverAction>, 70 pub actions: Vec<HoverAction>,
73}
74
75impl HoverResult {
76 pub fn new() -> HoverResult {
77 Self::default()
78 }
79
80 pub fn extend(&mut self, item: Option<String>) {
81 self.results.extend(item);
82 }
83
84 pub fn is_empty(&self) -> bool {
85 self.results.is_empty()
86 }
87
88 pub fn len(&self) -> usize {
89 self.results.len()
90 }
91
92 pub fn first(&self) -> Option<&str> {
93 self.results.first().map(String::as_str)
94 }
95
96 pub fn results(&self) -> &[String] {
97 &self.results
98 }
99
100 pub fn actions(&self) -> &[HoverAction] {
101 &self.actions
102 }
103
104 pub fn push_action(&mut self, action: HoverAction) {
105 self.actions.push(action);
106 }
107
108 /// Returns the results converted into markup
109 /// for displaying in a UI
110 ///
111 /// Does not process actions!
112 pub fn to_markup(&self) -> String {
113 self.results.join("\n\n___\n")
114 }
115} 71}
116 72
117// Feature: Hover 73// Feature: Hover
@@ -124,35 +80,32 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
124 let token = pick_best(file.token_at_offset(position.offset))?; 80 let token = pick_best(file.token_at_offset(position.offset))?;
125 let token = sema.descend_into_macros(token); 81 let token = sema.descend_into_macros(token);
126 82
127 let mut res = HoverResult::new(); 83 let mut res = HoverResult::default();
128 84
129 if let Some((node, name_kind)) = match_ast! { 85 let node = token.parent();
130 match (token.parent()) { 86 let definition = match_ast! {
131 ast::NameRef(name_ref) => { 87 match node {
132 classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d.definition())) 88 ast::NameRef(name_ref) => classify_name_ref(&sema, &name_ref).map(|d| d.definition()),
133 }, 89 ast::Name(name) => classify_name(&sema, &name).map(|d| d.definition()),
134 ast::Name(name) => {
135 classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition()))
136 },
137 _ => None, 90 _ => None,
138 } 91 }
139 } { 92 };
140 let range = sema.original_range(&node).range; 93 if let Some(definition) = definition {
141 res.extend(hover_text_from_name_kind(db, name_kind)); 94 if let Some(markup) = hover_for_definition(db, definition) {
142 95 res.markup = markup;
143 if !res.is_empty() { 96 if let Some(action) = show_implementations_action(db, definition) {
144 if let Some(action) = show_implementations_action(db, name_kind) { 97 res.actions.push(action);
145 res.push_action(action);
146 } 98 }
147 99
148 if let Some(action) = runnable_action(&sema, name_kind, position.file_id) { 100 if let Some(action) = runnable_action(&sema, definition, position.file_id) {
149 res.push_action(action); 101 res.actions.push(action);
150 } 102 }
151 103
152 if let Some(action) = goto_type_action(db, name_kind) { 104 if let Some(action) = goto_type_action(db, definition) {
153 res.push_action(action); 105 res.actions.push(action);
154 } 106 }
155 107
108 let range = sema.original_range(&node).range;
156 return Some(RangeInfo::new(range, res)); 109 return Some(RangeInfo::new(range, res));
157 } 110 }
158 } 111 }
@@ -163,22 +116,16 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
163 116
164 let ty = match_ast! { 117 let ty = match_ast! {
165 match node { 118 match node {
166 ast::MacroCall(_it) => { 119 ast::Expr(it) => sema.type_of_expr(&it)?,
167 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. 120 ast::Pat(it) => sema.type_of_pat(&it)?,
168 // (e.g expanding a builtin macro). So we give up here. 121 // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
169 return None; 122 // (e.g expanding a builtin macro). So we give up here.
170 }, 123 ast::MacroCall(_it) => return None,
171 ast::Expr(it) => { 124 _ => return None,
172 sema.type_of_expr(&it)
173 },
174 ast::Pat(it) => {
175 sema.type_of_pat(&it)
176 },
177 _ => None,
178 } 125 }
179 }?; 126 };
180 127
181 res.extend(Some(rust_code_markup(&ty.display(db)))); 128 res.markup = Markup::fenced_block(&ty.display(db));
182 let range = sema.original_range(&node).range; 129 let range = sema.original_range(&node).range;
183 Some(RangeInfo::new(range, res)) 130 Some(RangeInfo::new(range, res))
184} 131}
@@ -186,8 +133,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
186fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { 133fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
187 fn to_action(nav_target: NavigationTarget) -> HoverAction { 134 fn to_action(nav_target: NavigationTarget) -> HoverAction {
188 HoverAction::Implementaion(FilePosition { 135 HoverAction::Implementaion(FilePosition {
189 file_id: nav_target.file_id(), 136 file_id: nav_target.file_id,
190 offset: nav_target.range().start(), 137 offset: nav_target.focus_or_full_range().start(),
191 }) 138 })
192 } 139 }
193 140
@@ -259,7 +206,11 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
259 .into_iter() 206 .into_iter()
260 .filter_map(|it| { 207 .filter_map(|it| {
261 Some(HoverGotoTypeData { 208 Some(HoverGotoTypeData {
262 mod_path: mod_path(db, &it)?, 209 mod_path: render_path(
210 db,
211 it.module(db)?,
212 it.name(db).map(|name| name.to_string()),
213 ),
263 nav: it.try_to_nav(db)?, 214 nav: it.try_to_nav(db)?,
264 }) 215 })
265 }) 216 })
@@ -271,15 +222,28 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
271 } 222 }
272} 223}
273 224
274fn hover_text( 225fn hover_markup(
275 docs: Option<String>, 226 docs: Option<String>,
276 desc: Option<String>, 227 desc: Option<String>,
277 mod_path: Option<String>, 228 mod_path: Option<String>,
278) -> Option<String> { 229) -> Option<Markup> {
279 if let Some(desc) = desc { 230 match desc {
280 Some(rust_code_markup_with_doc(&desc, docs.as_deref(), mod_path.as_deref())) 231 Some(desc) => {
281 } else { 232 let mut buf = String::new();
282 docs 233
234 if let Some(mod_path) = mod_path {
235 if !mod_path.is_empty() {
236 format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
237 }
238 }
239 format_to!(buf, "```rust\n{}\n```", desc);
240
241 if let Some(doc) = docs {
242 format_to!(buf, "\n___\n\n{}", doc);
243 }
244 Some(buf.into())
245 }
246 None => docs.map(Markup::from),
283 } 247 }
284} 248}
285 249
@@ -301,43 +265,35 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
301 .map(|name| name.to_string()) 265 .map(|name| name.to_string())
302} 266}
303 267
304fn determine_mod_path(db: &RootDatabase, module: Module, name: Option<String>) -> String { 268fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
305 once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string)) 269 let crate_name =
306 .chain( 270 db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string);
307 module 271 let module_path = module
308 .path_to_root(db) 272 .path_to_root(db)
309 .into_iter() 273 .into_iter()
310 .rev() 274 .rev()
311 .map(|it| it.name(db).map(|name| name.to_string())), 275 .flat_map(|it| it.name(db).map(|name| name.to_string()));
312 ) 276 crate_name.into_iter().chain(module_path).chain(item_name).join("::")
313 .chain(once(name))
314 .flatten()
315 .join("::")
316}
317
318// returns None only for ModuleDef::BuiltinType
319fn mod_path(db: &RootDatabase, item: &ModuleDef) -> Option<String> {
320 Some(determine_mod_path(db, item.module(db)?, item.name(db).map(|name| name.to_string())))
321} 277}
322 278
323fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { 279fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
324 def.module(db).map(|module| determine_mod_path(db, module, definition_owner_name(db, def))) 280 def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
325} 281}
326 282
327fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { 283fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
328 let mod_path = definition_mod_path(db, &def); 284 let mod_path = definition_mod_path(db, &def);
329 return match def { 285 return match def {
330 Definition::Macro(it) => { 286 Definition::Macro(it) => {
331 let src = it.source(db); 287 let src = it.source(db);
332 let docs = Documentation::from_ast(&src.value).map(Into::into); 288 let docs = Documentation::from_ast(&src.value).map(Into::into);
333 hover_text(docs, Some(macro_label(&src.value)), mod_path) 289 hover_markup(docs, Some(macro_label(&src.value)), mod_path)
334 } 290 }
335 Definition::Field(it) => { 291 Definition::Field(it) => {
336 let src = it.source(db); 292 let src = it.source(db);
337 match src.value { 293 match src.value {
338 FieldSource::Named(it) => { 294 FieldSource::Named(it) => {
339 let docs = Documentation::from_ast(&it).map(Into::into); 295 let docs = Documentation::from_ast(&it).map(Into::into);
340 hover_text(docs, it.short_label(), mod_path) 296 hover_markup(docs, it.short_label(), mod_path)
341 } 297 }
342 _ => None, 298 _ => None,
343 } 299 }
@@ -346,7 +302,7 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
346 ModuleDef::Module(it) => match it.definition_source(db).value { 302 ModuleDef::Module(it) => match it.definition_source(db).value {
347 ModuleSource::Module(it) => { 303 ModuleSource::Module(it) => {
348 let docs = Documentation::from_ast(&it).map(Into::into); 304 let docs = Documentation::from_ast(&it).map(Into::into);
349 hover_text(docs, it.short_label(), mod_path) 305 hover_markup(docs, it.short_label(), mod_path)
350 } 306 }
351 _ => None, 307 _ => None,
352 }, 308 },
@@ -359,23 +315,23 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
359 ModuleDef::Static(it) => from_def_source(db, it, mod_path), 315 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
360 ModuleDef::Trait(it) => from_def_source(db, it, mod_path), 316 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
361 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 317 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
362 ModuleDef::BuiltinType(it) => Some(it.to_string()), 318 ModuleDef::BuiltinType(it) => return Some(it.to_string().into()),
363 }, 319 },
364 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display(db))), 320 Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))),
365 Definition::TypeParam(_) | Definition::SelfType(_) => { 321 Definition::TypeParam(_) | Definition::SelfType(_) => {
366 // FIXME: Hover for generic param 322 // FIXME: Hover for generic param
367 None 323 None
368 } 324 }
369 }; 325 };
370 326
371 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<String> 327 fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
372 where 328 where
373 D: HasSource<Ast = A>, 329 D: HasSource<Ast = A>,
374 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner, 330 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel + ast::AttrsOwner,
375 { 331 {
376 let src = def.source(db); 332 let src = def.source(db);
377 let docs = Documentation::from_ast(&src.value).map(Into::into); 333 let docs = Documentation::from_ast(&src.value).map(Into::into);
378 hover_text(docs, src.value.short_label(), mod_path) 334 hover_markup(docs, src.value.short_label(), mod_path)
379 } 335 }
380} 336}
381 337
@@ -384,7 +340,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
384 fn priority(n: &SyntaxToken) -> usize { 340 fn priority(n: &SyntaxToken) -> usize {
385 match n.kind() { 341 match n.kind() {
386 IDENT | INT_NUMBER => 3, 342 IDENT | INT_NUMBER => 3,
387 L_PAREN | R_PAREN => 2, 343 T!['('] | T![')'] => 2,
388 kind if kind.is_trivia() => 0, 344 kind if kind.is_trivia() => 0,
389 _ => 1, 345 _ => 1,
390 } 346 }
@@ -393,56 +349,38 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
393 349
394#[cfg(test)] 350#[cfg(test)]
395mod tests { 351mod tests {
396 use super::*; 352 use expect::{expect, Expect};
397 use insta::assert_debug_snapshot;
398
399 use ra_db::FileLoader; 353 use ra_db::FileLoader;
400 use ra_syntax::TextRange;
401 354
402 use crate::mock_analysis::analysis_and_position; 355 use crate::mock_analysis::analysis_and_position;
403 356
404 fn trim_markup(s: &str) -> &str { 357 use super::*;
405 s.trim_start_matches("```rust\n").trim_end_matches("\n```")
406 }
407
408 fn trim_markup_opt(s: Option<&str>) -> Option<&str> {
409 s.map(trim_markup)
410 }
411 358
412 fn assert_impl_action(action: &HoverAction, position: u32) { 359 fn check_hover_no_result(ra_fixture: &str) {
413 let offset = match action { 360 let (analysis, position) = analysis_and_position(ra_fixture);
414 HoverAction::Implementaion(pos) => pos.offset, 361 assert!(analysis.hover(position).unwrap().is_none());
415 it => panic!("Unexpected hover action: {:#?}", it),
416 };
417 assert_eq!(offset, position.into());
418 } 362 }
419 363
420 fn check_hover_result(ra_fixture: &str, expected: &[&str]) -> (String, Vec<HoverAction>) { 364 fn check(ra_fixture: &str, expect: Expect) {
421 let (analysis, position) = analysis_and_position(ra_fixture); 365 let (analysis, position) = analysis_and_position(ra_fixture);
422 let hover = analysis.hover(position).unwrap().unwrap(); 366 let hover = analysis.hover(position).unwrap().unwrap();
423 let mut results = Vec::from(hover.info.results());
424 results.sort();
425
426 for (markup, expected) in
427 results.iter().zip(expected.iter().chain(std::iter::repeat(&"<missing>")))
428 {
429 assert_eq!(trim_markup(&markup), *expected);
430 }
431
432 assert_eq!(hover.info.len(), expected.len());
433 367
434 let content = analysis.db.file_text(position.file_id); 368 let content = analysis.db.file_text(position.file_id);
435 (content[hover.range].to_string(), hover.info.actions().to_vec()) 369 let hovered_element = &content[hover.range];
370
371 let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
372 expect.assert_eq(&actual)
436 } 373 }
437 374
438 fn check_hover_no_result(ra_fixture: &str) { 375 fn check_actions(ra_fixture: &str, expect: Expect) {
439 let (analysis, position) = analysis_and_position(ra_fixture); 376 let (analysis, position) = analysis_and_position(ra_fixture);
440 assert!(analysis.hover(position).unwrap().is_none()); 377 let hover = analysis.hover(position).unwrap().unwrap();
378 expect.assert_debug_eq(&hover.info.actions)
441 } 379 }
442 380
443 #[test] 381 #[test]
444 fn hover_shows_type_of_an_expression() { 382 fn hover_shows_type_of_an_expression() {
445 let (analysis, position) = analysis_and_position( 383 check(
446 r#" 384 r#"
447pub fn foo() -> u32 { 1 } 385pub fn foo() -> u32 { 1 }
448 386
@@ -450,603 +388,643 @@ fn main() {
450 let foo_test = foo()<|>; 388 let foo_test = foo()<|>;
451} 389}
452"#, 390"#,
391 expect![[r#"
392 *foo()*
393 ```rust
394 u32
395 ```
396 "#]],
453 ); 397 );
454 let hover = analysis.hover(position).unwrap().unwrap();
455 assert_eq!(hover.range, TextRange::new(58.into(), 63.into()));
456 assert_eq!(trim_markup_opt(hover.info.first()), Some("u32"));
457 } 398 }
458 399
459 #[test] 400 #[test]
460 fn hover_shows_long_type_of_an_expression() { 401 fn hover_shows_long_type_of_an_expression() {
461 check_hover_result( 402 check(
462 r#" 403 r#"
463 //- /main.rs 404struct Scan<A, B, C> { a: A, b: B, c: C }
464 struct Scan<A, B, C> { 405struct Iter<I> { inner: I }
465 a: A, 406enum Option<T> { Some(T), None }
466 b: B,
467 c: C,
468 }
469 407
470 struct FakeIter<I> { 408struct OtherStruct<T> { i: T }
471 inner: I,
472 }
473
474 struct OtherStruct<T> {
475 i: T,
476 }
477 409
478 enum FakeOption<T> { 410fn scan<A, B, C>(a: A, b: B, c: C) -> Iter<Scan<OtherStruct<A>, B, C>> {
479 Some(T), 411 Iter { inner: Scan { a, b, c } }
480 None, 412}
481 }
482
483 fn scan<A, B, C>(a: A, b: B, c: C) -> FakeIter<Scan<OtherStruct<A>, B, C>> {
484 FakeIter { inner: Scan { a, b, c } }
485 }
486 413
487 fn main() { 414fn main() {
488 let num: i32 = 55; 415 let num: i32 = 55;
489 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> FakeOption<u32> { 416 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option<u32> {
490 FakeOption::Some(*memo + value) 417 Option::Some(*memo + value)
491 }; 418 };
492 let number = 5u32; 419 let number = 5u32;
493 let mut iter<|> = scan(OtherStruct { i: num }, closure, number); 420 let mut iter<|> = scan(OtherStruct { i: num }, closure, number);
494 } 421}
495 "#, 422"#,
496 &["FakeIter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> FakeOption<u32>, u32>>"], 423 expect![[r#"
424 *iter*
425 ```rust
426 Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
427 ```
428 "#]],
497 ); 429 );
498 } 430 }
499 431
500 #[test] 432 #[test]
501 fn hover_shows_fn_signature() { 433 fn hover_shows_fn_signature() {
502 // Single file with result 434 // Single file with result
503 check_hover_result( 435 check(
504 r#" 436 r#"
505 //- /main.rs 437pub fn foo() -> u32 { 1 }
506 pub fn foo() -> u32 { 1 }
507 438
508 fn main() { 439fn main() { let foo_test = fo<|>o(); }
509 let foo_test = fo<|>o(); 440"#,
510 } 441 expect![[r#"
511 "#, 442 *foo*
512 &["pub fn foo() -> u32"], 443 ```rust
444 pub fn foo() -> u32
445 ```
446 "#]],
513 ); 447 );
514 448
515 // Multiple candidates but results are ambiguous. 449 // Multiple candidates but results are ambiguous.
516 check_hover_result( 450 check(
517 r#" 451 r#"
518 //- /a.rs 452//- /a.rs
519 pub fn foo() -> u32 { 1 } 453pub fn foo() -> u32 { 1 }
520 454
521 //- /b.rs 455//- /b.rs
522 pub fn foo() -> &str { "" } 456pub fn foo() -> &str { "" }
523 457
524 //- /c.rs 458//- /c.rs
525 pub fn foo(a: u32, b: u32) {} 459pub fn foo(a: u32, b: u32) {}
526 460
527 //- /main.rs 461//- /main.rs
528 mod a; 462mod a;
529 mod b; 463mod b;
530 mod c; 464mod c;
531 465
532 fn main() { 466fn main() { let foo_test = fo<|>o(); }
533 let foo_test = fo<|>o();
534 }
535 "#, 467 "#,
536 &["{unknown}"], 468 expect![[r#"
469 *foo*
470 ```rust
471 {unknown}
472 ```
473 "#]],
537 ); 474 );
538 } 475 }
539 476
540 #[test] 477 #[test]
541 fn hover_shows_fn_signature_with_type_params() { 478 fn hover_shows_fn_signature_with_type_params() {
542 check_hover_result( 479 check(
543 r#" 480 r#"
544 //- /main.rs 481pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
545 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
546 482
547 fn main() { 483fn main() { let foo_test = fo<|>o(); }
548 let foo_test = fo<|>o();
549 }
550 "#, 484 "#,
551 &["pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str"], 485 expect![[r#"
486 *foo*
487 ```rust
488 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str
489 ```
490 "#]],
552 ); 491 );
553 } 492 }
554 493
555 #[test] 494 #[test]
556 fn hover_shows_fn_signature_on_fn_name() { 495 fn hover_shows_fn_signature_on_fn_name() {
557 check_hover_result( 496 check(
558 r#" 497 r#"
559 //- /main.rs 498pub fn foo<|>(a: u32, b: u32) -> u32 {}
560 pub fn foo<|>(a: u32, b: u32) -> u32 {}
561 499
562 fn main() { 500fn main() { }
563 } 501"#,
564 "#, 502 expect![[r#"
565 &["pub fn foo(a: u32, b: u32) -> u32"], 503 *foo*
504 ```rust
505 pub fn foo(a: u32, b: u32) -> u32
506 ```
507 "#]],
566 ); 508 );
567 } 509 }
568 510
569 #[test] 511 #[test]
570 fn hover_shows_struct_field_info() { 512 fn hover_shows_struct_field_info() {
571 // Hovering over the field when instantiating 513 // Hovering over the field when instantiating
572 check_hover_result( 514 check(
573 r#" 515 r#"
574 //- /main.rs 516struct Foo { field_a: u32 }
575 struct Foo {
576 field_a: u32,
577 }
578 517
579 fn main() { 518fn main() {
580 let foo = Foo { 519 let foo = Foo { field_a<|>: 0, };
581 field_a<|>: 0, 520}
582 }; 521"#,
583 } 522 expect![[r#"
584 "#, 523 *field_a*
585 &["Foo\n```\n\n```rust\nfield_a: u32"], 524 ```rust
525 Foo
526 ```
527
528 ```rust
529 field_a: u32
530 ```
531 "#]],
586 ); 532 );
587 533
588 // Hovering over the field in the definition 534 // Hovering over the field in the definition
589 check_hover_result( 535 check(
590 r#" 536 r#"
591 //- /main.rs 537struct Foo { field_a<|>: u32 }
592 struct Foo {
593 field_a<|>: u32,
594 }
595 538
596 fn main() { 539fn main() {
597 let foo = Foo { 540 let foo = Foo { field_a: 0 };
598 field_a: 0, 541}
599 }; 542"#,
600 } 543 expect![[r#"
601 "#, 544 *field_a*
602 &["Foo\n```\n\n```rust\nfield_a: u32"], 545 ```rust
546 Foo
547 ```
548
549 ```rust
550 field_a: u32
551 ```
552 "#]],
603 ); 553 );
604 } 554 }
605 555
606 #[test] 556 #[test]
607 fn hover_const_static() { 557 fn hover_const_static() {
608 check_hover_result( 558 check(
609 r#" 559 r#"const foo<|>: u32 = 0;"#,
610 //- /main.rs 560 expect![[r#"
611 const foo<|>: u32 = 0; 561 *foo*
612 "#, 562 ```rust
613 &["const foo: u32"], 563 const foo: u32
614 ); 564 ```
615 565 "#]],
616 check_hover_result( 566 );
617 r#" 567 check(
618 //- /main.rs 568 r#"static foo<|>: u32 = 0;"#,
619 static foo<|>: u32 = 0; 569 expect![[r#"
620 "#, 570 *foo*
621 &["static foo: u32"], 571 ```rust
572 static foo: u32
573 ```
574 "#]],
622 ); 575 );
623 } 576 }
624 577
625 #[test] 578 #[test]
626 fn hover_default_generic_types() { 579 fn hover_default_generic_types() {
627 check_hover_result( 580 check(
628 r#" 581 r#"
629//- /main.rs 582struct Test<K, T = u8> { k: K, t: T }
630struct Test<K, T = u8> {
631 k: K,
632 t: T,
633}
634 583
635fn main() { 584fn main() {
636 let zz<|> = Test { t: 23u8, k: 33 }; 585 let zz<|> = Test { t: 23u8, k: 33 };
637}"#, 586}"#,
638 &["Test<i32, u8>"], 587 expect![[r#"
588 *zz*
589 ```rust
590 Test<i32, u8>
591 ```
592 "#]],
639 ); 593 );
640 } 594 }
641 595
642 #[test] 596 #[test]
643 fn hover_some() { 597 fn hover_some() {
644 let (analysis, position) = analysis_and_position( 598 check(
645 " 599 r#"
646 enum Option<T> { Some(T) } 600enum Option<T> { Some(T) }
647 use Option::Some; 601use Option::Some;
648 602
649 fn main() { 603fn main() { So<|>me(12); }
650 So<|>me(12); 604"#,
651 } 605 expect![[r#"
652 ", 606 *Some*
607 ```rust
608 Option
609 ```
610
611 ```rust
612 Some
613 ```
614 "#]],
653 ); 615 );
654 let hover = analysis.hover(position).unwrap().unwrap();
655 assert_eq!(trim_markup_opt(hover.info.first()), Some("Option\n```\n\n```rust\nSome"));
656 616
657 let (analysis, position) = analysis_and_position( 617 check(
658 " 618 r#"
659 enum Option<T> { Some(T) } 619enum Option<T> { Some(T) }
660 use Option::Some; 620use Option::Some;
661 621
662 fn main() { 622fn main() { let b<|>ar = Some(12); }
663 let b<|>ar = Some(12); 623"#,
664 } 624 expect![[r#"
665 ", 625 *bar*
626 ```rust
627 Option<i32>
628 ```
629 "#]],
666 ); 630 );
667 let hover = analysis.hover(position).unwrap().unwrap();
668 assert_eq!(trim_markup_opt(hover.info.first()), Some("Option<i32>"));
669 } 631 }
670 632
671 #[test] 633 #[test]
672 fn hover_enum_variant() { 634 fn hover_enum_variant() {
673 check_hover_result( 635 check(
674 r#" 636 r#"
675 //- /main.rs 637enum Option<T> {
676 enum Option<T> { 638 /// The None variant
677 /// The None variant 639 Non<|>e
678 Non<|>e 640}
679 } 641"#,
680 "#, 642 expect![[r#"
681 &[" 643 *None*
682Option 644 ```rust
683``` 645 Option
646 ```
684 647
685```rust 648 ```rust
686None 649 None
687``` 650 ```
688___ 651 ___
689 652
690The None variant 653 The None variant
691 " 654 "#]],
692 .trim()],
693 ); 655 );
694 656
695 check_hover_result( 657 check(
696 r#" 658 r#"
697 //- /main.rs 659enum Option<T> {
698 enum Option<T> { 660 /// The Some variant
699 /// The Some variant 661 Some(T)
700 Some(T) 662}
701 } 663fn main() {
702 fn main() { 664 let s = Option::Som<|>e(12);
703 let s = Option::Som<|>e(12); 665}
704 } 666"#,
705 "#, 667 expect![[r#"
706 &[" 668 *Some*
707Option 669 ```rust
708``` 670 Option
671 ```
709 672
710```rust 673 ```rust
711Some 674 Some
712``` 675 ```
713___ 676 ___
714 677
715The Some variant 678 The Some variant
716 " 679 "#]],
717 .trim()],
718 ); 680 );
719 } 681 }
720 682
721 #[test] 683 #[test]
722 fn hover_for_local_variable() { 684 fn hover_for_local_variable() {
723 let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); 685 check(
724 let hover = analysis.hover(position).unwrap().unwrap(); 686 r#"fn func(foo: i32) { fo<|>o; }"#,
725 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); 687 expect![[r#"
688 *foo*
689 ```rust
690 i32
691 ```
692 "#]],
693 )
726 } 694 }
727 695
728 #[test] 696 #[test]
729 fn hover_for_local_variable_pat() { 697 fn hover_for_local_variable_pat() {
730 let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); 698 check(
731 let hover = analysis.hover(position).unwrap().unwrap(); 699 r#"fn func(fo<|>o: i32) {}"#,
732 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); 700 expect![[r#"
701 *foo*
702 ```rust
703 i32
704 ```
705 "#]],
706 )
733 } 707 }
734 708
735 #[test] 709 #[test]
736 fn hover_local_var_edge() { 710 fn hover_local_var_edge() {
737 let (analysis, position) = analysis_and_position( 711 check(
738 " 712 r#"fn func(foo: i32) { if true { <|>foo; }; }"#,
739fn func(foo: i32) { if true { <|>foo; }; } 713 expect![[r#"
740", 714 *foo*
741 ); 715 ```rust
742 let hover = analysis.hover(position).unwrap().unwrap(); 716 i32
743 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); 717 ```
718 "#]],
719 )
744 } 720 }
745 721
746 #[test] 722 #[test]
747 fn hover_for_param_edge() { 723 fn hover_for_param_edge() {
748 let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); 724 check(
749 let hover = analysis.hover(position).unwrap().unwrap(); 725 r#"fn func(<|>foo: i32) {}"#,
750 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); 726 expect![[r#"
727 *foo*
728 ```rust
729 i32
730 ```
731 "#]],
732 )
751 } 733 }
752 734
753 #[test] 735 #[test]
754 fn test_hover_infer_associated_method_result() { 736 fn test_hover_infer_associated_method_result() {
755 let (analysis, position) = analysis_and_position( 737 check(
756 " 738 r#"
757 struct Thing { x: u32 } 739struct Thing { x: u32 }
758 740
759 impl Thing { 741impl Thing {
760 fn new() -> Thing { 742 fn new() -> Thing { Thing { x: 0 } }
761 Thing { x: 0 } 743}
762 }
763 }
764 744
765 fn main() { 745fn main() { let foo_<|>test = Thing::new(); }
766 let foo_<|>test = Thing::new(); 746 "#,
767 } 747 expect![[r#"
768 ", 748 *foo_test*
769 ); 749 ```rust
770 let hover = analysis.hover(position).unwrap().unwrap(); 750 Thing
771 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); 751 ```
752 "#]],
753 )
772 } 754 }
773 755
774 #[test] 756 #[test]
775 fn test_hover_infer_associated_method_exact() { 757 fn test_hover_infer_associated_method_exact() {
776 let (analysis, position) = analysis_and_position( 758 check(
777 " 759 r#"
778 mod wrapper { 760mod wrapper {
779 struct Thing { x: u32 } 761 struct Thing { x: u32 }
780 762
781 impl Thing { 763 impl Thing {
782 fn new() -> Thing { 764 fn new() -> Thing { Thing { x: 0 } }
783 Thing { x: 0 } 765 }
784 } 766}
785 }
786 }
787 767
788 fn main() { 768fn main() { let foo_test = wrapper::Thing::new<|>(); }
789 let foo_test = wrapper::Thing::new<|>(); 769"#,
790 } 770 expect![[r#"
791 ", 771 *new*
792 ); 772 ```rust
793 let hover = analysis.hover(position).unwrap().unwrap(); 773 wrapper::Thing
794 assert_eq!( 774 ```
795 trim_markup_opt(hover.info.first()), 775
796 Some("wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") 776 ```rust
797 ); 777 fn new() -> Thing
778 ```
779 "#]],
780 )
798 } 781 }
799 782
800 #[test] 783 #[test]
801 fn test_hover_infer_associated_const_in_pattern() { 784 fn test_hover_infer_associated_const_in_pattern() {
802 let (analysis, position) = analysis_and_position( 785 check(
803 " 786 r#"
804 struct X; 787struct X;
805 impl X { 788impl X {
806 const C: u32 = 1; 789 const C: u32 = 1;
807 } 790}
808 791
809 fn main() { 792fn main() {
810 match 1 { 793 match 1 {
811 X::C<|> => {}, 794 X::C<|> => {},
812 2 => {}, 795 2 => {},
813 _ => {} 796 _ => {}
814 }; 797 };
815 } 798}
816 ", 799"#,
817 ); 800 expect![[r#"
818 let hover = analysis.hover(position).unwrap().unwrap(); 801 *C*
819 assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); 802 ```rust
803 const C: u32
804 ```
805 "#]],
806 )
820 } 807 }
821 808
822 #[test] 809 #[test]
823 fn test_hover_self() { 810 fn test_hover_self() {
824 let (analysis, position) = analysis_and_position( 811 check(
825 " 812 r#"
826 struct Thing { x: u32 } 813struct Thing { x: u32 }
827 impl Thing { 814impl Thing {
828 fn new() -> Self { 815 fn new() -> Self { Self<|> { x: 0 } }
829 Self<|> { x: 0 } 816}
830 } 817"#,
831 } 818 expect![[r#"
832 ", 819 *Self { x: 0 }*
833 ); 820 ```rust
834 let hover = analysis.hover(position).unwrap().unwrap(); 821 Thing
835 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); 822 ```
836 823 "#]],
837 /* FIXME: revive these tests 824 )
838 let (analysis, position) = analysis_and_position( 825 } /* FIXME: revive these tests
839 " 826 let (analysis, position) = analysis_and_position(
840 struct Thing { x: u32 } 827 "
841 impl Thing { 828 struct Thing { x: u32 }
842 fn new() -> Self<|> { 829 impl Thing {
843 Self { x: 0 } 830 fn new() -> Self<|> {
844 } 831 Self { x: 0 }
845 } 832 }
846 ", 833 }
847 ); 834 ",
848 835 );
849 let hover = analysis.hover(position).unwrap().unwrap(); 836
850 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); 837 let hover = analysis.hover(position).unwrap().unwrap();
851 838 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing"));
852 let (analysis, position) = analysis_and_position( 839
853 " 840 let (analysis, position) = analysis_and_position(
854 enum Thing { A } 841 "
855 impl Thing { 842 enum Thing { A }
856 pub fn new() -> Self<|> { 843 impl Thing {
857 Thing::A 844 pub fn new() -> Self<|> {
858 } 845 Thing::A
859 } 846 }
860 ", 847 }
861 ); 848 ",
862 let hover = analysis.hover(position).unwrap().unwrap(); 849 );
863 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); 850 let hover = analysis.hover(position).unwrap().unwrap();
864 851 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
865 let (analysis, position) = analysis_and_position( 852
866 " 853 let (analysis, position) = analysis_and_position(
867 enum Thing { A } 854 "
868 impl Thing { 855 enum Thing { A }
869 pub fn thing(a: Self<|>) { 856 impl Thing {
870 } 857 pub fn thing(a: Self<|>) {
871 } 858 }
872 ", 859 }
873 ); 860 ",
874 let hover = analysis.hover(position).unwrap().unwrap(); 861 );
875 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); 862 let hover = analysis.hover(position).unwrap().unwrap();
876 */ 863 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
877 } 864 */
878 865
879 #[test] 866 #[test]
880 fn test_hover_shadowing_pat() { 867 fn test_hover_shadowing_pat() {
881 let (analysis, position) = analysis_and_position( 868 check(
882 " 869 r#"
883 fn x() {} 870fn x() {}
884 871
885 fn y() { 872fn y() {
886 let x = 0i32; 873 let x = 0i32;
887 x<|>; 874 x<|>;
888 } 875}
889 ", 876"#,
890 ); 877 expect![[r#"
891 let hover = analysis.hover(position).unwrap().unwrap(); 878 *x*
892 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); 879 ```rust
880 i32
881 ```
882 "#]],
883 )
893 } 884 }
894 885
895 #[test] 886 #[test]
896 fn test_hover_macro_invocation() { 887 fn test_hover_macro_invocation() {
897 let (analysis, position) = analysis_and_position( 888 check(
898 " 889 r#"
899 macro_rules! foo { 890macro_rules! foo { () => {} }
900 () => {}
901 }
902 891
903 fn f() { 892fn f() { fo<|>o!(); }
904 fo<|>o!(); 893"#,
905 } 894 expect![[r#"
906 ", 895 *foo*
907 ); 896 ```rust
908 let hover = analysis.hover(position).unwrap().unwrap(); 897 macro_rules! foo
909 assert_eq!(trim_markup_opt(hover.info.first()), Some("macro_rules! foo")); 898 ```
899 "#]],
900 )
910 } 901 }
911 902
912 #[test] 903 #[test]
913 fn test_hover_tuple_field() { 904 fn test_hover_tuple_field() {
914 let (analysis, position) = analysis_and_position( 905 check(
915 " 906 r#"struct TS(String, i32<|>);"#,
916 struct TS(String, i32<|>); 907 expect![[r#"
917 ", 908 *i32*
918 ); 909 i32
919 let hover = analysis.hover(position).unwrap().unwrap(); 910 "#]],
920 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); 911 )
921 } 912 }
922 913
923 #[test] 914 #[test]
924 fn test_hover_through_macro() { 915 fn test_hover_through_macro() {
925 let (hover_on, _) = check_hover_result( 916 check(
926 r" 917 r#"
927 //- /lib.rs 918macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
928 macro_rules! id { 919fn foo() {}
929 ($($tt:tt)*) => { $($tt)* } 920id! {
930 } 921 fn bar() { fo<|>o(); }
931 fn foo() {} 922}
932 id! { 923"#,
933 fn bar() { 924 expect![[r#"
934 fo<|>o(); 925 *foo*
935 } 926 ```rust
936 } 927 fn foo()
937 ", 928 ```
938 &["fn foo()"], 929 "#]],
939 ); 930 );
940
941 assert_eq!(hover_on, "foo")
942 } 931 }
943 932
944 #[test] 933 #[test]
945 fn test_hover_through_expr_in_macro() { 934 fn test_hover_through_expr_in_macro() {
946 let (hover_on, _) = check_hover_result( 935 check(
947 r" 936 r#"
948 //- /lib.rs 937macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
949 macro_rules! id { 938fn foo(bar:u32) { let a = id!(ba<|>r); }
950 ($($tt:tt)*) => { $($tt)* } 939"#,
951 } 940 expect![[r#"
952 fn foo(bar:u32) { 941 *bar*
953 let a = id!(ba<|>r); 942 ```rust
954 } 943 u32
955 ", 944 ```
956 &["u32"], 945 "#]],
957 ); 946 );
958
959 assert_eq!(hover_on, "bar")
960 } 947 }
961 948
962 #[test] 949 #[test]
963 fn test_hover_through_expr_in_macro_recursive() { 950 fn test_hover_through_expr_in_macro_recursive() {
964 let (hover_on, _) = check_hover_result( 951 check(
965 r" 952 r#"
966 //- /lib.rs 953macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
967 macro_rules! id_deep { 954macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
968 ($($tt:tt)*) => { $($tt)* } 955fn foo(bar:u32) { let a = id!(ba<|>r); }
969 } 956"#,
970 macro_rules! id { 957 expect![[r#"
971 ($($tt:tt)*) => { id_deep!($($tt)*) } 958 *bar*
972 } 959 ```rust
973 fn foo(bar:u32) { 960 u32
974 let a = id!(ba<|>r); 961 ```
975 } 962 "#]],
976 ",
977 &["u32"],
978 ); 963 );
979
980 assert_eq!(hover_on, "bar")
981 } 964 }
982 965
983 #[test] 966 #[test]
984 fn test_hover_through_func_in_macro_recursive() { 967 fn test_hover_through_func_in_macro_recursive() {
985 let (hover_on, _) = check_hover_result( 968 check(
986 r" 969 r#"
987 //- /lib.rs 970macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
988 macro_rules! id_deep { 971macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
989 ($($tt:tt)*) => { $($tt)* } 972fn bar() -> u32 { 0 }
990 } 973fn foo() { let a = id!([0u32, bar(<|>)] ); }
991 macro_rules! id { 974"#,
992 ($($tt:tt)*) => { id_deep!($($tt)*) } 975 expect![[r#"
993 } 976 *bar()*
994 fn bar() -> u32 { 977 ```rust
995 0 978 u32
996 } 979 ```
997 fn foo() { 980 "#]],
998 let a = id!([0u32, bar(<|>)] );
999 }
1000 ",
1001 &["u32"],
1002 ); 981 );
1003
1004 assert_eq!(hover_on, "bar()")
1005 } 982 }
1006 983
1007 #[test] 984 #[test]
1008 fn test_hover_through_literal_string_in_macro() { 985 fn test_hover_through_literal_string_in_macro() {
1009 let (hover_on, _) = check_hover_result( 986 check(
1010 r#" 987 r#"
1011 //- /lib.rs 988macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } }
1012 macro_rules! arr { 989fn foo() {
1013 ($($tt:tt)*) => { [$($tt)*)] } 990 let mastered_for_itunes = "";
1014 } 991 let _ = arr!("Tr<|>acks", &mastered_for_itunes);
1015 fn foo() { 992}
1016 let mastered_for_itunes = ""; 993"#,
1017 let _ = arr!("Tr<|>acks", &mastered_for_itunes); 994 expect![[r#"
1018 } 995 *"Tracks"*
1019 "#, 996 ```rust
1020 &["&str"], 997 &str
998 ```
999 "#]],
1021 ); 1000 );
1022
1023 assert_eq!(hover_on, "\"Tracks\"");
1024 } 1001 }
1025 1002
1026 #[test] 1003 #[test]
1027 fn test_hover_through_assert_macro() { 1004 fn test_hover_through_assert_macro() {
1028 let (hover_on, _) = check_hover_result( 1005 check(
1029 r" 1006 r#"
1030 //- /lib.rs 1007#[rustc_builtin_macro]
1031 #[rustc_builtin_macro] 1008macro_rules! assert {}
1032 macro_rules! assert {}
1033 1009
1034 fn bar() -> bool { true } 1010fn bar() -> bool { true }
1035 fn foo() { 1011fn foo() {
1036 assert!(ba<|>r()); 1012 assert!(ba<|>r());
1037 } 1013}
1038 ", 1014"#,
1039 &["fn bar() -> bool"], 1015 expect![[r#"
1016 *bar*
1017 ```rust
1018 fn bar() -> bool
1019 ```
1020 "#]],
1040 ); 1021 );
1041
1042 assert_eq!(hover_on, "bar");
1043 } 1022 }
1044 1023
1045 #[test] 1024 #[test]
1046 fn test_hover_through_literal_string_in_builtin_macro() { 1025 fn test_hover_through_literal_string_in_builtin_macro() {
1047 check_hover_no_result( 1026 check_hover_no_result(
1048 r#" 1027 r#"
1049 //- /lib.rs
1050 #[rustc_builtin_macro] 1028 #[rustc_builtin_macro]
1051 macro_rules! format {} 1029 macro_rules! format {}
1052 1030
@@ -1059,122 +1037,159 @@ fn func(foo: i32) { if true { <|>foo; }; }
1059 1037
1060 #[test] 1038 #[test]
1061 fn test_hover_non_ascii_space_doc() { 1039 fn test_hover_non_ascii_space_doc() {
1062 check_hover_result( 1040 check(
1063 " 1041 "
1064 //- /lib.rs 1042/// <- `\u{3000}` here
1065 /// <- `\u{3000}` here 1043fn foo() { }
1066 fn foo() {
1067 }
1068 1044
1069 fn bar() { 1045fn bar() { fo<|>o(); }
1070 fo<|>o(); 1046",
1071 } 1047 expect![[r#"
1072 ", 1048 *foo*
1073 &["fn foo()\n```\n___\n\n<- `\u{3000}` here"], 1049 ```rust
1050 fn foo()
1051 ```
1052 ___
1053
1054 <- ` ` here
1055 "#]],
1074 ); 1056 );
1075 } 1057 }
1076 1058
1077 #[test] 1059 #[test]
1078 fn test_hover_function_show_qualifiers() { 1060 fn test_hover_function_show_qualifiers() {
1079 check_hover_result( 1061 check(
1080 r" 1062 r#"async fn foo<|>() {}"#,
1081 //- /lib.rs 1063 expect![[r#"
1082 async fn foo<|>() {} 1064 *foo*
1083 ", 1065 ```rust
1084 &["async fn foo()"], 1066 async fn foo()
1085 ); 1067 ```
1086 check_hover_result( 1068 "#]],
1087 r" 1069 );
1088 //- /lib.rs 1070 check(
1089 pub const unsafe fn foo<|>() {} 1071 r#"pub const unsafe fn foo<|>() {}"#,
1090 ", 1072 expect![[r#"
1091 &["pub const unsafe fn foo()"], 1073 *foo*
1092 ); 1074 ```rust
1093 check_hover_result( 1075 pub const unsafe fn foo()
1094 r#" 1076 ```
1095 //- /lib.rs 1077 "#]],
1096 pub(crate) async unsafe extern "C" fn foo<|>() {} 1078 );
1097 "#, 1079 check(
1098 &[r#"pub(crate) async unsafe extern "C" fn foo()"#], 1080 r#"pub(crate) async unsafe extern "C" fn foo<|>() {}"#,
1081 expect![[r#"
1082 *foo*
1083 ```rust
1084 pub(crate) async unsafe extern "C" fn foo()
1085 ```
1086 "#]],
1099 ); 1087 );
1100 } 1088 }
1101 1089
1102 #[test] 1090 #[test]
1103 fn test_hover_trait_show_qualifiers() { 1091 fn test_hover_trait_show_qualifiers() {
1104 let (_, actions) = check_hover_result( 1092 check_actions(
1105 r" 1093 r"unsafe trait foo<|>() {}",
1106 //- /lib.rs 1094 expect![[r#"
1107 unsafe trait foo<|>() {} 1095 [
1108 ", 1096 Implementaion(
1109 &["unsafe trait foo"], 1097 FilePosition {
1098 file_id: FileId(
1099 1,
1100 ),
1101 offset: 13,
1102 },
1103 ),
1104 ]
1105 "#]],
1110 ); 1106 );
1111 assert_impl_action(&actions[0], 13);
1112 } 1107 }
1113 1108
1114 #[test] 1109 #[test]
1115 fn test_hover_mod_with_same_name_as_function() { 1110 fn test_hover_mod_with_same_name_as_function() {
1116 check_hover_result( 1111 check(
1117 r" 1112 r#"
1118 //- /lib.rs 1113use self::m<|>y::Bar;
1119 use self::m<|>y::Bar; 1114mod my { pub struct Bar; }
1120
1121 mod my {
1122 pub struct Bar;
1123 }
1124 1115
1125 fn my() {} 1116fn my() {}
1126 ", 1117"#,
1127 &["mod my"], 1118 expect![[r#"
1119 *my*
1120 ```rust
1121 mod my
1122 ```
1123 "#]],
1128 ); 1124 );
1129 } 1125 }
1130 1126
1131 #[test] 1127 #[test]
1132 fn test_hover_struct_doc_comment() { 1128 fn test_hover_struct_doc_comment() {
1133 check_hover_result( 1129 check(
1134 r#" 1130 r#"
1135 //- /lib.rs 1131/// bar docs
1136 /// bar docs 1132struct Bar;
1137 struct Bar;
1138 1133
1139 fn foo() { 1134fn foo() { let bar = Ba<|>r; }
1140 let bar = Ba<|>r; 1135"#,
1141 } 1136 expect![[r#"
1142 "#, 1137 *Bar*
1143 &["struct Bar\n```\n___\n\nbar docs"], 1138 ```rust
1139 struct Bar
1140 ```
1141 ___
1142
1143 bar docs
1144 "#]],
1144 ); 1145 );
1145 } 1146 }
1146 1147
1147 #[test] 1148 #[test]
1148 fn test_hover_struct_doc_attr() { 1149 fn test_hover_struct_doc_attr() {
1149 check_hover_result( 1150 check(
1150 r#" 1151 r#"
1151 //- /lib.rs 1152#[doc = "bar docs"]
1152 #[doc = "bar docs"] 1153struct Bar;
1153 struct Bar;
1154 1154
1155 fn foo() { 1155fn foo() { let bar = Ba<|>r; }
1156 let bar = Ba<|>r; 1156"#,
1157 } 1157 expect![[r#"
1158 "#, 1158 *Bar*
1159 &["struct Bar\n```\n___\n\nbar docs"], 1159 ```rust
1160 struct Bar
1161 ```
1162 ___
1163
1164 bar docs
1165 "#]],
1160 ); 1166 );
1161 } 1167 }
1162 1168
1163 #[test] 1169 #[test]
1164 fn test_hover_struct_doc_attr_multiple_and_mixed() { 1170 fn test_hover_struct_doc_attr_multiple_and_mixed() {
1165 check_hover_result( 1171 check(
1166 r#" 1172 r#"
1167 //- /lib.rs 1173/// bar docs 0
1168 /// bar docs 0 1174#[doc = "bar docs 1"]
1169 #[doc = "bar docs 1"] 1175#[doc = "bar docs 2"]
1170 #[doc = "bar docs 2"] 1176struct Bar;
1171 struct Bar;
1172 1177
1173 fn foo() { 1178fn foo() { let bar = Ba<|>r; }
1174 let bar = Ba<|>r; 1179"#,
1175 } 1180 expect![[r#"
1176 "#, 1181 *Bar*
1177 &["struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2"], 1182 ```rust
1183 struct Bar
1184 ```
1185 ___
1186
1187 bar docs 0
1188
1189 bar docs 1
1190
1191 bar docs 2
1192 "#]],
1178 ); 1193 );
1179 } 1194 }
1180 1195
@@ -1182,27 +1197,35 @@ fn func(foo: i32) { if true { <|>foo; }; }
1182 fn test_hover_macro_generated_struct_fn_doc_comment() { 1197 fn test_hover_macro_generated_struct_fn_doc_comment() {
1183 mark::check!(hover_macro_generated_struct_fn_doc_comment); 1198 mark::check!(hover_macro_generated_struct_fn_doc_comment);
1184 1199
1185 check_hover_result( 1200 check(
1186 r#" 1201 r#"
1187 //- /lib.rs 1202macro_rules! bar {
1188 macro_rules! bar { 1203 () => {
1189 () => { 1204 struct Bar;
1190 struct Bar; 1205 impl Bar {
1191 impl Bar { 1206 /// Do the foo
1192 /// Do the foo 1207 fn foo(&self) {}
1193 fn foo(&self) {} 1208 }
1194 } 1209 }
1195 } 1210}
1196 }
1197 1211
1198 bar!(); 1212bar!();
1199 1213
1200 fn foo() { 1214fn foo() { let bar = Bar; bar.fo<|>o(); }
1201 let bar = Bar; 1215"#,
1202 bar.fo<|>o(); 1216 expect![[r#"
1203 } 1217 *foo*
1204 "#, 1218 ```rust
1205 &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\n Do the foo"], 1219 Bar
1220 ```
1221
1222 ```rust
1223 fn foo(&self)
1224 ```
1225 ___
1226
1227 Do the foo
1228 "#]],
1206 ); 1229 );
1207 } 1230 }
1208 1231
@@ -1210,1204 +1233,1155 @@ fn func(foo: i32) { if true { <|>foo; }; }
1210 fn test_hover_macro_generated_struct_fn_doc_attr() { 1233 fn test_hover_macro_generated_struct_fn_doc_attr() {
1211 mark::check!(hover_macro_generated_struct_fn_doc_attr); 1234 mark::check!(hover_macro_generated_struct_fn_doc_attr);
1212 1235
1213 check_hover_result( 1236 check(
1214 r#" 1237 r#"
1215 //- /lib.rs 1238macro_rules! bar {
1216 macro_rules! bar { 1239 () => {
1217 () => { 1240 struct Bar;
1218 struct Bar; 1241 impl Bar {
1219 impl Bar { 1242 #[doc = "Do the foo"]
1220 #[doc = "Do the foo"] 1243 fn foo(&self) {}
1221 fn foo(&self) {} 1244 }
1222 } 1245 }
1223 } 1246}
1224 }
1225 1247
1226 bar!(); 1248bar!();
1227 1249
1228 fn foo() { 1250fn foo() { let bar = Bar; bar.fo<|>o(); }
1229 let bar = Bar; 1251"#,
1230 bar.fo<|>o(); 1252 expect![[r#"
1231 } 1253 *foo*
1232 "#, 1254 ```rust
1233 &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"], 1255 Bar
1256 ```
1257
1258 ```rust
1259 fn foo(&self)
1260 ```
1261 ___
1262
1263 Do the foo
1264 "#]],
1234 ); 1265 );
1235 } 1266 }
1236 1267
1237 #[test] 1268 #[test]
1238 fn test_hover_trait_has_impl_action() { 1269 fn test_hover_trait_has_impl_action() {
1239 let (_, actions) = check_hover_result( 1270 check_actions(
1240 r" 1271 r#"trait foo<|>() {}"#,
1241 //- /lib.rs 1272 expect![[r#"
1242 trait foo<|>() {} 1273 [
1243 ", 1274 Implementaion(
1244 &["trait foo"], 1275 FilePosition {
1276 file_id: FileId(
1277 1,
1278 ),
1279 offset: 6,
1280 },
1281 ),
1282 ]
1283 "#]],
1245 ); 1284 );
1246 assert_impl_action(&actions[0], 6);
1247 } 1285 }
1248 1286
1249 #[test] 1287 #[test]
1250 fn test_hover_struct_has_impl_action() { 1288 fn test_hover_struct_has_impl_action() {
1251 let (_, actions) = check_hover_result( 1289 check_actions(
1252 r" 1290 r"struct foo<|>() {}",
1253 //- /lib.rs 1291 expect![[r#"
1254 struct foo<|>() {} 1292 [
1255 ", 1293 Implementaion(
1256 &["struct foo"], 1294 FilePosition {
1295 file_id: FileId(
1296 1,
1297 ),
1298 offset: 7,
1299 },
1300 ),
1301 ]
1302 "#]],
1257 ); 1303 );
1258 assert_impl_action(&actions[0], 7);
1259 } 1304 }
1260 1305
1261 #[test] 1306 #[test]
1262 fn test_hover_union_has_impl_action() { 1307 fn test_hover_union_has_impl_action() {
1263 let (_, actions) = check_hover_result( 1308 check_actions(
1264 r" 1309 r#"union foo<|>() {}"#,
1265 //- /lib.rs 1310 expect![[r#"
1266 union foo<|>() {} 1311 [
1267 ", 1312 Implementaion(
1268 &["union foo"], 1313 FilePosition {
1269 );
1270 assert_impl_action(&actions[0], 6);
1271 }
1272
1273 #[test]
1274 fn test_hover_enum_has_impl_action() {
1275 let (_, actions) = check_hover_result(
1276 r"
1277 //- /lib.rs
1278 enum foo<|>() {
1279 A,
1280 B
1281 }
1282 ",
1283 &["enum foo"],
1284 );
1285 assert_impl_action(&actions[0], 5);
1286 }
1287
1288 #[test]
1289 fn test_hover_test_has_action() {
1290 let (_, actions) = check_hover_result(
1291 r"
1292 //- /lib.rs
1293 #[test]
1294 fn foo_<|>test() {}
1295 ",
1296 &["fn foo_test()"],
1297 );
1298 assert_debug_snapshot!(actions,
1299 @r###"
1300 [
1301 Runnable(
1302 Runnable {
1303 nav: NavigationTarget {
1304 file_id: FileId( 1314 file_id: FileId(
1305 1, 1315 1,
1306 ), 1316 ),
1307 full_range: 0..24, 1317 offset: 6,
1308 name: "foo_test",
1309 kind: FN_DEF,
1310 focus_range: Some(
1311 11..19,
1312 ),
1313 container_name: None,
1314 description: None,
1315 docs: None,
1316 },
1317 kind: Test {
1318 test_id: Path(
1319 "foo_test",
1320 ),
1321 attr: TestAttr {
1322 ignore: false,
1323 },
1324 }, 1318 },
1325 cfg_exprs: [], 1319 ),
1326 }, 1320 ]
1327 ), 1321 "#]],
1328 ] 1322 );
1329 "###);
1330 } 1323 }
1331 1324
1332 #[test] 1325 #[test]
1333 fn test_hover_test_mod_has_action() { 1326 fn test_hover_enum_has_impl_action() {
1334 let (_, actions) = check_hover_result( 1327 check_actions(
1335 r" 1328 r"enum foo<|>() { A, B }",
1336 //- /lib.rs 1329 expect![[r#"
1337 mod tests<|> { 1330 [
1338 #[test] 1331 Implementaion(
1339 fn foo_test() {} 1332 FilePosition {
1340 }
1341 ",
1342 &["mod tests"],
1343 );
1344 assert_debug_snapshot!(actions,
1345 @r###"
1346 [
1347 Runnable(
1348 Runnable {
1349 nav: NavigationTarget {
1350 file_id: FileId( 1333 file_id: FileId(
1351 1, 1334 1,
1352 ), 1335 ),
1353 full_range: 0..46, 1336 offset: 5,
1354 name: "tests",
1355 kind: MODULE,
1356 focus_range: Some(
1357 4..9,
1358 ),
1359 container_name: None,
1360 description: None,
1361 docs: None,
1362 }, 1337 },
1363 kind: TestMod { 1338 ),
1364 path: "tests", 1339 ]
1365 }, 1340 "#]],
1366 cfg_exprs: [], 1341 );
1367 },
1368 ),
1369 ]
1370 "###);
1371 } 1342 }
1372 1343
1373 #[test] 1344 #[test]
1374 fn test_hover_struct_has_goto_type_action() { 1345 fn test_hover_test_has_action() {
1375 let (_, actions) = check_hover_result( 1346 check_actions(
1376 r" 1347 r#"
1377 //- /main.rs 1348#[test]
1378 struct S{ f1: u32 } 1349fn foo_<|>test() {}
1379 1350"#,
1380 fn main() { 1351 expect![[r#"
1381 let s<|>t = S{ f1:0 }; 1352 [
1382 } 1353 Runnable(
1383 ", 1354 Runnable {
1384 &["S"],
1385 );
1386 assert_debug_snapshot!(actions,
1387 @r###"
1388 [
1389 GoToType(
1390 [
1391 HoverGotoTypeData {
1392 mod_path: "S",
1393 nav: NavigationTarget { 1355 nav: NavigationTarget {
1394 file_id: FileId( 1356 file_id: FileId(
1395 1, 1357 1,
1396 ), 1358 ),
1397 full_range: 0..19, 1359 full_range: 0..24,
1398 name: "S",
1399 kind: STRUCT_DEF,
1400 focus_range: Some( 1360 focus_range: Some(
1401 7..8, 1361 11..19,
1402 ), 1362 ),
1363 name: "foo_test",
1364 kind: FN_DEF,
1403 container_name: None, 1365 container_name: None,
1404 description: Some( 1366 description: None,
1405 "struct S",
1406 ),
1407 docs: None, 1367 docs: None,
1408 }, 1368 },
1369 kind: Test {
1370 test_id: Path(
1371 "foo_test",
1372 ),
1373 attr: TestAttr {
1374 ignore: false,
1375 },
1376 },
1377 cfg_exprs: [],
1409 }, 1378 },
1410 ], 1379 ),
1411 ), 1380 ]
1412 ] 1381 "#]],
1413 "###); 1382 );
1414 } 1383 }
1415 1384
1416 #[test] 1385 #[test]
1417 fn test_hover_generic_struct_has_goto_type_actions() { 1386 fn test_hover_test_mod_has_action() {
1418 let (_, actions) = check_hover_result( 1387 check_actions(
1419 r" 1388 r#"
1420 //- /main.rs 1389mod tests<|> {
1421 struct Arg(u32); 1390 #[test]
1422 struct S<T>{ f1: T } 1391 fn foo_test() {}
1423 1392}
1424 fn main() { 1393"#,
1425 let s<|>t = S{ f1:Arg(0) }; 1394 expect![[r#"
1426 } 1395 [
1427 ", 1396 Runnable(
1428 &["S<Arg>"], 1397 Runnable {
1429 );
1430 assert_debug_snapshot!(actions,
1431 @r###"
1432 [
1433 GoToType(
1434 [
1435 HoverGotoTypeData {
1436 mod_path: "S",
1437 nav: NavigationTarget { 1398 nav: NavigationTarget {
1438 file_id: FileId( 1399 file_id: FileId(
1439 1, 1400 1,
1440 ), 1401 ),
1441 full_range: 17..37, 1402 full_range: 0..46,
1442 name: "S",
1443 kind: STRUCT_DEF,
1444 focus_range: Some( 1403 focus_range: Some(
1445 24..25, 1404 4..9,
1446 ), 1405 ),
1406 name: "tests",
1407 kind: MODULE,
1447 container_name: None, 1408 container_name: None,
1448 description: Some( 1409 description: None,
1449 "struct S",
1450 ),
1451 docs: None, 1410 docs: None,
1452 }, 1411 },
1453 }, 1412 kind: TestMod {
1454 HoverGotoTypeData { 1413 path: "tests",
1455 mod_path: "Arg",
1456 nav: NavigationTarget {
1457 file_id: FileId(
1458 1,
1459 ),
1460 full_range: 0..16,
1461 name: "Arg",
1462 kind: STRUCT_DEF,
1463 focus_range: Some(
1464 7..10,
1465 ),
1466 container_name: None,
1467 description: Some(
1468 "struct Arg",
1469 ),
1470 docs: None,
1471 }, 1414 },
1415 cfg_exprs: [],
1472 }, 1416 },
1473 ], 1417 ),
1474 ), 1418 ]
1475 ] 1419 "#]],
1476 "###); 1420 );
1477 } 1421 }
1478 1422
1479 #[test] 1423 #[test]
1480 fn test_hover_generic_struct_has_flattened_goto_type_actions() { 1424 fn test_hover_struct_has_goto_type_action() {
1481 let (_, actions) = check_hover_result( 1425 check_actions(
1482 r" 1426 r#"
1483 //- /main.rs 1427struct S{ f1: u32 }
1484 struct Arg(u32); 1428
1485 struct S<T>{ f1: T } 1429fn main() { let s<|>t = S{ f1:0 }; }
1486 1430 "#,
1487 fn main() { 1431 expect![[r#"
1488 let s<|>t = S{ f1: S{ f1: Arg(0) } }; 1432 [
1489 } 1433 GoToType(
1490 ", 1434 [
1491 &["S<S<Arg>>"], 1435 HoverGotoTypeData {
1436 mod_path: "S",
1437 nav: NavigationTarget {
1438 file_id: FileId(
1439 1,
1440 ),
1441 full_range: 0..19,
1442 focus_range: Some(
1443 7..8,
1444 ),
1445 name: "S",
1446 kind: STRUCT_DEF,
1447 container_name: None,
1448 description: Some(
1449 "struct S",
1450 ),
1451 docs: None,
1452 },
1453 },
1454 ],
1455 ),
1456 ]
1457 "#]],
1492 ); 1458 );
1493 assert_debug_snapshot!(actions, 1459 }
1494 @r###" 1460
1495 [ 1461 #[test]
1496 GoToType( 1462 fn test_hover_generic_struct_has_goto_type_actions() {
1497 [ 1463 check_actions(
1498 HoverGotoTypeData { 1464 r#"
1499 mod_path: "S", 1465struct Arg(u32);
1500 nav: NavigationTarget { 1466struct S<T>{ f1: T }
1501 file_id: FileId( 1467
1502 1, 1468fn main() { let s<|>t = S{ f1:Arg(0) }; }
1503 ), 1469"#,
1504 full_range: 17..37, 1470 expect![[r#"
1505 name: "S", 1471 [
1506 kind: STRUCT_DEF, 1472 GoToType(
1507 focus_range: Some( 1473 [
1508 24..25, 1474 HoverGotoTypeData {
1509 ), 1475 mod_path: "S",
1510 container_name: None, 1476 nav: NavigationTarget {
1511 description: Some( 1477 file_id: FileId(
1512 "struct S", 1478 1,
1513 ), 1479 ),
1514 docs: None, 1480 full_range: 17..37,
1481 focus_range: Some(
1482 24..25,
1483 ),
1484 name: "S",
1485 kind: STRUCT_DEF,
1486 container_name: None,
1487 description: Some(
1488 "struct S",
1489 ),
1490 docs: None,
1491 },
1515 }, 1492 },
1516 }, 1493 HoverGotoTypeData {
1517 HoverGotoTypeData { 1494 mod_path: "Arg",
1518 mod_path: "Arg", 1495 nav: NavigationTarget {
1519 nav: NavigationTarget { 1496 file_id: FileId(
1520 file_id: FileId( 1497 1,
1521 1, 1498 ),
1522 ), 1499 full_range: 0..16,
1523 full_range: 0..16, 1500 focus_range: Some(
1524 name: "Arg", 1501 7..10,
1525 kind: STRUCT_DEF, 1502 ),
1526 focus_range: Some( 1503 name: "Arg",
1527 7..10, 1504 kind: STRUCT_DEF,
1528 ), 1505 container_name: None,
1529 container_name: None, 1506 description: Some(
1530 description: Some( 1507 "struct Arg",
1531 "struct Arg", 1508 ),
1532 ), 1509 docs: None,
1533 docs: None, 1510 },
1534 }, 1511 },
1535 }, 1512 ],
1536 ], 1513 ),
1537 ), 1514 ]
1538 ] 1515 "#]],
1539 "###); 1516 );
1540 } 1517 }
1541 1518
1542 #[test] 1519 #[test]
1543 fn test_hover_tuple_has_goto_type_actions() { 1520 fn test_hover_generic_struct_has_flattened_goto_type_actions() {
1544 let (_, actions) = check_hover_result( 1521 check_actions(
1545 r" 1522 r#"
1546 //- /main.rs 1523struct Arg(u32);
1547 struct A(u32); 1524struct S<T>{ f1: T }
1548 struct B(u32);
1549 mod M {
1550 pub struct C(u32);
1551 }
1552 1525
1553 fn main() { 1526fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
1554 let s<|>t = (A(1), B(2), M::C(3) ); 1527 "#,
1555 } 1528 expect![[r#"
1556 ", 1529 [
1557 &["(A, B, C)"], 1530 GoToType(
1531 [
1532 HoverGotoTypeData {
1533 mod_path: "S",
1534 nav: NavigationTarget {
1535 file_id: FileId(
1536 1,
1537 ),
1538 full_range: 17..37,
1539 focus_range: Some(
1540 24..25,
1541 ),
1542 name: "S",
1543 kind: STRUCT_DEF,
1544 container_name: None,
1545 description: Some(
1546 "struct S",
1547 ),
1548 docs: None,
1549 },
1550 },
1551 HoverGotoTypeData {
1552 mod_path: "Arg",
1553 nav: NavigationTarget {
1554 file_id: FileId(
1555 1,
1556 ),
1557 full_range: 0..16,
1558 focus_range: Some(
1559 7..10,
1560 ),
1561 name: "Arg",
1562 kind: STRUCT_DEF,
1563 container_name: None,
1564 description: Some(
1565 "struct Arg",
1566 ),
1567 docs: None,
1568 },
1569 },
1570 ],
1571 ),
1572 ]
1573 "#]],
1558 ); 1574 );
1559 assert_debug_snapshot!(actions, 1575 }
1560 @r###" 1576
1561 [ 1577 #[test]
1562 GoToType( 1578 fn test_hover_tuple_has_goto_type_actions() {
1563 [ 1579 check_actions(
1564 HoverGotoTypeData { 1580 r#"
1565 mod_path: "A", 1581struct A(u32);
1566 nav: NavigationTarget { 1582struct B(u32);
1567 file_id: FileId( 1583mod M {
1568 1, 1584 pub struct C(u32);
1569 ), 1585}
1570 full_range: 0..14, 1586
1571 name: "A", 1587fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
1572 kind: STRUCT_DEF, 1588"#,
1573 focus_range: Some( 1589 expect![[r#"
1574 7..8, 1590 [
1575 ), 1591 GoToType(
1576 container_name: None, 1592 [
1577 description: Some( 1593 HoverGotoTypeData {
1578 "struct A", 1594 mod_path: "A",
1579 ), 1595 nav: NavigationTarget {
1580 docs: None, 1596 file_id: FileId(
1597 1,
1598 ),
1599 full_range: 0..14,
1600 focus_range: Some(
1601 7..8,
1602 ),
1603 name: "A",
1604 kind: STRUCT_DEF,
1605 container_name: None,
1606 description: Some(
1607 "struct A",
1608 ),
1609 docs: None,
1610 },
1581 }, 1611 },
1582 }, 1612 HoverGotoTypeData {
1583 HoverGotoTypeData { 1613 mod_path: "B",
1584 mod_path: "B", 1614 nav: NavigationTarget {
1585 nav: NavigationTarget { 1615 file_id: FileId(
1586 file_id: FileId( 1616 1,
1587 1, 1617 ),
1588 ), 1618 full_range: 15..29,
1589 full_range: 15..29, 1619 focus_range: Some(
1590 name: "B", 1620 22..23,
1591 kind: STRUCT_DEF, 1621 ),
1592 focus_range: Some( 1622 name: "B",
1593 22..23, 1623 kind: STRUCT_DEF,
1594 ), 1624 container_name: None,
1595 container_name: None, 1625 description: Some(
1596 description: Some( 1626 "struct B",
1597 "struct B", 1627 ),
1598 ), 1628 docs: None,
1599 docs: None, 1629 },
1600 }, 1630 },
1601 }, 1631 HoverGotoTypeData {
1602 HoverGotoTypeData { 1632 mod_path: "M::C",
1603 mod_path: "M::C", 1633 nav: NavigationTarget {
1604 nav: NavigationTarget { 1634 file_id: FileId(
1605 file_id: FileId( 1635 1,
1606 1, 1636 ),
1607 ), 1637 full_range: 42..60,
1608 full_range: 42..60, 1638 focus_range: Some(
1609 name: "C", 1639 53..54,
1610 kind: STRUCT_DEF, 1640 ),
1611 focus_range: Some( 1641 name: "C",
1612 53..54, 1642 kind: STRUCT_DEF,
1613 ), 1643 container_name: None,
1614 container_name: None, 1644 description: Some(
1615 description: Some( 1645 "pub struct C",
1616 "pub struct C", 1646 ),
1617 ), 1647 docs: None,
1618 docs: None, 1648 },
1619 }, 1649 },
1620 }, 1650 ],
1621 ], 1651 ),
1622 ), 1652 ]
1623 ] 1653 "#]],
1624 "###); 1654 );
1625 } 1655 }
1626 1656
1627 #[test] 1657 #[test]
1628 fn test_hover_return_impl_trait_has_goto_type_action() { 1658 fn test_hover_return_impl_trait_has_goto_type_action() {
1629 let (_, actions) = check_hover_result( 1659 check_actions(
1630 r" 1660 r#"
1631 //- /main.rs 1661trait Foo {}
1632 trait Foo {} 1662fn foo() -> impl Foo {}
1633
1634 fn foo() -> impl Foo {}
1635 1663
1636 fn main() { 1664fn main() { let s<|>t = foo(); }
1637 let s<|>t = foo(); 1665"#,
1638 } 1666 expect![[r#"
1639 ", 1667 [
1640 &["impl Foo"], 1668 GoToType(
1641 ); 1669 [
1642 assert_debug_snapshot!(actions, 1670 HoverGotoTypeData {
1643 @r###" 1671 mod_path: "Foo",
1644 [ 1672 nav: NavigationTarget {
1645 GoToType( 1673 file_id: FileId(
1646 [ 1674 1,
1647 HoverGotoTypeData { 1675 ),
1648 mod_path: "Foo", 1676 full_range: 0..12,
1649 nav: NavigationTarget { 1677 focus_range: Some(
1650 file_id: FileId( 1678 6..9,
1651 1, 1679 ),
1652 ), 1680 name: "Foo",
1653 full_range: 0..12, 1681 kind: TRAIT_DEF,
1654 name: "Foo", 1682 container_name: None,
1655 kind: TRAIT_DEF, 1683 description: Some(
1656 focus_range: Some( 1684 "trait Foo",
1657 6..9, 1685 ),
1658 ), 1686 docs: None,
1659 container_name: None, 1687 },
1660 description: Some(
1661 "trait Foo",
1662 ),
1663 docs: None,
1664 }, 1688 },
1665 }, 1689 ],
1666 ], 1690 ),
1667 ), 1691 ]
1668 ] 1692 "#]],
1669 "###); 1693 );
1670 } 1694 }
1671 1695
1672 #[test] 1696 #[test]
1673 fn test_hover_generic_return_impl_trait_has_goto_type_action() { 1697 fn test_hover_generic_return_impl_trait_has_goto_type_action() {
1674 let (_, actions) = check_hover_result( 1698 check_actions(
1675 r" 1699 r#"
1676 //- /main.rs 1700trait Foo<T> {}
1677 trait Foo<T> {} 1701struct S;
1678 struct S; 1702fn foo() -> impl Foo<S> {}
1679
1680 fn foo() -> impl Foo<S> {}
1681 1703
1682 fn main() { 1704fn main() { let s<|>t = foo(); }
1683 let s<|>t = foo(); 1705"#,
1684 } 1706 expect![[r#"
1685 ", 1707 [
1686 &["impl Foo<S>"], 1708 GoToType(
1687 ); 1709 [
1688 assert_debug_snapshot!(actions, 1710 HoverGotoTypeData {
1689 @r###" 1711 mod_path: "Foo",
1690 [ 1712 nav: NavigationTarget {
1691 GoToType( 1713 file_id: FileId(
1692 [ 1714 1,
1693 HoverGotoTypeData { 1715 ),
1694 mod_path: "Foo", 1716 full_range: 0..15,
1695 nav: NavigationTarget { 1717 focus_range: Some(
1696 file_id: FileId( 1718 6..9,
1697 1, 1719 ),
1698 ), 1720 name: "Foo",
1699 full_range: 0..15, 1721 kind: TRAIT_DEF,
1700 name: "Foo", 1722 container_name: None,
1701 kind: TRAIT_DEF, 1723 description: Some(
1702 focus_range: Some( 1724 "trait Foo",
1703 6..9, 1725 ),
1704 ), 1726 docs: None,
1705 container_name: None, 1727 },
1706 description: Some(
1707 "trait Foo",
1708 ),
1709 docs: None,
1710 }, 1728 },
1711 }, 1729 HoverGotoTypeData {
1712 HoverGotoTypeData { 1730 mod_path: "S",
1713 mod_path: "S", 1731 nav: NavigationTarget {
1714 nav: NavigationTarget { 1732 file_id: FileId(
1715 file_id: FileId( 1733 1,
1716 1, 1734 ),
1717 ), 1735 full_range: 16..25,
1718 full_range: 16..25, 1736 focus_range: Some(
1719 name: "S", 1737 23..24,
1720 kind: STRUCT_DEF, 1738 ),
1721 focus_range: Some( 1739 name: "S",
1722 23..24, 1740 kind: STRUCT_DEF,
1723 ), 1741 container_name: None,
1724 container_name: None, 1742 description: Some(
1725 description: Some( 1743 "struct S",
1726 "struct S", 1744 ),
1727 ), 1745 docs: None,
1728 docs: None, 1746 },
1729 }, 1747 },
1730 }, 1748 ],
1731 ], 1749 ),
1732 ), 1750 ]
1733 ] 1751 "#]],
1734 "###); 1752 );
1735 } 1753 }
1736 1754
1737 #[test] 1755 #[test]
1738 fn test_hover_return_impl_traits_has_goto_type_action() { 1756 fn test_hover_return_impl_traits_has_goto_type_action() {
1739 let (_, actions) = check_hover_result( 1757 check_actions(
1740 r" 1758 r#"
1741 //- /main.rs 1759trait Foo {}
1742 trait Foo {} 1760trait Bar {}
1743 trait Bar {} 1761fn foo() -> impl Foo + Bar {}
1744
1745 fn foo() -> impl Foo + Bar {}
1746 1762
1747 fn main() { 1763fn main() { let s<|>t = foo(); }
1748 let s<|>t = foo(); 1764 "#,
1749 } 1765 expect![[r#"
1750 ", 1766 [
1751 &["impl Foo + Bar"], 1767 GoToType(
1752 ); 1768 [
1753 assert_debug_snapshot!(actions, 1769 HoverGotoTypeData {
1754 @r###" 1770 mod_path: "Foo",
1755 [ 1771 nav: NavigationTarget {
1756 GoToType( 1772 file_id: FileId(
1757 [ 1773 1,
1758 HoverGotoTypeData { 1774 ),
1759 mod_path: "Foo", 1775 full_range: 0..12,
1760 nav: NavigationTarget { 1776 focus_range: Some(
1761 file_id: FileId( 1777 6..9,
1762 1, 1778 ),
1763 ), 1779 name: "Foo",
1764 full_range: 0..12, 1780 kind: TRAIT_DEF,
1765 name: "Foo", 1781 container_name: None,
1766 kind: TRAIT_DEF, 1782 description: Some(
1767 focus_range: Some( 1783 "trait Foo",
1768 6..9, 1784 ),
1769 ), 1785 docs: None,
1770 container_name: None, 1786 },
1771 description: Some(
1772 "trait Foo",
1773 ),
1774 docs: None,
1775 }, 1787 },
1776 }, 1788 HoverGotoTypeData {
1777 HoverGotoTypeData { 1789 mod_path: "Bar",
1778 mod_path: "Bar", 1790 nav: NavigationTarget {
1779 nav: NavigationTarget { 1791 file_id: FileId(
1780 file_id: FileId( 1792 1,
1781 1, 1793 ),
1782 ), 1794 full_range: 13..25,
1783 full_range: 13..25, 1795 focus_range: Some(
1784 name: "Bar", 1796 19..22,
1785 kind: TRAIT_DEF, 1797 ),
1786 focus_range: Some( 1798 name: "Bar",
1787 19..22, 1799 kind: TRAIT_DEF,
1788 ), 1800 container_name: None,
1789 container_name: None, 1801 description: Some(
1790 description: Some( 1802 "trait Bar",
1791 "trait Bar", 1803 ),
1792 ), 1804 docs: None,
1793 docs: None, 1805 },
1794 }, 1806 },
1795 }, 1807 ],
1796 ], 1808 ),
1797 ), 1809 ]
1798 ] 1810 "#]],
1799 "###); 1811 );
1800 } 1812 }
1801 1813
1802 #[test] 1814 #[test]
1803 fn test_hover_generic_return_impl_traits_has_goto_type_action() { 1815 fn test_hover_generic_return_impl_traits_has_goto_type_action() {
1804 let (_, actions) = check_hover_result( 1816 check_actions(
1805 r" 1817 r#"
1806 //- /main.rs 1818trait Foo<T> {}
1807 trait Foo<T> {} 1819trait Bar<T> {}
1808 trait Bar<T> {} 1820struct S1 {}
1809 struct S1 {} 1821struct S2 {}
1810 struct S2 {} 1822
1811 1823fn foo() -> impl Foo<S1> + Bar<S2> {}
1812 fn foo() -> impl Foo<S1> + Bar<S2> {} 1824
1813 1825fn main() { let s<|>t = foo(); }
1814 fn main() { 1826"#,
1815 let s<|>t = foo(); 1827 expect![[r#"
1816 } 1828 [
1817 ", 1829 GoToType(
1818 &["impl Foo<S1> + Bar<S2>"], 1830 [
1819 ); 1831 HoverGotoTypeData {
1820 assert_debug_snapshot!(actions, 1832 mod_path: "Foo",
1821 @r###" 1833 nav: NavigationTarget {
1822 [ 1834 file_id: FileId(
1823 GoToType( 1835 1,
1824 [ 1836 ),
1825 HoverGotoTypeData { 1837 full_range: 0..15,
1826 mod_path: "Foo", 1838 focus_range: Some(
1827 nav: NavigationTarget { 1839 6..9,
1828 file_id: FileId( 1840 ),
1829 1, 1841 name: "Foo",
1830 ), 1842 kind: TRAIT_DEF,
1831 full_range: 0..15, 1843 container_name: None,
1832 name: "Foo", 1844 description: Some(
1833 kind: TRAIT_DEF, 1845 "trait Foo",
1834 focus_range: Some( 1846 ),
1835 6..9, 1847 docs: None,
1836 ), 1848 },
1837 container_name: None,
1838 description: Some(
1839 "trait Foo",
1840 ),
1841 docs: None,
1842 }, 1849 },
1843 }, 1850 HoverGotoTypeData {
1844 HoverGotoTypeData { 1851 mod_path: "Bar",
1845 mod_path: "Bar", 1852 nav: NavigationTarget {
1846 nav: NavigationTarget { 1853 file_id: FileId(
1847 file_id: FileId( 1854 1,
1848 1, 1855 ),
1849 ), 1856 full_range: 16..31,
1850 full_range: 16..31, 1857 focus_range: Some(
1851 name: "Bar", 1858 22..25,
1852 kind: TRAIT_DEF, 1859 ),
1853 focus_range: Some( 1860 name: "Bar",
1854 22..25, 1861 kind: TRAIT_DEF,
1855 ), 1862 container_name: None,
1856 container_name: None, 1863 description: Some(
1857 description: Some( 1864 "trait Bar",
1858 "trait Bar", 1865 ),
1859 ), 1866 docs: None,
1860 docs: None, 1867 },
1861 }, 1868 },
1862 }, 1869 HoverGotoTypeData {
1863 HoverGotoTypeData { 1870 mod_path: "S1",
1864 mod_path: "S1", 1871 nav: NavigationTarget {
1865 nav: NavigationTarget { 1872 file_id: FileId(
1866 file_id: FileId( 1873 1,
1867 1, 1874 ),
1868 ), 1875 full_range: 32..44,
1869 full_range: 32..44, 1876 focus_range: Some(
1870 name: "S1", 1877 39..41,
1871 kind: STRUCT_DEF, 1878 ),
1872 focus_range: Some( 1879 name: "S1",
1873 39..41, 1880 kind: STRUCT_DEF,
1874 ), 1881 container_name: None,
1875 container_name: None, 1882 description: Some(
1876 description: Some( 1883 "struct S1",
1877 "struct S1", 1884 ),
1878 ), 1885 docs: None,
1879 docs: None, 1886 },
1880 }, 1887 },
1881 }, 1888 HoverGotoTypeData {
1882 HoverGotoTypeData { 1889 mod_path: "S2",
1883 mod_path: "S2", 1890 nav: NavigationTarget {
1884 nav: NavigationTarget { 1891 file_id: FileId(
1885 file_id: FileId( 1892 1,
1886 1, 1893 ),
1887 ), 1894 full_range: 45..57,
1888 full_range: 45..57, 1895 focus_range: Some(
1889 name: "S2", 1896 52..54,
1890 kind: STRUCT_DEF, 1897 ),
1891 focus_range: Some( 1898 name: "S2",
1892 52..54, 1899 kind: STRUCT_DEF,
1893 ), 1900 container_name: None,
1894 container_name: None, 1901 description: Some(
1895 description: Some( 1902 "struct S2",
1896 "struct S2", 1903 ),
1897 ), 1904 docs: None,
1898 docs: None, 1905 },
1899 }, 1906 },
1900 }, 1907 ],
1901 ], 1908 ),
1902 ), 1909 ]
1903 ] 1910 "#]],
1904 "###); 1911 );
1905 } 1912 }
1906 1913
1907 #[test] 1914 #[test]
1908 fn test_hover_arg_impl_trait_has_goto_type_action() { 1915 fn test_hover_arg_impl_trait_has_goto_type_action() {
1909 let (_, actions) = check_hover_result( 1916 check_actions(
1910 r" 1917 r#"
1911 //- /lib.rs 1918trait Foo {}
1912 trait Foo {} 1919fn foo(ar<|>g: &impl Foo) {}
1913 fn foo(ar<|>g: &impl Foo) {} 1920"#,
1914 ", 1921 expect![[r#"
1915 &["&impl Foo"], 1922 [
1916 ); 1923 GoToType(
1917 assert_debug_snapshot!(actions, 1924 [
1918 @r###" 1925 HoverGotoTypeData {
1919 [ 1926 mod_path: "Foo",
1920 GoToType( 1927 nav: NavigationTarget {
1921 [ 1928 file_id: FileId(
1922 HoverGotoTypeData { 1929 1,
1923 mod_path: "Foo", 1930 ),
1924 nav: NavigationTarget { 1931 full_range: 0..12,
1925 file_id: FileId( 1932 focus_range: Some(
1926 1, 1933 6..9,
1927 ), 1934 ),
1928 full_range: 0..12, 1935 name: "Foo",
1929 name: "Foo", 1936 kind: TRAIT_DEF,
1930 kind: TRAIT_DEF, 1937 container_name: None,
1931 focus_range: Some( 1938 description: Some(
1932 6..9, 1939 "trait Foo",
1933 ), 1940 ),
1934 container_name: None, 1941 docs: None,
1935 description: Some( 1942 },
1936 "trait Foo",
1937 ),
1938 docs: None,
1939 }, 1943 },
1940 }, 1944 ],
1941 ], 1945 ),
1942 ), 1946 ]
1943 ] 1947 "#]],
1944 "###); 1948 );
1945 } 1949 }
1946 1950
1947 #[test] 1951 #[test]
1948 fn test_hover_arg_impl_traits_has_goto_type_action() { 1952 fn test_hover_arg_impl_traits_has_goto_type_action() {
1949 let (_, actions) = check_hover_result( 1953 check_actions(
1950 r" 1954 r#"
1951 //- /lib.rs 1955trait Foo {}
1952 trait Foo {} 1956trait Bar<T> {}
1953 trait Bar<T> {} 1957struct S{}
1954 struct S{} 1958
1955 1959fn foo(ar<|>g: &impl Foo + Bar<S>) {}
1956 fn foo(ar<|>g: &impl Foo + Bar<S>) {} 1960"#,
1957 ", 1961 expect![[r#"
1958 &["&impl Foo + Bar<S>"], 1962 [
1959 ); 1963 GoToType(
1960 assert_debug_snapshot!(actions, 1964 [
1961 @r###" 1965 HoverGotoTypeData {
1962 [ 1966 mod_path: "Foo",
1963 GoToType( 1967 nav: NavigationTarget {
1964 [ 1968 file_id: FileId(
1965 HoverGotoTypeData { 1969 1,
1966 mod_path: "Foo", 1970 ),
1967 nav: NavigationTarget { 1971 full_range: 0..12,
1968 file_id: FileId( 1972 focus_range: Some(
1969 1, 1973 6..9,
1970 ), 1974 ),
1971 full_range: 0..12, 1975 name: "Foo",
1972 name: "Foo", 1976 kind: TRAIT_DEF,
1973 kind: TRAIT_DEF, 1977 container_name: None,
1974 focus_range: Some( 1978 description: Some(
1975 6..9, 1979 "trait Foo",
1976 ), 1980 ),
1977 container_name: None, 1981 docs: None,
1978 description: Some( 1982 },
1979 "trait Foo",
1980 ),
1981 docs: None,
1982 }, 1983 },
1983 }, 1984 HoverGotoTypeData {
1984 HoverGotoTypeData { 1985 mod_path: "Bar",
1985 mod_path: "Bar", 1986 nav: NavigationTarget {
1986 nav: NavigationTarget { 1987 file_id: FileId(
1987 file_id: FileId( 1988 1,
1988 1, 1989 ),
1989 ), 1990 full_range: 13..28,
1990 full_range: 13..28, 1991 focus_range: Some(
1991 name: "Bar", 1992 19..22,
1992 kind: TRAIT_DEF, 1993 ),
1993 focus_range: Some( 1994 name: "Bar",
1994 19..22, 1995 kind: TRAIT_DEF,
1995 ), 1996 container_name: None,
1996 container_name: None, 1997 description: Some(
1997 description: Some( 1998 "trait Bar",
1998 "trait Bar", 1999 ),
1999 ), 2000 docs: None,
2000 docs: None, 2001 },
2001 }, 2002 },
2002 }, 2003 HoverGotoTypeData {
2003 HoverGotoTypeData { 2004 mod_path: "S",
2004 mod_path: "S", 2005 nav: NavigationTarget {
2005 nav: NavigationTarget { 2006 file_id: FileId(
2006 file_id: FileId( 2007 1,
2007 1, 2008 ),
2008 ), 2009 full_range: 29..39,
2009 full_range: 29..39, 2010 focus_range: Some(
2010 name: "S", 2011 36..37,
2011 kind: STRUCT_DEF, 2012 ),
2012 focus_range: Some( 2013 name: "S",
2013 36..37, 2014 kind: STRUCT_DEF,
2014 ), 2015 container_name: None,
2015 container_name: None, 2016 description: Some(
2016 description: Some( 2017 "struct S",
2017 "struct S", 2018 ),
2018 ), 2019 docs: None,
2019 docs: None, 2020 },
2020 }, 2021 },
2021 }, 2022 ],
2022 ], 2023 ),
2023 ), 2024 ]
2024 ] 2025 "#]],
2025 "###); 2026 );
2026 } 2027 }
2027 2028
2028 #[test] 2029 #[test]
2029 fn test_hover_arg_generic_impl_trait_has_goto_type_action() { 2030 fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2030 let (_, actions) = check_hover_result( 2031 check_actions(
2031 r" 2032 r#"
2032 //- /lib.rs 2033trait Foo<T> {}
2033 trait Foo<T> {} 2034struct S {}
2034 struct S {} 2035fn foo(ar<|>g: &impl Foo<S>) {}
2035 fn foo(ar<|>g: &impl Foo<S>) {} 2036"#,
2036 ", 2037 expect![[r#"
2037 &["&impl Foo<S>"], 2038 [
2038 ); 2039 GoToType(
2039 assert_debug_snapshot!(actions, 2040 [
2040 @r###" 2041 HoverGotoTypeData {
2041 [ 2042 mod_path: "Foo",
2042 GoToType( 2043 nav: NavigationTarget {
2043 [ 2044 file_id: FileId(
2044 HoverGotoTypeData { 2045 1,
2045 mod_path: "Foo", 2046 ),
2046 nav: NavigationTarget { 2047 full_range: 0..15,
2047 file_id: FileId( 2048 focus_range: Some(
2048 1, 2049 6..9,
2049 ), 2050 ),
2050 full_range: 0..15, 2051 name: "Foo",
2051 name: "Foo", 2052 kind: TRAIT_DEF,
2052 kind: TRAIT_DEF, 2053 container_name: None,
2053 focus_range: Some( 2054 description: Some(
2054 6..9, 2055 "trait Foo",
2055 ), 2056 ),
2056 container_name: None, 2057 docs: None,
2057 description: Some( 2058 },
2058 "trait Foo",
2059 ),
2060 docs: None,
2061 }, 2059 },
2062 }, 2060 HoverGotoTypeData {
2063 HoverGotoTypeData { 2061 mod_path: "S",
2064 mod_path: "S", 2062 nav: NavigationTarget {
2065 nav: NavigationTarget { 2063 file_id: FileId(
2066 file_id: FileId( 2064 1,
2067 1, 2065 ),
2068 ), 2066 full_range: 16..27,
2069 full_range: 16..27, 2067 focus_range: Some(
2070 name: "S", 2068 23..24,
2071 kind: STRUCT_DEF, 2069 ),
2072 focus_range: Some( 2070 name: "S",
2073 23..24, 2071 kind: STRUCT_DEF,
2074 ), 2072 container_name: None,
2075 container_name: None, 2073 description: Some(
2076 description: Some( 2074 "struct S",
2077 "struct S", 2075 ),
2078 ), 2076 docs: None,
2079 docs: None, 2077 },
2080 }, 2078 },
2081 }, 2079 ],
2082 ], 2080 ),
2083 ), 2081 ]
2084 ] 2082 "#]],
2085 "###); 2083 );
2086 } 2084 }
2087 2085
2088 #[test] 2086 #[test]
2089 fn test_hover_dyn_return_has_goto_type_action() { 2087 fn test_hover_dyn_return_has_goto_type_action() {
2090 let (_, actions) = check_hover_result( 2088 check_actions(
2091 r" 2089 r#"
2092 //- /main.rs 2090trait Foo {}
2093 trait Foo {} 2091struct S;
2094 struct S; 2092impl Foo for S {}
2095 impl Foo for S {}
2096
2097 struct B<T>{}
2098 2093
2099 fn foo() -> B<dyn Foo> {} 2094struct B<T>{}
2095fn foo() -> B<dyn Foo> {}
2100 2096
2101 fn main() { 2097fn main() { let s<|>t = foo(); }
2102 let s<|>t = foo(); 2098"#,
2103 } 2099 expect![[r#"
2104 ",
2105 &["B<dyn Foo>"],
2106 );
2107 assert_debug_snapshot!(actions,
2108 @r###"
2109 [
2110 GoToType(
2111 [ 2100 [
2112 HoverGotoTypeData { 2101 GoToType(
2113 mod_path: "B", 2102 [
2114 nav: NavigationTarget { 2103 HoverGotoTypeData {
2115 file_id: FileId( 2104 mod_path: "B",
2116 1, 2105 nav: NavigationTarget {
2117 ), 2106 file_id: FileId(
2118 full_range: 42..55, 2107 1,
2119 name: "B", 2108 ),
2120 kind: STRUCT_DEF, 2109 full_range: 42..55,
2121 focus_range: Some( 2110 focus_range: Some(
2122 49..50, 2111 49..50,
2123 ), 2112 ),
2124 container_name: None, 2113 name: "B",
2125 description: Some( 2114 kind: STRUCT_DEF,
2126 "struct B", 2115 container_name: None,
2127 ), 2116 description: Some(
2128 docs: None, 2117 "struct B",
2129 }, 2118 ),
2130 }, 2119 docs: None,
2131 HoverGotoTypeData { 2120 },
2132 mod_path: "Foo", 2121 },
2133 nav: NavigationTarget { 2122 HoverGotoTypeData {
2134 file_id: FileId( 2123 mod_path: "Foo",
2135 1, 2124 nav: NavigationTarget {
2136 ), 2125 file_id: FileId(
2137 full_range: 0..12, 2126 1,
2138 name: "Foo", 2127 ),
2139 kind: TRAIT_DEF, 2128 full_range: 0..12,
2140 focus_range: Some( 2129 focus_range: Some(
2141 6..9, 2130 6..9,
2142 ), 2131 ),
2143 container_name: None, 2132 name: "Foo",
2144 description: Some( 2133 kind: TRAIT_DEF,
2145 "trait Foo", 2134 container_name: None,
2146 ), 2135 description: Some(
2147 docs: None, 2136 "trait Foo",
2148 }, 2137 ),
2149 }, 2138 docs: None,
2150 ], 2139 },
2151 ), 2140 },
2152 ] 2141 ],
2153 "###); 2142 ),
2143 ]
2144 "#]],
2145 );
2154 } 2146 }
2155 2147
2156 #[test] 2148 #[test]
2157 fn test_hover_dyn_arg_has_goto_type_action() { 2149 fn test_hover_dyn_arg_has_goto_type_action() {
2158 let (_, actions) = check_hover_result( 2150 check_actions(
2159 r" 2151 r#"
2160 //- /lib.rs 2152trait Foo {}
2161 trait Foo {} 2153fn foo(ar<|>g: &dyn Foo) {}
2162 fn foo(ar<|>g: &dyn Foo) {} 2154"#,
2163 ", 2155 expect![[r#"
2164 &["&dyn Foo"], 2156 [
2165 ); 2157 GoToType(
2166 assert_debug_snapshot!(actions, 2158 [
2167 @r###" 2159 HoverGotoTypeData {
2168 [ 2160 mod_path: "Foo",
2169 GoToType( 2161 nav: NavigationTarget {
2170 [ 2162 file_id: FileId(
2171 HoverGotoTypeData { 2163 1,
2172 mod_path: "Foo", 2164 ),
2173 nav: NavigationTarget { 2165 full_range: 0..12,
2174 file_id: FileId( 2166 focus_range: Some(
2175 1, 2167 6..9,
2176 ), 2168 ),
2177 full_range: 0..12, 2169 name: "Foo",
2178 name: "Foo", 2170 kind: TRAIT_DEF,
2179 kind: TRAIT_DEF, 2171 container_name: None,
2180 focus_range: Some( 2172 description: Some(
2181 6..9, 2173 "trait Foo",
2182 ), 2174 ),
2183 container_name: None, 2175 docs: None,
2184 description: Some( 2176 },
2185 "trait Foo",
2186 ),
2187 docs: None,
2188 }, 2177 },
2189 }, 2178 ],
2190 ], 2179 ),
2191 ), 2180 ]
2192 ] 2181 "#]],
2193 "###); 2182 );
2194 } 2183 }
2195 2184
2196 #[test] 2185 #[test]
2197 fn test_hover_generic_dyn_arg_has_goto_type_action() { 2186 fn test_hover_generic_dyn_arg_has_goto_type_action() {
2198 let (_, actions) = check_hover_result( 2187 check_actions(
2199 r" 2188 r#"
2200 //- /lib.rs 2189trait Foo<T> {}
2201 trait Foo<T> {} 2190struct S {}
2202 struct S {} 2191fn foo(ar<|>g: &dyn Foo<S>) {}
2203 fn foo(ar<|>g: &dyn Foo<S>) {} 2192"#,
2204 ", 2193 expect![[r#"
2205 &["&dyn Foo<S>"], 2194 [
2206 ); 2195 GoToType(
2207 assert_debug_snapshot!(actions, 2196 [
2208 @r###" 2197 HoverGotoTypeData {
2209 [ 2198 mod_path: "Foo",
2210 GoToType( 2199 nav: NavigationTarget {
2211 [ 2200 file_id: FileId(
2212 HoverGotoTypeData { 2201 1,
2213 mod_path: "Foo", 2202 ),
2214 nav: NavigationTarget { 2203 full_range: 0..15,
2215 file_id: FileId( 2204 focus_range: Some(
2216 1, 2205 6..9,
2217 ), 2206 ),
2218 full_range: 0..15, 2207 name: "Foo",
2219 name: "Foo", 2208 kind: TRAIT_DEF,
2220 kind: TRAIT_DEF, 2209 container_name: None,
2221 focus_range: Some( 2210 description: Some(
2222 6..9, 2211 "trait Foo",
2223 ), 2212 ),
2224 container_name: None, 2213 docs: None,
2225 description: Some( 2214 },
2226 "trait Foo",
2227 ),
2228 docs: None,
2229 }, 2215 },
2230 }, 2216 HoverGotoTypeData {
2231 HoverGotoTypeData { 2217 mod_path: "S",
2232 mod_path: "S", 2218 nav: NavigationTarget {
2233 nav: NavigationTarget { 2219 file_id: FileId(
2234 file_id: FileId( 2220 1,
2235 1, 2221 ),
2236 ), 2222 full_range: 16..27,
2237 full_range: 16..27, 2223 focus_range: Some(
2238 name: "S", 2224 23..24,
2239 kind: STRUCT_DEF, 2225 ),
2240 focus_range: Some( 2226 name: "S",
2241 23..24, 2227 kind: STRUCT_DEF,
2242 ), 2228 container_name: None,
2243 container_name: None, 2229 description: Some(
2244 description: Some( 2230 "struct S",
2245 "struct S", 2231 ),
2246 ), 2232 docs: None,
2247 docs: None, 2233 },
2248 }, 2234 },
2249 }, 2235 ],
2250 ], 2236 ),
2251 ), 2237 ]
2252 ] 2238 "#]],
2253 "###); 2239 );
2254 } 2240 }
2255 2241
2256 #[test] 2242 #[test]
2257 fn test_hover_goto_type_action_links_order() { 2243 fn test_hover_goto_type_action_links_order() {
2258 let (_, actions) = check_hover_result( 2244 check_actions(
2259 r" 2245 r#"
2260 //- /lib.rs 2246trait ImplTrait<T> {}
2261 trait ImplTrait<T> {} 2247trait DynTrait<T> {}
2262 trait DynTrait<T> {} 2248struct B<T> {}
2263 struct B<T> {} 2249struct S {}
2264 struct S {} 2250
2265 2251fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
2266 fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {} 2252 "#,
2267 ", 2253 expect![[r#"
2268 &["&impl ImplTrait<B<dyn DynTrait<B<S>>>>"], 2254 [
2269 ); 2255 GoToType(
2270 assert_debug_snapshot!(actions, 2256 [
2271 @r###" 2257 HoverGotoTypeData {
2272 [ 2258 mod_path: "ImplTrait",
2273 GoToType( 2259 nav: NavigationTarget {
2274 [ 2260 file_id: FileId(
2275 HoverGotoTypeData { 2261 1,
2276 mod_path: "ImplTrait", 2262 ),
2277 nav: NavigationTarget { 2263 full_range: 0..21,
2278 file_id: FileId( 2264 focus_range: Some(
2279 1, 2265 6..15,
2280 ), 2266 ),
2281 full_range: 0..21, 2267 name: "ImplTrait",
2282 name: "ImplTrait", 2268 kind: TRAIT_DEF,
2283 kind: TRAIT_DEF, 2269 container_name: None,
2284 focus_range: Some( 2270 description: Some(
2285 6..15, 2271 "trait ImplTrait",
2286 ), 2272 ),
2287 container_name: None, 2273 docs: None,
2288 description: Some( 2274 },
2289 "trait ImplTrait",
2290 ),
2291 docs: None,
2292 }, 2275 },
2293 }, 2276 HoverGotoTypeData {
2294 HoverGotoTypeData { 2277 mod_path: "B",
2295 mod_path: "B", 2278 nav: NavigationTarget {
2296 nav: NavigationTarget { 2279 file_id: FileId(
2297 file_id: FileId( 2280 1,
2298 1, 2281 ),
2299 ), 2282 full_range: 43..57,
2300 full_range: 43..57, 2283 focus_range: Some(
2301 name: "B", 2284 50..51,
2302 kind: STRUCT_DEF, 2285 ),
2303 focus_range: Some( 2286 name: "B",
2304 50..51, 2287 kind: STRUCT_DEF,
2305 ), 2288 container_name: None,
2306 container_name: None, 2289 description: Some(
2307 description: Some( 2290 "struct B",
2308 "struct B", 2291 ),
2309 ), 2292 docs: None,
2310 docs: None, 2293 },
2311 }, 2294 },
2312 }, 2295 HoverGotoTypeData {
2313 HoverGotoTypeData { 2296 mod_path: "DynTrait",
2314 mod_path: "DynTrait", 2297 nav: NavigationTarget {
2315 nav: NavigationTarget { 2298 file_id: FileId(
2316 file_id: FileId( 2299 1,
2317 1, 2300 ),
2318 ), 2301 full_range: 22..42,
2319 full_range: 22..42, 2302 focus_range: Some(
2320 name: "DynTrait", 2303 28..36,
2321 kind: TRAIT_DEF, 2304 ),
2322 focus_range: Some( 2305 name: "DynTrait",
2323 28..36, 2306 kind: TRAIT_DEF,
2324 ), 2307 container_name: None,
2325 container_name: None, 2308 description: Some(
2326 description: Some( 2309 "trait DynTrait",
2327 "trait DynTrait", 2310 ),
2328 ), 2311 docs: None,
2329 docs: None, 2312 },
2330 }, 2313 },
2331 }, 2314 HoverGotoTypeData {
2332 HoverGotoTypeData { 2315 mod_path: "S",
2333 mod_path: "S", 2316 nav: NavigationTarget {
2334 nav: NavigationTarget { 2317 file_id: FileId(
2335 file_id: FileId( 2318 1,
2336 1, 2319 ),
2337 ), 2320 full_range: 58..69,
2338 full_range: 58..69, 2321 focus_range: Some(
2339 name: "S", 2322 65..66,
2340 kind: STRUCT_DEF, 2323 ),
2341 focus_range: Some( 2324 name: "S",
2342 65..66, 2325 kind: STRUCT_DEF,
2343 ), 2326 container_name: None,
2344 container_name: None, 2327 description: Some(
2345 description: Some( 2328 "struct S",
2346 "struct S", 2329 ),
2347 ), 2330 docs: None,
2348 docs: None, 2331 },
2349 }, 2332 },
2350 }, 2333 ],
2351 ], 2334 ),
2352 ), 2335 ]
2353 ] 2336 "#]],
2354 "###); 2337 );
2355 } 2338 }
2356 2339
2357 #[test] 2340 #[test]
2358 fn test_hover_associated_type_has_goto_type_action() { 2341 fn test_hover_associated_type_has_goto_type_action() {
2359 let (_, actions) = check_hover_result( 2342 check_actions(
2360 r" 2343 r#"
2361 //- /main.rs 2344trait Foo {
2362 trait Foo { 2345 type Item;
2363 type Item; 2346 fn get(self) -> Self::Item {}
2364 fn get(self) -> Self::Item {} 2347}
2365 }
2366 2348
2367 struct Bar{} 2349struct Bar{}
2368 struct S{} 2350struct S{}
2369 2351
2370 impl Foo for S{ 2352impl Foo for S { type Item = Bar; }
2371 type Item = Bar;
2372 }
2373 2353
2374 fn test() -> impl Foo { 2354fn test() -> impl Foo { S {} }
2375 S{}
2376 }
2377 2355
2378 fn main() { 2356fn main() { let s<|>t = test().get(); }
2379 let s<|>t = test().get(); 2357"#,
2380 } 2358 expect![[r#"
2381 ", 2359 [
2382 &["Foo::Item<impl Foo>"], 2360 GoToType(
2383 ); 2361 [
2384 assert_debug_snapshot!(actions, 2362 HoverGotoTypeData {
2385 @r###" 2363 mod_path: "Foo",
2386 [ 2364 nav: NavigationTarget {
2387 GoToType( 2365 file_id: FileId(
2388 [ 2366 1,
2389 HoverGotoTypeData { 2367 ),
2390 mod_path: "Foo", 2368 full_range: 0..62,
2391 nav: NavigationTarget { 2369 focus_range: Some(
2392 file_id: FileId( 2370 6..9,
2393 1, 2371 ),
2394 ), 2372 name: "Foo",
2395 full_range: 0..62, 2373 kind: TRAIT_DEF,
2396 name: "Foo", 2374 container_name: None,
2397 kind: TRAIT_DEF, 2375 description: Some(
2398 focus_range: Some( 2376 "trait Foo",
2399 6..9, 2377 ),
2400 ), 2378 docs: None,
2401 container_name: None, 2379 },
2402 description: Some(
2403 "trait Foo",
2404 ),
2405 docs: None,
2406 }, 2380 },
2407 }, 2381 ],
2408 ], 2382 ),
2409 ), 2383 ]
2410 ] 2384 "#]],
2411 "###); 2385 );
2412 } 2386 }
2413} 2387}