aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast.rs')
-rw-r--r--crates/ra_syntax/src/ast.rs108
1 files changed, 5 insertions, 103 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 1ac0201b8..ab0f44dd2 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -11,10 +11,7 @@ pub mod make;
11use std::marker::PhantomData; 11use std::marker::PhantomData;
12 12
13use crate::{ 13use crate::{
14 syntax_node::{ 14 syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken},
15 NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren,
16 SyntaxToken,
17 },
18 SmolStr, SyntaxKind, 15 SmolStr, SyntaxKind,
19}; 16};
20 17
@@ -33,24 +30,16 @@ pub use self::{
33/// conversion itself has zero runtime cost: ast and syntax nodes have exactly 30/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
34/// the same representation: a pointer to the tree root and a pointer to the 31/// the same representation: a pointer to the tree root and a pointer to the
35/// node itself. 32/// node itself.
36pub trait AstNode: AstElement { 33pub trait AstNode {
37 fn can_cast(kind: SyntaxKind) -> bool 34 fn can_cast(kind: SyntaxKind) -> bool
38 where 35 where
39 Self: Sized; 36 Self: Sized;
40 37
41 fn cast_or_return(syntax: SyntaxNode) -> Result<Self, SyntaxNode>
42 where
43 Self: Sized;
44
45 fn cast(syntax: SyntaxNode) -> Option<Self> 38 fn cast(syntax: SyntaxNode) -> Option<Self>
46 where 39 where
47 Self: Sized, 40 Self: Sized;
48 {
49 <Self as AstNode>::cast_or_return(syntax).ok()
50 }
51 41
52 fn syntax(&self) -> &SyntaxNode; 42 fn syntax(&self) -> &SyntaxNode;
53 fn into_syntax(self) -> SyntaxNode;
54} 43}
55 44
56#[test] 45#[test]
@@ -59,51 +48,22 @@ fn assert_ast_is_object_safe() {
59} 48}
60 49
61/// Like `AstNode`, but wraps tokens rather than interior nodes. 50/// Like `AstNode`, but wraps tokens rather than interior nodes.
62pub trait AstToken: AstElement { 51pub trait AstToken {
63 fn can_cast(token: SyntaxKind) -> bool 52 fn can_cast(token: SyntaxKind) -> bool
64 where 53 where
65 Self: Sized; 54 Self: Sized;
66 55
67 fn cast_or_return(syntax: SyntaxToken) -> Result<Self, SyntaxToken>
68 where
69 Self: Sized;
70
71 fn cast(syntax: SyntaxToken) -> Option<Self> 56 fn cast(syntax: SyntaxToken) -> Option<Self>
72 where 57 where
73 Self: Sized, 58 Self: Sized;
74 {
75 <Self as AstToken>::cast_or_return(syntax).ok()
76 }
77 59
78 fn syntax(&self) -> &SyntaxToken; 60 fn syntax(&self) -> &SyntaxToken;
79 fn into_syntax(self) -> SyntaxToken;
80 61
81 fn text(&self) -> &SmolStr { 62 fn text(&self) -> &SmolStr {
82 self.syntax().text() 63 self.syntax().text()
83 } 64 }
84} 65}
85 66
86/// Like `AstNode`, but wraps either nodes or tokens rather than interior nodes.
87pub trait AstElement: std::fmt::Display {
88 fn can_cast_element(kind: SyntaxKind) -> bool
89 where
90 Self: Sized;
91
92 fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement>
93 where
94 Self: Sized;
95
96 fn cast_element(syntax: SyntaxElement) -> Option<Self>
97 where
98 Self: Sized,
99 {
100 <Self as AstElement>::cast_or_return_element(syntax).ok()
101 }
102
103 fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken>;
104 fn into_syntax_element(self) -> SyntaxElement;
105}
106
107/// An iterator over `SyntaxNode` children of a particular AST type. 67/// An iterator over `SyntaxNode` children of a particular AST type.
108#[derive(Debug, Clone)] 68#[derive(Debug, Clone)]
109pub struct AstChildren<N> { 69pub struct AstChildren<N> {
@@ -132,64 +92,6 @@ fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> {
132 AstChildren::new(parent.syntax()) 92 AstChildren::new(parent.syntax())
133} 93}
134 94
135/// An iterator over `SyntaxToken` children of a particular AST type.
136#[derive(Debug, Clone)]
137pub struct AstChildTokens<N> {
138 inner: SyntaxElementChildren,
139 ph: PhantomData<N>,
140}
141
142impl<N> AstChildTokens<N> {
143 fn new(parent: &SyntaxNode) -> Self {
144 AstChildTokens { inner: parent.children_with_tokens(), ph: PhantomData }
145 }
146}
147
148impl<N: AstToken> Iterator for AstChildTokens<N> {
149 type Item = N;
150 fn next(&mut self) -> Option<N> {
151 self.inner.by_ref().filter_map(|x| x.into_token()).find_map(N::cast)
152 }
153}
154
155fn child_token_opt<P: AstNode + ?Sized, C: AstToken>(parent: &P) -> Option<C> {
156 child_tokens(parent).next()
157}
158
159fn child_tokens<P: AstNode + ?Sized, C: AstToken>(parent: &P) -> AstChildTokens<C> {
160 AstChildTokens::new(parent.syntax())
161}
162
163/// An iterator over `SyntaxNode` children of a particular AST type.
164#[derive(Debug, Clone)]
165pub struct AstChildElements<N> {
166 inner: SyntaxElementChildren,
167 ph: PhantomData<N>,
168}
169
170impl<N> AstChildElements<N> {
171 fn new(parent: &SyntaxNode) -> Self {
172 AstChildElements { inner: parent.children_with_tokens(), ph: PhantomData }
173 }
174}
175
176impl<N: AstElement> Iterator for AstChildElements<N> {
177 type Item = N;
178 fn next(&mut self) -> Option<N> {
179 self.inner.by_ref().find_map(N::cast_element)
180 }
181}
182
183#[allow(dead_code)]
184fn child_element_opt<P: AstNode + ?Sized, C: AstElement>(parent: &P) -> Option<C> {
185 child_elements(parent).next()
186}
187
188#[allow(dead_code)]
189fn child_elements<P: AstNode + ?Sized, C: AstElement>(parent: &P) -> AstChildElements<C> {
190 AstChildElements::new(parent.syntax())
191}
192
193#[test] 95#[test]
194fn test_doc_comment_none() { 96fn test_doc_comment_none() {
195 let file = SourceFile::parse( 97 let file = SourceFile::parse(