diff options
Diffstat (limited to 'crates/ra_ide/src/hover.rs')
-rw-r--r-- | crates/ra_ide/src/hover.rs | 3400 |
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 @@ | |||
1 | use std::iter::once; | ||
2 | |||
3 | use hir::{ | 1 | use 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 | }; |
13 | use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; | 11 | use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
12 | use stdx::format_to; | ||
13 | use test_utils::mark; | ||
14 | 14 | ||
15 | use crate::{ | 15 | use 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 | }; |
22 | use test_utils::mark; | ||
23 | 21 | ||
24 | #[derive(Clone, Debug, PartialEq, Eq)] | 22 | #[derive(Clone, Debug, PartialEq, Eq)] |
25 | pub struct HoverConfig { | 23 | pub 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)] |
70 | pub struct HoverResult { | 68 | pub struct HoverResult { |
71 | results: Vec<String>, | 69 | pub markup: Markup, |
72 | actions: Vec<HoverAction>, | 70 | pub actions: Vec<HoverAction>, |
73 | } | ||
74 | |||
75 | impl 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 | |||
186 | fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | 133 | fn 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 | ||
274 | fn hover_text( | 225 | fn 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 | ||
304 | fn determine_mod_path(db: &RootDatabase, module: Module, name: Option<String>) -> String { | 268 | fn 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 | ||
319 | fn 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 | ||
323 | fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { | 279 | fn 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 | ||
327 | fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { | 283 | fn 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)] |
395 | mod tests { | 351 | mod 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#" |
447 | pub fn foo() -> u32 { 1 } | 385 | pub 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 | 404 | struct Scan<A, B, C> { a: A, b: B, c: C } |
464 | struct Scan<A, B, C> { | 405 | struct Iter<I> { inner: I } |
465 | a: A, | 406 | enum Option<T> { Some(T), None } |
466 | b: B, | ||
467 | c: C, | ||
468 | } | ||
469 | 407 | ||
470 | struct FakeIter<I> { | 408 | struct OtherStruct<T> { i: T } |
471 | inner: I, | ||
472 | } | ||
473 | |||
474 | struct OtherStruct<T> { | ||
475 | i: T, | ||
476 | } | ||
477 | 409 | ||
478 | enum FakeOption<T> { | 410 | fn 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() { | 414 | fn 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 | 437 | pub fn foo() -> u32 { 1 } |
506 | pub fn foo() -> u32 { 1 } | ||
507 | 438 | ||
508 | fn main() { | 439 | fn 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 } | 453 | pub fn foo() -> u32 { 1 } |
520 | 454 | ||
521 | //- /b.rs | 455 | //- /b.rs |
522 | pub fn foo() -> &str { "" } | 456 | pub fn foo() -> &str { "" } |
523 | 457 | ||
524 | //- /c.rs | 458 | //- /c.rs |
525 | pub fn foo(a: u32, b: u32) {} | 459 | pub fn foo(a: u32, b: u32) {} |
526 | 460 | ||
527 | //- /main.rs | 461 | //- /main.rs |
528 | mod a; | 462 | mod a; |
529 | mod b; | 463 | mod b; |
530 | mod c; | 464 | mod c; |
531 | 465 | ||
532 | fn main() { | 466 | fn 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 | 481 | pub 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() { | 483 | fn 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 | 498 | pub fn foo<|>(a: u32, b: u32) -> u32 {} |
560 | pub fn foo<|>(a: u32, b: u32) -> u32 {} | ||
561 | 499 | ||
562 | fn main() { | 500 | fn 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 | 516 | struct Foo { field_a: u32 } |
575 | struct Foo { | ||
576 | field_a: u32, | ||
577 | } | ||
578 | 517 | ||
579 | fn main() { | 518 | fn 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 | 537 | struct Foo { field_a<|>: u32 } |
592 | struct Foo { | ||
593 | field_a<|>: u32, | ||
594 | } | ||
595 | 538 | ||
596 | fn main() { | 539 | fn 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 | 582 | struct Test<K, T = u8> { k: K, t: T } |
630 | struct Test<K, T = u8> { | ||
631 | k: K, | ||
632 | t: T, | ||
633 | } | ||
634 | 583 | ||
635 | fn main() { | 584 | fn 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) } | 600 | enum Option<T> { Some(T) } |
647 | use Option::Some; | 601 | use Option::Some; |
648 | 602 | ||
649 | fn main() { | 603 | fn 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) } | 619 | enum Option<T> { Some(T) } |
660 | use Option::Some; | 620 | use Option::Some; |
661 | 621 | ||
662 | fn main() { | 622 | fn 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 | 637 | enum 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* |
682 | Option | 644 | ```rust |
683 | ``` | 645 | Option |
646 | ``` | ||
684 | 647 | ||
685 | ```rust | 648 | ```rust |
686 | None | 649 | None |
687 | ``` | 650 | ``` |
688 | ___ | 651 | ___ |
689 | 652 | ||
690 | The 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 | 659 | enum Option<T> { |
698 | enum Option<T> { | 660 | /// The Some variant |
699 | /// The Some variant | 661 | Some(T) |
700 | Some(T) | 662 | } |
701 | } | 663 | fn 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* |
707 | Option | 669 | ```rust |
708 | ``` | 670 | Option |
671 | ``` | ||
709 | 672 | ||
710 | ```rust | 673 | ```rust |
711 | Some | 674 | Some |
712 | ``` | 675 | ``` |
713 | ___ | 676 | ___ |
714 | 677 | ||
715 | The 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; }; }"#, |
739 | fn 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 } | 739 | struct Thing { x: u32 } |
758 | 740 | ||
759 | impl Thing { | 741 | impl Thing { |
760 | fn new() -> Thing { | 742 | fn new() -> Thing { Thing { x: 0 } } |
761 | Thing { x: 0 } | 743 | } |
762 | } | ||
763 | } | ||
764 | 744 | ||
765 | fn main() { | 745 | fn 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 { | 760 | mod 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() { | 768 | fn 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; | 787 | struct X; |
805 | impl X { | 788 | impl X { |
806 | const C: u32 = 1; | 789 | const C: u32 = 1; |
807 | } | 790 | } |
808 | 791 | ||
809 | fn main() { | 792 | fn 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 } | 813 | struct Thing { x: u32 } |
827 | impl Thing { | 814 | impl 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() {} | 870 | fn x() {} |
884 | 871 | ||
885 | fn y() { | 872 | fn 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 { | 890 | macro_rules! foo { () => {} } |
900 | () => {} | ||
901 | } | ||
902 | 891 | ||
903 | fn f() { | 892 | fn 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 | 918 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
928 | macro_rules! id { | 919 | fn foo() {} |
929 | ($($tt:tt)*) => { $($tt)* } | 920 | id! { |
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 | 937 | macro_rules! id { ($($tt:tt)*) => { $($tt)* } } |
949 | macro_rules! id { | 938 | fn 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 | 953 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } |
967 | macro_rules! id_deep { | 954 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } |
968 | ($($tt:tt)*) => { $($tt)* } | 955 | fn 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 | 970 | macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } |
988 | macro_rules! id_deep { | 971 | macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } |
989 | ($($tt:tt)*) => { $($tt)* } | 972 | fn bar() -> u32 { 0 } |
990 | } | 973 | fn 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 | 988 | macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } } |
1012 | macro_rules! arr { | 989 | fn 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] | 1008 | macro_rules! assert {} |
1032 | macro_rules! assert {} | ||
1033 | 1009 | ||
1034 | fn bar() -> bool { true } | 1010 | fn bar() -> bool { true } |
1035 | fn foo() { | 1011 | fn 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 | 1043 | fn foo() { } |
1066 | fn foo() { | ||
1067 | } | ||
1068 | 1044 | ||
1069 | fn bar() { | 1045 | fn 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 | 1113 | use self::m<|>y::Bar; |
1119 | use self::m<|>y::Bar; | 1114 | mod my { pub struct Bar; } |
1120 | |||
1121 | mod my { | ||
1122 | pub struct Bar; | ||
1123 | } | ||
1124 | 1115 | ||
1125 | fn my() {} | 1116 | fn 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 | 1132 | struct Bar; |
1137 | struct Bar; | ||
1138 | 1133 | ||
1139 | fn foo() { | 1134 | fn 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"] | 1153 | struct Bar; |
1153 | struct Bar; | ||
1154 | 1154 | ||
1155 | fn foo() { | 1155 | fn 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"] | 1176 | struct Bar; |
1171 | struct Bar; | ||
1172 | 1177 | ||
1173 | fn foo() { | 1178 | fn 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 | 1202 | macro_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!(); | 1212 | bar!(); |
1199 | 1213 | ||
1200 | fn foo() { | 1214 | fn 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 | 1238 | macro_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!(); | 1248 | bar!(); |
1227 | 1249 | ||
1228 | fn foo() { | 1250 | fn 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 } | 1349 | fn 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 | 1389 | mod 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 | 1427 | struct S{ f1: u32 } |
1484 | struct Arg(u32); | 1428 | |
1485 | struct S<T>{ f1: T } | 1429 | fn 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", | 1465 | struct Arg(u32); |
1500 | nav: NavigationTarget { | 1466 | struct S<T>{ f1: T } |
1501 | file_id: FileId( | 1467 | |
1502 | 1, | 1468 | fn 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 | 1523 | struct Arg(u32); |
1547 | struct A(u32); | 1524 | struct S<T>{ f1: T } |
1548 | struct B(u32); | ||
1549 | mod M { | ||
1550 | pub struct C(u32); | ||
1551 | } | ||
1552 | 1525 | ||
1553 | fn main() { | 1526 | fn 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", | 1581 | struct A(u32); |
1566 | nav: NavigationTarget { | 1582 | struct B(u32); |
1567 | file_id: FileId( | 1583 | mod M { |
1568 | 1, | 1584 | pub struct C(u32); |
1569 | ), | 1585 | } |
1570 | full_range: 0..14, | 1586 | |
1571 | name: "A", | 1587 | fn 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 | 1661 | trait Foo {} |
1632 | trait Foo {} | 1662 | fn foo() -> impl Foo {} |
1633 | |||
1634 | fn foo() -> impl Foo {} | ||
1635 | 1663 | ||
1636 | fn main() { | 1664 | fn 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 | 1700 | trait Foo<T> {} |
1677 | trait Foo<T> {} | 1701 | struct S; |
1678 | struct S; | 1702 | fn foo() -> impl Foo<S> {} |
1679 | |||
1680 | fn foo() -> impl Foo<S> {} | ||
1681 | 1703 | ||
1682 | fn main() { | 1704 | fn 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 | 1759 | trait Foo {} |
1742 | trait Foo {} | 1760 | trait Bar {} |
1743 | trait Bar {} | 1761 | fn foo() -> impl Foo + Bar {} |
1744 | |||
1745 | fn foo() -> impl Foo + Bar {} | ||
1746 | 1762 | ||
1747 | fn main() { | 1763 | fn 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 | 1818 | trait Foo<T> {} |
1807 | trait Foo<T> {} | 1819 | trait Bar<T> {} |
1808 | trait Bar<T> {} | 1820 | struct S1 {} |
1809 | struct S1 {} | 1821 | struct S2 {} |
1810 | struct S2 {} | 1822 | |
1811 | 1823 | fn foo() -> impl Foo<S1> + Bar<S2> {} | |
1812 | fn foo() -> impl Foo<S1> + Bar<S2> {} | 1824 | |
1813 | 1825 | fn 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 | 1918 | trait Foo {} |
1912 | trait Foo {} | 1919 | fn 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 | 1955 | trait Foo {} |
1952 | trait Foo {} | 1956 | trait Bar<T> {} |
1953 | trait Bar<T> {} | 1957 | struct S{} |
1954 | struct S{} | 1958 | |
1955 | 1959 | fn 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 | 2033 | trait Foo<T> {} |
2033 | trait Foo<T> {} | 2034 | struct S {} |
2034 | struct S {} | 2035 | fn 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 | 2090 | trait Foo {} |
2093 | trait Foo {} | 2091 | struct S; |
2094 | struct S; | 2092 | impl Foo for S {} |
2095 | impl Foo for S {} | ||
2096 | |||
2097 | struct B<T>{} | ||
2098 | 2093 | ||
2099 | fn foo() -> B<dyn Foo> {} | 2094 | struct B<T>{} |
2095 | fn foo() -> B<dyn Foo> {} | ||
2100 | 2096 | ||
2101 | fn main() { | 2097 | fn 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 | 2152 | trait Foo {} |
2161 | trait Foo {} | 2153 | fn 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 | 2189 | trait Foo<T> {} |
2201 | trait Foo<T> {} | 2190 | struct S {} |
2202 | struct S {} | 2191 | fn 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 | 2246 | trait ImplTrait<T> {} |
2261 | trait ImplTrait<T> {} | 2247 | trait DynTrait<T> {} |
2262 | trait DynTrait<T> {} | 2248 | struct B<T> {} |
2263 | struct B<T> {} | 2249 | struct S {} |
2264 | struct S {} | 2250 | |
2265 | 2251 | fn 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 | 2344 | trait 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{} | 2349 | struct Bar{} |
2368 | struct S{} | 2350 | struct S{} |
2369 | 2351 | ||
2370 | impl Foo for S{ | 2352 | impl Foo for S { type Item = Bar; } |
2371 | type Item = Bar; | ||
2372 | } | ||
2373 | 2353 | ||
2374 | fn test() -> impl Foo { | 2354 | fn test() -> impl Foo { S {} } |
2375 | S{} | ||
2376 | } | ||
2377 | 2355 | ||
2378 | fn main() { | 2356 | fn 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 | } |