diff options
author | vsrs <[email protected]> | 2020-06-10 19:24:36 +0100 |
---|---|---|
committer | vsrs <[email protected]> | 2020-06-18 08:15:43 +0100 |
commit | c50157f33025b6ff01809b975a3d12c0e43a0072 (patch) | |
tree | 2b40e6ee3cbb463000432c760311b8a2a1a3292c | |
parent | 4d6c6a6b1e00f61af96e16386c7f03f83f96a173 (diff) |
Add `Go to Type Definition` hover action.
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 108 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/display/navigation_target.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 811 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 46 |
8 files changed, 956 insertions, 35 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 1a9f6cc76..c22eb451b 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -26,8 +26,8 @@ use hir_ty::{ | |||
26 | autoderef, | 26 | autoderef, |
27 | display::{HirDisplayError, HirFormatter}, | 27 | display::{HirDisplayError, HirFormatter}, |
28 | expr::ExprValidator, | 28 | expr::ExprValidator, |
29 | method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty, | 29 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, OpaqueTyId, |
30 | TyDefId, TypeCtor, | 30 | Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, |
31 | }; | 31 | }; |
32 | use ra_db::{CrateId, CrateName, Edition, FileId}; | 32 | use ra_db::{CrateId, CrateName, Edition, FileId}; |
33 | use ra_prof::profile; | 33 | use ra_prof::profile; |
@@ -1380,6 +1380,87 @@ impl Type { | |||
1380 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, | 1380 | ty: InEnvironment { value: ty, environment: self.ty.environment.clone() }, |
1381 | } | 1381 | } |
1382 | } | 1382 | } |
1383 | |||
1384 | /// Returns a flattened list of all the ADTs and Traits mentioned in the type | ||
1385 | pub fn flattened_type_items(&self, db: &dyn HirDatabase) -> Vec<AdtOrTrait> { | ||
1386 | fn push_new_item(item: AdtOrTrait, acc: &mut Vec<AdtOrTrait>) { | ||
1387 | if !acc.contains(&item) { | ||
1388 | acc.push(item); | ||
1389 | } | ||
1390 | } | ||
1391 | |||
1392 | fn push_bounds( | ||
1393 | db: &dyn HirDatabase, | ||
1394 | predicates: &[GenericPredicate], | ||
1395 | acc: &mut Vec<AdtOrTrait>, | ||
1396 | ) { | ||
1397 | for p in predicates.iter() { | ||
1398 | match p { | ||
1399 | GenericPredicate::Implemented(trait_ref) => { | ||
1400 | push_new_item(Trait::from(trait_ref.trait_).into(), acc); | ||
1401 | walk_types(db, &trait_ref.substs, acc); | ||
1402 | } | ||
1403 | GenericPredicate::Projection(_) => {} | ||
1404 | GenericPredicate::Error => (), | ||
1405 | } | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | fn walk_types<T: TypeWalk>(db: &dyn HirDatabase, tw: &T, acc: &mut Vec<AdtOrTrait>) { | ||
1410 | tw.walk(&mut |ty| walk_type(db, ty, acc)); | ||
1411 | } | ||
1412 | |||
1413 | fn walk_type(db: &dyn HirDatabase, ty: &Ty, acc: &mut Vec<AdtOrTrait>) { | ||
1414 | match ty.strip_references() { | ||
1415 | Ty::Apply(ApplicationTy { ctor, parameters, .. }) => { | ||
1416 | match ctor { | ||
1417 | TypeCtor::Adt(adt_id) => push_new_item(Adt::from(*adt_id).into(), acc), | ||
1418 | _ => (), | ||
1419 | } | ||
1420 | // adt params, tuples, etc... | ||
1421 | walk_types(db, parameters, acc); | ||
1422 | } | ||
1423 | Ty::Dyn(predicates) => { | ||
1424 | push_bounds(db, predicates, acc); | ||
1425 | } | ||
1426 | Ty::Placeholder(id) => { | ||
1427 | let generic_params = db.generic_params(id.parent); | ||
1428 | let param_data = &generic_params.types[id.local_id]; | ||
1429 | match param_data.provenance { | ||
1430 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | ||
1431 | let predicates: Vec<_> = db | ||
1432 | .generic_predicates_for_param(*id) | ||
1433 | .into_iter() | ||
1434 | .map(|pred| pred.value.clone()) | ||
1435 | .collect(); | ||
1436 | push_bounds(db, &predicates, acc); | ||
1437 | } | ||
1438 | _ => (), | ||
1439 | } | ||
1440 | } | ||
1441 | Ty::Opaque(opaque_ty) => { | ||
1442 | let bounds = match opaque_ty.opaque_ty_id { | ||
1443 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | ||
1444 | let datas = db | ||
1445 | .return_type_impl_traits(func) | ||
1446 | .expect("impl trait id without data"); | ||
1447 | let data = (*datas) | ||
1448 | .as_ref() | ||
1449 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | ||
1450 | data.clone().subst(&opaque_ty.parameters) | ||
1451 | } | ||
1452 | }; | ||
1453 | push_bounds(db, &bounds.value, acc); | ||
1454 | walk_types(db, &opaque_ty.parameters, acc); | ||
1455 | } | ||
1456 | _ => (), | ||
1457 | } | ||
1458 | } | ||
1459 | |||
1460 | let mut res: Vec<AdtOrTrait> = Vec::new(); // not a Set to preserve the order | ||
1461 | walk_type(db, &self.ty.value, &mut res); | ||
1462 | res | ||
1463 | } | ||
1383 | } | 1464 | } |
1384 | 1465 | ||
1385 | impl HirDisplay for Type { | 1466 | impl HirDisplay for Type { |
@@ -1488,3 +1569,26 @@ pub trait HasVisibility { | |||
1488 | vis.is_visible_from(db.upcast(), module.id) | 1569 | vis.is_visible_from(db.upcast(), module.id) |
1489 | } | 1570 | } |
1490 | } | 1571 | } |
1572 | |||
1573 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
1574 | pub enum AdtOrTrait { | ||
1575 | Adt(Adt), | ||
1576 | Trait(Trait), | ||
1577 | } | ||
1578 | impl_froms!(AdtOrTrait: Adt, Trait); | ||
1579 | |||
1580 | impl AdtOrTrait { | ||
1581 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1582 | match self { | ||
1583 | AdtOrTrait::Adt(adt) => adt.module(db), | ||
1584 | AdtOrTrait::Trait(trait_) => trait_.module(db), | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | pub fn name(self, db: &dyn HirDatabase) -> Name { | ||
1589 | match self { | ||
1590 | AdtOrTrait::Adt(adt) => adt.name(db), | ||
1591 | AdtOrTrait::Trait(trait_) => trait_.name(db), | ||
1592 | } | ||
1593 | } | ||
1594 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3364a822f..eded039e4 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -51,10 +51,10 @@ mod has_source; | |||
51 | 51 | ||
52 | pub use crate::{ | 52 | pub use crate::{ |
53 | code_model::{ | 53 | code_model::{ |
54 | Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency, | 54 | Adt, AdtOrTrait, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, |
55 | DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, GenericDef, HasAttrs, | 55 | CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, |
56 | HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, | 56 | GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, |
57 | Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, | 57 | Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, |
58 | }, | 58 | }, |
59 | has_source::HasSource, | 59 | has_source::HasSource, |
60 | semantics::{original_range, PathResolution, Semantics, SemanticsScope}, | 60 | semantics::{original_range, PathResolution, Semantics, SemanticsScope}, |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 2b9372b4b..9d4d6aaa4 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -1052,10 +1052,10 @@ pub enum OpaqueTyId { | |||
1052 | 1052 | ||
1053 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1053 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1054 | pub struct ReturnTypeImplTraits { | 1054 | pub struct ReturnTypeImplTraits { |
1055 | pub(crate) impl_traits: Vec<ReturnTypeImplTrait>, | 1055 | pub impl_traits: Vec<ReturnTypeImplTrait>, |
1056 | } | 1056 | } |
1057 | 1057 | ||
1058 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1058 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1059 | pub(crate) struct ReturnTypeImplTrait { | 1059 | pub struct ReturnTypeImplTrait { |
1060 | pub(crate) bounds: Binders<Vec<GenericPredicate>>, | 1060 | pub bounds: Binders<Vec<GenericPredicate>>, |
1061 | } | 1061 | } |
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index c7bb1e69f..325b247bb 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs | |||
@@ -321,6 +321,15 @@ impl ToNav for hir::Adt { | |||
321 | } | 321 | } |
322 | } | 322 | } |
323 | 323 | ||
324 | impl ToNav for hir::AdtOrTrait { | ||
325 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
326 | match self { | ||
327 | hir::AdtOrTrait::Adt(adt) => adt.to_nav(db), | ||
328 | hir::AdtOrTrait::Trait(trait_) => trait_.to_nav(db), | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
324 | impl ToNav for hir::AssocItem { | 333 | impl ToNav for hir::AssocItem { |
325 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 334 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
326 | match self { | 335 | match self { |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index ad78b7671..c434e5c8b 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -1,8 +1,8 @@ | |||
1 | use std::iter::once; | 1 | use std::iter::once; |
2 | 2 | ||
3 | use hir::{ | 3 | use hir::{ |
4 | Adt, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, HirDisplay, | 4 | Adt, AdtOrTrait, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, |
5 | ModuleDef, ModuleSource, Semantics, | 5 | HirDisplay, Module, ModuleDef, ModuleSource, Semantics, |
6 | }; | 6 | }; |
7 | use itertools::Itertools; | 7 | use itertools::Itertools; |
8 | use ra_db::SourceDatabase; | 8 | use ra_db::SourceDatabase; |
@@ -24,19 +24,21 @@ pub struct HoverConfig { | |||
24 | pub implementations: bool, | 24 | pub implementations: bool, |
25 | pub run: bool, | 25 | pub run: bool, |
26 | pub debug: bool, | 26 | pub debug: bool, |
27 | pub goto_type_def: bool, | ||
27 | } | 28 | } |
28 | 29 | ||
29 | impl Default for HoverConfig { | 30 | impl Default for HoverConfig { |
30 | fn default() -> Self { | 31 | fn default() -> Self { |
31 | Self { implementations: true, run: true, debug: true } | 32 | Self { implementations: true, run: true, debug: true, goto_type_def: true } |
32 | } | 33 | } |
33 | } | 34 | } |
34 | 35 | ||
35 | impl HoverConfig { | 36 | impl HoverConfig { |
36 | pub const NO_ACTIONS: Self = Self { implementations: false, run: false, debug: false }; | 37 | pub const NO_ACTIONS: Self = |
38 | Self { implementations: false, run: false, debug: false, goto_type_def: false }; | ||
37 | 39 | ||
38 | pub fn any(&self) -> bool { | 40 | pub fn any(&self) -> bool { |
39 | self.implementations || self.runnable() | 41 | self.implementations || self.runnable() || self.goto_type_def |
40 | } | 42 | } |
41 | 43 | ||
42 | pub fn none(&self) -> bool { | 44 | pub fn none(&self) -> bool { |
@@ -52,6 +54,13 @@ impl HoverConfig { | |||
52 | pub enum HoverAction { | 54 | pub enum HoverAction { |
53 | Runnable(Runnable), | 55 | Runnable(Runnable), |
54 | Implementaion(FilePosition), | 56 | Implementaion(FilePosition), |
57 | GoToType(Vec<HoverGotoTypeData>), | ||
58 | } | ||
59 | |||
60 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
61 | pub struct HoverGotoTypeData { | ||
62 | pub mod_path: String, | ||
63 | pub nav: NavigationTarget, | ||
55 | } | 64 | } |
56 | 65 | ||
57 | /// Contains the results when hovering over an item | 66 | /// Contains the results when hovering over an item |
@@ -138,6 +147,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
138 | res.push_action(action); | 147 | res.push_action(action); |
139 | } | 148 | } |
140 | 149 | ||
150 | if let Some(action) = goto_type_action(db, name_kind) { | ||
151 | res.push_action(action); | ||
152 | } | ||
153 | |||
141 | return Some(RangeInfo::new(range, res)); | 154 | return Some(RangeInfo::new(range, res)); |
142 | } | 155 | } |
143 | } | 156 | } |
@@ -218,6 +231,24 @@ fn runnable_action( | |||
218 | } | 231 | } |
219 | } | 232 | } |
220 | 233 | ||
234 | fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | ||
235 | match def { | ||
236 | Definition::Local(it) => { | ||
237 | let ty = it.ty(db); | ||
238 | let v = ty.flattened_type_items(db); | ||
239 | let targets = v.into_iter() | ||
240 | .map(|it| HoverGotoTypeData { | ||
241 | mod_path: adt_or_trait_mod_path(db, &it), | ||
242 | nav: it.to_nav(db), | ||
243 | }) | ||
244 | .collect_vec(); | ||
245 | |||
246 | Some(HoverAction::GoToType(targets)) | ||
247 | } | ||
248 | _ => None, | ||
249 | } | ||
250 | } | ||
251 | |||
221 | fn hover_text( | 252 | fn hover_text( |
222 | docs: Option<String>, | 253 | docs: Option<String>, |
223 | desc: Option<String>, | 254 | desc: Option<String>, |
@@ -248,25 +279,30 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> | |||
248 | .map(|name| name.to_string()) | 279 | .map(|name| name.to_string()) |
249 | } | 280 | } |
250 | 281 | ||
251 | fn determine_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { | 282 | fn determine_mod_path(db: &RootDatabase, module: Module, name: Option<String>) -> String { |
252 | let mod_path = def.module(db).map(|module| { | 283 | once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string)) |
253 | once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string)) | 284 | .chain( |
254 | .chain( | 285 | module |
255 | module | 286 | .path_to_root(db) |
256 | .path_to_root(db) | 287 | .into_iter() |
257 | .into_iter() | 288 | .rev() |
258 | .rev() | 289 | .map(|it| it.name(db).map(|name| name.to_string())), |
259 | .map(|it| it.name(db).map(|name| name.to_string())), | 290 | ) |
260 | ) | 291 | .chain(once(name)) |
261 | .chain(once(definition_owner_name(db, def))) | 292 | .flatten() |
262 | .flatten() | 293 | .join("::") |
263 | .join("::") | 294 | } |
264 | }); | 295 | |
265 | mod_path | 296 | fn adt_or_trait_mod_path(db: &RootDatabase, item: &AdtOrTrait) -> String { |
297 | determine_mod_path(db, item.module(db), Some(item.name(db).to_string())) | ||
298 | } | ||
299 | |||
300 | fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { | ||
301 | def.module(db).map(|module| determine_mod_path(db, module, definition_owner_name(db, def))) | ||
266 | } | 302 | } |
267 | 303 | ||
268 | fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { | 304 | fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { |
269 | let mod_path = determine_mod_path(db, &def); | 305 | let mod_path = definition_mod_path(db, &def); |
270 | return match def { | 306 | return match def { |
271 | Definition::Macro(it) => { | 307 | Definition::Macro(it) => { |
272 | let src = it.source(db); | 308 | let src = it.source(db); |
@@ -1310,4 +1346,737 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
1310 | ] | 1346 | ] |
1311 | "###); | 1347 | "###); |
1312 | } | 1348 | } |
1349 | |||
1350 | #[test] | ||
1351 | fn test_hover_struct_has_goto_type_action() { | ||
1352 | let (_, actions) = check_hover_result( | ||
1353 | " | ||
1354 | //- /main.rs | ||
1355 | struct S{ f1: u32 } | ||
1356 | |||
1357 | fn main() { | ||
1358 | let s<|>t = S{ f1:0 }; | ||
1359 | } | ||
1360 | ", | ||
1361 | &["S"], | ||
1362 | ); | ||
1363 | assert_debug_snapshot!(actions, | ||
1364 | @r###" | ||
1365 | [ | ||
1366 | GoToType( | ||
1367 | [ | ||
1368 | HoverGotoTypeData { | ||
1369 | mod_path: "S", | ||
1370 | nav: NavigationTarget { | ||
1371 | file_id: FileId( | ||
1372 | 1, | ||
1373 | ), | ||
1374 | full_range: 0..19, | ||
1375 | name: "S", | ||
1376 | kind: STRUCT_DEF, | ||
1377 | focus_range: Some( | ||
1378 | 7..8, | ||
1379 | ), | ||
1380 | container_name: None, | ||
1381 | description: Some( | ||
1382 | "struct S", | ||
1383 | ), | ||
1384 | docs: None, | ||
1385 | }, | ||
1386 | }, | ||
1387 | ], | ||
1388 | ), | ||
1389 | ] | ||
1390 | "###); | ||
1391 | } | ||
1392 | |||
1393 | #[test] | ||
1394 | fn test_hover_generic_struct_has_goto_type_actions() { | ||
1395 | let (_, actions) = check_hover_result( | ||
1396 | " | ||
1397 | //- /main.rs | ||
1398 | struct Arg(u32); | ||
1399 | struct S<T>{ f1: T } | ||
1400 | |||
1401 | fn main() { | ||
1402 | let s<|>t = S{ f1:Arg(0) }; | ||
1403 | } | ||
1404 | ", | ||
1405 | &["S<Arg>"], | ||
1406 | ); | ||
1407 | assert_debug_snapshot!(actions, | ||
1408 | @r###" | ||
1409 | [ | ||
1410 | GoToType( | ||
1411 | [ | ||
1412 | HoverGotoTypeData { | ||
1413 | mod_path: "S", | ||
1414 | nav: NavigationTarget { | ||
1415 | file_id: FileId( | ||
1416 | 1, | ||
1417 | ), | ||
1418 | full_range: 17..37, | ||
1419 | name: "S", | ||
1420 | kind: STRUCT_DEF, | ||
1421 | focus_range: Some( | ||
1422 | 24..25, | ||
1423 | ), | ||
1424 | container_name: None, | ||
1425 | description: Some( | ||
1426 | "struct S", | ||
1427 | ), | ||
1428 | docs: None, | ||
1429 | }, | ||
1430 | }, | ||
1431 | HoverGotoTypeData { | ||
1432 | mod_path: "Arg", | ||
1433 | nav: NavigationTarget { | ||
1434 | file_id: FileId( | ||
1435 | 1, | ||
1436 | ), | ||
1437 | full_range: 0..16, | ||
1438 | name: "Arg", | ||
1439 | kind: STRUCT_DEF, | ||
1440 | focus_range: Some( | ||
1441 | 7..10, | ||
1442 | ), | ||
1443 | container_name: None, | ||
1444 | description: Some( | ||
1445 | "struct Arg", | ||
1446 | ), | ||
1447 | docs: None, | ||
1448 | }, | ||
1449 | }, | ||
1450 | ], | ||
1451 | ), | ||
1452 | ] | ||
1453 | "###); | ||
1454 | } | ||
1455 | |||
1456 | #[test] | ||
1457 | fn test_hover_generic_struct_has_flattened_goto_type_actions() { | ||
1458 | let (_, actions) = check_hover_result( | ||
1459 | " | ||
1460 | //- /main.rs | ||
1461 | struct Arg(u32); | ||
1462 | struct S<T>{ f1: T } | ||
1463 | |||
1464 | fn main() { | ||
1465 | let s<|>t = S{ f1: S{ f1: Arg(0) } }; | ||
1466 | } | ||
1467 | ", | ||
1468 | &["S<S<Arg>>"], | ||
1469 | ); | ||
1470 | assert_debug_snapshot!(actions, | ||
1471 | @r###" | ||
1472 | [ | ||
1473 | GoToType( | ||
1474 | [ | ||
1475 | HoverGotoTypeData { | ||
1476 | mod_path: "S", | ||
1477 | nav: NavigationTarget { | ||
1478 | file_id: FileId( | ||
1479 | 1, | ||
1480 | ), | ||
1481 | full_range: 17..37, | ||
1482 | name: "S", | ||
1483 | kind: STRUCT_DEF, | ||
1484 | focus_range: Some( | ||
1485 | 24..25, | ||
1486 | ), | ||
1487 | container_name: None, | ||
1488 | description: Some( | ||
1489 | "struct S", | ||
1490 | ), | ||
1491 | docs: None, | ||
1492 | }, | ||
1493 | }, | ||
1494 | HoverGotoTypeData { | ||
1495 | mod_path: "Arg", | ||
1496 | nav: NavigationTarget { | ||
1497 | file_id: FileId( | ||
1498 | 1, | ||
1499 | ), | ||
1500 | full_range: 0..16, | ||
1501 | name: "Arg", | ||
1502 | kind: STRUCT_DEF, | ||
1503 | focus_range: Some( | ||
1504 | 7..10, | ||
1505 | ), | ||
1506 | container_name: None, | ||
1507 | description: Some( | ||
1508 | "struct Arg", | ||
1509 | ), | ||
1510 | docs: None, | ||
1511 | }, | ||
1512 | }, | ||
1513 | ], | ||
1514 | ), | ||
1515 | ] | ||
1516 | "###); | ||
1517 | } | ||
1518 | |||
1519 | #[test] | ||
1520 | fn test_hover_tuple_has_goto_type_actions() { | ||
1521 | let (_, actions) = check_hover_result( | ||
1522 | " | ||
1523 | //- /main.rs | ||
1524 | struct A(u32); | ||
1525 | struct B(u32); | ||
1526 | mod M { | ||
1527 | pub struct C(u32); | ||
1528 | } | ||
1529 | |||
1530 | fn main() { | ||
1531 | let s<|>t = (A(1), B(2), M::C(3) ); | ||
1532 | } | ||
1533 | ", | ||
1534 | &["(A, B, C)"], | ||
1535 | ); | ||
1536 | assert_debug_snapshot!(actions, | ||
1537 | @r###" | ||
1538 | [ | ||
1539 | GoToType( | ||
1540 | [ | ||
1541 | HoverGotoTypeData { | ||
1542 | mod_path: "A", | ||
1543 | nav: NavigationTarget { | ||
1544 | file_id: FileId( | ||
1545 | 1, | ||
1546 | ), | ||
1547 | full_range: 0..14, | ||
1548 | name: "A", | ||
1549 | kind: STRUCT_DEF, | ||
1550 | focus_range: Some( | ||
1551 | 7..8, | ||
1552 | ), | ||
1553 | container_name: None, | ||
1554 | description: Some( | ||
1555 | "struct A", | ||
1556 | ), | ||
1557 | docs: None, | ||
1558 | }, | ||
1559 | }, | ||
1560 | HoverGotoTypeData { | ||
1561 | mod_path: "B", | ||
1562 | nav: NavigationTarget { | ||
1563 | file_id: FileId( | ||
1564 | 1, | ||
1565 | ), | ||
1566 | full_range: 15..29, | ||
1567 | name: "B", | ||
1568 | kind: STRUCT_DEF, | ||
1569 | focus_range: Some( | ||
1570 | 22..23, | ||
1571 | ), | ||
1572 | container_name: None, | ||
1573 | description: Some( | ||
1574 | "struct B", | ||
1575 | ), | ||
1576 | docs: None, | ||
1577 | }, | ||
1578 | }, | ||
1579 | HoverGotoTypeData { | ||
1580 | mod_path: "M::C", | ||
1581 | nav: NavigationTarget { | ||
1582 | file_id: FileId( | ||
1583 | 1, | ||
1584 | ), | ||
1585 | full_range: 42..60, | ||
1586 | name: "C", | ||
1587 | kind: STRUCT_DEF, | ||
1588 | focus_range: Some( | ||
1589 | 53..54, | ||
1590 | ), | ||
1591 | container_name: None, | ||
1592 | description: Some( | ||
1593 | "pub struct C", | ||
1594 | ), | ||
1595 | docs: None, | ||
1596 | }, | ||
1597 | }, | ||
1598 | ], | ||
1599 | ), | ||
1600 | ] | ||
1601 | "###); | ||
1602 | } | ||
1603 | |||
1604 | #[test] | ||
1605 | fn test_hover_return_impl_trait_has_goto_type_action() { | ||
1606 | let (_, actions) = check_hover_result( | ||
1607 | " | ||
1608 | //- /main.rs | ||
1609 | trait Foo {} | ||
1610 | |||
1611 | fn foo() -> impl Foo {} | ||
1612 | |||
1613 | fn main() { | ||
1614 | let s<|>t = foo(); | ||
1615 | } | ||
1616 | ", | ||
1617 | &["impl Foo"], | ||
1618 | ); | ||
1619 | assert_debug_snapshot!(actions, | ||
1620 | @r###" | ||
1621 | [ | ||
1622 | GoToType( | ||
1623 | [ | ||
1624 | HoverGotoTypeData { | ||
1625 | mod_path: "Foo", | ||
1626 | nav: NavigationTarget { | ||
1627 | file_id: FileId( | ||
1628 | 1, | ||
1629 | ), | ||
1630 | full_range: 0..12, | ||
1631 | name: "Foo", | ||
1632 | kind: TRAIT_DEF, | ||
1633 | focus_range: Some( | ||
1634 | 6..9, | ||
1635 | ), | ||
1636 | container_name: None, | ||
1637 | description: Some( | ||
1638 | "trait Foo", | ||
1639 | ), | ||
1640 | docs: None, | ||
1641 | }, | ||
1642 | }, | ||
1643 | ], | ||
1644 | ), | ||
1645 | ] | ||
1646 | "###); | ||
1647 | } | ||
1648 | |||
1649 | #[test] | ||
1650 | fn test_hover_generic_return_impl_trait_has_goto_type_action() { | ||
1651 | let (_, actions) = check_hover_result( | ||
1652 | " | ||
1653 | //- /main.rs | ||
1654 | trait Foo<T> {} | ||
1655 | struct S; | ||
1656 | |||
1657 | fn foo() -> impl Foo<S> {} | ||
1658 | |||
1659 | fn main() { | ||
1660 | let s<|>t = foo(); | ||
1661 | } | ||
1662 | ", | ||
1663 | &["impl Foo<S>"], | ||
1664 | ); | ||
1665 | assert_debug_snapshot!(actions, | ||
1666 | @r###" | ||
1667 | [ | ||
1668 | GoToType( | ||
1669 | [ | ||
1670 | HoverGotoTypeData { | ||
1671 | mod_path: "Foo", | ||
1672 | nav: NavigationTarget { | ||
1673 | file_id: FileId( | ||
1674 | 1, | ||
1675 | ), | ||
1676 | full_range: 0..15, | ||
1677 | name: "Foo", | ||
1678 | kind: TRAIT_DEF, | ||
1679 | focus_range: Some( | ||
1680 | 6..9, | ||
1681 | ), | ||
1682 | container_name: None, | ||
1683 | description: Some( | ||
1684 | "trait Foo", | ||
1685 | ), | ||
1686 | docs: None, | ||
1687 | }, | ||
1688 | }, | ||
1689 | HoverGotoTypeData { | ||
1690 | mod_path: "S", | ||
1691 | nav: NavigationTarget { | ||
1692 | file_id: FileId( | ||
1693 | 1, | ||
1694 | ), | ||
1695 | full_range: 16..25, | ||
1696 | name: "S", | ||
1697 | kind: STRUCT_DEF, | ||
1698 | focus_range: Some( | ||
1699 | 23..24, | ||
1700 | ), | ||
1701 | container_name: None, | ||
1702 | description: Some( | ||
1703 | "struct S", | ||
1704 | ), | ||
1705 | docs: None, | ||
1706 | }, | ||
1707 | }, | ||
1708 | ], | ||
1709 | ), | ||
1710 | ] | ||
1711 | "###); | ||
1712 | } | ||
1713 | |||
1714 | #[test] | ||
1715 | fn test_hover_arg_impl_trait_has_goto_type_action() { | ||
1716 | let (_, actions) = check_hover_result( | ||
1717 | " | ||
1718 | //- /lib.rs | ||
1719 | trait Foo {} | ||
1720 | fn foo(ar<|>g: &impl Foo) {} | ||
1721 | ", | ||
1722 | &["&impl Foo"], | ||
1723 | ); | ||
1724 | assert_debug_snapshot!(actions, | ||
1725 | @r###" | ||
1726 | [ | ||
1727 | GoToType( | ||
1728 | [ | ||
1729 | HoverGotoTypeData { | ||
1730 | mod_path: "Foo", | ||
1731 | nav: NavigationTarget { | ||
1732 | file_id: FileId( | ||
1733 | 1, | ||
1734 | ), | ||
1735 | full_range: 0..12, | ||
1736 | name: "Foo", | ||
1737 | kind: TRAIT_DEF, | ||
1738 | focus_range: Some( | ||
1739 | 6..9, | ||
1740 | ), | ||
1741 | container_name: None, | ||
1742 | description: Some( | ||
1743 | "trait Foo", | ||
1744 | ), | ||
1745 | docs: None, | ||
1746 | }, | ||
1747 | }, | ||
1748 | ], | ||
1749 | ), | ||
1750 | ] | ||
1751 | "###); | ||
1752 | } | ||
1753 | |||
1754 | #[test] | ||
1755 | fn test_hover_arg_generic_impl_trait_has_goto_type_action() { | ||
1756 | let (_, actions) = check_hover_result( | ||
1757 | " | ||
1758 | //- /lib.rs | ||
1759 | trait Foo<T> {} | ||
1760 | struct S {} | ||
1761 | fn foo(ar<|>g: &impl Foo<S>) {} | ||
1762 | ", | ||
1763 | &["&impl Foo<S>"], | ||
1764 | ); | ||
1765 | assert_debug_snapshot!(actions, | ||
1766 | @r###" | ||
1767 | [ | ||
1768 | GoToType( | ||
1769 | [ | ||
1770 | HoverGotoTypeData { | ||
1771 | mod_path: "Foo", | ||
1772 | nav: NavigationTarget { | ||
1773 | file_id: FileId( | ||
1774 | 1, | ||
1775 | ), | ||
1776 | full_range: 0..15, | ||
1777 | name: "Foo", | ||
1778 | kind: TRAIT_DEF, | ||
1779 | focus_range: Some( | ||
1780 | 6..9, | ||
1781 | ), | ||
1782 | container_name: None, | ||
1783 | description: Some( | ||
1784 | "trait Foo", | ||
1785 | ), | ||
1786 | docs: None, | ||
1787 | }, | ||
1788 | }, | ||
1789 | HoverGotoTypeData { | ||
1790 | mod_path: "S", | ||
1791 | nav: NavigationTarget { | ||
1792 | file_id: FileId( | ||
1793 | 1, | ||
1794 | ), | ||
1795 | full_range: 16..27, | ||
1796 | name: "S", | ||
1797 | kind: STRUCT_DEF, | ||
1798 | focus_range: Some( | ||
1799 | 23..24, | ||
1800 | ), | ||
1801 | container_name: None, | ||
1802 | description: Some( | ||
1803 | "struct S", | ||
1804 | ), | ||
1805 | docs: None, | ||
1806 | }, | ||
1807 | }, | ||
1808 | ], | ||
1809 | ), | ||
1810 | ] | ||
1811 | "###); | ||
1812 | } | ||
1813 | |||
1814 | #[test] | ||
1815 | fn test_hover_dyn_return_has_goto_type_action() { | ||
1816 | let (_, actions) = check_hover_result( | ||
1817 | " | ||
1818 | //- /main.rs | ||
1819 | trait Foo {} | ||
1820 | struct S; | ||
1821 | impl Foo for S {} | ||
1822 | |||
1823 | struct B<T>{} | ||
1824 | |||
1825 | fn foo() -> B<dyn Foo> {} | ||
1826 | |||
1827 | fn main() { | ||
1828 | let s<|>t = foo(); | ||
1829 | } | ||
1830 | ", | ||
1831 | &["B<dyn Foo>"], | ||
1832 | ); | ||
1833 | assert_debug_snapshot!(actions, | ||
1834 | @r###" | ||
1835 | [ | ||
1836 | GoToType( | ||
1837 | [ | ||
1838 | HoverGotoTypeData { | ||
1839 | mod_path: "B", | ||
1840 | nav: NavigationTarget { | ||
1841 | file_id: FileId( | ||
1842 | 1, | ||
1843 | ), | ||
1844 | full_range: 41..54, | ||
1845 | name: "B", | ||
1846 | kind: STRUCT_DEF, | ||
1847 | focus_range: Some( | ||
1848 | 48..49, | ||
1849 | ), | ||
1850 | container_name: None, | ||
1851 | description: Some( | ||
1852 | "struct B", | ||
1853 | ), | ||
1854 | docs: None, | ||
1855 | }, | ||
1856 | }, | ||
1857 | HoverGotoTypeData { | ||
1858 | mod_path: "Foo", | ||
1859 | nav: NavigationTarget { | ||
1860 | file_id: FileId( | ||
1861 | 1, | ||
1862 | ), | ||
1863 | full_range: 0..12, | ||
1864 | name: "Foo", | ||
1865 | kind: TRAIT_DEF, | ||
1866 | focus_range: Some( | ||
1867 | 6..9, | ||
1868 | ), | ||
1869 | container_name: None, | ||
1870 | description: Some( | ||
1871 | "trait Foo", | ||
1872 | ), | ||
1873 | docs: None, | ||
1874 | }, | ||
1875 | }, | ||
1876 | ], | ||
1877 | ), | ||
1878 | ] | ||
1879 | "###); | ||
1880 | } | ||
1881 | |||
1882 | #[test] | ||
1883 | fn test_hover_dyn_arg_has_goto_type_action() { | ||
1884 | let (_, actions) = check_hover_result( | ||
1885 | " | ||
1886 | //- /lib.rs | ||
1887 | trait Foo {} | ||
1888 | fn foo(ar<|>g: &dyn Foo) {} | ||
1889 | ", | ||
1890 | &["&dyn Foo"], | ||
1891 | ); | ||
1892 | assert_debug_snapshot!(actions, | ||
1893 | @r###" | ||
1894 | [ | ||
1895 | GoToType( | ||
1896 | [ | ||
1897 | HoverGotoTypeData { | ||
1898 | mod_path: "Foo", | ||
1899 | nav: NavigationTarget { | ||
1900 | file_id: FileId( | ||
1901 | 1, | ||
1902 | ), | ||
1903 | full_range: 0..12, | ||
1904 | name: "Foo", | ||
1905 | kind: TRAIT_DEF, | ||
1906 | focus_range: Some( | ||
1907 | 6..9, | ||
1908 | ), | ||
1909 | container_name: None, | ||
1910 | description: Some( | ||
1911 | "trait Foo", | ||
1912 | ), | ||
1913 | docs: None, | ||
1914 | }, | ||
1915 | }, | ||
1916 | ], | ||
1917 | ), | ||
1918 | ] | ||
1919 | "###); | ||
1920 | } | ||
1921 | |||
1922 | #[test] | ||
1923 | fn test_hover_generic_dyn_arg_has_goto_type_action() { | ||
1924 | let (_, actions) = check_hover_result( | ||
1925 | " | ||
1926 | //- /lib.rs | ||
1927 | trait Foo<T> {} | ||
1928 | struct S {} | ||
1929 | fn foo(ar<|>g: &dyn Foo<S>) {} | ||
1930 | ", | ||
1931 | &["&dyn Foo<S>"], | ||
1932 | ); | ||
1933 | assert_debug_snapshot!(actions, | ||
1934 | @r###" | ||
1935 | [ | ||
1936 | GoToType( | ||
1937 | [ | ||
1938 | HoverGotoTypeData { | ||
1939 | mod_path: "Foo", | ||
1940 | nav: NavigationTarget { | ||
1941 | file_id: FileId( | ||
1942 | 1, | ||
1943 | ), | ||
1944 | full_range: 0..15, | ||
1945 | name: "Foo", | ||
1946 | kind: TRAIT_DEF, | ||
1947 | focus_range: Some( | ||
1948 | 6..9, | ||
1949 | ), | ||
1950 | container_name: None, | ||
1951 | description: Some( | ||
1952 | "trait Foo", | ||
1953 | ), | ||
1954 | docs: None, | ||
1955 | }, | ||
1956 | }, | ||
1957 | HoverGotoTypeData { | ||
1958 | mod_path: "S", | ||
1959 | nav: NavigationTarget { | ||
1960 | file_id: FileId( | ||
1961 | 1, | ||
1962 | ), | ||
1963 | full_range: 16..27, | ||
1964 | name: "S", | ||
1965 | kind: STRUCT_DEF, | ||
1966 | focus_range: Some( | ||
1967 | 23..24, | ||
1968 | ), | ||
1969 | container_name: None, | ||
1970 | description: Some( | ||
1971 | "struct S", | ||
1972 | ), | ||
1973 | docs: None, | ||
1974 | }, | ||
1975 | }, | ||
1976 | ], | ||
1977 | ), | ||
1978 | ] | ||
1979 | "###); | ||
1980 | } | ||
1981 | |||
1982 | #[test] | ||
1983 | fn test_hover_arg_goto_type_action() { | ||
1984 | let (_, actions) = check_hover_result( | ||
1985 | " | ||
1986 | //- /lib.rs | ||
1987 | trait ImplTrait<T> {} | ||
1988 | trait DynTrait<T> {} | ||
1989 | struct B<T> {} | ||
1990 | struct S {} | ||
1991 | |||
1992 | fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<S>>>) {} | ||
1993 | ", | ||
1994 | &["&impl ImplTrait<B<dyn DynTrait<S>>>"], | ||
1995 | ); | ||
1996 | assert_debug_snapshot!(actions, | ||
1997 | @r###" | ||
1998 | [ | ||
1999 | GoToType( | ||
2000 | [ | ||
2001 | HoverGotoTypeData { | ||
2002 | mod_path: "ImplTrait", | ||
2003 | nav: NavigationTarget { | ||
2004 | file_id: FileId( | ||
2005 | 1, | ||
2006 | ), | ||
2007 | full_range: 0..21, | ||
2008 | name: "ImplTrait", | ||
2009 | kind: TRAIT_DEF, | ||
2010 | focus_range: Some( | ||
2011 | 6..15, | ||
2012 | ), | ||
2013 | container_name: None, | ||
2014 | description: Some( | ||
2015 | "trait ImplTrait", | ||
2016 | ), | ||
2017 | docs: None, | ||
2018 | }, | ||
2019 | }, | ||
2020 | HoverGotoTypeData { | ||
2021 | mod_path: "S", | ||
2022 | nav: NavigationTarget { | ||
2023 | file_id: FileId( | ||
2024 | 1, | ||
2025 | ), | ||
2026 | full_range: 58..69, | ||
2027 | name: "S", | ||
2028 | kind: STRUCT_DEF, | ||
2029 | focus_range: Some( | ||
2030 | 65..66, | ||
2031 | ), | ||
2032 | container_name: None, | ||
2033 | description: Some( | ||
2034 | "struct S", | ||
2035 | ), | ||
2036 | docs: None, | ||
2037 | }, | ||
2038 | }, | ||
2039 | HoverGotoTypeData { | ||
2040 | mod_path: "DynTrait", | ||
2041 | nav: NavigationTarget { | ||
2042 | file_id: FileId( | ||
2043 | 1, | ||
2044 | ), | ||
2045 | full_range: 22..42, | ||
2046 | name: "DynTrait", | ||
2047 | kind: TRAIT_DEF, | ||
2048 | focus_range: Some( | ||
2049 | 28..36, | ||
2050 | ), | ||
2051 | container_name: None, | ||
2052 | description: Some( | ||
2053 | "trait DynTrait", | ||
2054 | ), | ||
2055 | docs: None, | ||
2056 | }, | ||
2057 | }, | ||
2058 | HoverGotoTypeData { | ||
2059 | mod_path: "B", | ||
2060 | nav: NavigationTarget { | ||
2061 | file_id: FileId( | ||
2062 | 1, | ||
2063 | ), | ||
2064 | full_range: 43..57, | ||
2065 | name: "B", | ||
2066 | kind: STRUCT_DEF, | ||
2067 | focus_range: Some( | ||
2068 | 50..51, | ||
2069 | ), | ||
2070 | container_name: None, | ||
2071 | description: Some( | ||
2072 | "struct B", | ||
2073 | ), | ||
2074 | docs: None, | ||
2075 | }, | ||
2076 | }, | ||
2077 | ], | ||
2078 | ), | ||
2079 | ] | ||
2080 | "###); | ||
2081 | } | ||
1313 | } | 2082 | } |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 51dc1f041..be9ab62c0 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -66,7 +66,7 @@ pub use crate::{ | |||
66 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, | 66 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, |
67 | expand_macro::ExpandedMacro, | 67 | expand_macro::ExpandedMacro, |
68 | folding_ranges::{Fold, FoldKind}, | 68 | folding_ranges::{Fold, FoldKind}, |
69 | hover::{HoverAction, HoverConfig, HoverResult}, | 69 | hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, |
70 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, | 70 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, |
71 | references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, | 71 | references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, |
72 | runnables::{Runnable, RunnableKind, TestId}, | 72 | runnables::{Runnable, RunnableKind, TestId}, |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 0df7427cb..aa2c4ae15 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -296,6 +296,7 @@ impl Config { | |||
296 | set(value, "/hoverActions/implementations", &mut self.hover.implementations); | 296 | set(value, "/hoverActions/implementations", &mut self.hover.implementations); |
297 | set(value, "/hoverActions/run", &mut self.hover.run); | 297 | set(value, "/hoverActions/run", &mut self.hover.run); |
298 | set(value, "/hoverActions/debug", &mut self.hover.debug); | 298 | set(value, "/hoverActions/debug", &mut self.hover.debug); |
299 | set(value, "/hoverActions/gotoTypeDef", &mut self.hover.goto_type_def); | ||
299 | } else { | 300 | } else { |
300 | self.hover = HoverConfig::NO_ACTIONS; | 301 | self.hover = HoverConfig::NO_ACTIONS; |
301 | } | 302 | } |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index f3868bf17..2d7e649d2 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -18,8 +18,8 @@ use lsp_types::{ | |||
18 | TextDocumentIdentifier, Url, WorkspaceEdit, | 18 | TextDocumentIdentifier, Url, WorkspaceEdit, |
19 | }; | 19 | }; |
20 | use ra_ide::{ | 20 | use ra_ide::{ |
21 | FileId, FilePosition, FileRange, HoverAction, Query, RangeInfo, Runnable, RunnableKind, | 21 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, |
22 | SearchScope, TextEdit, | 22 | RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, |
23 | }; | 23 | }; |
24 | use ra_prof::profile; | 24 | use ra_prof::profile; |
25 | use ra_project_model::TargetKind; | 25 | use ra_project_model::TargetKind; |
@@ -1150,6 +1150,23 @@ fn debug_single_command(runnable: &lsp_ext::Runnable) -> Command { | |||
1150 | } | 1150 | } |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | fn goto_location_command(snap: &GlobalStateSnapshot, nav: &NavigationTarget) -> Option<Command> { | ||
1154 | let value = if snap.config.client_caps.location_link { | ||
1155 | let link = to_proto::location_link(snap, None, nav.clone()).ok()?; | ||
1156 | to_value(link).ok()? | ||
1157 | } else { | ||
1158 | let range = FileRange { file_id: nav.file_id(), range: nav.range() }; | ||
1159 | let location = to_proto::location(snap, range).ok()?; | ||
1160 | to_value(location).ok()? | ||
1161 | }; | ||
1162 | |||
1163 | Some(Command { | ||
1164 | title: nav.name().to_string(), | ||
1165 | command: "rust-analyzer.gotoLocation".into(), | ||
1166 | arguments: Some(vec![value]), | ||
1167 | }) | ||
1168 | } | ||
1169 | |||
1153 | fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink { | 1170 | fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink { |
1154 | lsp_ext::CommandLink { tooltip: Some(tooltip), command } | 1171 | lsp_ext::CommandLink { tooltip: Some(tooltip), command } |
1155 | } | 1172 | } |
@@ -1180,7 +1197,7 @@ fn show_impl_command_link( | |||
1180 | None | 1197 | None |
1181 | } | 1198 | } |
1182 | 1199 | ||
1183 | fn to_runnable_action( | 1200 | fn runnable_action_links( |
1184 | snap: &GlobalStateSnapshot, | 1201 | snap: &GlobalStateSnapshot, |
1185 | file_id: FileId, | 1202 | file_id: FileId, |
1186 | runnable: Runnable, | 1203 | runnable: Runnable, |
@@ -1208,6 +1225,26 @@ fn to_runnable_action( | |||
1208 | }) | 1225 | }) |
1209 | } | 1226 | } |
1210 | 1227 | ||
1228 | fn goto_type_action_links( | ||
1229 | snap: &GlobalStateSnapshot, | ||
1230 | nav_targets: &[HoverGotoTypeData], | ||
1231 | ) -> Option<lsp_ext::CommandLinkGroup> { | ||
1232 | if !snap.config.hover.goto_type_def || nav_targets.is_empty() { | ||
1233 | return None; | ||
1234 | } | ||
1235 | |||
1236 | Some(lsp_ext::CommandLinkGroup { | ||
1237 | title: Some("Go to ".into()), | ||
1238 | commands: nav_targets | ||
1239 | .iter() | ||
1240 | .filter_map(|it| { | ||
1241 | goto_location_command(snap, &it.nav) | ||
1242 | .map(|cmd| to_command_link(cmd, it.mod_path.clone())) | ||
1243 | }) | ||
1244 | .collect(), | ||
1245 | }) | ||
1246 | } | ||
1247 | |||
1211 | fn prepare_hover_actions( | 1248 | fn prepare_hover_actions( |
1212 | snap: &GlobalStateSnapshot, | 1249 | snap: &GlobalStateSnapshot, |
1213 | file_id: FileId, | 1250 | file_id: FileId, |
@@ -1221,7 +1258,8 @@ fn prepare_hover_actions( | |||
1221 | .iter() | 1258 | .iter() |
1222 | .filter_map(|it| match it { | 1259 | .filter_map(|it| match it { |
1223 | HoverAction::Implementaion(position) => show_impl_command_link(snap, position), | 1260 | HoverAction::Implementaion(position) => show_impl_command_link(snap, position), |
1224 | HoverAction::Runnable(r) => to_runnable_action(snap, file_id, r.clone()), | 1261 | HoverAction::Runnable(r) => runnable_action_links(snap, file_id, r.clone()), |
1262 | HoverAction::GoToType(targets) => goto_type_action_links(snap, targets), | ||
1225 | }) | 1263 | }) |
1226 | .collect() | 1264 | .collect() |
1227 | } | 1265 | } |