aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/path.rs')
-rw-r--r--crates/ra_hir/src/path.rs68
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 @@
1use std::sync::Arc;
2
1use ra_syntax::{ast, AstNode}; 3use ra_syntax::{ast, AstNode};
2 4
3use crate::{Name, AsName}; 5use crate::{Name, AsName, type_ref::TypeRef};
4 6
5#[derive(Debug, Clone, PartialEq, Eq, Hash)] 7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6pub struct Path { 8pub 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)]
14pub 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)]
23pub 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)]
30pub 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
129impl 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 => {