diff options
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r-- | crates/ra_hir/src/path.rs | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 7b0ce3b61..c3d14c689 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -1,11 +1,35 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
1 | use ra_syntax::{ast, AstNode}; | 3 | use ra_syntax::{ast, AstNode}; |
2 | 4 | ||
3 | use crate::{Name, AsName}; | 5 | use crate::{Name, AsName, type_ref::TypeRef}; |
4 | 6 | ||
5 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 7 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
6 | pub struct Path { | 8 | pub struct Path { |
7 | pub kind: PathKind, | 9 | pub kind: PathKind, |
8 | pub segments: Vec<Name>, | 10 | pub segments: Vec<PathSegment>, |
11 | } | ||
12 | |||
13 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
14 | pub struct PathSegment { | ||
15 | pub name: Name, | ||
16 | pub args_and_bindings: Option<Arc<GenericArgs>>, | ||
17 | } | ||
18 | |||
19 | /// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This | ||
20 | /// can (in the future) also include bindings of associated types, like in | ||
21 | /// `Iterator<Item = Foo>`. | ||
22 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
23 | pub struct GenericArgs { | ||
24 | pub args: Vec<GenericArg>, | ||
25 | // someday also bindings | ||
26 | } | ||
27 | |||
28 | /// A single generic argument. | ||
29 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
30 | pub enum GenericArg { | ||
31 | Type(TypeRef), | ||
32 | // or lifetime... | ||
9 | } | 33 | } |
10 | 34 | ||
11 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 35 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -34,7 +58,17 @@ impl Path { | |||
34 | loop { | 58 | loop { |
35 | let segment = path.segment()?; | 59 | let segment = path.segment()?; |
36 | match segment.kind()? { | 60 | match segment.kind()? { |
37 | ast::PathSegmentKind::Name(name) => segments.push(name.as_name()), | 61 | ast::PathSegmentKind::Name(name) => { |
62 | let args = segment | ||
63 | .type_arg_list() | ||
64 | .and_then(GenericArgs::from_ast) | ||
65 | .map(Arc::new); | ||
66 | let segment = PathSegment { | ||
67 | name: name.as_name(), | ||
68 | args_and_bindings: args, | ||
69 | }; | ||
70 | segments.push(segment); | ||
71 | } | ||
38 | ast::PathSegmentKind::CrateKw => { | 72 | ast::PathSegmentKind::CrateKw => { |
39 | kind = PathKind::Crate; | 73 | kind = PathKind::Crate; |
40 | break; | 74 | break; |
@@ -88,7 +122,23 @@ impl Path { | |||
88 | if self.kind != PathKind::Plain || self.segments.len() > 1 { | 122 | if self.kind != PathKind::Plain || self.segments.len() > 1 { |
89 | return None; | 123 | return None; |
90 | } | 124 | } |
91 | self.segments.first() | 125 | self.segments.first().map(|s| &s.name) |
126 | } | ||
127 | } | ||
128 | |||
129 | impl GenericArgs { | ||
130 | fn from_ast(node: &ast::TypeArgList) -> Option<GenericArgs> { | ||
131 | let mut args = Vec::new(); | ||
132 | for type_arg in node.type_args() { | ||
133 | let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); | ||
134 | args.push(GenericArg::Type(type_ref)); | ||
135 | } | ||
136 | // lifetimes and assoc type args ignored for now | ||
137 | if args.len() > 0 { | ||
138 | Some(GenericArgs { args }) | ||
139 | } else { | ||
140 | None | ||
141 | } | ||
92 | } | 142 | } |
93 | } | 143 | } |
94 | 144 | ||
@@ -96,7 +146,10 @@ impl From<Name> for Path { | |||
96 | fn from(name: Name) -> Path { | 146 | fn from(name: Name) -> Path { |
97 | Path { | 147 | Path { |
98 | kind: PathKind::Plain, | 148 | kind: PathKind::Plain, |
99 | segments: vec![name], | 149 | segments: vec![PathSegment { |
150 | name, | ||
151 | args_and_bindings: None, | ||
152 | }], | ||
100 | } | 153 | } |
101 | } | 154 | } |
102 | } | 155 | } |
@@ -160,7 +213,10 @@ fn convert_path(prefix: Option<Path>, path: &ast::Path) -> Option<Path> { | |||
160 | kind: PathKind::Plain, | 213 | kind: PathKind::Plain, |
161 | segments: Vec::with_capacity(1), | 214 | segments: Vec::with_capacity(1), |
162 | }); | 215 | }); |
163 | res.segments.push(name.as_name()); | 216 | res.segments.push(PathSegment { |
217 | name: name.as_name(), | ||
218 | args_and_bindings: None, // no type args in use | ||
219 | }); | ||
164 | res | 220 | res |
165 | } | 221 | } |
166 | ast::PathSegmentKind::CrateKw => { | 222 | ast::PathSegmentKind::CrateKw => { |