about summary refs log tree commit diff
path: root/crates/syntax/src
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2023-01-14 12:45:20 +0000
committerMaybe Waffle <waffle.lapkin@gmail.com>2023-01-14 12:45:20 +0000
commitcfc01150bf9793934f504c5cfdef680c3799ddea (patch)
tree1f8d757c8ab50db8756b17e750fa3726e5590ff7 /crates/syntax/src
parent32be158630e0b011a24545b07282753e6de37dd3 (diff)
downloadrust-cfc01150bf9793934f504c5cfdef680c3799ddea.tar.gz
rust-cfc01150bf9793934f504c5cfdef680c3799ddea.zip
implement `AstNode` for `Either`
Diffstat (limited to 'crates/syntax/src')
-rw-r--r--crates/syntax/src/ast.rs30
1 files changed, 30 insertions, 0 deletions
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index 10c04575833..385a4e0a3ce 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -13,6 +13,8 @@ pub mod prec;
 
 use std::marker::PhantomData;
 
+use itertools::Either;
+
 use crate::{
     syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken},
     SyntaxKind,
@@ -98,6 +100,34 @@ impl<N: AstNode> Iterator for AstChildren<N> {
     }
 }
 
+impl<L, R> AstNode for Either<L, R>
+where
+    L: AstNode,
+    R: AstNode,
+{
+    fn can_cast(kind: SyntaxKind) -> bool
+    where
+        Self: Sized,
+    {
+        L::can_cast(kind) || R::can_cast(kind)
+    }
+
+    fn cast(syntax: SyntaxNode) -> Option<Self>
+    where
+        Self: Sized,
+    {
+        if L::can_cast(syntax.kind()) {
+            L::cast(syntax).map(Either::Left)
+        } else {
+            R::cast(syntax).map(Either::Right)
+        }
+    }
+
+    fn syntax(&self) -> &SyntaxNode {
+        self.as_ref().either(L::syntax, R::syntax)
+    }
+}
+
 mod support {
     use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken};