diff options
Diffstat (limited to 'crates/ra_syntax/src/ast/node_ext.rs')
-rw-r--r-- | crates/ra_syntax/src/ast/node_ext.rs | 141 |
1 files changed, 76 insertions, 65 deletions
diff --git a/crates/ra_syntax/src/ast/node_ext.rs b/crates/ra_syntax/src/ast/node_ext.rs index 662c6f73e..733e97877 100644 --- a/crates/ra_syntax/src/ast/node_ext.rs +++ b/crates/ra_syntax/src/ast/node_ext.rs | |||
@@ -7,7 +7,7 @@ use itertools::Itertools; | |||
7 | use ra_parser::SyntaxKind; | 7 | use ra_parser::SyntaxKind; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | ast::{self, support, AstNode, AttrInput, NameOwner, SyntaxNode}, | 10 | ast::{self, support, AstNode, NameOwner, SyntaxNode}, |
11 | SmolStr, SyntaxElement, SyntaxToken, T, | 11 | SmolStr, SyntaxElement, SyntaxToken, T, |
12 | }; | 12 | }; |
13 | 13 | ||
@@ -39,29 +39,23 @@ pub enum AttrKind { | |||
39 | 39 | ||
40 | impl ast::Attr { | 40 | impl ast::Attr { |
41 | pub fn as_simple_atom(&self) -> Option<SmolStr> { | 41 | pub fn as_simple_atom(&self) -> Option<SmolStr> { |
42 | match self.input() { | 42 | if self.eq_token().is_some() || self.token_tree().is_some() { |
43 | None => self.simple_name(), | 43 | return None; |
44 | Some(_) => None, | ||
45 | } | 44 | } |
45 | self.simple_name() | ||
46 | } | 46 | } |
47 | 47 | ||
48 | pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { | 48 | pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> { |
49 | match self.input() { | 49 | let tt = self.token_tree()?; |
50 | Some(AttrInput::TokenTree(tt)) => Some((self.simple_name()?, tt)), | 50 | Some((self.simple_name()?, tt)) |
51 | _ => None, | ||
52 | } | ||
53 | } | 51 | } |
54 | 52 | ||
55 | pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> { | 53 | pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> { |
56 | match self.input() { | 54 | let lit = self.literal()?; |
57 | Some(AttrInput::Literal(lit)) => { | 55 | let key = self.simple_name()?; |
58 | let key = self.simple_name()?; | 56 | // FIXME: escape? raw string? |
59 | // FIXME: escape? raw string? | 57 | let value = lit.syntax().first_token()?.text().trim_matches('"').into(); |
60 | let value = lit.syntax().first_token()?.text().trim_matches('"').into(); | 58 | Some((key, value)) |
61 | Some((key, value)) | ||
62 | } | ||
63 | _ => None, | ||
64 | } | ||
65 | } | 59 | } |
66 | 60 | ||
67 | pub fn simple_name(&self) -> Option<SmolStr> { | 61 | pub fn simple_name(&self) -> Option<SmolStr> { |
@@ -88,7 +82,7 @@ impl ast::Attr { | |||
88 | #[derive(Debug, Clone, PartialEq, Eq)] | 82 | #[derive(Debug, Clone, PartialEq, Eq)] |
89 | pub enum PathSegmentKind { | 83 | pub enum PathSegmentKind { |
90 | Name(ast::NameRef), | 84 | Name(ast::NameRef), |
91 | Type { type_ref: Option<ast::TypeRef>, trait_ref: Option<ast::PathType> }, | 85 | Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> }, |
92 | SelfKw, | 86 | SelfKw, |
93 | SuperKw, | 87 | SuperKw, |
94 | CrateKw, | 88 | CrateKw, |
@@ -114,8 +108,8 @@ impl ast::PathSegment { | |||
114 | // <T> or <T as Trait> | 108 | // <T> or <T as Trait> |
115 | // T is any TypeRef, Trait has to be a PathType | 109 | // T is any TypeRef, Trait has to be a PathType |
116 | let mut type_refs = | 110 | let mut type_refs = |
117 | self.syntax().children().filter(|node| ast::TypeRef::can_cast(node.kind())); | 111 | self.syntax().children().filter(|node| ast::Type::can_cast(node.kind())); |
118 | let type_ref = type_refs.next().and_then(ast::TypeRef::cast); | 112 | let type_ref = type_refs.next().and_then(ast::Type::cast); |
119 | let trait_ref = type_refs.next().and_then(ast::PathType::cast); | 113 | let trait_ref = type_refs.next().and_then(ast::PathType::cast); |
120 | PathSegmentKind::Type { type_ref, trait_ref } | 114 | PathSegmentKind::Type { type_ref, trait_ref } |
121 | } | 115 | } |
@@ -141,22 +135,22 @@ impl ast::UseTreeList { | |||
141 | } | 135 | } |
142 | } | 136 | } |
143 | 137 | ||
144 | impl ast::ImplDef { | 138 | impl ast::Impl { |
145 | pub fn target_type(&self) -> Option<ast::TypeRef> { | 139 | pub fn self_ty(&self) -> Option<ast::Type> { |
146 | match self.target() { | 140 | match self.target() { |
147 | (Some(t), None) | (_, Some(t)) => Some(t), | 141 | (Some(t), None) | (_, Some(t)) => Some(t), |
148 | _ => None, | 142 | _ => None, |
149 | } | 143 | } |
150 | } | 144 | } |
151 | 145 | ||
152 | pub fn target_trait(&self) -> Option<ast::TypeRef> { | 146 | pub fn trait_(&self) -> Option<ast::Type> { |
153 | match self.target() { | 147 | match self.target() { |
154 | (Some(t), Some(_)) => Some(t), | 148 | (Some(t), Some(_)) => Some(t), |
155 | _ => None, | 149 | _ => None, |
156 | } | 150 | } |
157 | } | 151 | } |
158 | 152 | ||
159 | fn target(&self) -> (Option<ast::TypeRef>, Option<ast::TypeRef>) { | 153 | fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) { |
160 | let mut types = support::children(self.syntax()); | 154 | let mut types = support::children(self.syntax()); |
161 | let first = types.next(); | 155 | let first = types.next(); |
162 | let second = types.next(); | 156 | let second = types.next(); |
@@ -166,16 +160,16 @@ impl ast::ImplDef { | |||
166 | 160 | ||
167 | #[derive(Debug, Clone, PartialEq, Eq)] | 161 | #[derive(Debug, Clone, PartialEq, Eq)] |
168 | pub enum StructKind { | 162 | pub enum StructKind { |
169 | Record(ast::RecordFieldDefList), | 163 | Record(ast::RecordFieldList), |
170 | Tuple(ast::TupleFieldDefList), | 164 | Tuple(ast::TupleFieldList), |
171 | Unit, | 165 | Unit, |
172 | } | 166 | } |
173 | 167 | ||
174 | impl StructKind { | 168 | impl StructKind { |
175 | fn from_node<N: AstNode>(node: &N) -> StructKind { | 169 | fn from_node<N: AstNode>(node: &N) -> StructKind { |
176 | if let Some(nfdl) = support::child::<ast::RecordFieldDefList>(node.syntax()) { | 170 | if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) { |
177 | StructKind::Record(nfdl) | 171 | StructKind::Record(nfdl) |
178 | } else if let Some(pfl) = support::child::<ast::TupleFieldDefList>(node.syntax()) { | 172 | } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) { |
179 | StructKind::Tuple(pfl) | 173 | StructKind::Tuple(pfl) |
180 | } else { | 174 | } else { |
181 | StructKind::Unit | 175 | StructKind::Unit |
@@ -183,17 +177,17 @@ impl StructKind { | |||
183 | } | 177 | } |
184 | } | 178 | } |
185 | 179 | ||
186 | impl ast::StructDef { | 180 | impl ast::Struct { |
187 | pub fn kind(&self) -> StructKind { | 181 | pub fn kind(&self) -> StructKind { |
188 | StructKind::from_node(self) | 182 | StructKind::from_node(self) |
189 | } | 183 | } |
190 | } | 184 | } |
191 | 185 | ||
192 | impl ast::RecordField { | 186 | impl ast::RecordExprField { |
193 | pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordField> { | 187 | pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> { |
194 | let candidate = | 188 | let candidate = |
195 | field_name.syntax().parent().and_then(ast::RecordField::cast).or_else(|| { | 189 | field_name.syntax().parent().and_then(ast::RecordExprField::cast).or_else(|| { |
196 | field_name.syntax().ancestors().nth(4).and_then(ast::RecordField::cast) | 190 | field_name.syntax().ancestors().nth(4).and_then(ast::RecordExprField::cast) |
197 | })?; | 191 | })?; |
198 | if candidate.field_name().as_ref() == Some(field_name) { | 192 | if candidate.field_name().as_ref() == Some(field_name) { |
199 | Some(candidate) | 193 | Some(candidate) |
@@ -233,13 +227,13 @@ impl fmt::Display for NameOrNameRef { | |||
233 | } | 227 | } |
234 | } | 228 | } |
235 | 229 | ||
236 | impl ast::RecordFieldPat { | 230 | impl ast::RecordPatField { |
237 | /// Deals with field init shorthand | 231 | /// Deals with field init shorthand |
238 | pub fn field_name(&self) -> Option<NameOrNameRef> { | 232 | pub fn field_name(&self) -> Option<NameOrNameRef> { |
239 | if let Some(name_ref) = self.name_ref() { | 233 | if let Some(name_ref) = self.name_ref() { |
240 | return Some(NameOrNameRef::NameRef(name_ref)); | 234 | return Some(NameOrNameRef::NameRef(name_ref)); |
241 | } | 235 | } |
242 | if let Some(ast::Pat::BindPat(pat)) = self.pat() { | 236 | if let Some(ast::Pat::IdentPat(pat)) = self.pat() { |
243 | let name = pat.name()?; | 237 | let name = pat.name()?; |
244 | return Some(NameOrNameRef::Name(name)); | 238 | return Some(NameOrNameRef::Name(name)); |
245 | } | 239 | } |
@@ -247,12 +241,12 @@ impl ast::RecordFieldPat { | |||
247 | } | 241 | } |
248 | } | 242 | } |
249 | 243 | ||
250 | impl ast::EnumVariant { | 244 | impl ast::Variant { |
251 | pub fn parent_enum(&self) -> ast::EnumDef { | 245 | pub fn parent_enum(&self) -> ast::Enum { |
252 | self.syntax() | 246 | self.syntax() |
253 | .parent() | 247 | .parent() |
254 | .and_then(|it| it.parent()) | 248 | .and_then(|it| it.parent()) |
255 | .and_then(ast::EnumDef::cast) | 249 | .and_then(ast::Enum::cast) |
256 | .expect("EnumVariants are always nested in Enums") | 250 | .expect("EnumVariants are always nested in Enums") |
257 | } | 251 | } |
258 | pub fn kind(&self) -> StructKind { | 252 | pub fn kind(&self) -> StructKind { |
@@ -296,18 +290,18 @@ pub struct SlicePatComponents { | |||
296 | 290 | ||
297 | impl ast::SlicePat { | 291 | impl ast::SlicePat { |
298 | pub fn components(&self) -> SlicePatComponents { | 292 | pub fn components(&self) -> SlicePatComponents { |
299 | let mut args = self.args().peekable(); | 293 | let mut args = self.pats().peekable(); |
300 | let prefix = args | 294 | let prefix = args |
301 | .peeking_take_while(|p| match p { | 295 | .peeking_take_while(|p| match p { |
302 | ast::Pat::DotDotPat(_) => false, | 296 | ast::Pat::RestPat(_) => false, |
303 | ast::Pat::BindPat(bp) => match bp.pat() { | 297 | ast::Pat::IdentPat(bp) => match bp.pat() { |
304 | Some(ast::Pat::DotDotPat(_)) => false, | 298 | Some(ast::Pat::RestPat(_)) => false, |
305 | _ => true, | 299 | _ => true, |
306 | }, | 300 | }, |
307 | ast::Pat::RefPat(rp) => match rp.pat() { | 301 | ast::Pat::RefPat(rp) => match rp.pat() { |
308 | Some(ast::Pat::DotDotPat(_)) => false, | 302 | Some(ast::Pat::RestPat(_)) => false, |
309 | Some(ast::Pat::BindPat(bp)) => match bp.pat() { | 303 | Some(ast::Pat::IdentPat(bp)) => match bp.pat() { |
310 | Some(ast::Pat::DotDotPat(_)) => false, | 304 | Some(ast::Pat::RestPat(_)) => false, |
311 | _ => true, | 305 | _ => true, |
312 | }, | 306 | }, |
313 | _ => true, | 307 | _ => true, |
@@ -368,26 +362,6 @@ impl ast::TypeBound { | |||
368 | unreachable!() | 362 | unreachable!() |
369 | } | 363 | } |
370 | } | 364 | } |
371 | |||
372 | pub fn const_question_token(&self) -> Option<SyntaxToken> { | ||
373 | self.syntax() | ||
374 | .children_with_tokens() | ||
375 | .filter_map(|it| it.into_token()) | ||
376 | .take_while(|it| it.kind() != T![const]) | ||
377 | .find(|it| it.kind() == T![?]) | ||
378 | } | ||
379 | |||
380 | pub fn question_token(&self) -> Option<SyntaxToken> { | ||
381 | if self.const_token().is_some() { | ||
382 | self.syntax() | ||
383 | .children_with_tokens() | ||
384 | .filter_map(|it| it.into_token()) | ||
385 | .skip_while(|it| it.kind() != T![const]) | ||
386 | .find(|it| it.kind() == T![?]) | ||
387 | } else { | ||
388 | support::token(&self.syntax, T![?]) | ||
389 | } | ||
390 | } | ||
391 | } | 365 | } |
392 | 366 | ||
393 | pub enum VisibilityKind { | 367 | pub enum VisibilityKind { |
@@ -472,3 +446,40 @@ impl ast::TokenTree { | |||
472 | .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']'])) | 446 | .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']'])) |
473 | } | 447 | } |
474 | } | 448 | } |
449 | |||
450 | impl ast::GenericParamList { | ||
451 | pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> { | ||
452 | self.generic_params().filter_map(|param| match param { | ||
453 | ast::GenericParam::LifetimeParam(it) => Some(it), | ||
454 | ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None, | ||
455 | }) | ||
456 | } | ||
457 | pub fn type_params(&self) -> impl Iterator<Item = ast::TypeParam> { | ||
458 | self.generic_params().filter_map(|param| match param { | ||
459 | ast::GenericParam::TypeParam(it) => Some(it), | ||
460 | ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None, | ||
461 | }) | ||
462 | } | ||
463 | pub fn const_params(&self) -> impl Iterator<Item = ast::ConstParam> { | ||
464 | self.generic_params().filter_map(|param| match param { | ||
465 | ast::GenericParam::ConstParam(it) => Some(it), | ||
466 | ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None, | ||
467 | }) | ||
468 | } | ||
469 | } | ||
470 | |||
471 | impl ast::DocCommentsOwner for ast::SourceFile {} | ||
472 | impl ast::DocCommentsOwner for ast::Fn {} | ||
473 | impl ast::DocCommentsOwner for ast::Struct {} | ||
474 | impl ast::DocCommentsOwner for ast::Union {} | ||
475 | impl ast::DocCommentsOwner for ast::RecordField {} | ||
476 | impl ast::DocCommentsOwner for ast::TupleField {} | ||
477 | impl ast::DocCommentsOwner for ast::Enum {} | ||
478 | impl ast::DocCommentsOwner for ast::Variant {} | ||
479 | impl ast::DocCommentsOwner for ast::Trait {} | ||
480 | impl ast::DocCommentsOwner for ast::Module {} | ||
481 | impl ast::DocCommentsOwner for ast::Static {} | ||
482 | impl ast::DocCommentsOwner for ast::Const {} | ||
483 | impl ast::DocCommentsOwner for ast::TypeAlias {} | ||
484 | impl ast::DocCommentsOwner for ast::Impl {} | ||
485 | impl ast::DocCommentsOwner for ast::MacroCall {} | ||