aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast/mod.rs')
-rw-r--r--crates/ra_syntax/src/ast/mod.rs206
1 files changed, 206 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/mod.rs b/crates/ra_syntax/src/ast/mod.rs
new file mode 100644
index 000000000..a6da82957
--- /dev/null
+++ b/crates/ra_syntax/src/ast/mod.rs
@@ -0,0 +1,206 @@
1mod generated;
2
3use std::marker::PhantomData;
4
5use itertools::Itertools;
6use smol_str::SmolStr;
7
8use {
9 SyntaxNodeRef, SyntaxKind::*,
10 yellow::{RefRoot, SyntaxNodeChildren},
11};
12pub use self::generated::*;
13
14pub trait AstNode<'a>: Clone + Copy + 'a {
15 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self>
16 where Self: Sized;
17 fn syntax(self) -> SyntaxNodeRef<'a>;
18}
19
20pub trait NameOwner<'a>: AstNode<'a> {
21 fn name(self) -> Option<Name<'a>> {
22 child_opt(self)
23 }
24}
25
26pub trait LoopBodyOwner<'a>: AstNode<'a> {
27 fn loop_body(self) -> Option<Block<'a>> {
28 child_opt(self)
29 }
30}
31
32pub trait ArgListOwner<'a>: AstNode<'a> {
33 fn arg_list(self) -> Option<ArgList<'a>> {
34 child_opt(self)
35 }
36}
37
38pub trait FnDefOwner<'a>: AstNode<'a> {
39 fn functions(self) -> AstChildren<'a, FnDef<'a>> {
40 children(self)
41 }
42}
43
44pub trait ModuleItemOwner<'a>: AstNode<'a> {
45 fn items(self) -> AstChildren<'a, ModuleItem<'a>> {
46 children(self)
47 }
48}
49
50pub trait TypeParamsOwner<'a>: AstNode<'a> {
51 fn type_param_list(self) -> Option<TypeParamList<'a>> {
52 child_opt(self)
53 }
54
55 fn where_clause(self) -> Option<WhereClause<'a>> {
56 child_opt(self)
57 }
58}
59
60pub trait AttrsOwner<'a>: AstNode<'a> {
61 fn attrs(self) -> AstChildren<'a, Attr<'a>> {
62 children(self)
63 }
64}
65
66impl<'a> FnDef<'a> {
67 pub fn has_atom_attr(&self, atom: &str) -> bool {
68 self.attrs()
69 .filter_map(|x| x.as_atom())
70 .any(|x| x == atom)
71 }
72}
73
74impl<'a> Attr<'a> {
75 pub fn as_atom(&self) -> Option<SmolStr> {
76 let tt = self.value()?;
77 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?;
78 if attr.kind() == IDENT {
79 Some(attr.leaf_text().unwrap())
80 } else {
81 None
82 }
83 }
84
85 pub fn as_call(&self) -> Option<(SmolStr, TokenTree<'a>)> {
86 let tt = self.value()?;
87 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?;
88 let args = TokenTree::cast(args)?;
89 if attr.kind() == IDENT {
90 Some((attr.leaf_text().unwrap(), args))
91 } else {
92 None
93 }
94 }
95}
96
97impl<'a> Lifetime<'a> {
98 pub fn text(&self) -> SmolStr {
99 self.syntax().leaf_text().unwrap()
100 }
101}
102
103impl<'a> Name<'a> {
104 pub fn text(&self) -> SmolStr {
105 let ident = self.syntax().first_child()
106 .unwrap();
107 ident.leaf_text().unwrap()
108 }
109}
110
111impl<'a> NameRef<'a> {
112 pub fn text(&self) -> SmolStr {
113 let ident = self.syntax().first_child()
114 .unwrap();
115 ident.leaf_text().unwrap()
116 }
117}
118
119impl<'a> ImplItem<'a> {
120 pub fn target_type(self) -> Option<TypeRef<'a>> {
121 match self.target() {
122 (Some(t), None) | (_, Some(t)) => Some(t),
123 _ => None,
124 }
125 }
126
127 pub fn target_trait(self) -> Option<TypeRef<'a>> {
128 match self.target() {
129 (Some(t), Some(_)) => Some(t),
130 _ => None,
131 }
132 }
133
134 fn target(self) -> (Option<TypeRef<'a>>, Option<TypeRef<'a>>) {
135 let mut types = children(self);
136 let first = types.next();
137 let second = types.next();
138 (first, second)
139 }
140}
141
142impl<'a> Module<'a> {
143 pub fn has_semi(self) -> bool {
144 match self.syntax().last_child() {
145 None => false,
146 Some(node) => node.kind() == SEMI,
147 }
148 }
149}
150
151impl<'a> LetStmt<'a> {
152 pub fn has_semi(self) -> bool {
153 match self.syntax().last_child() {
154 None => false,
155 Some(node) => node.kind() == SEMI,
156 }
157 }
158}
159
160impl<'a> IfExpr<'a> {
161 pub fn then_branch(self) -> Option<Block<'a>> {
162 self.blocks().nth(0)
163 }
164 pub fn else_branch(self) -> Option<Block<'a>> {
165 self.blocks().nth(1)
166 }
167 fn blocks(self) -> AstChildren<'a, Block<'a>> {
168 children(self)
169 }
170}
171
172fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> {
173 children(parent).next()
174}
175
176fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstChildren<'a, C> {
177 AstChildren::new(parent.syntax())
178}
179
180
181#[derive(Debug)]
182pub struct AstChildren<'a, N> {
183 inner: SyntaxNodeChildren<RefRoot<'a>>,
184 ph: PhantomData<N>,
185}
186
187impl<'a, N> AstChildren<'a, N> {
188 fn new(parent: SyntaxNodeRef<'a>) -> Self {
189 AstChildren {
190 inner: parent.children(),
191 ph: PhantomData,
192 }
193 }
194}
195
196impl<'a, N: AstNode<'a>> Iterator for AstChildren<'a, N> {
197 type Item = N;
198 fn next(&mut self) -> Option<N> {
199 loop {
200 match N::cast(self.inner.next()?) {
201 Some(n) => return Some(n),
202 None => (),
203 }
204 }
205 }
206}