aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/node_ext.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast/node_ext.rs')
-rw-r--r--crates/ra_syntax/src/ast/node_ext.rs141
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;
7use ra_parser::SyntaxKind; 7use ra_parser::SyntaxKind;
8 8
9use crate::{ 9use 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
40impl ast::Attr { 40impl 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)]
89pub enum PathSegmentKind { 83pub 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
144impl ast::ImplDef { 138impl 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)]
168pub enum StructKind { 162pub 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
174impl StructKind { 168impl 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
186impl ast::StructDef { 180impl 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
192impl ast::RecordField { 186impl 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
236impl ast::RecordFieldPat { 230impl 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
250impl ast::EnumVariant { 244impl 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
297impl ast::SlicePat { 291impl 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
393pub enum VisibilityKind { 367pub 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
450impl 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
471impl ast::DocCommentsOwner for ast::SourceFile {}
472impl ast::DocCommentsOwner for ast::Fn {}
473impl ast::DocCommentsOwner for ast::Struct {}
474impl ast::DocCommentsOwner for ast::Union {}
475impl ast::DocCommentsOwner for ast::RecordField {}
476impl ast::DocCommentsOwner for ast::TupleField {}
477impl ast::DocCommentsOwner for ast::Enum {}
478impl ast::DocCommentsOwner for ast::Variant {}
479impl ast::DocCommentsOwner for ast::Trait {}
480impl ast::DocCommentsOwner for ast::Module {}
481impl ast::DocCommentsOwner for ast::Static {}
482impl ast::DocCommentsOwner for ast::Const {}
483impl ast::DocCommentsOwner for ast::TypeAlias {}
484impl ast::DocCommentsOwner for ast::Impl {}
485impl ast::DocCommentsOwner for ast::MacroCall {}