aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-01-12 23:19:20 +0000
committerFlorian Diebold <[email protected]>2019-01-19 15:02:06 +0000
commit5862542dedd5aca9bbdcba19c5f8cd895591005d (patch)
tree58fb630e97583db371eed1111d2c067bde2982b4 /crates
parent688a45e00b53412a7a16360c6d678a5d91a95789 (diff)
Add AST/HIR for type args in path segments
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs10
-rw-r--r--crates/ra_hir/src/nameres.rs24
-rw-r--r--crates/ra_hir/src/path.rs68
-rw-r--r--crates/ra_syntax/src/ast/generated.rs128
-rw-r--r--crates/ra_syntax/src/grammar.ron10
5 files changed, 217 insertions, 23 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 @@
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 => {
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 271040bf4..9fe946172 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -105,6 +105,38 @@ impl ArrayType {
105 } 105 }
106} 106}
107 107
108// AssocTypeArg
109#[derive(Debug, PartialEq, Eq, Hash)]
110#[repr(transparent)]
111pub struct AssocTypeArg {
112 pub(crate) syntax: SyntaxNode,
113}
114unsafe impl TransparentNewType for AssocTypeArg {
115 type Repr = rowan::SyntaxNode<RaTypes>;
116}
117
118impl AstNode for AssocTypeArg {
119 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
120 match syntax.kind() {
121 ASSOC_TYPE_ARG => Some(AssocTypeArg::from_repr(syntax.into_repr())),
122 _ => None,
123 }
124 }
125 fn syntax(&self) -> &SyntaxNode { &self.syntax }
126 fn to_owned(&self) -> TreeArc<AssocTypeArg> { TreeArc::cast(self.syntax.to_owned()) }
127}
128
129
130impl AssocTypeArg {
131 pub fn name_ref(&self) -> Option<&NameRef> {
132 super::child_opt(self)
133 }
134
135 pub fn type_ref(&self) -> Option<&TypeRef> {
136 super::child_opt(self)
137 }
138}
139
108// Attr 140// Attr
109#[derive(Debug, PartialEq, Eq, Hash)] 141#[derive(Debug, PartialEq, Eq, Hash)]
110#[repr(transparent)] 142#[repr(transparent)]
@@ -1397,6 +1429,34 @@ impl AstNode for Lifetime {
1397impl ast::AstToken for Lifetime {} 1429impl ast::AstToken for Lifetime {}
1398impl Lifetime {} 1430impl Lifetime {}
1399 1431
1432// LifetimeArg
1433#[derive(Debug, PartialEq, Eq, Hash)]
1434#[repr(transparent)]
1435pub struct LifetimeArg {
1436 pub(crate) syntax: SyntaxNode,
1437}
1438unsafe impl TransparentNewType for LifetimeArg {
1439 type Repr = rowan::SyntaxNode<RaTypes>;
1440}
1441
1442impl AstNode for LifetimeArg {
1443 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1444 match syntax.kind() {
1445 LIFETIME_ARG => Some(LifetimeArg::from_repr(syntax.into_repr())),
1446 _ => None,
1447 }
1448 }
1449 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1450 fn to_owned(&self) -> TreeArc<LifetimeArg> { TreeArc::cast(self.syntax.to_owned()) }
1451}
1452
1453
1454impl LifetimeArg {
1455 pub fn lifetime(&self) -> Option<&Lifetime> {
1456 super::child_opt(self)
1457 }
1458}
1459
1400// LifetimeParam 1460// LifetimeParam
1401#[derive(Debug, PartialEq, Eq, Hash)] 1461#[derive(Debug, PartialEq, Eq, Hash)]
1402#[repr(transparent)] 1462#[repr(transparent)]
@@ -2355,6 +2415,10 @@ impl PathSegment {
2355 pub fn name_ref(&self) -> Option<&NameRef> { 2415 pub fn name_ref(&self) -> Option<&NameRef> {
2356 super::child_opt(self) 2416 super::child_opt(self)
2357 } 2417 }
2418
2419 pub fn type_arg_list(&self) -> Option<&TypeArgList> {
2420 super::child_opt(self)
2421 }
2358} 2422}
2359 2423
2360// PathType 2424// PathType
@@ -3335,6 +3399,70 @@ impl TupleType {
3335 } 3399 }
3336} 3400}
3337 3401
3402// TypeArg
3403#[derive(Debug, PartialEq, Eq, Hash)]
3404#[repr(transparent)]
3405pub struct TypeArg {
3406 pub(crate) syntax: SyntaxNode,
3407}
3408unsafe impl TransparentNewType for TypeArg {
3409 type Repr = rowan::SyntaxNode<RaTypes>;
3410}
3411
3412impl AstNode for TypeArg {
3413 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3414 match syntax.kind() {
3415 TYPE_ARG => Some(TypeArg::from_repr(syntax.into_repr())),
3416 _ => None,
3417 }
3418 }
3419 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3420 fn to_owned(&self) -> TreeArc<TypeArg> { TreeArc::cast(self.syntax.to_owned()) }
3421}
3422
3423
3424impl TypeArg {
3425 pub fn type_ref(&self) -> Option<&TypeRef> {
3426 super::child_opt(self)
3427 }
3428}
3429
3430// TypeArgList
3431#[derive(Debug, PartialEq, Eq, Hash)]
3432#[repr(transparent)]
3433pub struct TypeArgList {
3434 pub(crate) syntax: SyntaxNode,
3435}
3436unsafe impl TransparentNewType for TypeArgList {
3437 type Repr = rowan::SyntaxNode<RaTypes>;
3438}
3439
3440impl AstNode for TypeArgList {
3441 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
3442 match syntax.kind() {
3443 TYPE_ARG_LIST => Some(TypeArgList::from_repr(syntax.into_repr())),
3444 _ => None,
3445 }
3446 }
3447 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3448 fn to_owned(&self) -> TreeArc<TypeArgList> { TreeArc::cast(self.syntax.to_owned()) }
3449}
3450
3451
3452impl TypeArgList {
3453 pub fn type_args(&self) -> impl Iterator<Item = &TypeArg> {
3454 super::children(self)
3455 }
3456
3457 pub fn lifetime_args(&self) -> impl Iterator<Item = &LifetimeArg> {
3458 super::children(self)
3459 }
3460
3461 pub fn assoc_type_args(&self) -> impl Iterator<Item = &AssocTypeArg> {
3462 super::children(self)
3463 }
3464}
3465
3338// TypeDef 3466// TypeDef
3339#[derive(Debug, PartialEq, Eq, Hash)] 3467#[derive(Debug, PartialEq, Eq, Hash)]
3340#[repr(transparent)] 3468#[repr(transparent)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index fc47c36d3..0385183fd 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -597,8 +597,16 @@ Grammar(
597 ] 597 ]
598 ), 598 ),
599 "PathSegment": ( 599 "PathSegment": (
600 options: [ "NameRef" ] 600 options: [ "NameRef", "TypeArgList" ]
601 ), 601 ),
602 "TypeArgList": (collections: [
603 ["type_args", "TypeArg"],
604 ["lifetime_args", "LifetimeArg"],
605 ["assoc_type_args", "AssocTypeArg"],
606 ]),
607 "TypeArg": (options: ["TypeRef"]),
608 "AssocTypeArg": (options: ["NameRef", "TypeRef"]),
609 "LifetimeArg": (options: ["Lifetime"]),
602 "Comment": ( traits: ["AstToken"] ), 610 "Comment": ( traits: ["AstToken"] ),
603 "Whitespace": ( traits: ["AstToken"] ), 611 "Whitespace": ( traits: ["AstToken"] ),
604 }, 612 },