diff options
Diffstat (limited to 'crates/ra_hir/src/resolve.rs')
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 78 |
1 files changed, 59 insertions, 19 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 00b55eae9..9f4d4ab42 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -33,27 +33,68 @@ pub(crate) struct ExprScope { | |||
33 | } | 33 | } |
34 | 34 | ||
35 | #[derive(Debug, Clone)] | 35 | #[derive(Debug, Clone)] |
36 | pub enum PathResult { | 36 | pub struct PathResult { |
37 | /// Path was fully resolved | 37 | /// The actual path resolution |
38 | FullyResolved(PerNs<Resolution>), | 38 | resolution: PerNs<Resolution>, |
39 | /// Path was partially resolved, first element contains the resolution | 39 | /// The first index in the path that we |
40 | /// second contains the index in the Path.segments which we were unable to resolve | 40 | /// were unable to resolve. |
41 | PartiallyResolved(PerNs<Resolution>, usize), | 41 | /// When path is fully resolved, this is 0. |
42 | remaining_index: usize, | ||
42 | } | 43 | } |
43 | 44 | ||
44 | impl PathResult { | 45 | impl PathResult { |
45 | pub fn segment_index(&self) -> Option<usize> { | 46 | /// Returns the remaining index in the result |
46 | match self { | 47 | /// returns None if the path was fully resolved |
47 | PathResult::FullyResolved(_) => None, | 48 | pub fn remaining_index(&self) -> Option<usize> { |
48 | PathResult::PartiallyResolved(_, ref i) => Some(*i), | 49 | if self.remaining_index > 0 { |
50 | Some(self.remaining_index) | ||
51 | } else { | ||
52 | None | ||
49 | } | 53 | } |
50 | } | 54 | } |
51 | 55 | ||
52 | /// Consumes `PathResult` and returns the contained `PerNs<Resolution>` | 56 | /// Consumes `PathResult` and returns the contained `PerNs<Resolution>` |
57 | /// if the path was fully resolved, meaning we have no remaining items | ||
53 | pub fn into_per_ns(self) -> PerNs<Resolution> { | 58 | pub fn into_per_ns(self) -> PerNs<Resolution> { |
54 | match self { | 59 | if self.remaining_index().is_none() { |
55 | PathResult::FullyResolved(def) => def, | 60 | self.resolution |
56 | PathResult::PartiallyResolved(def, _) => def, | 61 | } else { |
62 | PerNs::none() | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /// Consumes `PathResult` and returns the resolution and the | ||
67 | /// remaining_index as a tuple. | ||
68 | pub fn into_inner(self) -> (PerNs<Resolution>, Option<usize>) { | ||
69 | let index = self.remaining_index(); | ||
70 | (self.resolution, index) | ||
71 | } | ||
72 | |||
73 | /// Path is fully resolved when `remaining_index` is none | ||
74 | /// and the resolution contains anything | ||
75 | pub fn is_fully_resolved(&self) -> bool { | ||
76 | !self.resolution.is_none() && self.remaining_index().is_none() | ||
77 | } | ||
78 | |||
79 | /// Empty path result is where the resolution is `none` | ||
80 | /// and the remaining index is 0 | ||
81 | pub fn is_empty(&self) -> bool { | ||
82 | self.resolution.is_none() && self.remaining_index().is_none() | ||
83 | } | ||
84 | |||
85 | fn empty() -> PathResult { | ||
86 | PathResult { resolution: PerNs::none(), remaining_index: 0 } | ||
87 | } | ||
88 | |||
89 | fn from_resolution(res: PerNs<Resolution>) -> PathResult { | ||
90 | PathResult::from_resolution_with_index(res, 0) | ||
91 | } | ||
92 | |||
93 | fn from_resolution_with_index(res: PerNs<Resolution>, remaining_index: usize) -> PathResult { | ||
94 | if res.is_none() { | ||
95 | PathResult::empty() | ||
96 | } else { | ||
97 | PathResult { resolution: res, remaining_index } | ||
57 | } | 98 | } |
58 | } | 99 | } |
59 | } | 100 | } |
@@ -94,24 +135,23 @@ impl Resolver { | |||
94 | } | 135 | } |
95 | 136 | ||
96 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PathResult { | 137 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PathResult { |
97 | use self::PathResult::*; | ||
98 | if let Some(name) = path.as_ident() { | 138 | if let Some(name) = path.as_ident() { |
99 | FullyResolved(self.resolve_name(db, name)) | 139 | PathResult::from_resolution(self.resolve_name(db, name)) |
100 | } else if path.is_self() { | 140 | } else if path.is_self() { |
101 | FullyResolved(self.resolve_name(db, &Name::self_param())) | 141 | PathResult::from_resolution(self.resolve_name(db, &Name::self_param())) |
102 | } else { | 142 | } else { |
103 | let (item_map, module) = match self.module() { | 143 | let (item_map, module) = match self.module() { |
104 | Some(m) => m, | 144 | Some(m) => m, |
105 | _ => return FullyResolved(PerNs::none()), | 145 | _ => return PathResult::empty(), |
106 | }; | 146 | }; |
107 | let (module_res, segment_index) = item_map.resolve_path(db, module, path); | 147 | let (module_res, segment_index) = item_map.resolve_path(db, module, path); |
108 | 148 | ||
109 | let def = module_res.map(Resolution::Def); | 149 | let def = module_res.map(Resolution::Def); |
110 | 150 | ||
111 | if let Some(index) = segment_index { | 151 | if let Some(index) = segment_index { |
112 | PartiallyResolved(def, index) | 152 | PathResult::from_resolution_with_index(def, index) |
113 | } else { | 153 | } else { |
114 | FullyResolved(def) | 154 | PathResult::from_resolution(def) |
115 | } | 155 | } |
116 | } | 156 | } |
117 | } | 157 | } |