diff options
Diffstat (limited to 'crates/syntax/src/ast')
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 61 |
1 files changed, 51 insertions, 10 deletions
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 307e150e9..c1f8101b2 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -298,25 +298,66 @@ impl ast::RecordExprField { | |||
298 | } | 298 | } |
299 | 299 | ||
300 | #[derive(Debug, Clone, PartialEq)] | 300 | #[derive(Debug, Clone, PartialEq)] |
301 | pub enum NameOrNameRef { | 301 | pub enum NameLike { |
302 | Name(ast::Name), | ||
303 | NameRef(ast::NameRef), | 302 | NameRef(ast::NameRef), |
303 | Name(ast::Name), | ||
304 | Lifetime(ast::Lifetime), | ||
304 | } | 305 | } |
305 | 306 | ||
306 | impl fmt::Display for NameOrNameRef { | 307 | impl NameLike { |
308 | pub fn as_name_ref(&self) -> Option<&ast::NameRef> { | ||
309 | match self { | ||
310 | NameLike::NameRef(name_ref) => Some(name_ref), | ||
311 | _ => None, | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
316 | impl ast::AstNode for NameLike { | ||
317 | fn can_cast(kind: SyntaxKind) -> bool { | ||
318 | matches!(kind, SyntaxKind::NAME | SyntaxKind::NAME_REF | SyntaxKind::LIFETIME) | ||
319 | } | ||
320 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
321 | let res = match syntax.kind() { | ||
322 | SyntaxKind::NAME => NameLike::Name(ast::Name { syntax }), | ||
323 | SyntaxKind::NAME_REF => NameLike::NameRef(ast::NameRef { syntax }), | ||
324 | SyntaxKind::LIFETIME => NameLike::Lifetime(ast::Lifetime { syntax }), | ||
325 | _ => return None, | ||
326 | }; | ||
327 | Some(res) | ||
328 | } | ||
329 | fn syntax(&self) -> &SyntaxNode { | ||
330 | match self { | ||
331 | NameLike::NameRef(it) => it.syntax(), | ||
332 | NameLike::Name(it) => it.syntax(), | ||
333 | NameLike::Lifetime(it) => it.syntax(), | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | |||
338 | impl fmt::Display for NameLike { | ||
307 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 339 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
308 | match self { | 340 | match self { |
309 | NameOrNameRef::Name(it) => fmt::Display::fmt(it, f), | 341 | NameLike::Name(it) => fmt::Display::fmt(it, f), |
310 | NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f), | 342 | NameLike::NameRef(it) => fmt::Display::fmt(it, f), |
343 | NameLike::Lifetime(it) => fmt::Display::fmt(it, f), | ||
311 | } | 344 | } |
312 | } | 345 | } |
313 | } | 346 | } |
314 | 347 | ||
348 | mod __ { | ||
349 | use super::{ | ||
350 | ast::{Lifetime, Name, NameRef}, | ||
351 | NameLike, | ||
352 | }; | ||
353 | stdx::impl_from!(NameRef, Name, Lifetime for NameLike); | ||
354 | } | ||
355 | |||
315 | impl ast::RecordPatField { | 356 | impl ast::RecordPatField { |
316 | pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> { | 357 | pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> { |
317 | let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?; | 358 | let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?; |
318 | match candidate.field_name()? { | 359 | match candidate.field_name()? { |
319 | NameOrNameRef::NameRef(name_ref) if name_ref == *field_name => Some(candidate), | 360 | NameLike::NameRef(name_ref) if name_ref == *field_name => Some(candidate), |
320 | _ => None, | 361 | _ => None, |
321 | } | 362 | } |
322 | } | 363 | } |
@@ -325,19 +366,19 @@ impl ast::RecordPatField { | |||
325 | let candidate = | 366 | let candidate = |
326 | field_name.syntax().ancestors().nth(2).and_then(ast::RecordPatField::cast)?; | 367 | field_name.syntax().ancestors().nth(2).and_then(ast::RecordPatField::cast)?; |
327 | match candidate.field_name()? { | 368 | match candidate.field_name()? { |
328 | NameOrNameRef::Name(name) if name == *field_name => Some(candidate), | 369 | NameLike::Name(name) if name == *field_name => Some(candidate), |
329 | _ => None, | 370 | _ => None, |
330 | } | 371 | } |
331 | } | 372 | } |
332 | 373 | ||
333 | /// Deals with field init shorthand | 374 | /// Deals with field init shorthand |
334 | pub fn field_name(&self) -> Option<NameOrNameRef> { | 375 | pub fn field_name(&self) -> Option<NameLike> { |
335 | if let Some(name_ref) = self.name_ref() { | 376 | if let Some(name_ref) = self.name_ref() { |
336 | return Some(NameOrNameRef::NameRef(name_ref)); | 377 | return Some(NameLike::NameRef(name_ref)); |
337 | } | 378 | } |
338 | if let Some(ast::Pat::IdentPat(pat)) = self.pat() { | 379 | if let Some(ast::Pat::IdentPat(pat)) = self.pat() { |
339 | let name = pat.name()?; | 380 | let name = pat.name()?; |
340 | return Some(NameOrNameRef::Name(name)); | 381 | return Some(NameLike::Name(name)); |
341 | } | 382 | } |
342 | None | 383 | None |
343 | } | 384 | } |