diff options
author | Florian Diebold <[email protected]> | 2019-01-12 23:19:20 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-01-19 15:02:06 +0000 |
commit | 5862542dedd5aca9bbdcba19c5f8cd895591005d (patch) | |
tree | 58fb630e97583db371eed1111d2c067bde2982b4 /crates/ra_hir/src | |
parent | 688a45e00b53412a7a16360c6d678a5d91a95789 (diff) |
Add AST/HIR for type args in path segments
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/path.rs | 68 |
3 files changed, 80 insertions, 22 deletions
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 7215236f9..2014f1090 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -147,7 +147,7 @@ impl Module { | |||
147 | .def_id, | 147 | .def_id, |
148 | ); | 148 | ); |
149 | 149 | ||
150 | for name in path.segments.iter() { | 150 | for segment in path.segments.iter() { |
151 | let curr = match curr_per_ns.as_ref().take_types() { | 151 | let curr = match curr_per_ns.as_ref().take_types() { |
152 | Some(r) => r, | 152 | Some(r) => r, |
153 | None => { | 153 | None => { |
@@ -163,15 +163,17 @@ impl Module { | |||
163 | curr_per_ns = match curr.resolve(db) { | 163 | curr_per_ns = match curr.resolve(db) { |
164 | Def::Module(m) => { | 164 | Def::Module(m) => { |
165 | let scope = m.scope(db); | 165 | let scope = m.scope(db); |
166 | match scope.get(&name) { | 166 | match scope.get(&segment.name) { |
167 | Some(r) => r.def_id, | 167 | Some(r) => r.def_id, |
168 | None => PerNs::none(), | 168 | None => PerNs::none(), |
169 | } | 169 | } |
170 | } | 170 | } |
171 | Def::Enum(e) => { | 171 | Def::Enum(e) => { |
172 | // enum variant | 172 | // enum variant |
173 | let matching_variant = | 173 | let matching_variant = e |
174 | e.variants(db).into_iter().find(|(n, _variant)| n == name); | 174 | .variants(db) |
175 | .into_iter() | ||
176 | .find(|(n, _variant)| n == &segment.name); | ||
175 | 177 | ||
176 | match matching_variant { | 178 | match matching_variant { |
177 | Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), | 179 | Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 4efafd409..4874e82f3 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -221,10 +221,10 @@ where | |||
221 | }; | 221 | }; |
222 | } | 222 | } |
223 | for (import_id, import_data) in input.imports.iter() { | 223 | for (import_id, import_data) in input.imports.iter() { |
224 | if let Some(name) = import_data.path.segments.iter().last() { | 224 | if let Some(segment) = import_data.path.segments.iter().last() { |
225 | if !import_data.is_glob { | 225 | if !import_data.is_glob { |
226 | module_items.items.insert( | 226 | module_items.items.insert( |
227 | name.clone(), | 227 | segment.name.clone(), |
228 | Resolution { | 228 | Resolution { |
229 | def_id: PerNs::none(), | 229 | def_id: PerNs::none(), |
230 | import: Some(import_id), | 230 | import: Some(import_id), |
@@ -319,13 +319,13 @@ where | |||
319 | PathKind::Crate => module_id.crate_root(&self.module_tree), | 319 | PathKind::Crate => module_id.crate_root(&self.module_tree), |
320 | }; | 320 | }; |
321 | 321 | ||
322 | for (i, name) in import.path.segments.iter().enumerate() { | 322 | for (i, segment) in import.path.segments.iter().enumerate() { |
323 | let is_last = i == import.path.segments.len() - 1; | 323 | let is_last = i == import.path.segments.len() - 1; |
324 | 324 | ||
325 | let def_id = match self.result.per_module[&curr].items.get(name) { | 325 | let def_id = match self.result.per_module[&curr].items.get(&segment.name) { |
326 | Some(res) if !res.def_id.is_none() => res.def_id, | 326 | Some(res) if !res.def_id.is_none() => res.def_id, |
327 | _ => { | 327 | _ => { |
328 | log::debug!("path segment {:?} not found", name); | 328 | log::debug!("path segment {:?} not found", segment.name); |
329 | return false; | 329 | return false; |
330 | } | 330 | } |
331 | }; | 331 | }; |
@@ -336,7 +336,7 @@ where | |||
336 | } else { | 336 | } else { |
337 | log::debug!( | 337 | log::debug!( |
338 | "path segment {:?} resolved to value only, but is not last", | 338 | "path segment {:?} resolved to value only, but is not last", |
339 | name | 339 | segment.name |
340 | ); | 340 | ); |
341 | return false; | 341 | return false; |
342 | }; | 342 | }; |
@@ -358,17 +358,17 @@ where | |||
358 | log::debug!("resolving {:?} in other source root", path); | 358 | log::debug!("resolving {:?} in other source root", path); |
359 | let def_id = module.resolve_path(self.db, &path); | 359 | let def_id = module.resolve_path(self.db, &path); |
360 | if !def_id.is_none() { | 360 | if !def_id.is_none() { |
361 | let name = path.segments.last().unwrap(); | 361 | let last_segment = path.segments.last().unwrap(); |
362 | self.update(module_id, |items| { | 362 | self.update(module_id, |items| { |
363 | let res = Resolution { | 363 | let res = Resolution { |
364 | def_id, | 364 | def_id, |
365 | import: Some(import_id), | 365 | import: Some(import_id), |
366 | }; | 366 | }; |
367 | items.items.insert(name.clone(), res); | 367 | items.items.insert(last_segment.name.clone(), res); |
368 | }); | 368 | }); |
369 | log::debug!( | 369 | log::debug!( |
370 | "resolved import {:?} ({:?}) cross-source root to {:?}", | 370 | "resolved import {:?} ({:?}) cross-source root to {:?}", |
371 | name, | 371 | last_segment.name, |
372 | import, | 372 | import, |
373 | def_id.map(|did| did.loc(self.db)) | 373 | def_id.map(|did| did.loc(self.db)) |
374 | ); | 374 | ); |
@@ -382,7 +382,7 @@ where | |||
382 | _ => { | 382 | _ => { |
383 | log::debug!( | 383 | log::debug!( |
384 | "path segment {:?} resolved to non-module {:?}, but is not last", | 384 | "path segment {:?} resolved to non-module {:?}, but is not last", |
385 | name, | 385 | segment.name, |
386 | type_def_id.loc(self.db) | 386 | type_def_id.loc(self.db) |
387 | ); | 387 | ); |
388 | return true; // this resolved to a non-module, so the path won't ever resolve | 388 | return true; // this resolved to a non-module, so the path won't ever resolve |
@@ -391,7 +391,7 @@ where | |||
391 | } else { | 391 | } else { |
392 | log::debug!( | 392 | log::debug!( |
393 | "resolved import {:?} ({:?}) within source root to {:?}", | 393 | "resolved import {:?} ({:?}) within source root to {:?}", |
394 | name, | 394 | segment.name, |
395 | import, | 395 | import, |
396 | def_id.map(|did| did.loc(self.db)) | 396 | def_id.map(|did| did.loc(self.db)) |
397 | ); | 397 | ); |
@@ -400,7 +400,7 @@ where | |||
400 | def_id, | 400 | def_id, |
401 | import: Some(import_id), | 401 | import: Some(import_id), |
402 | }; | 402 | }; |
403 | items.items.insert(name.clone(), res); | 403 | items.items.insert(segment.name.clone(), res); |
404 | }) | 404 | }) |
405 | } | 405 | } |
406 | } | 406 | } |
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 => { |