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 /crates/ra_ide | |
parent | 4d6c6a6b1e00f61af96e16386c7f03f83f96a173 (diff) |
Add `Go to Type Definition` hover action.
Diffstat (limited to 'crates/ra_ide')
-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 |
3 files changed, 800 insertions, 22 deletions
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}, |