aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src/ast
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-02-17 13:45:27 +0000
committerGitHub <[email protected]>2021-02-17 13:45:27 +0000
commit4054525c418085db4ceb2df70475a1ac9c019aff (patch)
tree64adbc8c62df3a6ebbe8c1a799589a94ddfbf490 /crates/syntax/src/ast
parent056601b41fbc5208cae5d996ec7fd18526d79e41 (diff)
parente1dbf43cf85f84c3a7e40f9731fc1f7ac96f8979 (diff)
Merge #7699
7699: Implement ast::AstNode for NameLike and move it to node_ext r=matklad a=Veykril With this `search`(and 2 other modules) don't necessarily go through 3 calls of `find_node_at_offset_with_descend` to find the correct node. Also makes the code that searches for NameLikes a bit easier on the eyes imo, though that can be fixed with just a helper function as well so its not that relevant. Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates/syntax/src/ast')
-rw-r--r--crates/syntax/src/ast/node_ext.rs61
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)]
301pub enum NameOrNameRef { 301pub 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
306impl fmt::Display for NameOrNameRef { 307impl 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
316impl 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
338impl 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
348mod __ {
349 use super::{
350 ast::{Lifetime, Name, NameRef},
351 NameLike,
352 };
353 stdx::impl_from!(NameRef, Name, Lifetime for NameLike);
354}
355
315impl ast::RecordPatField { 356impl 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 }