aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src
diff options
context:
space:
mode:
authorZac Pullar-Strecker <[email protected]>2020-08-24 10:19:53 +0100
committerZac Pullar-Strecker <[email protected]>2020-08-24 10:20:13 +0100
commit7bbca7a1b3f9293d2f5cc5745199bc5f8396f2f0 (patch)
treebdb47765991cb973b2cd5481a088fac636bd326c /crates/syntax/src
parentca464650eeaca6195891199a93f4f76cf3e7e697 (diff)
parente65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff)
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Diffstat (limited to 'crates/syntax/src')
-rw-r--r--crates/syntax/src/algo.rs406
-rw-r--r--crates/syntax/src/ast.rs331
-rw-r--r--crates/syntax/src/ast/edit.rs673
-rw-r--r--crates/syntax/src/ast/expr_ext.rs418
-rw-r--r--crates/syntax/src/ast/generated.rs41
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs4068
-rw-r--r--crates/syntax/src/ast/generated/tokens.rs91
-rw-r--r--crates/syntax/src/ast/make.rs402
-rw-r--r--crates/syntax/src/ast/node_ext.rs485
-rw-r--r--crates/syntax/src/ast/token_ext.rs538
-rw-r--r--crates/syntax/src/ast/traits.rs141
-rw-r--r--crates/syntax/src/fuzz.rs73
-rw-r--r--crates/syntax/src/lib.rs388
-rw-r--r--crates/syntax/src/parsing.rs59
-rw-r--r--crates/syntax/src/parsing/lexer.rs244
-rw-r--r--crates/syntax/src/parsing/reparsing.rs455
-rw-r--r--crates/syntax/src/parsing/text_token_source.rs84
-rw-r--r--crates/syntax/src/parsing/text_tree_sink.rs183
-rw-r--r--crates/syntax/src/ptr.rs105
-rw-r--r--crates/syntax/src/syntax_error.rs44
-rw-r--r--crates/syntax/src/syntax_node.rs77
-rw-r--r--crates/syntax/src/tests.rs280
-rw-r--r--crates/syntax/src/validation.rs303
-rw-r--r--crates/syntax/src/validation/block.rs22
24 files changed, 9911 insertions, 0 deletions
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
new file mode 100644
index 000000000..6254b38ba
--- /dev/null
+++ b/crates/syntax/src/algo.rs
@@ -0,0 +1,406 @@
1//! FIXME: write short doc here
2
3use std::{
4 fmt,
5 ops::{self, RangeInclusive},
6};
7
8use itertools::Itertools;
9use rustc_hash::FxHashMap;
10use text_edit::TextEditBuilder;
11
12use crate::{
13 AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxNodePtr,
14 SyntaxToken, TextRange, TextSize,
15};
16
17/// Returns ancestors of the node at the offset, sorted by length. This should
18/// do the right thing at an edge, e.g. when searching for expressions at `{
19/// <|>foo }` we will get the name reference instead of the whole block, which
20/// we would get if we just did `find_token_at_offset(...).flat_map(|t|
21/// t.parent().ancestors())`.
22pub fn ancestors_at_offset(
23 node: &SyntaxNode,
24 offset: TextSize,
25) -> impl Iterator<Item = SyntaxNode> {
26 node.token_at_offset(offset)
27 .map(|token| token.parent().ancestors())
28 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
29}
30
31/// Finds a node of specific Ast type at offset. Note that this is slightly
32/// imprecise: if the cursor is strictly between two nodes of the desired type,
33/// as in
34///
35/// ```no-run
36/// struct Foo {}|struct Bar;
37/// ```
38///
39/// then the shorter node will be silently preferred.
40pub fn find_node_at_offset<N: AstNode>(syntax: &SyntaxNode, offset: TextSize) -> Option<N> {
41 ancestors_at_offset(syntax, offset).find_map(N::cast)
42}
43
44pub fn find_node_at_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
45 find_covering_element(syntax, range).ancestors().find_map(N::cast)
46}
47
48/// Skip to next non `trivia` token
49pub fn skip_trivia_token(mut token: SyntaxToken, direction: Direction) -> Option<SyntaxToken> {
50 while token.kind().is_trivia() {
51 token = match direction {
52 Direction::Next => token.next_token()?,
53 Direction::Prev => token.prev_token()?,
54 }
55 }
56 Some(token)
57}
58
59/// Finds the first sibling in the given direction which is not `trivia`
60pub fn non_trivia_sibling(element: SyntaxElement, direction: Direction) -> Option<SyntaxElement> {
61 return match element {
62 NodeOrToken::Node(node) => node.siblings_with_tokens(direction).skip(1).find(not_trivia),
63 NodeOrToken::Token(token) => token.siblings_with_tokens(direction).skip(1).find(not_trivia),
64 };
65
66 fn not_trivia(element: &SyntaxElement) -> bool {
67 match element {
68 NodeOrToken::Node(_) => true,
69 NodeOrToken::Token(token) => !token.kind().is_trivia(),
70 }
71 }
72}
73
74pub fn find_covering_element(root: &SyntaxNode, range: TextRange) -> SyntaxElement {
75 root.covering_element(range)
76}
77
78pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNode> {
79 if u == v {
80 return Some(u.clone());
81 }
82
83 let u_depth = u.ancestors().count();
84 let v_depth = v.ancestors().count();
85 let keep = u_depth.min(v_depth);
86
87 let u_candidates = u.ancestors().skip(u_depth - keep);
88 let v_canidates = v.ancestors().skip(v_depth - keep);
89 let (res, _) = u_candidates.zip(v_canidates).find(|(x, y)| x == y)?;
90 Some(res)
91}
92
93pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {
94 me.syntax().siblings(direction).skip(1).find_map(T::cast)
95}
96
97pub fn has_errors(node: &SyntaxNode) -> bool {
98 node.children().any(|it| it.kind() == SyntaxKind::ERROR)
99}
100
101#[derive(Debug, PartialEq, Eq, Clone, Copy)]
102pub enum InsertPosition<T> {
103 First,
104 Last,
105 Before(T),
106 After(T),
107}
108
109pub struct TreeDiff {
110 replacements: FxHashMap<SyntaxElement, SyntaxElement>,
111}
112
113impl TreeDiff {
114 pub fn into_text_edit(&self, builder: &mut TextEditBuilder) {
115 for (from, to) in self.replacements.iter() {
116 builder.replace(from.text_range(), to.to_string())
117 }
118 }
119
120 pub fn is_empty(&self) -> bool {
121 self.replacements.is_empty()
122 }
123}
124
125/// Finds minimal the diff, which, applied to `from`, will result in `to`.
126///
127/// Specifically, returns a map whose keys are descendants of `from` and values
128/// are descendants of `to`, such that `replace_descendants(from, map) == to`.
129///
130/// A trivial solution is a singleton map `{ from: to }`, but this function
131/// tries to find a more fine-grained diff.
132pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff {
133 let mut buf = FxHashMap::default();
134 // FIXME: this is both horrible inefficient and gives larger than
135 // necessary diff. I bet there's a cool algorithm to diff trees properly.
136 go(&mut buf, from.clone().into(), to.clone().into());
137 return TreeDiff { replacements: buf };
138
139 fn go(
140 buf: &mut FxHashMap<SyntaxElement, SyntaxElement>,
141 lhs: SyntaxElement,
142 rhs: SyntaxElement,
143 ) {
144 if lhs.kind() == rhs.kind()
145 && lhs.text_range().len() == rhs.text_range().len()
146 && match (&lhs, &rhs) {
147 (NodeOrToken::Node(lhs), NodeOrToken::Node(rhs)) => {
148 lhs.green() == rhs.green() || lhs.text() == rhs.text()
149 }
150 (NodeOrToken::Token(lhs), NodeOrToken::Token(rhs)) => lhs.text() == rhs.text(),
151 _ => false,
152 }
153 {
154 return;
155 }
156 if let (Some(lhs), Some(rhs)) = (lhs.as_node(), rhs.as_node()) {
157 if lhs.children_with_tokens().count() == rhs.children_with_tokens().count() {
158 for (lhs, rhs) in lhs.children_with_tokens().zip(rhs.children_with_tokens()) {
159 go(buf, lhs, rhs)
160 }
161 return;
162 }
163 }
164 buf.insert(lhs, rhs);
165 }
166}
167
168/// Adds specified children (tokens or nodes) to the current node at the
169/// specific position.
170///
171/// This is a type-unsafe low-level editing API, if you need to use it,
172/// prefer to create a type-safe abstraction on top of it instead.
173pub fn insert_children(
174 parent: &SyntaxNode,
175 position: InsertPosition<SyntaxElement>,
176 to_insert: impl IntoIterator<Item = SyntaxElement>,
177) -> SyntaxNode {
178 let mut to_insert = to_insert.into_iter();
179 _insert_children(parent, position, &mut to_insert)
180}
181
182fn _insert_children(
183 parent: &SyntaxNode,
184 position: InsertPosition<SyntaxElement>,
185 to_insert: &mut dyn Iterator<Item = SyntaxElement>,
186) -> SyntaxNode {
187 let mut delta = TextSize::default();
188 let to_insert = to_insert.map(|element| {
189 delta += element.text_range().len();
190 to_green_element(element)
191 });
192
193 let mut old_children = parent.green().children().map(|it| match it {
194 NodeOrToken::Token(it) => NodeOrToken::Token(it.clone()),
195 NodeOrToken::Node(it) => NodeOrToken::Node(it.clone()),
196 });
197
198 let new_children = match &position {
199 InsertPosition::First => to_insert.chain(old_children).collect::<Vec<_>>(),
200 InsertPosition::Last => old_children.chain(to_insert).collect::<Vec<_>>(),
201 InsertPosition::Before(anchor) | InsertPosition::After(anchor) => {
202 let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 };
203 let split_at = position_of_child(parent, anchor.clone()) + take_anchor;
204 let before = old_children.by_ref().take(split_at).collect::<Vec<_>>();
205 before.into_iter().chain(to_insert).chain(old_children).collect::<Vec<_>>()
206 }
207 };
208
209 with_children(parent, new_children)
210}
211
212/// Replaces all nodes in `to_delete` with nodes from `to_insert`
213///
214/// This is a type-unsafe low-level editing API, if you need to use it,
215/// prefer to create a type-safe abstraction on top of it instead.
216pub fn replace_children(
217 parent: &SyntaxNode,
218 to_delete: RangeInclusive<SyntaxElement>,
219 to_insert: impl IntoIterator<Item = SyntaxElement>,
220) -> SyntaxNode {
221 let mut to_insert = to_insert.into_iter();
222 _replace_children(parent, to_delete, &mut to_insert)
223}
224
225fn _replace_children(
226 parent: &SyntaxNode,
227 to_delete: RangeInclusive<SyntaxElement>,
228 to_insert: &mut dyn Iterator<Item = SyntaxElement>,
229) -> SyntaxNode {
230 let start = position_of_child(parent, to_delete.start().clone());
231 let end = position_of_child(parent, to_delete.end().clone());
232 let mut old_children = parent.green().children().map(|it| match it {
233 NodeOrToken::Token(it) => NodeOrToken::Token(it.clone()),
234 NodeOrToken::Node(it) => NodeOrToken::Node(it.clone()),
235 });
236
237 let before = old_children.by_ref().take(start).collect::<Vec<_>>();
238 let new_children = before
239 .into_iter()
240 .chain(to_insert.map(to_green_element))
241 .chain(old_children.skip(end + 1 - start))
242 .collect::<Vec<_>>();
243 with_children(parent, new_children)
244}
245
246#[derive(Default)]
247pub struct SyntaxRewriter<'a> {
248 f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>,
249 //FIXME: add debug_assertions that all elements are in fact from the same file.
250 replacements: FxHashMap<SyntaxElement, Replacement>,
251}
252
253impl fmt::Debug for SyntaxRewriter<'_> {
254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255 f.debug_struct("SyntaxRewriter").field("replacements", &self.replacements).finish()
256 }
257}
258
259impl<'a> SyntaxRewriter<'a> {
260 pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> {
261 SyntaxRewriter { f: Some(Box::new(f)), replacements: FxHashMap::default() }
262 }
263 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) {
264 let what = what.clone().into();
265 let replacement = Replacement::Delete;
266 self.replacements.insert(what, replacement);
267 }
268 pub fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
269 let what = what.clone().into();
270 let replacement = Replacement::Single(with.clone().into());
271 self.replacements.insert(what, replacement);
272 }
273 pub fn replace_with_many<T: Clone + Into<SyntaxElement>>(
274 &mut self,
275 what: &T,
276 with: Vec<SyntaxElement>,
277 ) {
278 let what = what.clone().into();
279 let replacement = Replacement::Many(with);
280 self.replacements.insert(what, replacement);
281 }
282 pub fn replace_ast<T: AstNode>(&mut self, what: &T, with: &T) {
283 self.replace(what.syntax(), with.syntax())
284 }
285
286 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
287 if self.f.is_none() && self.replacements.is_empty() {
288 return node.clone();
289 }
290 self.rewrite_children(node)
291 }
292
293 pub fn rewrite_ast<N: AstNode>(self, node: &N) -> N {
294 N::cast(self.rewrite(node.syntax())).unwrap()
295 }
296
297 /// Returns a node that encompasses all replacements to be done by this rewriter.
298 ///
299 /// Passing the returned node to `rewrite` will apply all replacements queued up in `self`.
300 ///
301 /// Returns `None` when there are no replacements.
302 pub fn rewrite_root(&self) -> Option<SyntaxNode> {
303 assert!(self.f.is_none());
304 self.replacements
305 .keys()
306 .map(|element| match element {
307 SyntaxElement::Node(it) => it.clone(),
308 SyntaxElement::Token(it) => it.parent(),
309 })
310 // If we only have one replacement, we must return its parent node, since `rewrite` does
311 // not replace the node passed to it.
312 .map(|it| it.parent().unwrap_or(it))
313 .fold1(|a, b| least_common_ancestor(&a, &b).unwrap())
314 }
315
316 fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> {
317 if let Some(f) = &self.f {
318 assert!(self.replacements.is_empty());
319 return f(element).map(Replacement::Single);
320 }
321 self.replacements.get(element).cloned()
322 }
323
324 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode {
325 // FIXME: this could be made much faster.
326 let mut new_children = Vec::new();
327 for child in node.children_with_tokens() {
328 self.rewrite_self(&mut new_children, &child);
329 }
330 with_children(node, new_children)
331 }
332
333 fn rewrite_self(
334 &self,
335 acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
336 element: &SyntaxElement,
337 ) {
338 if let Some(replacement) = self.replacement(&element) {
339 match replacement {
340 Replacement::Single(NodeOrToken::Node(it)) => {
341 acc.push(NodeOrToken::Node(it.green().clone()))
342 }
343 Replacement::Single(NodeOrToken::Token(it)) => {
344 acc.push(NodeOrToken::Token(it.green().clone()))
345 }
346 Replacement::Many(replacements) => {
347 acc.extend(replacements.iter().map(|it| match it {
348 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
349 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
350 }))
351 }
352 Replacement::Delete => (),
353 };
354 return;
355 }
356 let res = match element {
357 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
358 NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()),
359 };
360 acc.push(res)
361 }
362}
363
364impl ops::AddAssign for SyntaxRewriter<'_> {
365 fn add_assign(&mut self, rhs: SyntaxRewriter) {
366 assert!(rhs.f.is_none());
367 self.replacements.extend(rhs.replacements)
368 }
369}
370
371#[derive(Clone, Debug)]
372enum Replacement {
373 Delete,
374 Single(SyntaxElement),
375 Many(Vec<SyntaxElement>),
376}
377
378fn with_children(
379 parent: &SyntaxNode,
380 new_children: Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
381) -> SyntaxNode {
382 let len = new_children.iter().map(|it| it.text_len()).sum::<TextSize>();
383 let new_node = rowan::GreenNode::new(rowan::SyntaxKind(parent.kind() as u16), new_children);
384 let new_root_node = parent.replace_with(new_node);
385 let new_root_node = SyntaxNode::new_root(new_root_node);
386
387 // FIXME: use a more elegant way to re-fetch the node (#1185), make
388 // `range` private afterwards
389 let mut ptr = SyntaxNodePtr::new(parent);
390 ptr.range = TextRange::at(ptr.range.start(), len);
391 ptr.to_node(&new_root_node)
392}
393
394fn position_of_child(parent: &SyntaxNode, child: SyntaxElement) -> usize {
395 parent
396 .children_with_tokens()
397 .position(|it| it == child)
398 .expect("element is not a child of current element")
399}
400
401fn to_green_element(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
402 match element {
403 NodeOrToken::Node(it) => it.green().clone().into(),
404 NodeOrToken::Token(it) => it.green().clone().into(),
405 }
406}
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
new file mode 100644
index 000000000..d536bb1e7
--- /dev/null
+++ b/crates/syntax/src/ast.rs
@@ -0,0 +1,331 @@
1//! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s
2
3mod generated;
4mod traits;
5mod token_ext;
6mod node_ext;
7mod expr_ext;
8pub mod edit;
9pub mod make;
10
11use std::marker::PhantomData;
12
13use crate::{
14 syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken},
15 SmolStr, SyntaxKind,
16};
17
18pub use self::{
19 expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
20 generated::*,
21 node_ext::{
22 AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
23 StructKind, TypeBoundKind, VisibilityKind,
24 },
25 token_ext::*,
26 traits::*,
27};
28
29/// The main trait to go from untyped `SyntaxNode` to a typed ast. The
30/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
31/// the same representation: a pointer to the tree root and a pointer to the
32/// node itself.
33pub trait AstNode {
34 fn can_cast(kind: SyntaxKind) -> bool
35 where
36 Self: Sized;
37
38 fn cast(syntax: SyntaxNode) -> Option<Self>
39 where
40 Self: Sized;
41
42 fn syntax(&self) -> &SyntaxNode;
43}
44
45/// Like `AstNode`, but wraps tokens rather than interior nodes.
46pub trait AstToken {
47 fn can_cast(token: SyntaxKind) -> bool
48 where
49 Self: Sized;
50
51 fn cast(syntax: SyntaxToken) -> Option<Self>
52 where
53 Self: Sized;
54
55 fn syntax(&self) -> &SyntaxToken;
56
57 fn text(&self) -> &SmolStr {
58 self.syntax().text()
59 }
60}
61
62/// An iterator over `SyntaxNode` children of a particular AST type.
63#[derive(Debug, Clone)]
64pub struct AstChildren<N> {
65 inner: SyntaxNodeChildren,
66 ph: PhantomData<N>,
67}
68
69impl<N> AstChildren<N> {
70 fn new(parent: &SyntaxNode) -> Self {
71 AstChildren { inner: parent.children(), ph: PhantomData }
72 }
73}
74
75impl<N: AstNode> Iterator for AstChildren<N> {
76 type Item = N;
77 fn next(&mut self) -> Option<N> {
78 self.inner.find_map(N::cast)
79 }
80}
81
82mod support {
83 use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken};
84
85 pub(super) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
86 parent.children().find_map(N::cast)
87 }
88
89 pub(super) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
90 AstChildren::new(parent)
91 }
92
93 pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
94 parent.children_with_tokens().filter_map(|it| it.into_token()).find(|it| it.kind() == kind)
95 }
96}
97
98#[test]
99fn assert_ast_is_object_safe() {
100 fn _f(_: &dyn AstNode, _: &dyn NameOwner) {}
101}
102
103#[test]
104fn test_doc_comment_none() {
105 let file = SourceFile::parse(
106 r#"
107 // non-doc
108 mod foo {}
109 "#,
110 )
111 .ok()
112 .unwrap();
113 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
114 assert!(module.doc_comment_text().is_none());
115}
116
117#[test]
118fn test_doc_comment_of_items() {
119 let file = SourceFile::parse(
120 r#"
121 //! doc
122 // non-doc
123 mod foo {}
124 "#,
125 )
126 .ok()
127 .unwrap();
128 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
129 assert_eq!("doc", module.doc_comment_text().unwrap());
130}
131
132#[test]
133fn test_doc_comment_of_statics() {
134 let file = SourceFile::parse(
135 r#"
136 /// Number of levels
137 static LEVELS: i32 = 0;
138 "#,
139 )
140 .ok()
141 .unwrap();
142 let st = file.syntax().descendants().find_map(Static::cast).unwrap();
143 assert_eq!("Number of levels", st.doc_comment_text().unwrap());
144}
145
146#[test]
147fn test_doc_comment_preserves_indents() {
148 let file = SourceFile::parse(
149 r#"
150 /// doc1
151 /// ```
152 /// fn foo() {
153 /// // ...
154 /// }
155 /// ```
156 mod foo {}
157 "#,
158 )
159 .ok()
160 .unwrap();
161 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
162 assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap());
163}
164
165#[test]
166fn test_doc_comment_preserves_newlines() {
167 let file = SourceFile::parse(
168 r#"
169 /// this
170 /// is
171 /// mod
172 /// foo
173 mod foo {}
174 "#,
175 )
176 .ok()
177 .unwrap();
178 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
179 assert_eq!("this\nis\nmod\nfoo", module.doc_comment_text().unwrap());
180}
181
182#[test]
183fn test_doc_comment_single_line_block_strips_suffix() {
184 let file = SourceFile::parse(
185 r#"
186 /** this is mod foo*/
187 mod foo {}
188 "#,
189 )
190 .ok()
191 .unwrap();
192 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
193 assert_eq!("this is mod foo", module.doc_comment_text().unwrap());
194}
195
196#[test]
197fn test_doc_comment_single_line_block_strips_suffix_whitespace() {
198 let file = SourceFile::parse(
199 r#"
200 /** this is mod foo */
201 mod foo {}
202 "#,
203 )
204 .ok()
205 .unwrap();
206 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
207 assert_eq!("this is mod foo ", module.doc_comment_text().unwrap());
208}
209
210#[test]
211fn test_doc_comment_multi_line_block_strips_suffix() {
212 let file = SourceFile::parse(
213 r#"
214 /**
215 this
216 is
217 mod foo
218 */
219 mod foo {}
220 "#,
221 )
222 .ok()
223 .unwrap();
224 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
225 assert_eq!(
226 " this\n is\n mod foo\n ",
227 module.doc_comment_text().unwrap()
228 );
229}
230
231#[test]
232fn test_comments_preserve_trailing_whitespace() {
233 let file = SourceFile::parse(
234 "\n/// Representation of a Realm. \n/// In the specification these are called Realm Records.\nstruct Realm {}",
235 )
236 .ok()
237 .unwrap();
238 let def = file.syntax().descendants().find_map(Struct::cast).unwrap();
239 assert_eq!(
240 "Representation of a Realm. \nIn the specification these are called Realm Records.",
241 def.doc_comment_text().unwrap()
242 );
243}
244
245#[test]
246fn test_four_slash_line_comment() {
247 let file = SourceFile::parse(
248 r#"
249 //// too many slashes to be a doc comment
250 /// doc comment
251 mod foo {}
252 "#,
253 )
254 .ok()
255 .unwrap();
256 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
257 assert_eq!("doc comment", module.doc_comment_text().unwrap());
258}
259
260#[test]
261fn test_where_predicates() {
262 fn assert_bound(text: &str, bound: Option<TypeBound>) {
263 assert_eq!(text, bound.unwrap().syntax().text().to_string());
264 }
265
266 let file = SourceFile::parse(
267 r#"
268fn foo()
269where
270 T: Clone + Copy + Debug + 'static,
271 'a: 'b + 'c,
272 Iterator::Item: 'a + Debug,
273 Iterator::Item: Debug + 'a,
274 <T as Iterator>::Item: Debug + 'a,
275 for<'a> F: Fn(&'a str)
276{}
277 "#,
278 )
279 .ok()
280 .unwrap();
281 let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap();
282
283 let mut predicates = where_clause.predicates();
284
285 let pred = predicates.next().unwrap();
286 let mut bounds = pred.type_bound_list().unwrap().bounds();
287
288 assert!(pred.for_token().is_none());
289 assert!(pred.generic_param_list().is_none());
290 assert_eq!("T", pred.ty().unwrap().syntax().text().to_string());
291 assert_bound("Clone", bounds.next());
292 assert_bound("Copy", bounds.next());
293 assert_bound("Debug", bounds.next());
294 assert_bound("'static", bounds.next());
295
296 let pred = predicates.next().unwrap();
297 let mut bounds = pred.type_bound_list().unwrap().bounds();
298
299 assert_eq!("'a", pred.lifetime_token().unwrap().text());
300
301 assert_bound("'b", bounds.next());
302 assert_bound("'c", bounds.next());
303
304 let pred = predicates.next().unwrap();
305 let mut bounds = pred.type_bound_list().unwrap().bounds();
306
307 assert_eq!("Iterator::Item", pred.ty().unwrap().syntax().text().to_string());
308 assert_bound("'a", bounds.next());
309
310 let pred = predicates.next().unwrap();
311 let mut bounds = pred.type_bound_list().unwrap().bounds();
312
313 assert_eq!("Iterator::Item", pred.ty().unwrap().syntax().text().to_string());
314 assert_bound("Debug", bounds.next());
315 assert_bound("'a", bounds.next());
316
317 let pred = predicates.next().unwrap();
318 let mut bounds = pred.type_bound_list().unwrap().bounds();
319
320 assert_eq!("<T as Iterator>::Item", pred.ty().unwrap().syntax().text().to_string());
321 assert_bound("Debug", bounds.next());
322 assert_bound("'a", bounds.next());
323
324 let pred = predicates.next().unwrap();
325 let mut bounds = pred.type_bound_list().unwrap().bounds();
326
327 assert!(pred.for_token().is_some());
328 assert_eq!("<'a>", pred.generic_param_list().unwrap().syntax().text().to_string());
329 assert_eq!("F", pred.ty().unwrap().syntax().text().to_string());
330 assert_bound("Fn(&'a str)", bounds.next());
331}
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
new file mode 100644
index 000000000..060b20966
--- /dev/null
+++ b/crates/syntax/src/ast/edit.rs
@@ -0,0 +1,673 @@
1//! This module contains functions for editing syntax trees. As the trees are
2//! immutable, all function here return a fresh copy of the tree, instead of
3//! doing an in-place modification.
4use std::{
5 fmt, iter,
6 ops::{self, RangeInclusive},
7};
8
9use arrayvec::ArrayVec;
10
11use crate::{
12 algo::{self, neighbor, SyntaxRewriter},
13 ast::{
14 self,
15 make::{self, tokens},
16 AstNode, TypeBoundsOwner,
17 },
18 AstToken, Direction, InsertPosition, SmolStr, SyntaxElement, SyntaxKind,
19 SyntaxKind::{ATTR, COMMENT, WHITESPACE},
20 SyntaxNode, SyntaxToken, T,
21};
22
23impl ast::BinExpr {
24 #[must_use]
25 pub fn replace_op(&self, op: SyntaxKind) -> Option<ast::BinExpr> {
26 let op_node: SyntaxElement = self.op_details()?.0.into();
27 let to_insert: Option<SyntaxElement> = Some(make::token(op).into());
28 Some(self.replace_children(single_node(op_node), to_insert))
29 }
30}
31
32impl ast::Fn {
33 #[must_use]
34 pub fn with_body(&self, body: ast::BlockExpr) -> ast::Fn {
35 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
36 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
37 old_body.syntax().clone().into()
38 } else if let Some(semi) = self.semicolon_token() {
39 to_insert.push(make::tokens::single_space().into());
40 semi.into()
41 } else {
42 to_insert.push(make::tokens::single_space().into());
43 to_insert.push(body.syntax().clone().into());
44 return self.insert_children(InsertPosition::Last, to_insert);
45 };
46 to_insert.push(body.syntax().clone().into());
47 self.replace_children(single_node(old_body_or_semi), to_insert)
48 }
49}
50
51fn make_multiline<N>(node: N) -> N
52where
53 N: AstNode + Clone,
54{
55 let l_curly = match node.syntax().children_with_tokens().find(|it| it.kind() == T!['{']) {
56 Some(it) => it,
57 None => return node,
58 };
59 let sibling = match l_curly.next_sibling_or_token() {
60 Some(it) => it,
61 None => return node,
62 };
63 let existing_ws = match sibling.as_token() {
64 None => None,
65 Some(tok) if tok.kind() != WHITESPACE => None,
66 Some(ws) => {
67 if ws.text().contains('\n') {
68 return node;
69 }
70 Some(ws.clone())
71 }
72 };
73
74 let indent = leading_indent(node.syntax()).unwrap_or_default();
75 let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
76 let to_insert = iter::once(ws.ws().into());
77 match existing_ws {
78 None => node.insert_children(InsertPosition::After(l_curly), to_insert),
79 Some(ws) => node.replace_children(single_node(ws), to_insert),
80 }
81}
82
83impl ast::AssocItemList {
84 #[must_use]
85 pub fn append_items(
86 &self,
87 items: impl IntoIterator<Item = ast::AssocItem>,
88 ) -> ast::AssocItemList {
89 let mut res = self.clone();
90 if !self.syntax().text().contains_char('\n') {
91 res = make_multiline(res);
92 }
93 items.into_iter().for_each(|it| res = res.append_item(it));
94 res.fixup_trailing_whitespace().unwrap_or(res)
95 }
96
97 #[must_use]
98 pub fn append_item(&self, item: ast::AssocItem) -> ast::AssocItemList {
99 let (indent, position, whitespace) = match self.assoc_items().last() {
100 Some(it) => (
101 leading_indent(it.syntax()).unwrap_or_default().to_string(),
102 InsertPosition::After(it.syntax().clone().into()),
103 "\n\n",
104 ),
105 None => match self.l_curly_token() {
106 Some(it) => (
107 " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
108 InsertPosition::After(it.into()),
109 "\n",
110 ),
111 None => return self.clone(),
112 },
113 };
114 let ws = tokens::WsBuilder::new(&format!("{}{}", whitespace, indent));
115 let to_insert: ArrayVec<[SyntaxElement; 2]> =
116 [ws.ws().into(), item.syntax().clone().into()].into();
117 self.insert_children(position, to_insert)
118 }
119
120 /// Remove extra whitespace between last item and closing curly brace.
121 fn fixup_trailing_whitespace(&self) -> Option<ast::AssocItemList> {
122 let first_token_after_items =
123 self.assoc_items().last()?.syntax().next_sibling_or_token()?;
124 let last_token_before_curly = self.r_curly_token()?.prev_sibling_or_token()?;
125 if last_token_before_curly != first_token_after_items {
126 // there is something more between last item and
127 // right curly than just whitespace - bail out
128 return None;
129 }
130 let whitespace =
131 last_token_before_curly.clone().into_token().and_then(ast::Whitespace::cast)?;
132 let text = whitespace.syntax().text();
133 let newline = text.rfind("\n")?;
134 let keep = tokens::WsBuilder::new(&text[newline..]);
135 Some(self.replace_children(
136 first_token_after_items..=last_token_before_curly,
137 std::iter::once(keep.ws().into()),
138 ))
139 }
140}
141
142impl ast::RecordExprFieldList {
143 #[must_use]
144 pub fn append_field(&self, field: &ast::RecordExprField) -> ast::RecordExprFieldList {
145 self.insert_field(InsertPosition::Last, field)
146 }
147
148 #[must_use]
149 pub fn insert_field(
150 &self,
151 position: InsertPosition<&'_ ast::RecordExprField>,
152 field: &ast::RecordExprField,
153 ) -> ast::RecordExprFieldList {
154 let is_multiline = self.syntax().text().contains_char('\n');
155 let ws;
156 let space = if is_multiline {
157 ws = tokens::WsBuilder::new(&format!(
158 "\n{} ",
159 leading_indent(self.syntax()).unwrap_or_default()
160 ));
161 ws.ws()
162 } else {
163 tokens::single_space()
164 };
165
166 let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new();
167 to_insert.push(space.into());
168 to_insert.push(field.syntax().clone().into());
169 to_insert.push(make::token(T![,]).into());
170
171 macro_rules! after_l_curly {
172 () => {{
173 let anchor = match self.l_curly_token() {
174 Some(it) => it.into(),
175 None => return self.clone(),
176 };
177 InsertPosition::After(anchor)
178 }};
179 }
180
181 macro_rules! after_field {
182 ($anchor:expr) => {
183 if let Some(comma) = $anchor
184 .syntax()
185 .siblings_with_tokens(Direction::Next)
186 .find(|it| it.kind() == T![,])
187 {
188 InsertPosition::After(comma)
189 } else {
190 to_insert.insert(0, make::token(T![,]).into());
191 InsertPosition::After($anchor.syntax().clone().into())
192 }
193 };
194 };
195
196 let position = match position {
197 InsertPosition::First => after_l_curly!(),
198 InsertPosition::Last => {
199 if !is_multiline {
200 // don't insert comma before curly
201 to_insert.pop();
202 }
203 match self.fields().last() {
204 Some(it) => after_field!(it),
205 None => after_l_curly!(),
206 }
207 }
208 InsertPosition::Before(anchor) => {
209 InsertPosition::Before(anchor.syntax().clone().into())
210 }
211 InsertPosition::After(anchor) => after_field!(anchor),
212 };
213
214 self.insert_children(position, to_insert)
215 }
216}
217
218impl ast::TypeAlias {
219 #[must_use]
220 pub fn remove_bounds(&self) -> ast::TypeAlias {
221 let colon = match self.colon_token() {
222 Some(it) => it,
223 None => return self.clone(),
224 };
225 let end = match self.type_bound_list() {
226 Some(it) => it.syntax().clone().into(),
227 None => colon.clone().into(),
228 };
229 self.replace_children(colon.into()..=end, iter::empty())
230 }
231}
232
233impl ast::TypeParam {
234 #[must_use]
235 pub fn remove_bounds(&self) -> ast::TypeParam {
236 let colon = match self.colon_token() {
237 Some(it) => it,
238 None => return self.clone(),
239 };
240 let end = match self.type_bound_list() {
241 Some(it) => it.syntax().clone().into(),
242 None => colon.clone().into(),
243 };
244 self.replace_children(colon.into()..=end, iter::empty())
245 }
246}
247
248impl ast::Path {
249 #[must_use]
250 pub fn with_segment(&self, segment: ast::PathSegment) -> ast::Path {
251 if let Some(old) = self.segment() {
252 return self.replace_children(
253 single_node(old.syntax().clone()),
254 iter::once(segment.syntax().clone().into()),
255 );
256 }
257 self.clone()
258 }
259}
260
261impl ast::PathSegment {
262 #[must_use]
263 pub fn with_type_args(&self, type_args: ast::GenericArgList) -> ast::PathSegment {
264 self._with_type_args(type_args, false)
265 }
266
267 #[must_use]
268 pub fn with_turbo_fish(&self, type_args: ast::GenericArgList) -> ast::PathSegment {
269 self._with_type_args(type_args, true)
270 }
271
272 fn _with_type_args(&self, type_args: ast::GenericArgList, turbo: bool) -> ast::PathSegment {
273 if let Some(old) = self.generic_arg_list() {
274 return self.replace_children(
275 single_node(old.syntax().clone()),
276 iter::once(type_args.syntax().clone().into()),
277 );
278 }
279 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
280 if turbo {
281 to_insert.push(make::token(T![::]).into());
282 }
283 to_insert.push(type_args.syntax().clone().into());
284 self.insert_children(InsertPosition::Last, to_insert)
285 }
286}
287
288impl ast::Use {
289 #[must_use]
290 pub fn with_use_tree(&self, use_tree: ast::UseTree) -> ast::Use {
291 if let Some(old) = self.use_tree() {
292 return self.replace_descendant(old, use_tree);
293 }
294 self.clone()
295 }
296
297 pub fn remove(&self) -> SyntaxRewriter<'static> {
298 let mut res = SyntaxRewriter::default();
299 res.delete(self.syntax());
300 let next_ws = self
301 .syntax()
302 .next_sibling_or_token()
303 .and_then(|it| it.into_token())
304 .and_then(ast::Whitespace::cast);
305 if let Some(next_ws) = next_ws {
306 let ws_text = next_ws.syntax().text();
307 if ws_text.starts_with('\n') {
308 let rest = &ws_text[1..];
309 if rest.is_empty() {
310 res.delete(next_ws.syntax())
311 } else {
312 res.replace(next_ws.syntax(), &make::tokens::whitespace(rest));
313 }
314 }
315 }
316 res
317 }
318}
319
320impl ast::UseTree {
321 #[must_use]
322 pub fn with_path(&self, path: ast::Path) -> ast::UseTree {
323 if let Some(old) = self.path() {
324 return self.replace_descendant(old, path);
325 }
326 self.clone()
327 }
328
329 #[must_use]
330 pub fn with_use_tree_list(&self, use_tree_list: ast::UseTreeList) -> ast::UseTree {
331 if let Some(old) = self.use_tree_list() {
332 return self.replace_descendant(old, use_tree_list);
333 }
334 self.clone()
335 }
336
337 #[must_use]
338 pub fn split_prefix(&self, prefix: &ast::Path) -> ast::UseTree {
339 let suffix = if self.path().as_ref() == Some(prefix) && self.use_tree_list().is_none() {
340 make::path_unqualified(make::path_segment_self())
341 } else {
342 match split_path_prefix(&prefix) {
343 Some(it) => it,
344 None => return self.clone(),
345 }
346 };
347
348 let use_tree = make::use_tree(
349 suffix,
350 self.use_tree_list(),
351 self.rename(),
352 self.star_token().is_some(),
353 );
354 let nested = make::use_tree_list(iter::once(use_tree));
355 return make::use_tree(prefix.clone(), Some(nested), None, false);
356
357 fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> {
358 let parent = prefix.parent_path()?;
359 let segment = parent.segment()?;
360 if algo::has_errors(segment.syntax()) {
361 return None;
362 }
363 let mut res = make::path_unqualified(segment);
364 for p in iter::successors(parent.parent_path(), |it| it.parent_path()) {
365 res = make::path_qualified(res, p.segment()?);
366 }
367 Some(res)
368 }
369 }
370
371 pub fn remove(&self) -> SyntaxRewriter<'static> {
372 let mut res = SyntaxRewriter::default();
373 res.delete(self.syntax());
374 for &dir in [Direction::Next, Direction::Prev].iter() {
375 if let Some(nb) = neighbor(self, dir) {
376 self.syntax()
377 .siblings_with_tokens(dir)
378 .skip(1)
379 .take_while(|it| it.as_node() != Some(nb.syntax()))
380 .for_each(|el| res.delete(&el));
381 return res;
382 }
383 }
384 res
385 }
386}
387
388impl ast::MatchArmList {
389 #[must_use]
390 pub fn append_arms(&self, items: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
391 let mut res = self.clone();
392 res = res.strip_if_only_whitespace();
393 if !res.syntax().text().contains_char('\n') {
394 res = make_multiline(res);
395 }
396 items.into_iter().for_each(|it| res = res.append_arm(it));
397 res
398 }
399
400 fn strip_if_only_whitespace(&self) -> ast::MatchArmList {
401 let mut iter = self.syntax().children_with_tokens().skip_while(|it| it.kind() != T!['{']);
402 iter.next(); // Eat the curly
403 let mut inner = iter.take_while(|it| it.kind() != T!['}']);
404 if !inner.clone().all(|it| it.kind() == WHITESPACE) {
405 return self.clone();
406 }
407 let start = match inner.next() {
408 Some(s) => s,
409 None => return self.clone(),
410 };
411 let end = match inner.last() {
412 Some(s) => s,
413 None => start.clone(),
414 };
415 self.replace_children(start..=end, &mut iter::empty())
416 }
417
418 #[must_use]
419 pub fn remove_placeholder(&self) -> ast::MatchArmList {
420 let placeholder =
421 self.arms().find(|arm| matches!(arm.pat(), Some(ast::Pat::WildcardPat(_))));
422 if let Some(placeholder) = placeholder {
423 self.remove_arm(&placeholder)
424 } else {
425 self.clone()
426 }
427 }
428
429 #[must_use]
430 fn remove_arm(&self, arm: &ast::MatchArm) -> ast::MatchArmList {
431 let start = arm.syntax().clone();
432 let end = if let Some(comma) = start
433 .siblings_with_tokens(Direction::Next)
434 .skip(1)
435 .skip_while(|it| it.kind().is_trivia())
436 .next()
437 .filter(|it| it.kind() == T![,])
438 {
439 comma
440 } else {
441 start.clone().into()
442 };
443 self.replace_children(start.into()..=end, None)
444 }
445
446 #[must_use]
447 pub fn append_arm(&self, item: ast::MatchArm) -> ast::MatchArmList {
448 let r_curly = match self.syntax().children_with_tokens().find(|it| it.kind() == T!['}']) {
449 Some(t) => t,
450 None => return self.clone(),
451 };
452 let position = InsertPosition::Before(r_curly.into());
453 let arm_ws = tokens::WsBuilder::new(" ");
454 let match_indent = &leading_indent(self.syntax()).unwrap_or_default();
455 let match_ws = tokens::WsBuilder::new(&format!("\n{}", match_indent));
456 let to_insert: ArrayVec<[SyntaxElement; 3]> =
457 [arm_ws.ws().into(), item.syntax().clone().into(), match_ws.ws().into()].into();
458 self.insert_children(position, to_insert)
459 }
460}
461
462#[must_use]
463pub fn remove_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N {
464 N::cast(remove_attrs_and_docs_inner(node.syntax().clone())).unwrap()
465}
466
467fn remove_attrs_and_docs_inner(mut node: SyntaxNode) -> SyntaxNode {
468 while let Some(start) =
469 node.children_with_tokens().find(|it| it.kind() == ATTR || it.kind() == COMMENT)
470 {
471 let end = match &start.next_sibling_or_token() {
472 Some(el) if el.kind() == WHITESPACE => el.clone(),
473 Some(_) | None => start.clone(),
474 };
475 node = algo::replace_children(&node, start..=end, &mut iter::empty());
476 }
477 node
478}
479
480#[derive(Debug, Clone, Copy)]
481pub struct IndentLevel(pub u8);
482
483impl From<u8> for IndentLevel {
484 fn from(level: u8) -> IndentLevel {
485 IndentLevel(level)
486 }
487}
488
489impl fmt::Display for IndentLevel {
490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491 let spaces = " ";
492 let buf;
493 let len = self.0 as usize * 4;
494 let indent = if len <= spaces.len() {
495 &spaces[..len]
496 } else {
497 buf = iter::repeat(' ').take(len).collect::<String>();
498 &buf
499 };
500 fmt::Display::fmt(indent, f)
501 }
502}
503
504impl ops::Add<u8> for IndentLevel {
505 type Output = IndentLevel;
506 fn add(self, rhs: u8) -> IndentLevel {
507 IndentLevel(self.0 + rhs)
508 }
509}
510
511impl IndentLevel {
512 pub fn from_node(node: &SyntaxNode) -> IndentLevel {
513 let first_token = match node.first_token() {
514 Some(it) => it,
515 None => return IndentLevel(0),
516 };
517 for ws in prev_tokens(first_token).filter_map(ast::Whitespace::cast) {
518 let text = ws.syntax().text();
519 if let Some(pos) = text.rfind('\n') {
520 let level = text[pos + 1..].chars().count() / 4;
521 return IndentLevel(level as u8);
522 }
523 }
524 IndentLevel(0)
525 }
526
527 /// XXX: this intentionally doesn't change the indent of the very first token.
528 /// Ie, in something like
529 /// ```
530 /// fn foo() {
531 /// 92
532 /// }
533 /// ```
534 /// if you indent the block, the `{` token would stay put.
535 fn increase_indent(self, node: SyntaxNode) -> SyntaxNode {
536 let mut rewriter = SyntaxRewriter::default();
537 node.descendants_with_tokens()
538 .filter_map(|el| el.into_token())
539 .filter_map(ast::Whitespace::cast)
540 .filter(|ws| {
541 let text = ws.syntax().text();
542 text.contains('\n')
543 })
544 .for_each(|ws| {
545 let new_ws = make::tokens::whitespace(&format!("{}{}", ws.syntax(), self,));
546 rewriter.replace(ws.syntax(), &new_ws)
547 });
548 rewriter.rewrite(&node)
549 }
550
551 fn decrease_indent(self, node: SyntaxNode) -> SyntaxNode {
552 let mut rewriter = SyntaxRewriter::default();
553 node.descendants_with_tokens()
554 .filter_map(|el| el.into_token())
555 .filter_map(ast::Whitespace::cast)
556 .filter(|ws| {
557 let text = ws.syntax().text();
558 text.contains('\n')
559 })
560 .for_each(|ws| {
561 let new_ws = make::tokens::whitespace(
562 &ws.syntax().text().replace(&format!("\n{}", self), "\n"),
563 );
564 rewriter.replace(ws.syntax(), &new_ws)
565 });
566 rewriter.rewrite(&node)
567 }
568}
569
570// FIXME: replace usages with IndentLevel above
571fn leading_indent(node: &SyntaxNode) -> Option<SmolStr> {
572 for token in prev_tokens(node.first_token()?) {
573 if let Some(ws) = ast::Whitespace::cast(token.clone()) {
574 let ws_text = ws.text();
575 if let Some(pos) = ws_text.rfind('\n') {
576 return Some(ws_text[pos + 1..].into());
577 }
578 }
579 if token.text().contains('\n') {
580 break;
581 }
582 }
583 None
584}
585
586fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
587 iter::successors(Some(token), |token| token.prev_token())
588}
589
590pub trait AstNodeEdit: AstNode + Clone + Sized {
591 #[must_use]
592 fn insert_children(
593 &self,
594 position: InsertPosition<SyntaxElement>,
595 to_insert: impl IntoIterator<Item = SyntaxElement>,
596 ) -> Self {
597 let new_syntax = algo::insert_children(self.syntax(), position, to_insert);
598 Self::cast(new_syntax).unwrap()
599 }
600
601 #[must_use]
602 fn replace_children(
603 &self,
604 to_replace: RangeInclusive<SyntaxElement>,
605 to_insert: impl IntoIterator<Item = SyntaxElement>,
606 ) -> Self {
607 let new_syntax = algo::replace_children(self.syntax(), to_replace, to_insert);
608 Self::cast(new_syntax).unwrap()
609 }
610
611 #[must_use]
612 fn replace_descendant<D: AstNode>(&self, old: D, new: D) -> Self {
613 self.replace_descendants(iter::once((old, new)))
614 }
615
616 #[must_use]
617 fn replace_descendants<D: AstNode>(
618 &self,
619 replacement_map: impl IntoIterator<Item = (D, D)>,
620 ) -> Self {
621 let mut rewriter = SyntaxRewriter::default();
622 for (from, to) in replacement_map {
623 rewriter.replace(from.syntax(), to.syntax())
624 }
625 rewriter.rewrite_ast(self)
626 }
627 fn indent_level(&self) -> IndentLevel {
628 IndentLevel::from_node(self.syntax())
629 }
630 #[must_use]
631 fn indent(&self, level: IndentLevel) -> Self {
632 Self::cast(level.increase_indent(self.syntax().clone())).unwrap()
633 }
634 #[must_use]
635 fn dedent(&self, level: IndentLevel) -> Self {
636 Self::cast(level.decrease_indent(self.syntax().clone())).unwrap()
637 }
638 #[must_use]
639 fn reset_indent(&self) -> Self {
640 let level = IndentLevel::from_node(self.syntax());
641 self.dedent(level)
642 }
643}
644
645impl<N: AstNode + Clone> AstNodeEdit for N {}
646
647fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElement> {
648 let element = element.into();
649 element.clone()..=element
650}
651
652#[test]
653fn test_increase_indent() {
654 let arm_list = {
655 let arm = make::match_arm(iter::once(make::wildcard_pat().into()), make::expr_unit());
656 make::match_arm_list(vec![arm.clone(), arm])
657 };
658 assert_eq!(
659 arm_list.syntax().to_string(),
660 "{
661 _ => (),
662 _ => (),
663}"
664 );
665 let indented = arm_list.indent(IndentLevel(2));
666 assert_eq!(
667 indented.syntax().to_string(),
668 "{
669 _ => (),
670 _ => (),
671 }"
672 );
673}
diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs
new file mode 100644
index 000000000..f5ba87223
--- /dev/null
+++ b/crates/syntax/src/ast/expr_ext.rs
@@ -0,0 +1,418 @@
1//! Various extension methods to ast Expr Nodes, which are hard to code-generate.
2
3use crate::{
4 ast::{self, support, AstChildren, AstNode},
5 SmolStr,
6 SyntaxKind::*,
7 SyntaxToken, T,
8};
9
10impl ast::AttrsOwner for ast::Expr {}
11
12impl ast::Expr {
13 pub fn is_block_like(&self) -> bool {
14 match self {
15 ast::Expr::IfExpr(_)
16 | ast::Expr::LoopExpr(_)
17 | ast::Expr::ForExpr(_)
18 | ast::Expr::WhileExpr(_)
19 | ast::Expr::BlockExpr(_)
20 | ast::Expr::MatchExpr(_)
21 | ast::Expr::EffectExpr(_) => true,
22 _ => false,
23 }
24 }
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum ElseBranch {
29 Block(ast::BlockExpr),
30 IfExpr(ast::IfExpr),
31}
32
33impl ast::IfExpr {
34 pub fn then_branch(&self) -> Option<ast::BlockExpr> {
35 self.blocks().next()
36 }
37 pub fn else_branch(&self) -> Option<ElseBranch> {
38 let res = match self.blocks().nth(1) {
39 Some(block) => ElseBranch::Block(block),
40 None => {
41 let elif: ast::IfExpr = support::child(self.syntax())?;
42 ElseBranch::IfExpr(elif)
43 }
44 };
45 Some(res)
46 }
47
48 pub fn blocks(&self) -> AstChildren<ast::BlockExpr> {
49 support::children(self.syntax())
50 }
51}
52
53#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
54pub enum PrefixOp {
55 /// The `*` operator for dereferencing
56 Deref,
57 /// The `!` operator for logical inversion
58 Not,
59 /// The `-` operator for negation
60 Neg,
61}
62
63impl ast::PrefixExpr {
64 pub fn op_kind(&self) -> Option<PrefixOp> {
65 match self.op_token()?.kind() {
66 T![*] => Some(PrefixOp::Deref),
67 T![!] => Some(PrefixOp::Not),
68 T![-] => Some(PrefixOp::Neg),
69 _ => None,
70 }
71 }
72
73 pub fn op_token(&self) -> Option<SyntaxToken> {
74 self.syntax().first_child_or_token()?.into_token()
75 }
76}
77
78#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
79pub enum BinOp {
80 /// The `||` operator for boolean OR
81 BooleanOr,
82 /// The `&&` operator for boolean AND
83 BooleanAnd,
84 /// The `==` operator for equality testing
85 EqualityTest,
86 /// The `!=` operator for equality testing
87 NegatedEqualityTest,
88 /// The `<=` operator for lesser-equal testing
89 LesserEqualTest,
90 /// The `>=` operator for greater-equal testing
91 GreaterEqualTest,
92 /// The `<` operator for comparison
93 LesserTest,
94 /// The `>` operator for comparison
95 GreaterTest,
96 /// The `+` operator for addition
97 Addition,
98 /// The `*` operator for multiplication
99 Multiplication,
100 /// The `-` operator for subtraction
101 Subtraction,
102 /// The `/` operator for division
103 Division,
104 /// The `%` operator for remainder after division
105 Remainder,
106 /// The `<<` operator for left shift
107 LeftShift,
108 /// The `>>` operator for right shift
109 RightShift,
110 /// The `^` operator for bitwise XOR
111 BitwiseXor,
112 /// The `|` operator for bitwise OR
113 BitwiseOr,
114 /// The `&` operator for bitwise AND
115 BitwiseAnd,
116 /// The `=` operator for assignment
117 Assignment,
118 /// The `+=` operator for assignment after addition
119 AddAssign,
120 /// The `/=` operator for assignment after division
121 DivAssign,
122 /// The `*=` operator for assignment after multiplication
123 MulAssign,
124 /// The `%=` operator for assignment after remainders
125 RemAssign,
126 /// The `>>=` operator for assignment after shifting right
127 ShrAssign,
128 /// The `<<=` operator for assignment after shifting left
129 ShlAssign,
130 /// The `-=` operator for assignment after subtraction
131 SubAssign,
132 /// The `|=` operator for assignment after bitwise OR
133 BitOrAssign,
134 /// The `&=` operator for assignment after bitwise AND
135 BitAndAssign,
136 /// The `^=` operator for assignment after bitwise XOR
137 BitXorAssign,
138}
139
140impl BinOp {
141 pub fn is_assignment(self) -> bool {
142 match self {
143 BinOp::Assignment
144 | BinOp::AddAssign
145 | BinOp::DivAssign
146 | BinOp::MulAssign
147 | BinOp::RemAssign
148 | BinOp::ShrAssign
149 | BinOp::ShlAssign
150 | BinOp::SubAssign
151 | BinOp::BitOrAssign
152 | BinOp::BitAndAssign
153 | BinOp::BitXorAssign => true,
154 _ => false,
155 }
156 }
157}
158
159impl ast::BinExpr {
160 pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
161 self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| {
162 let bin_op = match c.kind() {
163 T![||] => BinOp::BooleanOr,
164 T![&&] => BinOp::BooleanAnd,
165 T![==] => BinOp::EqualityTest,
166 T![!=] => BinOp::NegatedEqualityTest,
167 T![<=] => BinOp::LesserEqualTest,
168 T![>=] => BinOp::GreaterEqualTest,
169 T![<] => BinOp::LesserTest,
170 T![>] => BinOp::GreaterTest,
171 T![+] => BinOp::Addition,
172 T![*] => BinOp::Multiplication,
173 T![-] => BinOp::Subtraction,
174 T![/] => BinOp::Division,
175 T![%] => BinOp::Remainder,
176 T![<<] => BinOp::LeftShift,
177 T![>>] => BinOp::RightShift,
178 T![^] => BinOp::BitwiseXor,
179 T![|] => BinOp::BitwiseOr,
180 T![&] => BinOp::BitwiseAnd,
181 T![=] => BinOp::Assignment,
182 T![+=] => BinOp::AddAssign,
183 T![/=] => BinOp::DivAssign,
184 T![*=] => BinOp::MulAssign,
185 T![%=] => BinOp::RemAssign,
186 T![>>=] => BinOp::ShrAssign,
187 T![<<=] => BinOp::ShlAssign,
188 T![-=] => BinOp::SubAssign,
189 T![|=] => BinOp::BitOrAssign,
190 T![&=] => BinOp::BitAndAssign,
191 T![^=] => BinOp::BitXorAssign,
192 _ => return None,
193 };
194 Some((c, bin_op))
195 })
196 }
197
198 pub fn op_kind(&self) -> Option<BinOp> {
199 self.op_details().map(|t| t.1)
200 }
201
202 pub fn op_token(&self) -> Option<SyntaxToken> {
203 self.op_details().map(|t| t.0)
204 }
205
206 pub fn lhs(&self) -> Option<ast::Expr> {
207 support::children(self.syntax()).next()
208 }
209
210 pub fn rhs(&self) -> Option<ast::Expr> {
211 support::children(self.syntax()).nth(1)
212 }
213
214 pub fn sub_exprs(&self) -> (Option<ast::Expr>, Option<ast::Expr>) {
215 let mut children = support::children(self.syntax());
216 let first = children.next();
217 let second = children.next();
218 (first, second)
219 }
220}
221
222#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
223pub enum RangeOp {
224 /// `..`
225 Exclusive,
226 /// `..=`
227 Inclusive,
228}
229
230impl ast::RangeExpr {
231 fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> {
232 self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| {
233 let token = child.into_token()?;
234 let bin_op = match token.kind() {
235 T![..] => RangeOp::Exclusive,
236 T![..=] => RangeOp::Inclusive,
237 _ => return None,
238 };
239 Some((ix, token, bin_op))
240 })
241 }
242
243 pub fn op_kind(&self) -> Option<RangeOp> {
244 self.op_details().map(|t| t.2)
245 }
246
247 pub fn op_token(&self) -> Option<SyntaxToken> {
248 self.op_details().map(|t| t.1)
249 }
250
251 pub fn start(&self) -> Option<ast::Expr> {
252 let op_ix = self.op_details()?.0;
253 self.syntax()
254 .children_with_tokens()
255 .take(op_ix)
256 .find_map(|it| ast::Expr::cast(it.into_node()?))
257 }
258
259 pub fn end(&self) -> Option<ast::Expr> {
260 let op_ix = self.op_details()?.0;
261 self.syntax()
262 .children_with_tokens()
263 .skip(op_ix + 1)
264 .find_map(|it| ast::Expr::cast(it.into_node()?))
265 }
266}
267
268impl ast::IndexExpr {
269 pub fn base(&self) -> Option<ast::Expr> {
270 support::children(self.syntax()).next()
271 }
272 pub fn index(&self) -> Option<ast::Expr> {
273 support::children(self.syntax()).nth(1)
274 }
275}
276
277pub enum ArrayExprKind {
278 Repeat { initializer: Option<ast::Expr>, repeat: Option<ast::Expr> },
279 ElementList(AstChildren<ast::Expr>),
280}
281
282impl ast::ArrayExpr {
283 pub fn kind(&self) -> ArrayExprKind {
284 if self.is_repeat() {
285 ArrayExprKind::Repeat {
286 initializer: support::children(self.syntax()).next(),
287 repeat: support::children(self.syntax()).nth(1),
288 }
289 } else {
290 ArrayExprKind::ElementList(support::children(self.syntax()))
291 }
292 }
293
294 fn is_repeat(&self) -> bool {
295 self.syntax().children_with_tokens().any(|it| it.kind() == T![;])
296 }
297}
298
299#[derive(Clone, Debug, PartialEq, Eq, Hash)]
300pub enum LiteralKind {
301 String,
302 ByteString,
303 Char,
304 Byte,
305 IntNumber { suffix: Option<SmolStr> },
306 FloatNumber { suffix: Option<SmolStr> },
307 Bool(bool),
308}
309
310impl ast::Literal {
311 pub fn token(&self) -> SyntaxToken {
312 self.syntax()
313 .children_with_tokens()
314 .find(|e| e.kind() != ATTR && !e.kind().is_trivia())
315 .and_then(|e| e.into_token())
316 .unwrap()
317 }
318
319 fn find_suffix(text: &str, possible_suffixes: &[&str]) -> Option<SmolStr> {
320 possible_suffixes
321 .iter()
322 .find(|&suffix| text.ends_with(suffix))
323 .map(|&suffix| SmolStr::new(suffix))
324 }
325
326 pub fn kind(&self) -> LiteralKind {
327 const INT_SUFFIXES: [&str; 12] = [
328 "u64", "u32", "u16", "u8", "usize", "isize", "i64", "i32", "i16", "i8", "u128", "i128",
329 ];
330 const FLOAT_SUFFIXES: [&str; 2] = ["f32", "f64"];
331
332 let token = self.token();
333
334 match token.kind() {
335 INT_NUMBER => {
336 // FYI: there was a bug here previously, thus the if statement below is necessary.
337 // The lexer treats e.g. `1f64` as an integer literal. See
338 // https://github.com/rust-analyzer/rust-analyzer/issues/1592
339 // and the comments on the linked PR.
340
341 let text = token.text();
342 if let suffix @ Some(_) = Self::find_suffix(&text, &FLOAT_SUFFIXES) {
343 LiteralKind::FloatNumber { suffix }
344 } else {
345 LiteralKind::IntNumber { suffix: Self::find_suffix(&text, &INT_SUFFIXES) }
346 }
347 }
348 FLOAT_NUMBER => {
349 let text = token.text();
350 LiteralKind::FloatNumber { suffix: Self::find_suffix(&text, &FLOAT_SUFFIXES) }
351 }
352 STRING | RAW_STRING => LiteralKind::String,
353 T![true] => LiteralKind::Bool(true),
354 T![false] => LiteralKind::Bool(false),
355 BYTE_STRING | RAW_BYTE_STRING => LiteralKind::ByteString,
356 CHAR => LiteralKind::Char,
357 BYTE => LiteralKind::Byte,
358 _ => unreachable!(),
359 }
360 }
361}
362
363#[derive(Debug, Clone, PartialEq, Eq)]
364pub enum Effect {
365 Async(SyntaxToken),
366 Unsafe(SyntaxToken),
367 Try(SyntaxToken),
368 // Very much not an effect, but we stuff it into this node anyway
369 Label(ast::Label),
370}
371
372impl ast::EffectExpr {
373 pub fn effect(&self) -> Effect {
374 if let Some(token) = self.async_token() {
375 return Effect::Async(token);
376 }
377 if let Some(token) = self.unsafe_token() {
378 return Effect::Unsafe(token);
379 }
380 if let Some(token) = self.try_token() {
381 return Effect::Try(token);
382 }
383 if let Some(label) = self.label() {
384 return Effect::Label(label);
385 }
386 unreachable!("ast::EffectExpr without Effect")
387 }
388}
389
390impl ast::BlockExpr {
391 /// false if the block is an intrinsic part of the syntax and can't be
392 /// replaced with arbitrary expression.
393 ///
394 /// ```not_rust
395 /// fn foo() { not_stand_alone }
396 /// const FOO: () = { stand_alone };
397 /// ```
398 pub fn is_standalone(&self) -> bool {
399 let parent = match self.syntax().parent() {
400 Some(it) => it,
401 None => return true,
402 };
403 !matches!(parent.kind(), FN | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR)
404 }
405}
406
407#[test]
408fn test_literal_with_attr() {
409 let parse = ast::SourceFile::parse(r#"const _: &str = { #[attr] "Hello" };"#);
410 let lit = parse.tree().syntax().descendants().find_map(ast::Literal::cast).unwrap();
411 assert_eq!(lit.token().text(), r#""Hello""#);
412}
413
414impl ast::RecordExprField {
415 pub fn parent_record_lit(&self) -> ast::RecordExpr {
416 self.syntax().ancestors().find_map(ast::RecordExpr::cast).unwrap()
417 }
418}
diff --git a/crates/syntax/src/ast/generated.rs b/crates/syntax/src/ast/generated.rs
new file mode 100644
index 000000000..4a6f41ee7
--- /dev/null
+++ b/crates/syntax/src/ast/generated.rs
@@ -0,0 +1,41 @@
1//! This file is actually hand-written, but the submodules are indeed generated.
2#[rustfmt::skip]
3mod nodes;
4#[rustfmt::skip]
5mod tokens;
6
7use crate::{
8 AstNode,
9 SyntaxKind::{self, *},
10 SyntaxNode,
11};
12
13pub use {nodes::*, tokens::*};
14
15// Stmt is the only nested enum, so it's easier to just hand-write it
16impl AstNode for Stmt {
17 fn can_cast(kind: SyntaxKind) -> bool {
18 match kind {
19 LET_STMT | EXPR_STMT => true,
20 _ => Item::can_cast(kind),
21 }
22 }
23 fn cast(syntax: SyntaxNode) -> Option<Self> {
24 let res = match syntax.kind() {
25 LET_STMT => Stmt::LetStmt(LetStmt { syntax }),
26 EXPR_STMT => Stmt::ExprStmt(ExprStmt { syntax }),
27 _ => {
28 let item = Item::cast(syntax)?;
29 Stmt::Item(item)
30 }
31 };
32 Some(res)
33 }
34 fn syntax(&self) -> &SyntaxNode {
35 match self {
36 Stmt::LetStmt(it) => &it.syntax,
37 Stmt::ExprStmt(it) => &it.syntax,
38 Stmt::Item(it) => it.syntax(),
39 }
40 }
41}
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
new file mode 100644
index 000000000..6317407c6
--- /dev/null
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -0,0 +1,4068 @@
1//! Generated file, do not edit by hand, see `xtask/src/codegen`
2
3use crate::{
4 ast::{self, support, AstChildren, AstNode},
5 SyntaxKind::{self, *},
6 SyntaxNode, SyntaxToken, T,
7};
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct Name {
10 pub(crate) syntax: SyntaxNode,
11}
12impl Name {
13 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
14}
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct NameRef {
17 pub(crate) syntax: SyntaxNode,
18}
19impl NameRef {
20 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
21}
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct Path {
24 pub(crate) syntax: SyntaxNode,
25}
26impl Path {
27 pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
28 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
29 pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
30}
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
32pub struct PathSegment {
33 pub(crate) syntax: SyntaxNode,
34}
35impl PathSegment {
36 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
37 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
38 pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
39 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
40 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
41 pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
42 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
43 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
44 pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
45 pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
46 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
47 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
48}
49#[derive(Debug, Clone, PartialEq, Eq, Hash)]
50pub struct GenericArgList {
51 pub(crate) syntax: SyntaxNode,
52}
53impl GenericArgList {
54 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
55 pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
56 pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
57 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
58}
59#[derive(Debug, Clone, PartialEq, Eq, Hash)]
60pub struct ParamList {
61 pub(crate) syntax: SyntaxNode,
62}
63impl ParamList {
64 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
65 pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
66 pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
67 pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
68 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
69 pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
70}
71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub struct RetType {
73 pub(crate) syntax: SyntaxNode,
74}
75impl RetType {
76 pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
77 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
78}
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80pub struct PathType {
81 pub(crate) syntax: SyntaxNode,
82}
83impl PathType {
84 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
85}
86#[derive(Debug, Clone, PartialEq, Eq, Hash)]
87pub struct TypeArg {
88 pub(crate) syntax: SyntaxNode,
89}
90impl TypeArg {
91 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
92}
93#[derive(Debug, Clone, PartialEq, Eq, Hash)]
94pub struct AssocTypeArg {
95 pub(crate) syntax: SyntaxNode,
96}
97impl ast::TypeBoundsOwner for AssocTypeArg {}
98impl AssocTypeArg {
99 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
100 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
101 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
102}
103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
104pub struct LifetimeArg {
105 pub(crate) syntax: SyntaxNode,
106}
107impl LifetimeArg {
108 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
109 support::token(&self.syntax, T![lifetime])
110 }
111}
112#[derive(Debug, Clone, PartialEq, Eq, Hash)]
113pub struct ConstArg {
114 pub(crate) syntax: SyntaxNode,
115}
116impl ConstArg {
117 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
118}
119#[derive(Debug, Clone, PartialEq, Eq, Hash)]
120pub struct TypeBoundList {
121 pub(crate) syntax: SyntaxNode,
122}
123impl TypeBoundList {
124 pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
125}
126#[derive(Debug, Clone, PartialEq, Eq, Hash)]
127pub struct MacroCall {
128 pub(crate) syntax: SyntaxNode,
129}
130impl ast::AttrsOwner for MacroCall {}
131impl ast::NameOwner for MacroCall {}
132impl MacroCall {
133 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
134 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
135 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
136 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
137}
138#[derive(Debug, Clone, PartialEq, Eq, Hash)]
139pub struct Attr {
140 pub(crate) syntax: SyntaxNode,
141}
142impl Attr {
143 pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
144 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
145 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
146 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
147 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
148 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
149 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
150 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
151}
152#[derive(Debug, Clone, PartialEq, Eq, Hash)]
153pub struct TokenTree {
154 pub(crate) syntax: SyntaxNode,
155}
156impl TokenTree {
157 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
158 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
159 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
160 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
161 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
162 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
163}
164#[derive(Debug, Clone, PartialEq, Eq, Hash)]
165pub struct MacroItems {
166 pub(crate) syntax: SyntaxNode,
167}
168impl ast::ModuleItemOwner for MacroItems {}
169impl MacroItems {}
170#[derive(Debug, Clone, PartialEq, Eq, Hash)]
171pub struct MacroStmts {
172 pub(crate) syntax: SyntaxNode,
173}
174impl MacroStmts {
175 pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
176 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
177}
178#[derive(Debug, Clone, PartialEq, Eq, Hash)]
179pub struct SourceFile {
180 pub(crate) syntax: SyntaxNode,
181}
182impl ast::AttrsOwner for SourceFile {}
183impl ast::ModuleItemOwner for SourceFile {}
184impl SourceFile {
185 pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
186}
187#[derive(Debug, Clone, PartialEq, Eq, Hash)]
188pub struct Const {
189 pub(crate) syntax: SyntaxNode,
190}
191impl ast::AttrsOwner for Const {}
192impl ast::NameOwner for Const {}
193impl ast::VisibilityOwner for Const {}
194impl Const {
195 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
196 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
197 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
198 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
199 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
200 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
201 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
202 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
203}
204#[derive(Debug, Clone, PartialEq, Eq, Hash)]
205pub struct Enum {
206 pub(crate) syntax: SyntaxNode,
207}
208impl ast::AttrsOwner for Enum {}
209impl ast::NameOwner for Enum {}
210impl ast::VisibilityOwner for Enum {}
211impl ast::GenericParamsOwner for Enum {}
212impl Enum {
213 pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
214 pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
215}
216#[derive(Debug, Clone, PartialEq, Eq, Hash)]
217pub struct ExternBlock {
218 pub(crate) syntax: SyntaxNode,
219}
220impl ast::AttrsOwner for ExternBlock {}
221impl ExternBlock {
222 pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
223 pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
224}
225#[derive(Debug, Clone, PartialEq, Eq, Hash)]
226pub struct ExternCrate {
227 pub(crate) syntax: SyntaxNode,
228}
229impl ast::AttrsOwner for ExternCrate {}
230impl ast::VisibilityOwner for ExternCrate {}
231impl ExternCrate {
232 pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
233 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
234 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
235 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
236 pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
237 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
238}
239#[derive(Debug, Clone, PartialEq, Eq, Hash)]
240pub struct Fn {
241 pub(crate) syntax: SyntaxNode,
242}
243impl ast::AttrsOwner for Fn {}
244impl ast::NameOwner for Fn {}
245impl ast::VisibilityOwner for Fn {}
246impl ast::GenericParamsOwner for Fn {}
247impl Fn {
248 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
249 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
250 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
251 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
252 pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
253 pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
254 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
255 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
256 pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
257 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
258}
259#[derive(Debug, Clone, PartialEq, Eq, Hash)]
260pub struct Impl {
261 pub(crate) syntax: SyntaxNode,
262}
263impl ast::AttrsOwner for Impl {}
264impl ast::VisibilityOwner for Impl {}
265impl ast::GenericParamsOwner for Impl {}
266impl Impl {
267 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
268 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
269 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
270 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
271 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
272 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
273 pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
274}
275#[derive(Debug, Clone, PartialEq, Eq, Hash)]
276pub struct Module {
277 pub(crate) syntax: SyntaxNode,
278}
279impl ast::AttrsOwner for Module {}
280impl ast::NameOwner for Module {}
281impl ast::VisibilityOwner for Module {}
282impl Module {
283 pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
284 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
285 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
286}
287#[derive(Debug, Clone, PartialEq, Eq, Hash)]
288pub struct Static {
289 pub(crate) syntax: SyntaxNode,
290}
291impl ast::AttrsOwner for Static {}
292impl ast::NameOwner for Static {}
293impl ast::VisibilityOwner for Static {}
294impl Static {
295 pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
296 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
297 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
298 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
299 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
300 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
301 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
302}
303#[derive(Debug, Clone, PartialEq, Eq, Hash)]
304pub struct Struct {
305 pub(crate) syntax: SyntaxNode,
306}
307impl ast::AttrsOwner for Struct {}
308impl ast::NameOwner for Struct {}
309impl ast::VisibilityOwner for Struct {}
310impl ast::GenericParamsOwner for Struct {}
311impl Struct {
312 pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) }
313 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
314 pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
315}
316#[derive(Debug, Clone, PartialEq, Eq, Hash)]
317pub struct Trait {
318 pub(crate) syntax: SyntaxNode,
319}
320impl ast::AttrsOwner for Trait {}
321impl ast::NameOwner for Trait {}
322impl ast::VisibilityOwner for Trait {}
323impl ast::GenericParamsOwner for Trait {}
324impl ast::TypeBoundsOwner for Trait {}
325impl Trait {
326 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
327 pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
328 pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
329 pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
330}
331#[derive(Debug, Clone, PartialEq, Eq, Hash)]
332pub struct TypeAlias {
333 pub(crate) syntax: SyntaxNode,
334}
335impl ast::AttrsOwner for TypeAlias {}
336impl ast::NameOwner for TypeAlias {}
337impl ast::VisibilityOwner for TypeAlias {}
338impl ast::GenericParamsOwner for TypeAlias {}
339impl ast::TypeBoundsOwner for TypeAlias {}
340impl TypeAlias {
341 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
342 pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
343 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
344 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
345 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
346}
347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
348pub struct Union {
349 pub(crate) syntax: SyntaxNode,
350}
351impl ast::AttrsOwner for Union {}
352impl ast::NameOwner for Union {}
353impl ast::VisibilityOwner for Union {}
354impl ast::GenericParamsOwner for Union {}
355impl Union {
356 pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) }
357 pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
358}
359#[derive(Debug, Clone, PartialEq, Eq, Hash)]
360pub struct Use {
361 pub(crate) syntax: SyntaxNode,
362}
363impl ast::AttrsOwner for Use {}
364impl ast::VisibilityOwner for Use {}
365impl Use {
366 pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
367 pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
368 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
369}
370#[derive(Debug, Clone, PartialEq, Eq, Hash)]
371pub struct Visibility {
372 pub(crate) syntax: SyntaxNode,
373}
374impl Visibility {
375 pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
376 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
377 pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
378 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
379 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
380 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
381 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
382 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
383}
384#[derive(Debug, Clone, PartialEq, Eq, Hash)]
385pub struct ItemList {
386 pub(crate) syntax: SyntaxNode,
387}
388impl ast::AttrsOwner for ItemList {}
389impl ast::ModuleItemOwner for ItemList {}
390impl ItemList {
391 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
392 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
393}
394#[derive(Debug, Clone, PartialEq, Eq, Hash)]
395pub struct Rename {
396 pub(crate) syntax: SyntaxNode,
397}
398impl ast::NameOwner for Rename {}
399impl Rename {
400 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
401 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
402}
403#[derive(Debug, Clone, PartialEq, Eq, Hash)]
404pub struct UseTree {
405 pub(crate) syntax: SyntaxNode,
406}
407impl UseTree {
408 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
409 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
410 pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
411 pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
412 pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
413}
414#[derive(Debug, Clone, PartialEq, Eq, Hash)]
415pub struct UseTreeList {
416 pub(crate) syntax: SyntaxNode,
417}
418impl UseTreeList {
419 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
420 pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
421 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
422}
423#[derive(Debug, Clone, PartialEq, Eq, Hash)]
424pub struct Abi {
425 pub(crate) syntax: SyntaxNode,
426}
427impl Abi {
428 pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
429}
430#[derive(Debug, Clone, PartialEq, Eq, Hash)]
431pub struct GenericParamList {
432 pub(crate) syntax: SyntaxNode,
433}
434impl GenericParamList {
435 pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
436 pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
437 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
438}
439#[derive(Debug, Clone, PartialEq, Eq, Hash)]
440pub struct WhereClause {
441 pub(crate) syntax: SyntaxNode,
442}
443impl WhereClause {
444 pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) }
445 pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) }
446}
447#[derive(Debug, Clone, PartialEq, Eq, Hash)]
448pub struct BlockExpr {
449 pub(crate) syntax: SyntaxNode,
450}
451impl ast::AttrsOwner for BlockExpr {}
452impl BlockExpr {
453 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
454 pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
455 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
456 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
457}
458#[derive(Debug, Clone, PartialEq, Eq, Hash)]
459pub struct SelfParam {
460 pub(crate) syntax: SyntaxNode,
461}
462impl ast::AttrsOwner for SelfParam {}
463impl SelfParam {
464 pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
465 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
466 support::token(&self.syntax, T![lifetime])
467 }
468 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
469 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
470 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
471 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
472}
473#[derive(Debug, Clone, PartialEq, Eq, Hash)]
474pub struct Param {
475 pub(crate) syntax: SyntaxNode,
476}
477impl ast::AttrsOwner for Param {}
478impl Param {
479 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
480 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
481 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
482 pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
483}
484#[derive(Debug, Clone, PartialEq, Eq, Hash)]
485pub struct RecordFieldList {
486 pub(crate) syntax: SyntaxNode,
487}
488impl RecordFieldList {
489 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
490 pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) }
491 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
492}
493#[derive(Debug, Clone, PartialEq, Eq, Hash)]
494pub struct TupleFieldList {
495 pub(crate) syntax: SyntaxNode,
496}
497impl TupleFieldList {
498 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
499 pub fn fields(&self) -> AstChildren<TupleField> { support::children(&self.syntax) }
500 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
501}
502#[derive(Debug, Clone, PartialEq, Eq, Hash)]
503pub struct RecordField {
504 pub(crate) syntax: SyntaxNode,
505}
506impl ast::AttrsOwner for RecordField {}
507impl ast::NameOwner for RecordField {}
508impl ast::VisibilityOwner for RecordField {}
509impl RecordField {
510 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
511 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
512}
513#[derive(Debug, Clone, PartialEq, Eq, Hash)]
514pub struct TupleField {
515 pub(crate) syntax: SyntaxNode,
516}
517impl ast::AttrsOwner for TupleField {}
518impl ast::VisibilityOwner for TupleField {}
519impl TupleField {
520 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
521}
522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
523pub struct VariantList {
524 pub(crate) syntax: SyntaxNode,
525}
526impl VariantList {
527 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
528 pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
529 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
530}
531#[derive(Debug, Clone, PartialEq, Eq, Hash)]
532pub struct Variant {
533 pub(crate) syntax: SyntaxNode,
534}
535impl ast::AttrsOwner for Variant {}
536impl ast::NameOwner for Variant {}
537impl ast::VisibilityOwner for Variant {}
538impl Variant {
539 pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
540 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
541 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
542}
543#[derive(Debug, Clone, PartialEq, Eq, Hash)]
544pub struct AssocItemList {
545 pub(crate) syntax: SyntaxNode,
546}
547impl ast::AttrsOwner for AssocItemList {}
548impl AssocItemList {
549 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
550 pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
551 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
552}
553#[derive(Debug, Clone, PartialEq, Eq, Hash)]
554pub struct ExternItemList {
555 pub(crate) syntax: SyntaxNode,
556}
557impl ast::AttrsOwner for ExternItemList {}
558impl ExternItemList {
559 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
560 pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) }
561 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
562}
563#[derive(Debug, Clone, PartialEq, Eq, Hash)]
564pub struct ConstParam {
565 pub(crate) syntax: SyntaxNode,
566}
567impl ast::AttrsOwner for ConstParam {}
568impl ast::NameOwner for ConstParam {}
569impl ConstParam {
570 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
571 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
572 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
573 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
574 pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) }
575}
576#[derive(Debug, Clone, PartialEq, Eq, Hash)]
577pub struct LifetimeParam {
578 pub(crate) syntax: SyntaxNode,
579}
580impl ast::AttrsOwner for LifetimeParam {}
581impl ast::TypeBoundsOwner for LifetimeParam {}
582impl LifetimeParam {
583 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
584 support::token(&self.syntax, T![lifetime])
585 }
586}
587#[derive(Debug, Clone, PartialEq, Eq, Hash)]
588pub struct TypeParam {
589 pub(crate) syntax: SyntaxNode,
590}
591impl ast::AttrsOwner for TypeParam {}
592impl ast::NameOwner for TypeParam {}
593impl ast::TypeBoundsOwner for TypeParam {}
594impl TypeParam {
595 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
596 pub fn default_type(&self) -> Option<Type> { support::child(&self.syntax) }
597}
598#[derive(Debug, Clone, PartialEq, Eq, Hash)]
599pub struct WherePred {
600 pub(crate) syntax: SyntaxNode,
601}
602impl ast::TypeBoundsOwner for WherePred {}
603impl WherePred {
604 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
605 pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
606 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
607 support::token(&self.syntax, T![lifetime])
608 }
609 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
610}
611#[derive(Debug, Clone, PartialEq, Eq, Hash)]
612pub struct Literal {
613 pub(crate) syntax: SyntaxNode,
614}
615impl ast::AttrsOwner for Literal {}
616impl Literal {}
617#[derive(Debug, Clone, PartialEq, Eq, Hash)]
618pub struct ExprStmt {
619 pub(crate) syntax: SyntaxNode,
620}
621impl ast::AttrsOwner for ExprStmt {}
622impl ExprStmt {
623 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
624 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
625}
626#[derive(Debug, Clone, PartialEq, Eq, Hash)]
627pub struct LetStmt {
628 pub(crate) syntax: SyntaxNode,
629}
630impl ast::AttrsOwner for LetStmt {}
631impl LetStmt {
632 pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
633 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
634 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
635 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
636 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
637 pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
638 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
639}
640#[derive(Debug, Clone, PartialEq, Eq, Hash)]
641pub struct ArrayExpr {
642 pub(crate) syntax: SyntaxNode,
643}
644impl ast::AttrsOwner for ArrayExpr {}
645impl ArrayExpr {
646 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
647 pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
648 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
649 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
650 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
651}
652#[derive(Debug, Clone, PartialEq, Eq, Hash)]
653pub struct AwaitExpr {
654 pub(crate) syntax: SyntaxNode,
655}
656impl ast::AttrsOwner for AwaitExpr {}
657impl AwaitExpr {
658 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
659 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
660 pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
661}
662#[derive(Debug, Clone, PartialEq, Eq, Hash)]
663pub struct BinExpr {
664 pub(crate) syntax: SyntaxNode,
665}
666impl ast::AttrsOwner for BinExpr {}
667impl BinExpr {}
668#[derive(Debug, Clone, PartialEq, Eq, Hash)]
669pub struct BoxExpr {
670 pub(crate) syntax: SyntaxNode,
671}
672impl ast::AttrsOwner for BoxExpr {}
673impl BoxExpr {
674 pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
675 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
676}
677#[derive(Debug, Clone, PartialEq, Eq, Hash)]
678pub struct BreakExpr {
679 pub(crate) syntax: SyntaxNode,
680}
681impl ast::AttrsOwner for BreakExpr {}
682impl BreakExpr {
683 pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
684 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
685 support::token(&self.syntax, T![lifetime])
686 }
687 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
688}
689#[derive(Debug, Clone, PartialEq, Eq, Hash)]
690pub struct CallExpr {
691 pub(crate) syntax: SyntaxNode,
692}
693impl ast::AttrsOwner for CallExpr {}
694impl ast::ArgListOwner for CallExpr {}
695impl CallExpr {
696 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
697}
698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
699pub struct CastExpr {
700 pub(crate) syntax: SyntaxNode,
701}
702impl ast::AttrsOwner for CastExpr {}
703impl CastExpr {
704 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
705 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
706 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
707}
708#[derive(Debug, Clone, PartialEq, Eq, Hash)]
709pub struct ClosureExpr {
710 pub(crate) syntax: SyntaxNode,
711}
712impl ast::AttrsOwner for ClosureExpr {}
713impl ClosureExpr {
714 pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
715 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
716 pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
717 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
718 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
719 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
720}
721#[derive(Debug, Clone, PartialEq, Eq, Hash)]
722pub struct ContinueExpr {
723 pub(crate) syntax: SyntaxNode,
724}
725impl ast::AttrsOwner for ContinueExpr {}
726impl ContinueExpr {
727 pub fn continue_token(&self) -> Option<SyntaxToken> {
728 support::token(&self.syntax, T![continue])
729 }
730 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
731 support::token(&self.syntax, T![lifetime])
732 }
733}
734#[derive(Debug, Clone, PartialEq, Eq, Hash)]
735pub struct EffectExpr {
736 pub(crate) syntax: SyntaxNode,
737}
738impl ast::AttrsOwner for EffectExpr {}
739impl EffectExpr {
740 pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
741 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
742 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
743 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
744 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
745}
746#[derive(Debug, Clone, PartialEq, Eq, Hash)]
747pub struct FieldExpr {
748 pub(crate) syntax: SyntaxNode,
749}
750impl ast::AttrsOwner for FieldExpr {}
751impl FieldExpr {
752 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
753 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
754 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
755}
756#[derive(Debug, Clone, PartialEq, Eq, Hash)]
757pub struct ForExpr {
758 pub(crate) syntax: SyntaxNode,
759}
760impl ast::AttrsOwner for ForExpr {}
761impl ast::LoopBodyOwner for ForExpr {}
762impl ForExpr {
763 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
764 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
765 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
766 pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) }
767}
768#[derive(Debug, Clone, PartialEq, Eq, Hash)]
769pub struct IfExpr {
770 pub(crate) syntax: SyntaxNode,
771}
772impl ast::AttrsOwner for IfExpr {}
773impl IfExpr {
774 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
775 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
776 pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
777}
778#[derive(Debug, Clone, PartialEq, Eq, Hash)]
779pub struct IndexExpr {
780 pub(crate) syntax: SyntaxNode,
781}
782impl ast::AttrsOwner for IndexExpr {}
783impl IndexExpr {
784 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
785 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
786}
787#[derive(Debug, Clone, PartialEq, Eq, Hash)]
788pub struct LoopExpr {
789 pub(crate) syntax: SyntaxNode,
790}
791impl ast::AttrsOwner for LoopExpr {}
792impl ast::LoopBodyOwner for LoopExpr {}
793impl LoopExpr {
794 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
795}
796#[derive(Debug, Clone, PartialEq, Eq, Hash)]
797pub struct MatchExpr {
798 pub(crate) syntax: SyntaxNode,
799}
800impl ast::AttrsOwner for MatchExpr {}
801impl MatchExpr {
802 pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) }
803 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
804 pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) }
805}
806#[derive(Debug, Clone, PartialEq, Eq, Hash)]
807pub struct MethodCallExpr {
808 pub(crate) syntax: SyntaxNode,
809}
810impl ast::AttrsOwner for MethodCallExpr {}
811impl ast::ArgListOwner for MethodCallExpr {}
812impl MethodCallExpr {
813 pub fn receiver(&self) -> Option<Expr> { support::child(&self.syntax) }
814 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
815 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
816 pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
817}
818#[derive(Debug, Clone, PartialEq, Eq, Hash)]
819pub struct ParenExpr {
820 pub(crate) syntax: SyntaxNode,
821}
822impl ast::AttrsOwner for ParenExpr {}
823impl ParenExpr {
824 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
825 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
826 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
827}
828#[derive(Debug, Clone, PartialEq, Eq, Hash)]
829pub struct PathExpr {
830 pub(crate) syntax: SyntaxNode,
831}
832impl ast::AttrsOwner for PathExpr {}
833impl PathExpr {
834 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
835}
836#[derive(Debug, Clone, PartialEq, Eq, Hash)]
837pub struct PrefixExpr {
838 pub(crate) syntax: SyntaxNode,
839}
840impl ast::AttrsOwner for PrefixExpr {}
841impl PrefixExpr {
842 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
843}
844#[derive(Debug, Clone, PartialEq, Eq, Hash)]
845pub struct RangeExpr {
846 pub(crate) syntax: SyntaxNode,
847}
848impl ast::AttrsOwner for RangeExpr {}
849impl RangeExpr {}
850#[derive(Debug, Clone, PartialEq, Eq, Hash)]
851pub struct RecordExpr {
852 pub(crate) syntax: SyntaxNode,
853}
854impl RecordExpr {
855 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
856 pub fn record_expr_field_list(&self) -> Option<RecordExprFieldList> {
857 support::child(&self.syntax)
858 }
859}
860#[derive(Debug, Clone, PartialEq, Eq, Hash)]
861pub struct RefExpr {
862 pub(crate) syntax: SyntaxNode,
863}
864impl ast::AttrsOwner for RefExpr {}
865impl RefExpr {
866 pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
867 pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
868 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
869 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
870 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
871}
872#[derive(Debug, Clone, PartialEq, Eq, Hash)]
873pub struct ReturnExpr {
874 pub(crate) syntax: SyntaxNode,
875}
876impl ast::AttrsOwner for ReturnExpr {}
877impl ReturnExpr {
878 pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) }
879 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
880}
881#[derive(Debug, Clone, PartialEq, Eq, Hash)]
882pub struct TryExpr {
883 pub(crate) syntax: SyntaxNode,
884}
885impl ast::AttrsOwner for TryExpr {}
886impl TryExpr {
887 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
888 pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
889}
890#[derive(Debug, Clone, PartialEq, Eq, Hash)]
891pub struct TupleExpr {
892 pub(crate) syntax: SyntaxNode,
893}
894impl ast::AttrsOwner for TupleExpr {}
895impl TupleExpr {
896 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
897 pub fn fields(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
898 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
899}
900#[derive(Debug, Clone, PartialEq, Eq, Hash)]
901pub struct WhileExpr {
902 pub(crate) syntax: SyntaxNode,
903}
904impl ast::AttrsOwner for WhileExpr {}
905impl ast::LoopBodyOwner for WhileExpr {}
906impl WhileExpr {
907 pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
908 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
909}
910#[derive(Debug, Clone, PartialEq, Eq, Hash)]
911pub struct Label {
912 pub(crate) syntax: SyntaxNode,
913}
914impl Label {
915 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
916 support::token(&self.syntax, T![lifetime])
917 }
918}
919#[derive(Debug, Clone, PartialEq, Eq, Hash)]
920pub struct RecordExprFieldList {
921 pub(crate) syntax: SyntaxNode,
922}
923impl ast::AttrsOwner for RecordExprFieldList {}
924impl RecordExprFieldList {
925 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
926 pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) }
927 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
928 pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
929 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
930}
931#[derive(Debug, Clone, PartialEq, Eq, Hash)]
932pub struct RecordExprField {
933 pub(crate) syntax: SyntaxNode,
934}
935impl ast::AttrsOwner for RecordExprField {}
936impl RecordExprField {
937 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
938 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
939 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
940}
941#[derive(Debug, Clone, PartialEq, Eq, Hash)]
942pub struct ArgList {
943 pub(crate) syntax: SyntaxNode,
944}
945impl ArgList {
946 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
947 pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
948 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
949}
950#[derive(Debug, Clone, PartialEq, Eq, Hash)]
951pub struct Condition {
952 pub(crate) syntax: SyntaxNode,
953}
954impl Condition {
955 pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
956 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
957 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
958 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
959}
960#[derive(Debug, Clone, PartialEq, Eq, Hash)]
961pub struct MatchArmList {
962 pub(crate) syntax: SyntaxNode,
963}
964impl ast::AttrsOwner for MatchArmList {}
965impl MatchArmList {
966 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
967 pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) }
968 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
969}
970#[derive(Debug, Clone, PartialEq, Eq, Hash)]
971pub struct MatchArm {
972 pub(crate) syntax: SyntaxNode,
973}
974impl ast::AttrsOwner for MatchArm {}
975impl MatchArm {
976 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
977 pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) }
978 pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
979 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
980 pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
981}
982#[derive(Debug, Clone, PartialEq, Eq, Hash)]
983pub struct MatchGuard {
984 pub(crate) syntax: SyntaxNode,
985}
986impl MatchGuard {
987 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
988 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
989}
990#[derive(Debug, Clone, PartialEq, Eq, Hash)]
991pub struct ArrayType {
992 pub(crate) syntax: SyntaxNode,
993}
994impl ArrayType {
995 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
996 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
997 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
998 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
999 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
1000}
1001#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1002pub struct DynTraitType {
1003 pub(crate) syntax: SyntaxNode,
1004}
1005impl DynTraitType {
1006 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
1007 pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
1008}
1009#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1010pub struct FnPtrType {
1011 pub(crate) syntax: SyntaxNode,
1012}
1013impl FnPtrType {
1014 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
1015 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
1016 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
1017 pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
1018 pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
1019 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
1020 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
1021}
1022#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1023pub struct ForType {
1024 pub(crate) syntax: SyntaxNode,
1025}
1026impl ForType {
1027 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
1028 pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
1029 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1030}
1031#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1032pub struct ImplTraitType {
1033 pub(crate) syntax: SyntaxNode,
1034}
1035impl ImplTraitType {
1036 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
1037 pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
1038}
1039#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1040pub struct InferType {
1041 pub(crate) syntax: SyntaxNode,
1042}
1043impl InferType {
1044 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
1045}
1046#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1047pub struct NeverType {
1048 pub(crate) syntax: SyntaxNode,
1049}
1050impl NeverType {
1051 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
1052}
1053#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1054pub struct ParenType {
1055 pub(crate) syntax: SyntaxNode,
1056}
1057impl ParenType {
1058 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
1059 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1060 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1061}
1062#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1063pub struct PtrType {
1064 pub(crate) syntax: SyntaxNode,
1065}
1066impl PtrType {
1067 pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
1068 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
1069 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
1070 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1071}
1072#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1073pub struct RefType {
1074 pub(crate) syntax: SyntaxNode,
1075}
1076impl RefType {
1077 pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
1078 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
1079 support::token(&self.syntax, T![lifetime])
1080 }
1081 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
1082 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1083}
1084#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1085pub struct SliceType {
1086 pub(crate) syntax: SyntaxNode,
1087}
1088impl SliceType {
1089 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
1090 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1091 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
1092}
1093#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1094pub struct TupleType {
1095 pub(crate) syntax: SyntaxNode,
1096}
1097impl TupleType {
1098 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
1099 pub fn fields(&self) -> AstChildren<Type> { support::children(&self.syntax) }
1100 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1101}
1102#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1103pub struct TypeBound {
1104 pub(crate) syntax: SyntaxNode,
1105}
1106impl TypeBound {
1107 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
1108 support::token(&self.syntax, T![lifetime])
1109 }
1110 pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
1111 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1112}
1113#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1114pub struct IdentPat {
1115 pub(crate) syntax: SyntaxNode,
1116}
1117impl ast::AttrsOwner for IdentPat {}
1118impl ast::NameOwner for IdentPat {}
1119impl IdentPat {
1120 pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) }
1121 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
1122 pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
1123 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1124}
1125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1126pub struct BoxPat {
1127 pub(crate) syntax: SyntaxNode,
1128}
1129impl BoxPat {
1130 pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
1131 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1132}
1133#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1134pub struct RestPat {
1135 pub(crate) syntax: SyntaxNode,
1136}
1137impl RestPat {
1138 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
1139}
1140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1141pub struct LiteralPat {
1142 pub(crate) syntax: SyntaxNode,
1143}
1144impl LiteralPat {
1145 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
1146}
1147#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1148pub struct MacroPat {
1149 pub(crate) syntax: SyntaxNode,
1150}
1151impl MacroPat {
1152 pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
1153}
1154#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1155pub struct OrPat {
1156 pub(crate) syntax: SyntaxNode,
1157}
1158impl OrPat {
1159 pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
1160}
1161#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1162pub struct ParenPat {
1163 pub(crate) syntax: SyntaxNode,
1164}
1165impl ParenPat {
1166 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
1167 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1168 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1169}
1170#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1171pub struct PathPat {
1172 pub(crate) syntax: SyntaxNode,
1173}
1174impl PathPat {
1175 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
1176}
1177#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1178pub struct WildcardPat {
1179 pub(crate) syntax: SyntaxNode,
1180}
1181impl WildcardPat {
1182 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
1183}
1184#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1185pub struct RangePat {
1186 pub(crate) syntax: SyntaxNode,
1187}
1188impl RangePat {}
1189#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1190pub struct RecordPat {
1191 pub(crate) syntax: SyntaxNode,
1192}
1193impl RecordPat {
1194 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
1195 pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> {
1196 support::child(&self.syntax)
1197 }
1198}
1199#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1200pub struct RefPat {
1201 pub(crate) syntax: SyntaxNode,
1202}
1203impl RefPat {
1204 pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
1205 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
1206 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1207}
1208#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1209pub struct SlicePat {
1210 pub(crate) syntax: SyntaxNode,
1211}
1212impl SlicePat {
1213 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
1214 pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
1215 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
1216}
1217#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1218pub struct TuplePat {
1219 pub(crate) syntax: SyntaxNode,
1220}
1221impl TuplePat {
1222 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
1223 pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
1224 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1225}
1226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1227pub struct TupleStructPat {
1228 pub(crate) syntax: SyntaxNode,
1229}
1230impl TupleStructPat {
1231 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
1232 pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
1233 pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
1234 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1235}
1236#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1237pub struct RecordPatFieldList {
1238 pub(crate) syntax: SyntaxNode,
1239}
1240impl RecordPatFieldList {
1241 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
1242 pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
1243 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
1244 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
1245}
1246#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1247pub struct RecordPatField {
1248 pub(crate) syntax: SyntaxNode,
1249}
1250impl ast::AttrsOwner for RecordPatField {}
1251impl RecordPatField {
1252 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
1253 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
1254 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1255}
1256#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1257pub enum GenericArg {
1258 TypeArg(TypeArg),
1259 AssocTypeArg(AssocTypeArg),
1260 LifetimeArg(LifetimeArg),
1261 ConstArg(ConstArg),
1262}
1263#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1264pub enum Type {
1265 ArrayType(ArrayType),
1266 DynTraitType(DynTraitType),
1267 FnPtrType(FnPtrType),
1268 ForType(ForType),
1269 ImplTraitType(ImplTraitType),
1270 InferType(InferType),
1271 NeverType(NeverType),
1272 ParenType(ParenType),
1273 PathType(PathType),
1274 PtrType(PtrType),
1275 RefType(RefType),
1276 SliceType(SliceType),
1277 TupleType(TupleType),
1278}
1279#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1280pub enum Expr {
1281 ArrayExpr(ArrayExpr),
1282 AwaitExpr(AwaitExpr),
1283 BinExpr(BinExpr),
1284 BlockExpr(BlockExpr),
1285 BoxExpr(BoxExpr),
1286 BreakExpr(BreakExpr),
1287 CallExpr(CallExpr),
1288 CastExpr(CastExpr),
1289 ClosureExpr(ClosureExpr),
1290 ContinueExpr(ContinueExpr),
1291 EffectExpr(EffectExpr),
1292 FieldExpr(FieldExpr),
1293 ForExpr(ForExpr),
1294 IfExpr(IfExpr),
1295 IndexExpr(IndexExpr),
1296 Literal(Literal),
1297 LoopExpr(LoopExpr),
1298 MacroCall(MacroCall),
1299 MatchExpr(MatchExpr),
1300 MethodCallExpr(MethodCallExpr),
1301 ParenExpr(ParenExpr),
1302 PathExpr(PathExpr),
1303 PrefixExpr(PrefixExpr),
1304 RangeExpr(RangeExpr),
1305 RecordExpr(RecordExpr),
1306 RefExpr(RefExpr),
1307 ReturnExpr(ReturnExpr),
1308 TryExpr(TryExpr),
1309 TupleExpr(TupleExpr),
1310 WhileExpr(WhileExpr),
1311}
1312#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1313pub enum Item {
1314 Const(Const),
1315 Enum(Enum),
1316 ExternBlock(ExternBlock),
1317 ExternCrate(ExternCrate),
1318 Fn(Fn),
1319 Impl(Impl),
1320 MacroCall(MacroCall),
1321 Module(Module),
1322 Static(Static),
1323 Struct(Struct),
1324 Trait(Trait),
1325 TypeAlias(TypeAlias),
1326 Union(Union),
1327 Use(Use),
1328}
1329impl ast::AttrsOwner for Item {}
1330#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1331pub enum Stmt {
1332 ExprStmt(ExprStmt),
1333 Item(Item),
1334 LetStmt(LetStmt),
1335}
1336#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1337pub enum Pat {
1338 IdentPat(IdentPat),
1339 BoxPat(BoxPat),
1340 RestPat(RestPat),
1341 LiteralPat(LiteralPat),
1342 MacroPat(MacroPat),
1343 OrPat(OrPat),
1344 ParenPat(ParenPat),
1345 PathPat(PathPat),
1346 WildcardPat(WildcardPat),
1347 RangePat(RangePat),
1348 RecordPat(RecordPat),
1349 RefPat(RefPat),
1350 SlicePat(SlicePat),
1351 TuplePat(TuplePat),
1352 TupleStructPat(TupleStructPat),
1353}
1354#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1355pub enum FieldList {
1356 RecordFieldList(RecordFieldList),
1357 TupleFieldList(TupleFieldList),
1358}
1359#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1360pub enum AdtDef {
1361 Enum(Enum),
1362 Struct(Struct),
1363 Union(Union),
1364}
1365impl ast::AttrsOwner for AdtDef {}
1366impl ast::GenericParamsOwner for AdtDef {}
1367impl ast::NameOwner for AdtDef {}
1368impl ast::VisibilityOwner for AdtDef {}
1369#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1370pub enum AssocItem {
1371 Const(Const),
1372 Fn(Fn),
1373 MacroCall(MacroCall),
1374 TypeAlias(TypeAlias),
1375}
1376impl ast::AttrsOwner for AssocItem {}
1377impl ast::NameOwner for AssocItem {}
1378#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1379pub enum ExternItem {
1380 Fn(Fn),
1381 MacroCall(MacroCall),
1382 Static(Static),
1383}
1384impl ast::AttrsOwner for ExternItem {}
1385impl ast::NameOwner for ExternItem {}
1386#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1387pub enum GenericParam {
1388 ConstParam(ConstParam),
1389 LifetimeParam(LifetimeParam),
1390 TypeParam(TypeParam),
1391}
1392impl ast::AttrsOwner for GenericParam {}
1393impl AstNode for Name {
1394 fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
1395 fn cast(syntax: SyntaxNode) -> Option<Self> {
1396 if Self::can_cast(syntax.kind()) {
1397 Some(Self { syntax })
1398 } else {
1399 None
1400 }
1401 }
1402 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1403}
1404impl AstNode for NameRef {
1405 fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF }
1406 fn cast(syntax: SyntaxNode) -> Option<Self> {
1407 if Self::can_cast(syntax.kind()) {
1408 Some(Self { syntax })
1409 } else {
1410 None
1411 }
1412 }
1413 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1414}
1415impl AstNode for Path {
1416 fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
1417 fn cast(syntax: SyntaxNode) -> Option<Self> {
1418 if Self::can_cast(syntax.kind()) {
1419 Some(Self { syntax })
1420 } else {
1421 None
1422 }
1423 }
1424 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1425}
1426impl AstNode for PathSegment {
1427 fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
1428 fn cast(syntax: SyntaxNode) -> Option<Self> {
1429 if Self::can_cast(syntax.kind()) {
1430 Some(Self { syntax })
1431 } else {
1432 None
1433 }
1434 }
1435 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1436}
1437impl AstNode for GenericArgList {
1438 fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST }
1439 fn cast(syntax: SyntaxNode) -> Option<Self> {
1440 if Self::can_cast(syntax.kind()) {
1441 Some(Self { syntax })
1442 } else {
1443 None
1444 }
1445 }
1446 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1447}
1448impl AstNode for ParamList {
1449 fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
1450 fn cast(syntax: SyntaxNode) -> Option<Self> {
1451 if Self::can_cast(syntax.kind()) {
1452 Some(Self { syntax })
1453 } else {
1454 None
1455 }
1456 }
1457 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1458}
1459impl AstNode for RetType {
1460 fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
1461 fn cast(syntax: SyntaxNode) -> Option<Self> {
1462 if Self::can_cast(syntax.kind()) {
1463 Some(Self { syntax })
1464 } else {
1465 None
1466 }
1467 }
1468 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1469}
1470impl AstNode for PathType {
1471 fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE }
1472 fn cast(syntax: SyntaxNode) -> Option<Self> {
1473 if Self::can_cast(syntax.kind()) {
1474 Some(Self { syntax })
1475 } else {
1476 None
1477 }
1478 }
1479 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1480}
1481impl AstNode for TypeArg {
1482 fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG }
1483 fn cast(syntax: SyntaxNode) -> Option<Self> {
1484 if Self::can_cast(syntax.kind()) {
1485 Some(Self { syntax })
1486 } else {
1487 None
1488 }
1489 }
1490 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1491}
1492impl AstNode for AssocTypeArg {
1493 fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
1494 fn cast(syntax: SyntaxNode) -> Option<Self> {
1495 if Self::can_cast(syntax.kind()) {
1496 Some(Self { syntax })
1497 } else {
1498 None
1499 }
1500 }
1501 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1502}
1503impl AstNode for LifetimeArg {
1504 fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
1505 fn cast(syntax: SyntaxNode) -> Option<Self> {
1506 if Self::can_cast(syntax.kind()) {
1507 Some(Self { syntax })
1508 } else {
1509 None
1510 }
1511 }
1512 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1513}
1514impl AstNode for ConstArg {
1515 fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG }
1516 fn cast(syntax: SyntaxNode) -> Option<Self> {
1517 if Self::can_cast(syntax.kind()) {
1518 Some(Self { syntax })
1519 } else {
1520 None
1521 }
1522 }
1523 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1524}
1525impl AstNode for TypeBoundList {
1526 fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
1527 fn cast(syntax: SyntaxNode) -> Option<Self> {
1528 if Self::can_cast(syntax.kind()) {
1529 Some(Self { syntax })
1530 } else {
1531 None
1532 }
1533 }
1534 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1535}
1536impl AstNode for MacroCall {
1537 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL }
1538 fn cast(syntax: SyntaxNode) -> Option<Self> {
1539 if Self::can_cast(syntax.kind()) {
1540 Some(Self { syntax })
1541 } else {
1542 None
1543 }
1544 }
1545 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1546}
1547impl AstNode for Attr {
1548 fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR }
1549 fn cast(syntax: SyntaxNode) -> Option<Self> {
1550 if Self::can_cast(syntax.kind()) {
1551 Some(Self { syntax })
1552 } else {
1553 None
1554 }
1555 }
1556 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1557}
1558impl AstNode for TokenTree {
1559 fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE }
1560 fn cast(syntax: SyntaxNode) -> Option<Self> {
1561 if Self::can_cast(syntax.kind()) {
1562 Some(Self { syntax })
1563 } else {
1564 None
1565 }
1566 }
1567 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1568}
1569impl AstNode for MacroItems {
1570 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS }
1571 fn cast(syntax: SyntaxNode) -> Option<Self> {
1572 if Self::can_cast(syntax.kind()) {
1573 Some(Self { syntax })
1574 } else {
1575 None
1576 }
1577 }
1578 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1579}
1580impl AstNode for MacroStmts {
1581 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
1582 fn cast(syntax: SyntaxNode) -> Option<Self> {
1583 if Self::can_cast(syntax.kind()) {
1584 Some(Self { syntax })
1585 } else {
1586 None
1587 }
1588 }
1589 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1590}
1591impl AstNode for SourceFile {
1592 fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
1593 fn cast(syntax: SyntaxNode) -> Option<Self> {
1594 if Self::can_cast(syntax.kind()) {
1595 Some(Self { syntax })
1596 } else {
1597 None
1598 }
1599 }
1600 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1601}
1602impl AstNode for Const {
1603 fn can_cast(kind: SyntaxKind) -> bool { kind == CONST }
1604 fn cast(syntax: SyntaxNode) -> Option<Self> {
1605 if Self::can_cast(syntax.kind()) {
1606 Some(Self { syntax })
1607 } else {
1608 None
1609 }
1610 }
1611 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1612}
1613impl AstNode for Enum {
1614 fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM }
1615 fn cast(syntax: SyntaxNode) -> Option<Self> {
1616 if Self::can_cast(syntax.kind()) {
1617 Some(Self { syntax })
1618 } else {
1619 None
1620 }
1621 }
1622 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1623}
1624impl AstNode for ExternBlock {
1625 fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK }
1626 fn cast(syntax: SyntaxNode) -> Option<Self> {
1627 if Self::can_cast(syntax.kind()) {
1628 Some(Self { syntax })
1629 } else {
1630 None
1631 }
1632 }
1633 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1634}
1635impl AstNode for ExternCrate {
1636 fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE }
1637 fn cast(syntax: SyntaxNode) -> Option<Self> {
1638 if Self::can_cast(syntax.kind()) {
1639 Some(Self { syntax })
1640 } else {
1641 None
1642 }
1643 }
1644 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1645}
1646impl AstNode for Fn {
1647 fn can_cast(kind: SyntaxKind) -> bool { kind == FN }
1648 fn cast(syntax: SyntaxNode) -> Option<Self> {
1649 if Self::can_cast(syntax.kind()) {
1650 Some(Self { syntax })
1651 } else {
1652 None
1653 }
1654 }
1655 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1656}
1657impl AstNode for Impl {
1658 fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL }
1659 fn cast(syntax: SyntaxNode) -> Option<Self> {
1660 if Self::can_cast(syntax.kind()) {
1661 Some(Self { syntax })
1662 } else {
1663 None
1664 }
1665 }
1666 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1667}
1668impl AstNode for Module {
1669 fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
1670 fn cast(syntax: SyntaxNode) -> Option<Self> {
1671 if Self::can_cast(syntax.kind()) {
1672 Some(Self { syntax })
1673 } else {
1674 None
1675 }
1676 }
1677 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1678}
1679impl AstNode for Static {
1680 fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC }
1681 fn cast(syntax: SyntaxNode) -> Option<Self> {
1682 if Self::can_cast(syntax.kind()) {
1683 Some(Self { syntax })
1684 } else {
1685 None
1686 }
1687 }
1688 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1689}
1690impl AstNode for Struct {
1691 fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT }
1692 fn cast(syntax: SyntaxNode) -> Option<Self> {
1693 if Self::can_cast(syntax.kind()) {
1694 Some(Self { syntax })
1695 } else {
1696 None
1697 }
1698 }
1699 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1700}
1701impl AstNode for Trait {
1702 fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT }
1703 fn cast(syntax: SyntaxNode) -> Option<Self> {
1704 if Self::can_cast(syntax.kind()) {
1705 Some(Self { syntax })
1706 } else {
1707 None
1708 }
1709 }
1710 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1711}
1712impl AstNode for TypeAlias {
1713 fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS }
1714 fn cast(syntax: SyntaxNode) -> Option<Self> {
1715 if Self::can_cast(syntax.kind()) {
1716 Some(Self { syntax })
1717 } else {
1718 None
1719 }
1720 }
1721 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1722}
1723impl AstNode for Union {
1724 fn can_cast(kind: SyntaxKind) -> bool { kind == UNION }
1725 fn cast(syntax: SyntaxNode) -> Option<Self> {
1726 if Self::can_cast(syntax.kind()) {
1727 Some(Self { syntax })
1728 } else {
1729 None
1730 }
1731 }
1732 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1733}
1734impl AstNode for Use {
1735 fn can_cast(kind: SyntaxKind) -> bool { kind == USE }
1736 fn cast(syntax: SyntaxNode) -> Option<Self> {
1737 if Self::can_cast(syntax.kind()) {
1738 Some(Self { syntax })
1739 } else {
1740 None
1741 }
1742 }
1743 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1744}
1745impl AstNode for Visibility {
1746 fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
1747 fn cast(syntax: SyntaxNode) -> Option<Self> {
1748 if Self::can_cast(syntax.kind()) {
1749 Some(Self { syntax })
1750 } else {
1751 None
1752 }
1753 }
1754 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1755}
1756impl AstNode for ItemList {
1757 fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
1758 fn cast(syntax: SyntaxNode) -> Option<Self> {
1759 if Self::can_cast(syntax.kind()) {
1760 Some(Self { syntax })
1761 } else {
1762 None
1763 }
1764 }
1765 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1766}
1767impl AstNode for Rename {
1768 fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME }
1769 fn cast(syntax: SyntaxNode) -> Option<Self> {
1770 if Self::can_cast(syntax.kind()) {
1771 Some(Self { syntax })
1772 } else {
1773 None
1774 }
1775 }
1776 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1777}
1778impl AstNode for UseTree {
1779 fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
1780 fn cast(syntax: SyntaxNode) -> Option<Self> {
1781 if Self::can_cast(syntax.kind()) {
1782 Some(Self { syntax })
1783 } else {
1784 None
1785 }
1786 }
1787 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1788}
1789impl AstNode for UseTreeList {
1790 fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
1791 fn cast(syntax: SyntaxNode) -> Option<Self> {
1792 if Self::can_cast(syntax.kind()) {
1793 Some(Self { syntax })
1794 } else {
1795 None
1796 }
1797 }
1798 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1799}
1800impl AstNode for Abi {
1801 fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
1802 fn cast(syntax: SyntaxNode) -> Option<Self> {
1803 if Self::can_cast(syntax.kind()) {
1804 Some(Self { syntax })
1805 } else {
1806 None
1807 }
1808 }
1809 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1810}
1811impl AstNode for GenericParamList {
1812 fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
1813 fn cast(syntax: SyntaxNode) -> Option<Self> {
1814 if Self::can_cast(syntax.kind()) {
1815 Some(Self { syntax })
1816 } else {
1817 None
1818 }
1819 }
1820 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1821}
1822impl AstNode for WhereClause {
1823 fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
1824 fn cast(syntax: SyntaxNode) -> Option<Self> {
1825 if Self::can_cast(syntax.kind()) {
1826 Some(Self { syntax })
1827 } else {
1828 None
1829 }
1830 }
1831 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1832}
1833impl AstNode for BlockExpr {
1834 fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR }
1835 fn cast(syntax: SyntaxNode) -> Option<Self> {
1836 if Self::can_cast(syntax.kind()) {
1837 Some(Self { syntax })
1838 } else {
1839 None
1840 }
1841 }
1842 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1843}
1844impl AstNode for SelfParam {
1845 fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
1846 fn cast(syntax: SyntaxNode) -> Option<Self> {
1847 if Self::can_cast(syntax.kind()) {
1848 Some(Self { syntax })
1849 } else {
1850 None
1851 }
1852 }
1853 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1854}
1855impl AstNode for Param {
1856 fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
1857 fn cast(syntax: SyntaxNode) -> Option<Self> {
1858 if Self::can_cast(syntax.kind()) {
1859 Some(Self { syntax })
1860 } else {
1861 None
1862 }
1863 }
1864 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1865}
1866impl AstNode for RecordFieldList {
1867 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST }
1868 fn cast(syntax: SyntaxNode) -> Option<Self> {
1869 if Self::can_cast(syntax.kind()) {
1870 Some(Self { syntax })
1871 } else {
1872 None
1873 }
1874 }
1875 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1876}
1877impl AstNode for TupleFieldList {
1878 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST }
1879 fn cast(syntax: SyntaxNode) -> Option<Self> {
1880 if Self::can_cast(syntax.kind()) {
1881 Some(Self { syntax })
1882 } else {
1883 None
1884 }
1885 }
1886 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1887}
1888impl AstNode for RecordField {
1889 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD }
1890 fn cast(syntax: SyntaxNode) -> Option<Self> {
1891 if Self::can_cast(syntax.kind()) {
1892 Some(Self { syntax })
1893 } else {
1894 None
1895 }
1896 }
1897 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1898}
1899impl AstNode for TupleField {
1900 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD }
1901 fn cast(syntax: SyntaxNode) -> Option<Self> {
1902 if Self::can_cast(syntax.kind()) {
1903 Some(Self { syntax })
1904 } else {
1905 None
1906 }
1907 }
1908 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1909}
1910impl AstNode for VariantList {
1911 fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST }
1912 fn cast(syntax: SyntaxNode) -> Option<Self> {
1913 if Self::can_cast(syntax.kind()) {
1914 Some(Self { syntax })
1915 } else {
1916 None
1917 }
1918 }
1919 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1920}
1921impl AstNode for Variant {
1922 fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT }
1923 fn cast(syntax: SyntaxNode) -> Option<Self> {
1924 if Self::can_cast(syntax.kind()) {
1925 Some(Self { syntax })
1926 } else {
1927 None
1928 }
1929 }
1930 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1931}
1932impl AstNode for AssocItemList {
1933 fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST }
1934 fn cast(syntax: SyntaxNode) -> Option<Self> {
1935 if Self::can_cast(syntax.kind()) {
1936 Some(Self { syntax })
1937 } else {
1938 None
1939 }
1940 }
1941 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1942}
1943impl AstNode for ExternItemList {
1944 fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST }
1945 fn cast(syntax: SyntaxNode) -> Option<Self> {
1946 if Self::can_cast(syntax.kind()) {
1947 Some(Self { syntax })
1948 } else {
1949 None
1950 }
1951 }
1952 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1953}
1954impl AstNode for ConstParam {
1955 fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM }
1956 fn cast(syntax: SyntaxNode) -> Option<Self> {
1957 if Self::can_cast(syntax.kind()) {
1958 Some(Self { syntax })
1959 } else {
1960 None
1961 }
1962 }
1963 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1964}
1965impl AstNode for LifetimeParam {
1966 fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM }
1967 fn cast(syntax: SyntaxNode) -> Option<Self> {
1968 if Self::can_cast(syntax.kind()) {
1969 Some(Self { syntax })
1970 } else {
1971 None
1972 }
1973 }
1974 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1975}
1976impl AstNode for TypeParam {
1977 fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM }
1978 fn cast(syntax: SyntaxNode) -> Option<Self> {
1979 if Self::can_cast(syntax.kind()) {
1980 Some(Self { syntax })
1981 } else {
1982 None
1983 }
1984 }
1985 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1986}
1987impl AstNode for WherePred {
1988 fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED }
1989 fn cast(syntax: SyntaxNode) -> Option<Self> {
1990 if Self::can_cast(syntax.kind()) {
1991 Some(Self { syntax })
1992 } else {
1993 None
1994 }
1995 }
1996 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1997}
1998impl AstNode for Literal {
1999 fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
2000 fn cast(syntax: SyntaxNode) -> Option<Self> {
2001 if Self::can_cast(syntax.kind()) {
2002 Some(Self { syntax })
2003 } else {
2004 None
2005 }
2006 }
2007 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2008}
2009impl AstNode for ExprStmt {
2010 fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
2011 fn cast(syntax: SyntaxNode) -> Option<Self> {
2012 if Self::can_cast(syntax.kind()) {
2013 Some(Self { syntax })
2014 } else {
2015 None
2016 }
2017 }
2018 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2019}
2020impl AstNode for LetStmt {
2021 fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT }
2022 fn cast(syntax: SyntaxNode) -> Option<Self> {
2023 if Self::can_cast(syntax.kind()) {
2024 Some(Self { syntax })
2025 } else {
2026 None
2027 }
2028 }
2029 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2030}
2031impl AstNode for ArrayExpr {
2032 fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR }
2033 fn cast(syntax: SyntaxNode) -> Option<Self> {
2034 if Self::can_cast(syntax.kind()) {
2035 Some(Self { syntax })
2036 } else {
2037 None
2038 }
2039 }
2040 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2041}
2042impl AstNode for AwaitExpr {
2043 fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
2044 fn cast(syntax: SyntaxNode) -> Option<Self> {
2045 if Self::can_cast(syntax.kind()) {
2046 Some(Self { syntax })
2047 } else {
2048 None
2049 }
2050 }
2051 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2052}
2053impl AstNode for BinExpr {
2054 fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
2055 fn cast(syntax: SyntaxNode) -> Option<Self> {
2056 if Self::can_cast(syntax.kind()) {
2057 Some(Self { syntax })
2058 } else {
2059 None
2060 }
2061 }
2062 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2063}
2064impl AstNode for BoxExpr {
2065 fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR }
2066 fn cast(syntax: SyntaxNode) -> Option<Self> {
2067 if Self::can_cast(syntax.kind()) {
2068 Some(Self { syntax })
2069 } else {
2070 None
2071 }
2072 }
2073 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2074}
2075impl AstNode for BreakExpr {
2076 fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR }
2077 fn cast(syntax: SyntaxNode) -> Option<Self> {
2078 if Self::can_cast(syntax.kind()) {
2079 Some(Self { syntax })
2080 } else {
2081 None
2082 }
2083 }
2084 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2085}
2086impl AstNode for CallExpr {
2087 fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR }
2088 fn cast(syntax: SyntaxNode) -> Option<Self> {
2089 if Self::can_cast(syntax.kind()) {
2090 Some(Self { syntax })
2091 } else {
2092 None
2093 }
2094 }
2095 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2096}
2097impl AstNode for CastExpr {
2098 fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR }
2099 fn cast(syntax: SyntaxNode) -> Option<Self> {
2100 if Self::can_cast(syntax.kind()) {
2101 Some(Self { syntax })
2102 } else {
2103 None
2104 }
2105 }
2106 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2107}
2108impl AstNode for ClosureExpr {
2109 fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR }
2110 fn cast(syntax: SyntaxNode) -> Option<Self> {
2111 if Self::can_cast(syntax.kind()) {
2112 Some(Self { syntax })
2113 } else {
2114 None
2115 }
2116 }
2117 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2118}
2119impl AstNode for ContinueExpr {
2120 fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR }
2121 fn cast(syntax: SyntaxNode) -> Option<Self> {
2122 if Self::can_cast(syntax.kind()) {
2123 Some(Self { syntax })
2124 } else {
2125 None
2126 }
2127 }
2128 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2129}
2130impl AstNode for EffectExpr {
2131 fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR }
2132 fn cast(syntax: SyntaxNode) -> Option<Self> {
2133 if Self::can_cast(syntax.kind()) {
2134 Some(Self { syntax })
2135 } else {
2136 None
2137 }
2138 }
2139 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2140}
2141impl AstNode for FieldExpr {
2142 fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR }
2143 fn cast(syntax: SyntaxNode) -> Option<Self> {
2144 if Self::can_cast(syntax.kind()) {
2145 Some(Self { syntax })
2146 } else {
2147 None
2148 }
2149 }
2150 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2151}
2152impl AstNode for ForExpr {
2153 fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
2154 fn cast(syntax: SyntaxNode) -> Option<Self> {
2155 if Self::can_cast(syntax.kind()) {
2156 Some(Self { syntax })
2157 } else {
2158 None
2159 }
2160 }
2161 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2162}
2163impl AstNode for IfExpr {
2164 fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
2165 fn cast(syntax: SyntaxNode) -> Option<Self> {
2166 if Self::can_cast(syntax.kind()) {
2167 Some(Self { syntax })
2168 } else {
2169 None
2170 }
2171 }
2172 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2173}
2174impl AstNode for IndexExpr {
2175 fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR }
2176 fn cast(syntax: SyntaxNode) -> Option<Self> {
2177 if Self::can_cast(syntax.kind()) {
2178 Some(Self { syntax })
2179 } else {
2180 None
2181 }
2182 }
2183 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2184}
2185impl AstNode for LoopExpr {
2186 fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
2187 fn cast(syntax: SyntaxNode) -> Option<Self> {
2188 if Self::can_cast(syntax.kind()) {
2189 Some(Self { syntax })
2190 } else {
2191 None
2192 }
2193 }
2194 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2195}
2196impl AstNode for MatchExpr {
2197 fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
2198 fn cast(syntax: SyntaxNode) -> Option<Self> {
2199 if Self::can_cast(syntax.kind()) {
2200 Some(Self { syntax })
2201 } else {
2202 None
2203 }
2204 }
2205 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2206}
2207impl AstNode for MethodCallExpr {
2208 fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR }
2209 fn cast(syntax: SyntaxNode) -> Option<Self> {
2210 if Self::can_cast(syntax.kind()) {
2211 Some(Self { syntax })
2212 } else {
2213 None
2214 }
2215 }
2216 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2217}
2218impl AstNode for ParenExpr {
2219 fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
2220 fn cast(syntax: SyntaxNode) -> Option<Self> {
2221 if Self::can_cast(syntax.kind()) {
2222 Some(Self { syntax })
2223 } else {
2224 None
2225 }
2226 }
2227 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2228}
2229impl AstNode for PathExpr {
2230 fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR }
2231 fn cast(syntax: SyntaxNode) -> Option<Self> {
2232 if Self::can_cast(syntax.kind()) {
2233 Some(Self { syntax })
2234 } else {
2235 None
2236 }
2237 }
2238 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2239}
2240impl AstNode for PrefixExpr {
2241 fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR }
2242 fn cast(syntax: SyntaxNode) -> Option<Self> {
2243 if Self::can_cast(syntax.kind()) {
2244 Some(Self { syntax })
2245 } else {
2246 None
2247 }
2248 }
2249 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2250}
2251impl AstNode for RangeExpr {
2252 fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR }
2253 fn cast(syntax: SyntaxNode) -> Option<Self> {
2254 if Self::can_cast(syntax.kind()) {
2255 Some(Self { syntax })
2256 } else {
2257 None
2258 }
2259 }
2260 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2261}
2262impl AstNode for RecordExpr {
2263 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR }
2264 fn cast(syntax: SyntaxNode) -> Option<Self> {
2265 if Self::can_cast(syntax.kind()) {
2266 Some(Self { syntax })
2267 } else {
2268 None
2269 }
2270 }
2271 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2272}
2273impl AstNode for RefExpr {
2274 fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR }
2275 fn cast(syntax: SyntaxNode) -> Option<Self> {
2276 if Self::can_cast(syntax.kind()) {
2277 Some(Self { syntax })
2278 } else {
2279 None
2280 }
2281 }
2282 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2283}
2284impl AstNode for ReturnExpr {
2285 fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR }
2286 fn cast(syntax: SyntaxNode) -> Option<Self> {
2287 if Self::can_cast(syntax.kind()) {
2288 Some(Self { syntax })
2289 } else {
2290 None
2291 }
2292 }
2293 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2294}
2295impl AstNode for TryExpr {
2296 fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
2297 fn cast(syntax: SyntaxNode) -> Option<Self> {
2298 if Self::can_cast(syntax.kind()) {
2299 Some(Self { syntax })
2300 } else {
2301 None
2302 }
2303 }
2304 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2305}
2306impl AstNode for TupleExpr {
2307 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR }
2308 fn cast(syntax: SyntaxNode) -> Option<Self> {
2309 if Self::can_cast(syntax.kind()) {
2310 Some(Self { syntax })
2311 } else {
2312 None
2313 }
2314 }
2315 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2316}
2317impl AstNode for WhileExpr {
2318 fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR }
2319 fn cast(syntax: SyntaxNode) -> Option<Self> {
2320 if Self::can_cast(syntax.kind()) {
2321 Some(Self { syntax })
2322 } else {
2323 None
2324 }
2325 }
2326 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2327}
2328impl AstNode for Label {
2329 fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
2330 fn cast(syntax: SyntaxNode) -> Option<Self> {
2331 if Self::can_cast(syntax.kind()) {
2332 Some(Self { syntax })
2333 } else {
2334 None
2335 }
2336 }
2337 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2338}
2339impl AstNode for RecordExprFieldList {
2340 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST }
2341 fn cast(syntax: SyntaxNode) -> Option<Self> {
2342 if Self::can_cast(syntax.kind()) {
2343 Some(Self { syntax })
2344 } else {
2345 None
2346 }
2347 }
2348 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2349}
2350impl AstNode for RecordExprField {
2351 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD }
2352 fn cast(syntax: SyntaxNode) -> Option<Self> {
2353 if Self::can_cast(syntax.kind()) {
2354 Some(Self { syntax })
2355 } else {
2356 None
2357 }
2358 }
2359 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2360}
2361impl AstNode for ArgList {
2362 fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST }
2363 fn cast(syntax: SyntaxNode) -> Option<Self> {
2364 if Self::can_cast(syntax.kind()) {
2365 Some(Self { syntax })
2366 } else {
2367 None
2368 }
2369 }
2370 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2371}
2372impl AstNode for Condition {
2373 fn can_cast(kind: SyntaxKind) -> bool { kind == CONDITION }
2374 fn cast(syntax: SyntaxNode) -> Option<Self> {
2375 if Self::can_cast(syntax.kind()) {
2376 Some(Self { syntax })
2377 } else {
2378 None
2379 }
2380 }
2381 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2382}
2383impl AstNode for MatchArmList {
2384 fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST }
2385 fn cast(syntax: SyntaxNode) -> Option<Self> {
2386 if Self::can_cast(syntax.kind()) {
2387 Some(Self { syntax })
2388 } else {
2389 None
2390 }
2391 }
2392 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2393}
2394impl AstNode for MatchArm {
2395 fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM }
2396 fn cast(syntax: SyntaxNode) -> Option<Self> {
2397 if Self::can_cast(syntax.kind()) {
2398 Some(Self { syntax })
2399 } else {
2400 None
2401 }
2402 }
2403 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2404}
2405impl AstNode for MatchGuard {
2406 fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD }
2407 fn cast(syntax: SyntaxNode) -> Option<Self> {
2408 if Self::can_cast(syntax.kind()) {
2409 Some(Self { syntax })
2410 } else {
2411 None
2412 }
2413 }
2414 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2415}
2416impl AstNode for ArrayType {
2417 fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE }
2418 fn cast(syntax: SyntaxNode) -> Option<Self> {
2419 if Self::can_cast(syntax.kind()) {
2420 Some(Self { syntax })
2421 } else {
2422 None
2423 }
2424 }
2425 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2426}
2427impl AstNode for DynTraitType {
2428 fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE }
2429 fn cast(syntax: SyntaxNode) -> Option<Self> {
2430 if Self::can_cast(syntax.kind()) {
2431 Some(Self { syntax })
2432 } else {
2433 None
2434 }
2435 }
2436 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2437}
2438impl AstNode for FnPtrType {
2439 fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE }
2440 fn cast(syntax: SyntaxNode) -> Option<Self> {
2441 if Self::can_cast(syntax.kind()) {
2442 Some(Self { syntax })
2443 } else {
2444 None
2445 }
2446 }
2447 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2448}
2449impl AstNode for ForType {
2450 fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE }
2451 fn cast(syntax: SyntaxNode) -> Option<Self> {
2452 if Self::can_cast(syntax.kind()) {
2453 Some(Self { syntax })
2454 } else {
2455 None
2456 }
2457 }
2458 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2459}
2460impl AstNode for ImplTraitType {
2461 fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE }
2462 fn cast(syntax: SyntaxNode) -> Option<Self> {
2463 if Self::can_cast(syntax.kind()) {
2464 Some(Self { syntax })
2465 } else {
2466 None
2467 }
2468 }
2469 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2470}
2471impl AstNode for InferType {
2472 fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE }
2473 fn cast(syntax: SyntaxNode) -> Option<Self> {
2474 if Self::can_cast(syntax.kind()) {
2475 Some(Self { syntax })
2476 } else {
2477 None
2478 }
2479 }
2480 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2481}
2482impl AstNode for NeverType {
2483 fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
2484 fn cast(syntax: SyntaxNode) -> Option<Self> {
2485 if Self::can_cast(syntax.kind()) {
2486 Some(Self { syntax })
2487 } else {
2488 None
2489 }
2490 }
2491 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2492}
2493impl AstNode for ParenType {
2494 fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE }
2495 fn cast(syntax: SyntaxNode) -> Option<Self> {
2496 if Self::can_cast(syntax.kind()) {
2497 Some(Self { syntax })
2498 } else {
2499 None
2500 }
2501 }
2502 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2503}
2504impl AstNode for PtrType {
2505 fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE }
2506 fn cast(syntax: SyntaxNode) -> Option<Self> {
2507 if Self::can_cast(syntax.kind()) {
2508 Some(Self { syntax })
2509 } else {
2510 None
2511 }
2512 }
2513 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2514}
2515impl AstNode for RefType {
2516 fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE }
2517 fn cast(syntax: SyntaxNode) -> Option<Self> {
2518 if Self::can_cast(syntax.kind()) {
2519 Some(Self { syntax })
2520 } else {
2521 None
2522 }
2523 }
2524 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2525}
2526impl AstNode for SliceType {
2527 fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE }
2528 fn cast(syntax: SyntaxNode) -> Option<Self> {
2529 if Self::can_cast(syntax.kind()) {
2530 Some(Self { syntax })
2531 } else {
2532 None
2533 }
2534 }
2535 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2536}
2537impl AstNode for TupleType {
2538 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE }
2539 fn cast(syntax: SyntaxNode) -> Option<Self> {
2540 if Self::can_cast(syntax.kind()) {
2541 Some(Self { syntax })
2542 } else {
2543 None
2544 }
2545 }
2546 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2547}
2548impl AstNode for TypeBound {
2549 fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND }
2550 fn cast(syntax: SyntaxNode) -> Option<Self> {
2551 if Self::can_cast(syntax.kind()) {
2552 Some(Self { syntax })
2553 } else {
2554 None
2555 }
2556 }
2557 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2558}
2559impl AstNode for IdentPat {
2560 fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT }
2561 fn cast(syntax: SyntaxNode) -> Option<Self> {
2562 if Self::can_cast(syntax.kind()) {
2563 Some(Self { syntax })
2564 } else {
2565 None
2566 }
2567 }
2568 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2569}
2570impl AstNode for BoxPat {
2571 fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT }
2572 fn cast(syntax: SyntaxNode) -> Option<Self> {
2573 if Self::can_cast(syntax.kind()) {
2574 Some(Self { syntax })
2575 } else {
2576 None
2577 }
2578 }
2579 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2580}
2581impl AstNode for RestPat {
2582 fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT }
2583 fn cast(syntax: SyntaxNode) -> Option<Self> {
2584 if Self::can_cast(syntax.kind()) {
2585 Some(Self { syntax })
2586 } else {
2587 None
2588 }
2589 }
2590 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2591}
2592impl AstNode for LiteralPat {
2593 fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT }
2594 fn cast(syntax: SyntaxNode) -> Option<Self> {
2595 if Self::can_cast(syntax.kind()) {
2596 Some(Self { syntax })
2597 } else {
2598 None
2599 }
2600 }
2601 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2602}
2603impl AstNode for MacroPat {
2604 fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT }
2605 fn cast(syntax: SyntaxNode) -> Option<Self> {
2606 if Self::can_cast(syntax.kind()) {
2607 Some(Self { syntax })
2608 } else {
2609 None
2610 }
2611 }
2612 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2613}
2614impl AstNode for OrPat {
2615 fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT }
2616 fn cast(syntax: SyntaxNode) -> Option<Self> {
2617 if Self::can_cast(syntax.kind()) {
2618 Some(Self { syntax })
2619 } else {
2620 None
2621 }
2622 }
2623 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2624}
2625impl AstNode for ParenPat {
2626 fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT }
2627 fn cast(syntax: SyntaxNode) -> Option<Self> {
2628 if Self::can_cast(syntax.kind()) {
2629 Some(Self { syntax })
2630 } else {
2631 None
2632 }
2633 }
2634 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2635}
2636impl AstNode for PathPat {
2637 fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT }
2638 fn cast(syntax: SyntaxNode) -> Option<Self> {
2639 if Self::can_cast(syntax.kind()) {
2640 Some(Self { syntax })
2641 } else {
2642 None
2643 }
2644 }
2645 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2646}
2647impl AstNode for WildcardPat {
2648 fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT }
2649 fn cast(syntax: SyntaxNode) -> Option<Self> {
2650 if Self::can_cast(syntax.kind()) {
2651 Some(Self { syntax })
2652 } else {
2653 None
2654 }
2655 }
2656 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2657}
2658impl AstNode for RangePat {
2659 fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT }
2660 fn cast(syntax: SyntaxNode) -> Option<Self> {
2661 if Self::can_cast(syntax.kind()) {
2662 Some(Self { syntax })
2663 } else {
2664 None
2665 }
2666 }
2667 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2668}
2669impl AstNode for RecordPat {
2670 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT }
2671 fn cast(syntax: SyntaxNode) -> Option<Self> {
2672 if Self::can_cast(syntax.kind()) {
2673 Some(Self { syntax })
2674 } else {
2675 None
2676 }
2677 }
2678 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2679}
2680impl AstNode for RefPat {
2681 fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT }
2682 fn cast(syntax: SyntaxNode) -> Option<Self> {
2683 if Self::can_cast(syntax.kind()) {
2684 Some(Self { syntax })
2685 } else {
2686 None
2687 }
2688 }
2689 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2690}
2691impl AstNode for SlicePat {
2692 fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT }
2693 fn cast(syntax: SyntaxNode) -> Option<Self> {
2694 if Self::can_cast(syntax.kind()) {
2695 Some(Self { syntax })
2696 } else {
2697 None
2698 }
2699 }
2700 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2701}
2702impl AstNode for TuplePat {
2703 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT }
2704 fn cast(syntax: SyntaxNode) -> Option<Self> {
2705 if Self::can_cast(syntax.kind()) {
2706 Some(Self { syntax })
2707 } else {
2708 None
2709 }
2710 }
2711 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2712}
2713impl AstNode for TupleStructPat {
2714 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT }
2715 fn cast(syntax: SyntaxNode) -> Option<Self> {
2716 if Self::can_cast(syntax.kind()) {
2717 Some(Self { syntax })
2718 } else {
2719 None
2720 }
2721 }
2722 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2723}
2724impl AstNode for RecordPatFieldList {
2725 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
2726 fn cast(syntax: SyntaxNode) -> Option<Self> {
2727 if Self::can_cast(syntax.kind()) {
2728 Some(Self { syntax })
2729 } else {
2730 None
2731 }
2732 }
2733 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2734}
2735impl AstNode for RecordPatField {
2736 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
2737 fn cast(syntax: SyntaxNode) -> Option<Self> {
2738 if Self::can_cast(syntax.kind()) {
2739 Some(Self { syntax })
2740 } else {
2741 None
2742 }
2743 }
2744 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2745}
2746impl From<TypeArg> for GenericArg {
2747 fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) }
2748}
2749impl From<AssocTypeArg> for GenericArg {
2750 fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) }
2751}
2752impl From<LifetimeArg> for GenericArg {
2753 fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) }
2754}
2755impl From<ConstArg> for GenericArg {
2756 fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
2757}
2758impl AstNode for GenericArg {
2759 fn can_cast(kind: SyntaxKind) -> bool {
2760 match kind {
2761 TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG => true,
2762 _ => false,
2763 }
2764 }
2765 fn cast(syntax: SyntaxNode) -> Option<Self> {
2766 let res = match syntax.kind() {
2767 TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
2768 ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
2769 LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
2770 CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
2771 _ => return None,
2772 };
2773 Some(res)
2774 }
2775 fn syntax(&self) -> &SyntaxNode {
2776 match self {
2777 GenericArg::TypeArg(it) => &it.syntax,
2778 GenericArg::AssocTypeArg(it) => &it.syntax,
2779 GenericArg::LifetimeArg(it) => &it.syntax,
2780 GenericArg::ConstArg(it) => &it.syntax,
2781 }
2782 }
2783}
2784impl From<ArrayType> for Type {
2785 fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
2786}
2787impl From<DynTraitType> for Type {
2788 fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) }
2789}
2790impl From<FnPtrType> for Type {
2791 fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) }
2792}
2793impl From<ForType> for Type {
2794 fn from(node: ForType) -> Type { Type::ForType(node) }
2795}
2796impl From<ImplTraitType> for Type {
2797 fn from(node: ImplTraitType) -> Type { Type::ImplTraitType(node) }
2798}
2799impl From<InferType> for Type {
2800 fn from(node: InferType) -> Type { Type::InferType(node) }
2801}
2802impl From<NeverType> for Type {
2803 fn from(node: NeverType) -> Type { Type::NeverType(node) }
2804}
2805impl From<ParenType> for Type {
2806 fn from(node: ParenType) -> Type { Type::ParenType(node) }
2807}
2808impl From<PathType> for Type {
2809 fn from(node: PathType) -> Type { Type::PathType(node) }
2810}
2811impl From<PtrType> for Type {
2812 fn from(node: PtrType) -> Type { Type::PtrType(node) }
2813}
2814impl From<RefType> for Type {
2815 fn from(node: RefType) -> Type { Type::RefType(node) }
2816}
2817impl From<SliceType> for Type {
2818 fn from(node: SliceType) -> Type { Type::SliceType(node) }
2819}
2820impl From<TupleType> for Type {
2821 fn from(node: TupleType) -> Type { Type::TupleType(node) }
2822}
2823impl AstNode for Type {
2824 fn can_cast(kind: SyntaxKind) -> bool {
2825 match kind {
2826 ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE
2827 | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE | SLICE_TYPE
2828 | TUPLE_TYPE => true,
2829 _ => false,
2830 }
2831 }
2832 fn cast(syntax: SyntaxNode) -> Option<Self> {
2833 let res = match syntax.kind() {
2834 ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }),
2835 DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }),
2836 FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }),
2837 FOR_TYPE => Type::ForType(ForType { syntax }),
2838 IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }),
2839 INFER_TYPE => Type::InferType(InferType { syntax }),
2840 NEVER_TYPE => Type::NeverType(NeverType { syntax }),
2841 PAREN_TYPE => Type::ParenType(ParenType { syntax }),
2842 PATH_TYPE => Type::PathType(PathType { syntax }),
2843 PTR_TYPE => Type::PtrType(PtrType { syntax }),
2844 REF_TYPE => Type::RefType(RefType { syntax }),
2845 SLICE_TYPE => Type::SliceType(SliceType { syntax }),
2846 TUPLE_TYPE => Type::TupleType(TupleType { syntax }),
2847 _ => return None,
2848 };
2849 Some(res)
2850 }
2851 fn syntax(&self) -> &SyntaxNode {
2852 match self {
2853 Type::ArrayType(it) => &it.syntax,
2854 Type::DynTraitType(it) => &it.syntax,
2855 Type::FnPtrType(it) => &it.syntax,
2856 Type::ForType(it) => &it.syntax,
2857 Type::ImplTraitType(it) => &it.syntax,
2858 Type::InferType(it) => &it.syntax,
2859 Type::NeverType(it) => &it.syntax,
2860 Type::ParenType(it) => &it.syntax,
2861 Type::PathType(it) => &it.syntax,
2862 Type::PtrType(it) => &it.syntax,
2863 Type::RefType(it) => &it.syntax,
2864 Type::SliceType(it) => &it.syntax,
2865 Type::TupleType(it) => &it.syntax,
2866 }
2867 }
2868}
2869impl From<ArrayExpr> for Expr {
2870 fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) }
2871}
2872impl From<AwaitExpr> for Expr {
2873 fn from(node: AwaitExpr) -> Expr { Expr::AwaitExpr(node) }
2874}
2875impl From<BinExpr> for Expr {
2876 fn from(node: BinExpr) -> Expr { Expr::BinExpr(node) }
2877}
2878impl From<BlockExpr> for Expr {
2879 fn from(node: BlockExpr) -> Expr { Expr::BlockExpr(node) }
2880}
2881impl From<BoxExpr> for Expr {
2882 fn from(node: BoxExpr) -> Expr { Expr::BoxExpr(node) }
2883}
2884impl From<BreakExpr> for Expr {
2885 fn from(node: BreakExpr) -> Expr { Expr::BreakExpr(node) }
2886}
2887impl From<CallExpr> for Expr {
2888 fn from(node: CallExpr) -> Expr { Expr::CallExpr(node) }
2889}
2890impl From<CastExpr> for Expr {
2891 fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
2892}
2893impl From<ClosureExpr> for Expr {
2894 fn from(node: ClosureExpr) -> Expr { Expr::ClosureExpr(node) }
2895}
2896impl From<ContinueExpr> for Expr {
2897 fn from(node: ContinueExpr) -> Expr { Expr::ContinueExpr(node) }
2898}
2899impl From<EffectExpr> for Expr {
2900 fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) }
2901}
2902impl From<FieldExpr> for Expr {
2903 fn from(node: FieldExpr) -> Expr { Expr::FieldExpr(node) }
2904}
2905impl From<ForExpr> for Expr {
2906 fn from(node: ForExpr) -> Expr { Expr::ForExpr(node) }
2907}
2908impl From<IfExpr> for Expr {
2909 fn from(node: IfExpr) -> Expr { Expr::IfExpr(node) }
2910}
2911impl From<IndexExpr> for Expr {
2912 fn from(node: IndexExpr) -> Expr { Expr::IndexExpr(node) }
2913}
2914impl From<Literal> for Expr {
2915 fn from(node: Literal) -> Expr { Expr::Literal(node) }
2916}
2917impl From<LoopExpr> for Expr {
2918 fn from(node: LoopExpr) -> Expr { Expr::LoopExpr(node) }
2919}
2920impl From<MacroCall> for Expr {
2921 fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) }
2922}
2923impl From<MatchExpr> for Expr {
2924 fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) }
2925}
2926impl From<MethodCallExpr> for Expr {
2927 fn from(node: MethodCallExpr) -> Expr { Expr::MethodCallExpr(node) }
2928}
2929impl From<ParenExpr> for Expr {
2930 fn from(node: ParenExpr) -> Expr { Expr::ParenExpr(node) }
2931}
2932impl From<PathExpr> for Expr {
2933 fn from(node: PathExpr) -> Expr { Expr::PathExpr(node) }
2934}
2935impl From<PrefixExpr> for Expr {
2936 fn from(node: PrefixExpr) -> Expr { Expr::PrefixExpr(node) }
2937}
2938impl From<RangeExpr> for Expr {
2939 fn from(node: RangeExpr) -> Expr { Expr::RangeExpr(node) }
2940}
2941impl From<RecordExpr> for Expr {
2942 fn from(node: RecordExpr) -> Expr { Expr::RecordExpr(node) }
2943}
2944impl From<RefExpr> for Expr {
2945 fn from(node: RefExpr) -> Expr { Expr::RefExpr(node) }
2946}
2947impl From<ReturnExpr> for Expr {
2948 fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) }
2949}
2950impl From<TryExpr> for Expr {
2951 fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
2952}
2953impl From<TupleExpr> for Expr {
2954 fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) }
2955}
2956impl From<WhileExpr> for Expr {
2957 fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) }
2958}
2959impl AstNode for Expr {
2960 fn can_cast(kind: SyntaxKind) -> bool {
2961 match kind {
2962 ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR
2963 | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR
2964 | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR
2965 | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
2966 | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR => true,
2967 _ => false,
2968 }
2969 }
2970 fn cast(syntax: SyntaxNode) -> Option<Self> {
2971 let res = match syntax.kind() {
2972 ARRAY_EXPR => Expr::ArrayExpr(ArrayExpr { syntax }),
2973 AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
2974 BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
2975 BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
2976 BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }),
2977 BREAK_EXPR => Expr::BreakExpr(BreakExpr { syntax }),
2978 CALL_EXPR => Expr::CallExpr(CallExpr { syntax }),
2979 CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
2980 CLOSURE_EXPR => Expr::ClosureExpr(ClosureExpr { syntax }),
2981 CONTINUE_EXPR => Expr::ContinueExpr(ContinueExpr { syntax }),
2982 EFFECT_EXPR => Expr::EffectExpr(EffectExpr { syntax }),
2983 FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
2984 FOR_EXPR => Expr::ForExpr(ForExpr { syntax }),
2985 IF_EXPR => Expr::IfExpr(IfExpr { syntax }),
2986 INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
2987 LITERAL => Expr::Literal(Literal { syntax }),
2988 LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
2989 MACRO_CALL => Expr::MacroCall(MacroCall { syntax }),
2990 MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
2991 METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
2992 PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
2993 PATH_EXPR => Expr::PathExpr(PathExpr { syntax }),
2994 PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
2995 RANGE_EXPR => Expr::RangeExpr(RangeExpr { syntax }),
2996 RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }),
2997 REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
2998 RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
2999 TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
3000 TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
3001 WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
3002 _ => return None,
3003 };
3004 Some(res)
3005 }
3006 fn syntax(&self) -> &SyntaxNode {
3007 match self {
3008 Expr::ArrayExpr(it) => &it.syntax,
3009 Expr::AwaitExpr(it) => &it.syntax,
3010 Expr::BinExpr(it) => &it.syntax,
3011 Expr::BlockExpr(it) => &it.syntax,
3012 Expr::BoxExpr(it) => &it.syntax,
3013 Expr::BreakExpr(it) => &it.syntax,
3014 Expr::CallExpr(it) => &it.syntax,
3015 Expr::CastExpr(it) => &it.syntax,
3016 Expr::ClosureExpr(it) => &it.syntax,
3017 Expr::ContinueExpr(it) => &it.syntax,
3018 Expr::EffectExpr(it) => &it.syntax,
3019 Expr::FieldExpr(it) => &it.syntax,
3020 Expr::ForExpr(it) => &it.syntax,
3021 Expr::IfExpr(it) => &it.syntax,
3022 Expr::IndexExpr(it) => &it.syntax,
3023 Expr::Literal(it) => &it.syntax,
3024 Expr::LoopExpr(it) => &it.syntax,
3025 Expr::MacroCall(it) => &it.syntax,
3026 Expr::MatchExpr(it) => &it.syntax,
3027 Expr::MethodCallExpr(it) => &it.syntax,
3028 Expr::ParenExpr(it) => &it.syntax,
3029 Expr::PathExpr(it) => &it.syntax,
3030 Expr::PrefixExpr(it) => &it.syntax,
3031 Expr::RangeExpr(it) => &it.syntax,
3032 Expr::RecordExpr(it) => &it.syntax,
3033 Expr::RefExpr(it) => &it.syntax,
3034 Expr::ReturnExpr(it) => &it.syntax,
3035 Expr::TryExpr(it) => &it.syntax,
3036 Expr::TupleExpr(it) => &it.syntax,
3037 Expr::WhileExpr(it) => &it.syntax,
3038 }
3039 }
3040}
3041impl From<Const> for Item {
3042 fn from(node: Const) -> Item { Item::Const(node) }
3043}
3044impl From<Enum> for Item {
3045 fn from(node: Enum) -> Item { Item::Enum(node) }
3046}
3047impl From<ExternBlock> for Item {
3048 fn from(node: ExternBlock) -> Item { Item::ExternBlock(node) }
3049}
3050impl From<ExternCrate> for Item {
3051 fn from(node: ExternCrate) -> Item { Item::ExternCrate(node) }
3052}
3053impl From<Fn> for Item {
3054 fn from(node: Fn) -> Item { Item::Fn(node) }
3055}
3056impl From<Impl> for Item {
3057 fn from(node: Impl) -> Item { Item::Impl(node) }
3058}
3059impl From<MacroCall> for Item {
3060 fn from(node: MacroCall) -> Item { Item::MacroCall(node) }
3061}
3062impl From<Module> for Item {
3063 fn from(node: Module) -> Item { Item::Module(node) }
3064}
3065impl From<Static> for Item {
3066 fn from(node: Static) -> Item { Item::Static(node) }
3067}
3068impl From<Struct> for Item {
3069 fn from(node: Struct) -> Item { Item::Struct(node) }
3070}
3071impl From<Trait> for Item {
3072 fn from(node: Trait) -> Item { Item::Trait(node) }
3073}
3074impl From<TypeAlias> for Item {
3075 fn from(node: TypeAlias) -> Item { Item::TypeAlias(node) }
3076}
3077impl From<Union> for Item {
3078 fn from(node: Union) -> Item { Item::Union(node) }
3079}
3080impl From<Use> for Item {
3081 fn from(node: Use) -> Item { Item::Use(node) }
3082}
3083impl AstNode for Item {
3084 fn can_cast(kind: SyntaxKind) -> bool {
3085 match kind {
3086 CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MODULE
3087 | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true,
3088 _ => false,
3089 }
3090 }
3091 fn cast(syntax: SyntaxNode) -> Option<Self> {
3092 let res = match syntax.kind() {
3093 CONST => Item::Const(Const { syntax }),
3094 ENUM => Item::Enum(Enum { syntax }),
3095 EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }),
3096 EXTERN_CRATE => Item::ExternCrate(ExternCrate { syntax }),
3097 FN => Item::Fn(Fn { syntax }),
3098 IMPL => Item::Impl(Impl { syntax }),
3099 MACRO_CALL => Item::MacroCall(MacroCall { syntax }),
3100 MODULE => Item::Module(Module { syntax }),
3101 STATIC => Item::Static(Static { syntax }),
3102 STRUCT => Item::Struct(Struct { syntax }),
3103 TRAIT => Item::Trait(Trait { syntax }),
3104 TYPE_ALIAS => Item::TypeAlias(TypeAlias { syntax }),
3105 UNION => Item::Union(Union { syntax }),
3106 USE => Item::Use(Use { syntax }),
3107 _ => return None,
3108 };
3109 Some(res)
3110 }
3111 fn syntax(&self) -> &SyntaxNode {
3112 match self {
3113 Item::Const(it) => &it.syntax,
3114 Item::Enum(it) => &it.syntax,
3115 Item::ExternBlock(it) => &it.syntax,
3116 Item::ExternCrate(it) => &it.syntax,
3117 Item::Fn(it) => &it.syntax,
3118 Item::Impl(it) => &it.syntax,
3119 Item::MacroCall(it) => &it.syntax,
3120 Item::Module(it) => &it.syntax,
3121 Item::Static(it) => &it.syntax,
3122 Item::Struct(it) => &it.syntax,
3123 Item::Trait(it) => &it.syntax,
3124 Item::TypeAlias(it) => &it.syntax,
3125 Item::Union(it) => &it.syntax,
3126 Item::Use(it) => &it.syntax,
3127 }
3128 }
3129}
3130impl From<ExprStmt> for Stmt {
3131 fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) }
3132}
3133impl From<Item> for Stmt {
3134 fn from(node: Item) -> Stmt { Stmt::Item(node) }
3135}
3136impl From<LetStmt> for Stmt {
3137 fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
3138}
3139impl From<IdentPat> for Pat {
3140 fn from(node: IdentPat) -> Pat { Pat::IdentPat(node) }
3141}
3142impl From<BoxPat> for Pat {
3143 fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) }
3144}
3145impl From<RestPat> for Pat {
3146 fn from(node: RestPat) -> Pat { Pat::RestPat(node) }
3147}
3148impl From<LiteralPat> for Pat {
3149 fn from(node: LiteralPat) -> Pat { Pat::LiteralPat(node) }
3150}
3151impl From<MacroPat> for Pat {
3152 fn from(node: MacroPat) -> Pat { Pat::MacroPat(node) }
3153}
3154impl From<OrPat> for Pat {
3155 fn from(node: OrPat) -> Pat { Pat::OrPat(node) }
3156}
3157impl From<ParenPat> for Pat {
3158 fn from(node: ParenPat) -> Pat { Pat::ParenPat(node) }
3159}
3160impl From<PathPat> for Pat {
3161 fn from(node: PathPat) -> Pat { Pat::PathPat(node) }
3162}
3163impl From<WildcardPat> for Pat {
3164 fn from(node: WildcardPat) -> Pat { Pat::WildcardPat(node) }
3165}
3166impl From<RangePat> for Pat {
3167 fn from(node: RangePat) -> Pat { Pat::RangePat(node) }
3168}
3169impl From<RecordPat> for Pat {
3170 fn from(node: RecordPat) -> Pat { Pat::RecordPat(node) }
3171}
3172impl From<RefPat> for Pat {
3173 fn from(node: RefPat) -> Pat { Pat::RefPat(node) }
3174}
3175impl From<SlicePat> for Pat {
3176 fn from(node: SlicePat) -> Pat { Pat::SlicePat(node) }
3177}
3178impl From<TuplePat> for Pat {
3179 fn from(node: TuplePat) -> Pat { Pat::TuplePat(node) }
3180}
3181impl From<TupleStructPat> for Pat {
3182 fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) }
3183}
3184impl AstNode for Pat {
3185 fn can_cast(kind: SyntaxKind) -> bool {
3186 match kind {
3187 IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT
3188 | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT
3189 | TUPLE_PAT | TUPLE_STRUCT_PAT => true,
3190 _ => false,
3191 }
3192 }
3193 fn cast(syntax: SyntaxNode) -> Option<Self> {
3194 let res = match syntax.kind() {
3195 IDENT_PAT => Pat::IdentPat(IdentPat { syntax }),
3196 BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
3197 REST_PAT => Pat::RestPat(RestPat { syntax }),
3198 LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }),
3199 MACRO_PAT => Pat::MacroPat(MacroPat { syntax }),
3200 OR_PAT => Pat::OrPat(OrPat { syntax }),
3201 PAREN_PAT => Pat::ParenPat(ParenPat { syntax }),
3202 PATH_PAT => Pat::PathPat(PathPat { syntax }),
3203 WILDCARD_PAT => Pat::WildcardPat(WildcardPat { syntax }),
3204 RANGE_PAT => Pat::RangePat(RangePat { syntax }),
3205 RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
3206 REF_PAT => Pat::RefPat(RefPat { syntax }),
3207 SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
3208 TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
3209 TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
3210 _ => return None,
3211 };
3212 Some(res)
3213 }
3214 fn syntax(&self) -> &SyntaxNode {
3215 match self {
3216 Pat::IdentPat(it) => &it.syntax,
3217 Pat::BoxPat(it) => &it.syntax,
3218 Pat::RestPat(it) => &it.syntax,
3219 Pat::LiteralPat(it) => &it.syntax,
3220 Pat::MacroPat(it) => &it.syntax,
3221 Pat::OrPat(it) => &it.syntax,
3222 Pat::ParenPat(it) => &it.syntax,
3223 Pat::PathPat(it) => &it.syntax,
3224 Pat::WildcardPat(it) => &it.syntax,
3225 Pat::RangePat(it) => &it.syntax,
3226 Pat::RecordPat(it) => &it.syntax,
3227 Pat::RefPat(it) => &it.syntax,
3228 Pat::SlicePat(it) => &it.syntax,
3229 Pat::TuplePat(it) => &it.syntax,
3230 Pat::TupleStructPat(it) => &it.syntax,
3231 }
3232 }
3233}
3234impl From<RecordFieldList> for FieldList {
3235 fn from(node: RecordFieldList) -> FieldList { FieldList::RecordFieldList(node) }
3236}
3237impl From<TupleFieldList> for FieldList {
3238 fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) }
3239}
3240impl AstNode for FieldList {
3241 fn can_cast(kind: SyntaxKind) -> bool {
3242 match kind {
3243 RECORD_FIELD_LIST | TUPLE_FIELD_LIST => true,
3244 _ => false,
3245 }
3246 }
3247 fn cast(syntax: SyntaxNode) -> Option<Self> {
3248 let res = match syntax.kind() {
3249 RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }),
3250 TUPLE_FIELD_LIST => FieldList::TupleFieldList(TupleFieldList { syntax }),
3251 _ => return None,
3252 };
3253 Some(res)
3254 }
3255 fn syntax(&self) -> &SyntaxNode {
3256 match self {
3257 FieldList::RecordFieldList(it) => &it.syntax,
3258 FieldList::TupleFieldList(it) => &it.syntax,
3259 }
3260 }
3261}
3262impl From<Enum> for AdtDef {
3263 fn from(node: Enum) -> AdtDef { AdtDef::Enum(node) }
3264}
3265impl From<Struct> for AdtDef {
3266 fn from(node: Struct) -> AdtDef { AdtDef::Struct(node) }
3267}
3268impl From<Union> for AdtDef {
3269 fn from(node: Union) -> AdtDef { AdtDef::Union(node) }
3270}
3271impl AstNode for AdtDef {
3272 fn can_cast(kind: SyntaxKind) -> bool {
3273 match kind {
3274 ENUM | STRUCT | UNION => true,
3275 _ => false,
3276 }
3277 }
3278 fn cast(syntax: SyntaxNode) -> Option<Self> {
3279 let res = match syntax.kind() {
3280 ENUM => AdtDef::Enum(Enum { syntax }),
3281 STRUCT => AdtDef::Struct(Struct { syntax }),
3282 UNION => AdtDef::Union(Union { syntax }),
3283 _ => return None,
3284 };
3285 Some(res)
3286 }
3287 fn syntax(&self) -> &SyntaxNode {
3288 match self {
3289 AdtDef::Enum(it) => &it.syntax,
3290 AdtDef::Struct(it) => &it.syntax,
3291 AdtDef::Union(it) => &it.syntax,
3292 }
3293 }
3294}
3295impl From<Const> for AssocItem {
3296 fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
3297}
3298impl From<Fn> for AssocItem {
3299 fn from(node: Fn) -> AssocItem { AssocItem::Fn(node) }
3300}
3301impl From<MacroCall> for AssocItem {
3302 fn from(node: MacroCall) -> AssocItem { AssocItem::MacroCall(node) }
3303}
3304impl From<TypeAlias> for AssocItem {
3305 fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) }
3306}
3307impl AstNode for AssocItem {
3308 fn can_cast(kind: SyntaxKind) -> bool {
3309 match kind {
3310 CONST | FN | MACRO_CALL | TYPE_ALIAS => true,
3311 _ => false,
3312 }
3313 }
3314 fn cast(syntax: SyntaxNode) -> Option<Self> {
3315 let res = match syntax.kind() {
3316 CONST => AssocItem::Const(Const { syntax }),
3317 FN => AssocItem::Fn(Fn { syntax }),
3318 MACRO_CALL => AssocItem::MacroCall(MacroCall { syntax }),
3319 TYPE_ALIAS => AssocItem::TypeAlias(TypeAlias { syntax }),
3320 _ => return None,
3321 };
3322 Some(res)
3323 }
3324 fn syntax(&self) -> &SyntaxNode {
3325 match self {
3326 AssocItem::Const(it) => &it.syntax,
3327 AssocItem::Fn(it) => &it.syntax,
3328 AssocItem::MacroCall(it) => &it.syntax,
3329 AssocItem::TypeAlias(it) => &it.syntax,
3330 }
3331 }
3332}
3333impl From<Fn> for ExternItem {
3334 fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) }
3335}
3336impl From<MacroCall> for ExternItem {
3337 fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) }
3338}
3339impl From<Static> for ExternItem {
3340 fn from(node: Static) -> ExternItem { ExternItem::Static(node) }
3341}
3342impl AstNode for ExternItem {
3343 fn can_cast(kind: SyntaxKind) -> bool {
3344 match kind {
3345 FN | MACRO_CALL | STATIC => true,
3346 _ => false,
3347 }
3348 }
3349 fn cast(syntax: SyntaxNode) -> Option<Self> {
3350 let res = match syntax.kind() {
3351 FN => ExternItem::Fn(Fn { syntax }),
3352 MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }),
3353 STATIC => ExternItem::Static(Static { syntax }),
3354 _ => return None,
3355 };
3356 Some(res)
3357 }
3358 fn syntax(&self) -> &SyntaxNode {
3359 match self {
3360 ExternItem::Fn(it) => &it.syntax,
3361 ExternItem::MacroCall(it) => &it.syntax,
3362 ExternItem::Static(it) => &it.syntax,
3363 }
3364 }
3365}
3366impl From<ConstParam> for GenericParam {
3367 fn from(node: ConstParam) -> GenericParam { GenericParam::ConstParam(node) }
3368}
3369impl From<LifetimeParam> for GenericParam {
3370 fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) }
3371}
3372impl From<TypeParam> for GenericParam {
3373 fn from(node: TypeParam) -> GenericParam { GenericParam::TypeParam(node) }
3374}
3375impl AstNode for GenericParam {
3376 fn can_cast(kind: SyntaxKind) -> bool {
3377 match kind {
3378 CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM => true,
3379 _ => false,
3380 }
3381 }
3382 fn cast(syntax: SyntaxNode) -> Option<Self> {
3383 let res = match syntax.kind() {
3384 CONST_PARAM => GenericParam::ConstParam(ConstParam { syntax }),
3385 LIFETIME_PARAM => GenericParam::LifetimeParam(LifetimeParam { syntax }),
3386 TYPE_PARAM => GenericParam::TypeParam(TypeParam { syntax }),
3387 _ => return None,
3388 };
3389 Some(res)
3390 }
3391 fn syntax(&self) -> &SyntaxNode {
3392 match self {
3393 GenericParam::ConstParam(it) => &it.syntax,
3394 GenericParam::LifetimeParam(it) => &it.syntax,
3395 GenericParam::TypeParam(it) => &it.syntax,
3396 }
3397 }
3398}
3399impl std::fmt::Display for GenericArg {
3400 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3401 std::fmt::Display::fmt(self.syntax(), f)
3402 }
3403}
3404impl std::fmt::Display for Type {
3405 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3406 std::fmt::Display::fmt(self.syntax(), f)
3407 }
3408}
3409impl std::fmt::Display for Expr {
3410 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3411 std::fmt::Display::fmt(self.syntax(), f)
3412 }
3413}
3414impl std::fmt::Display for Item {
3415 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3416 std::fmt::Display::fmt(self.syntax(), f)
3417 }
3418}
3419impl std::fmt::Display for Stmt {
3420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3421 std::fmt::Display::fmt(self.syntax(), f)
3422 }
3423}
3424impl std::fmt::Display for Pat {
3425 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3426 std::fmt::Display::fmt(self.syntax(), f)
3427 }
3428}
3429impl std::fmt::Display for FieldList {
3430 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3431 std::fmt::Display::fmt(self.syntax(), f)
3432 }
3433}
3434impl std::fmt::Display for AdtDef {
3435 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3436 std::fmt::Display::fmt(self.syntax(), f)
3437 }
3438}
3439impl std::fmt::Display for AssocItem {
3440 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3441 std::fmt::Display::fmt(self.syntax(), f)
3442 }
3443}
3444impl std::fmt::Display for ExternItem {
3445 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3446 std::fmt::Display::fmt(self.syntax(), f)
3447 }
3448}
3449impl std::fmt::Display for GenericParam {
3450 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3451 std::fmt::Display::fmt(self.syntax(), f)
3452 }
3453}
3454impl std::fmt::Display for Name {
3455 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3456 std::fmt::Display::fmt(self.syntax(), f)
3457 }
3458}
3459impl std::fmt::Display for NameRef {
3460 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3461 std::fmt::Display::fmt(self.syntax(), f)
3462 }
3463}
3464impl std::fmt::Display for Path {
3465 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3466 std::fmt::Display::fmt(self.syntax(), f)
3467 }
3468}
3469impl std::fmt::Display for PathSegment {
3470 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3471 std::fmt::Display::fmt(self.syntax(), f)
3472 }
3473}
3474impl std::fmt::Display for GenericArgList {
3475 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3476 std::fmt::Display::fmt(self.syntax(), f)
3477 }
3478}
3479impl std::fmt::Display for ParamList {
3480 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3481 std::fmt::Display::fmt(self.syntax(), f)
3482 }
3483}
3484impl std::fmt::Display for RetType {
3485 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3486 std::fmt::Display::fmt(self.syntax(), f)
3487 }
3488}
3489impl std::fmt::Display for PathType {
3490 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3491 std::fmt::Display::fmt(self.syntax(), f)
3492 }
3493}
3494impl std::fmt::Display for TypeArg {
3495 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3496 std::fmt::Display::fmt(self.syntax(), f)
3497 }
3498}
3499impl std::fmt::Display for AssocTypeArg {
3500 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3501 std::fmt::Display::fmt(self.syntax(), f)
3502 }
3503}
3504impl std::fmt::Display for LifetimeArg {
3505 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3506 std::fmt::Display::fmt(self.syntax(), f)
3507 }
3508}
3509impl std::fmt::Display for ConstArg {
3510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3511 std::fmt::Display::fmt(self.syntax(), f)
3512 }
3513}
3514impl std::fmt::Display for TypeBoundList {
3515 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3516 std::fmt::Display::fmt(self.syntax(), f)
3517 }
3518}
3519impl std::fmt::Display for MacroCall {
3520 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3521 std::fmt::Display::fmt(self.syntax(), f)
3522 }
3523}
3524impl std::fmt::Display for Attr {
3525 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3526 std::fmt::Display::fmt(self.syntax(), f)
3527 }
3528}
3529impl std::fmt::Display for TokenTree {
3530 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3531 std::fmt::Display::fmt(self.syntax(), f)
3532 }
3533}
3534impl std::fmt::Display for MacroItems {
3535 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3536 std::fmt::Display::fmt(self.syntax(), f)
3537 }
3538}
3539impl std::fmt::Display for MacroStmts {
3540 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3541 std::fmt::Display::fmt(self.syntax(), f)
3542 }
3543}
3544impl std::fmt::Display for SourceFile {
3545 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3546 std::fmt::Display::fmt(self.syntax(), f)
3547 }
3548}
3549impl std::fmt::Display for Const {
3550 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3551 std::fmt::Display::fmt(self.syntax(), f)
3552 }
3553}
3554impl std::fmt::Display for Enum {
3555 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3556 std::fmt::Display::fmt(self.syntax(), f)
3557 }
3558}
3559impl std::fmt::Display for ExternBlock {
3560 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3561 std::fmt::Display::fmt(self.syntax(), f)
3562 }
3563}
3564impl std::fmt::Display for ExternCrate {
3565 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3566 std::fmt::Display::fmt(self.syntax(), f)
3567 }
3568}
3569impl std::fmt::Display for Fn {
3570 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3571 std::fmt::Display::fmt(self.syntax(), f)
3572 }
3573}
3574impl std::fmt::Display for Impl {
3575 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3576 std::fmt::Display::fmt(self.syntax(), f)
3577 }
3578}
3579impl std::fmt::Display for Module {
3580 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3581 std::fmt::Display::fmt(self.syntax(), f)
3582 }
3583}
3584impl std::fmt::Display for Static {
3585 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3586 std::fmt::Display::fmt(self.syntax(), f)
3587 }
3588}
3589impl std::fmt::Display for Struct {
3590 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3591 std::fmt::Display::fmt(self.syntax(), f)
3592 }
3593}
3594impl std::fmt::Display for Trait {
3595 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3596 std::fmt::Display::fmt(self.syntax(), f)
3597 }
3598}
3599impl std::fmt::Display for TypeAlias {
3600 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3601 std::fmt::Display::fmt(self.syntax(), f)
3602 }
3603}
3604impl std::fmt::Display for Union {
3605 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3606 std::fmt::Display::fmt(self.syntax(), f)
3607 }
3608}
3609impl std::fmt::Display for Use {
3610 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3611 std::fmt::Display::fmt(self.syntax(), f)
3612 }
3613}
3614impl std::fmt::Display for Visibility {
3615 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3616 std::fmt::Display::fmt(self.syntax(), f)
3617 }
3618}
3619impl std::fmt::Display for ItemList {
3620 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3621 std::fmt::Display::fmt(self.syntax(), f)
3622 }
3623}
3624impl std::fmt::Display for Rename {
3625 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3626 std::fmt::Display::fmt(self.syntax(), f)
3627 }
3628}
3629impl std::fmt::Display for UseTree {
3630 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3631 std::fmt::Display::fmt(self.syntax(), f)
3632 }
3633}
3634impl std::fmt::Display for UseTreeList {
3635 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3636 std::fmt::Display::fmt(self.syntax(), f)
3637 }
3638}
3639impl std::fmt::Display for Abi {
3640 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3641 std::fmt::Display::fmt(self.syntax(), f)
3642 }
3643}
3644impl std::fmt::Display for GenericParamList {
3645 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3646 std::fmt::Display::fmt(self.syntax(), f)
3647 }
3648}
3649impl std::fmt::Display for WhereClause {
3650 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3651 std::fmt::Display::fmt(self.syntax(), f)
3652 }
3653}
3654impl std::fmt::Display for BlockExpr {
3655 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3656 std::fmt::Display::fmt(self.syntax(), f)
3657 }
3658}
3659impl std::fmt::Display for SelfParam {
3660 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3661 std::fmt::Display::fmt(self.syntax(), f)
3662 }
3663}
3664impl std::fmt::Display for Param {
3665 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3666 std::fmt::Display::fmt(self.syntax(), f)
3667 }
3668}
3669impl std::fmt::Display for RecordFieldList {
3670 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3671 std::fmt::Display::fmt(self.syntax(), f)
3672 }
3673}
3674impl std::fmt::Display for TupleFieldList {
3675 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3676 std::fmt::Display::fmt(self.syntax(), f)
3677 }
3678}
3679impl std::fmt::Display for RecordField {
3680 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3681 std::fmt::Display::fmt(self.syntax(), f)
3682 }
3683}
3684impl std::fmt::Display for TupleField {
3685 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3686 std::fmt::Display::fmt(self.syntax(), f)
3687 }
3688}
3689impl std::fmt::Display for VariantList {
3690 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3691 std::fmt::Display::fmt(self.syntax(), f)
3692 }
3693}
3694impl std::fmt::Display for Variant {
3695 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3696 std::fmt::Display::fmt(self.syntax(), f)
3697 }
3698}
3699impl std::fmt::Display for AssocItemList {
3700 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3701 std::fmt::Display::fmt(self.syntax(), f)
3702 }
3703}
3704impl std::fmt::Display for ExternItemList {
3705 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3706 std::fmt::Display::fmt(self.syntax(), f)
3707 }
3708}
3709impl std::fmt::Display for ConstParam {
3710 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3711 std::fmt::Display::fmt(self.syntax(), f)
3712 }
3713}
3714impl std::fmt::Display for LifetimeParam {
3715 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3716 std::fmt::Display::fmt(self.syntax(), f)
3717 }
3718}
3719impl std::fmt::Display for TypeParam {
3720 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3721 std::fmt::Display::fmt(self.syntax(), f)
3722 }
3723}
3724impl std::fmt::Display for WherePred {
3725 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3726 std::fmt::Display::fmt(self.syntax(), f)
3727 }
3728}
3729impl std::fmt::Display for Literal {
3730 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3731 std::fmt::Display::fmt(self.syntax(), f)
3732 }
3733}
3734impl std::fmt::Display for ExprStmt {
3735 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3736 std::fmt::Display::fmt(self.syntax(), f)
3737 }
3738}
3739impl std::fmt::Display for LetStmt {
3740 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3741 std::fmt::Display::fmt(self.syntax(), f)
3742 }
3743}
3744impl std::fmt::Display for ArrayExpr {
3745 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3746 std::fmt::Display::fmt(self.syntax(), f)
3747 }
3748}
3749impl std::fmt::Display for AwaitExpr {
3750 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3751 std::fmt::Display::fmt(self.syntax(), f)
3752 }
3753}
3754impl std::fmt::Display for BinExpr {
3755 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3756 std::fmt::Display::fmt(self.syntax(), f)
3757 }
3758}
3759impl std::fmt::Display for BoxExpr {
3760 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3761 std::fmt::Display::fmt(self.syntax(), f)
3762 }
3763}
3764impl std::fmt::Display for BreakExpr {
3765 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3766 std::fmt::Display::fmt(self.syntax(), f)
3767 }
3768}
3769impl std::fmt::Display for CallExpr {
3770 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3771 std::fmt::Display::fmt(self.syntax(), f)
3772 }
3773}
3774impl std::fmt::Display for CastExpr {
3775 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3776 std::fmt::Display::fmt(self.syntax(), f)
3777 }
3778}
3779impl std::fmt::Display for ClosureExpr {
3780 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3781 std::fmt::Display::fmt(self.syntax(), f)
3782 }
3783}
3784impl std::fmt::Display for ContinueExpr {
3785 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3786 std::fmt::Display::fmt(self.syntax(), f)
3787 }
3788}
3789impl std::fmt::Display for EffectExpr {
3790 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3791 std::fmt::Display::fmt(self.syntax(), f)
3792 }
3793}
3794impl std::fmt::Display for FieldExpr {
3795 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3796 std::fmt::Display::fmt(self.syntax(), f)
3797 }
3798}
3799impl std::fmt::Display for ForExpr {
3800 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3801 std::fmt::Display::fmt(self.syntax(), f)
3802 }
3803}
3804impl std::fmt::Display for IfExpr {
3805 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3806 std::fmt::Display::fmt(self.syntax(), f)
3807 }
3808}
3809impl std::fmt::Display for IndexExpr {
3810 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3811 std::fmt::Display::fmt(self.syntax(), f)
3812 }
3813}
3814impl std::fmt::Display for LoopExpr {
3815 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3816 std::fmt::Display::fmt(self.syntax(), f)
3817 }
3818}
3819impl std::fmt::Display for MatchExpr {
3820 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3821 std::fmt::Display::fmt(self.syntax(), f)
3822 }
3823}
3824impl std::fmt::Display for MethodCallExpr {
3825 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3826 std::fmt::Display::fmt(self.syntax(), f)
3827 }
3828}
3829impl std::fmt::Display for ParenExpr {
3830 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3831 std::fmt::Display::fmt(self.syntax(), f)
3832 }
3833}
3834impl std::fmt::Display for PathExpr {
3835 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3836 std::fmt::Display::fmt(self.syntax(), f)
3837 }
3838}
3839impl std::fmt::Display for PrefixExpr {
3840 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3841 std::fmt::Display::fmt(self.syntax(), f)
3842 }
3843}
3844impl std::fmt::Display for RangeExpr {
3845 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3846 std::fmt::Display::fmt(self.syntax(), f)
3847 }
3848}
3849impl std::fmt::Display for RecordExpr {
3850 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3851 std::fmt::Display::fmt(self.syntax(), f)
3852 }
3853}
3854impl std::fmt::Display for RefExpr {
3855 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3856 std::fmt::Display::fmt(self.syntax(), f)
3857 }
3858}
3859impl std::fmt::Display for ReturnExpr {
3860 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3861 std::fmt::Display::fmt(self.syntax(), f)
3862 }
3863}
3864impl std::fmt::Display for TryExpr {
3865 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3866 std::fmt::Display::fmt(self.syntax(), f)
3867 }
3868}
3869impl std::fmt::Display for TupleExpr {
3870 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3871 std::fmt::Display::fmt(self.syntax(), f)
3872 }
3873}
3874impl std::fmt::Display for WhileExpr {
3875 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3876 std::fmt::Display::fmt(self.syntax(), f)
3877 }
3878}
3879impl std::fmt::Display for Label {
3880 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3881 std::fmt::Display::fmt(self.syntax(), f)
3882 }
3883}
3884impl std::fmt::Display for RecordExprFieldList {
3885 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3886 std::fmt::Display::fmt(self.syntax(), f)
3887 }
3888}
3889impl std::fmt::Display for RecordExprField {
3890 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3891 std::fmt::Display::fmt(self.syntax(), f)
3892 }
3893}
3894impl std::fmt::Display for ArgList {
3895 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3896 std::fmt::Display::fmt(self.syntax(), f)
3897 }
3898}
3899impl std::fmt::Display for Condition {
3900 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3901 std::fmt::Display::fmt(self.syntax(), f)
3902 }
3903}
3904impl std::fmt::Display for MatchArmList {
3905 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3906 std::fmt::Display::fmt(self.syntax(), f)
3907 }
3908}
3909impl std::fmt::Display for MatchArm {
3910 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3911 std::fmt::Display::fmt(self.syntax(), f)
3912 }
3913}
3914impl std::fmt::Display for MatchGuard {
3915 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3916 std::fmt::Display::fmt(self.syntax(), f)
3917 }
3918}
3919impl std::fmt::Display for ArrayType {
3920 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3921 std::fmt::Display::fmt(self.syntax(), f)
3922 }
3923}
3924impl std::fmt::Display for DynTraitType {
3925 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3926 std::fmt::Display::fmt(self.syntax(), f)
3927 }
3928}
3929impl std::fmt::Display for FnPtrType {
3930 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3931 std::fmt::Display::fmt(self.syntax(), f)
3932 }
3933}
3934impl std::fmt::Display for ForType {
3935 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3936 std::fmt::Display::fmt(self.syntax(), f)
3937 }
3938}
3939impl std::fmt::Display for ImplTraitType {
3940 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3941 std::fmt::Display::fmt(self.syntax(), f)
3942 }
3943}
3944impl std::fmt::Display for InferType {
3945 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3946 std::fmt::Display::fmt(self.syntax(), f)
3947 }
3948}
3949impl std::fmt::Display for NeverType {
3950 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3951 std::fmt::Display::fmt(self.syntax(), f)
3952 }
3953}
3954impl std::fmt::Display for ParenType {
3955 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3956 std::fmt::Display::fmt(self.syntax(), f)
3957 }
3958}
3959impl std::fmt::Display for PtrType {
3960 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3961 std::fmt::Display::fmt(self.syntax(), f)
3962 }
3963}
3964impl std::fmt::Display for RefType {
3965 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3966 std::fmt::Display::fmt(self.syntax(), f)
3967 }
3968}
3969impl std::fmt::Display for SliceType {
3970 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3971 std::fmt::Display::fmt(self.syntax(), f)
3972 }
3973}
3974impl std::fmt::Display for TupleType {
3975 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3976 std::fmt::Display::fmt(self.syntax(), f)
3977 }
3978}
3979impl std::fmt::Display for TypeBound {
3980 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3981 std::fmt::Display::fmt(self.syntax(), f)
3982 }
3983}
3984impl std::fmt::Display for IdentPat {
3985 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3986 std::fmt::Display::fmt(self.syntax(), f)
3987 }
3988}
3989impl std::fmt::Display for BoxPat {
3990 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3991 std::fmt::Display::fmt(self.syntax(), f)
3992 }
3993}
3994impl std::fmt::Display for RestPat {
3995 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3996 std::fmt::Display::fmt(self.syntax(), f)
3997 }
3998}
3999impl std::fmt::Display for LiteralPat {
4000 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4001 std::fmt::Display::fmt(self.syntax(), f)
4002 }
4003}
4004impl std::fmt::Display for MacroPat {
4005 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4006 std::fmt::Display::fmt(self.syntax(), f)
4007 }
4008}
4009impl std::fmt::Display for OrPat {
4010 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4011 std::fmt::Display::fmt(self.syntax(), f)
4012 }
4013}
4014impl std::fmt::Display for ParenPat {
4015 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4016 std::fmt::Display::fmt(self.syntax(), f)
4017 }
4018}
4019impl std::fmt::Display for PathPat {
4020 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4021 std::fmt::Display::fmt(self.syntax(), f)
4022 }
4023}
4024impl std::fmt::Display for WildcardPat {
4025 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4026 std::fmt::Display::fmt(self.syntax(), f)
4027 }
4028}
4029impl std::fmt::Display for RangePat {
4030 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4031 std::fmt::Display::fmt(self.syntax(), f)
4032 }
4033}
4034impl std::fmt::Display for RecordPat {
4035 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4036 std::fmt::Display::fmt(self.syntax(), f)
4037 }
4038}
4039impl std::fmt::Display for RefPat {
4040 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4041 std::fmt::Display::fmt(self.syntax(), f)
4042 }
4043}
4044impl std::fmt::Display for SlicePat {
4045 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4046 std::fmt::Display::fmt(self.syntax(), f)
4047 }
4048}
4049impl std::fmt::Display for TuplePat {
4050 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4051 std::fmt::Display::fmt(self.syntax(), f)
4052 }
4053}
4054impl std::fmt::Display for TupleStructPat {
4055 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4056 std::fmt::Display::fmt(self.syntax(), f)
4057 }
4058}
4059impl std::fmt::Display for RecordPatFieldList {
4060 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4061 std::fmt::Display::fmt(self.syntax(), f)
4062 }
4063}
4064impl std::fmt::Display for RecordPatField {
4065 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4066 std::fmt::Display::fmt(self.syntax(), f)
4067 }
4068}
diff --git a/crates/syntax/src/ast/generated/tokens.rs b/crates/syntax/src/ast/generated/tokens.rs
new file mode 100644
index 000000000..abadd0b61
--- /dev/null
+++ b/crates/syntax/src/ast/generated/tokens.rs
@@ -0,0 +1,91 @@
1//! Generated file, do not edit by hand, see `xtask/src/codegen`
2
3use crate::{
4 ast::AstToken,
5 SyntaxKind::{self, *},
6 SyntaxToken,
7};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct Whitespace {
11 pub(crate) syntax: SyntaxToken,
12}
13impl std::fmt::Display for Whitespace {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 std::fmt::Display::fmt(&self.syntax, f)
16 }
17}
18impl AstToken for Whitespace {
19 fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
20 fn cast(syntax: SyntaxToken) -> Option<Self> {
21 if Self::can_cast(syntax.kind()) {
22 Some(Self { syntax })
23 } else {
24 None
25 }
26 }
27 fn syntax(&self) -> &SyntaxToken { &self.syntax }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Hash)]
31pub struct Comment {
32 pub(crate) syntax: SyntaxToken,
33}
34impl std::fmt::Display for Comment {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 std::fmt::Display::fmt(&self.syntax, f)
37 }
38}
39impl AstToken for Comment {
40 fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
41 fn cast(syntax: SyntaxToken) -> Option<Self> {
42 if Self::can_cast(syntax.kind()) {
43 Some(Self { syntax })
44 } else {
45 None
46 }
47 }
48 fn syntax(&self) -> &SyntaxToken { &self.syntax }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash)]
52pub struct String {
53 pub(crate) syntax: SyntaxToken,
54}
55impl std::fmt::Display for String {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 std::fmt::Display::fmt(&self.syntax, f)
58 }
59}
60impl AstToken for String {
61 fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
62 fn cast(syntax: SyntaxToken) -> Option<Self> {
63 if Self::can_cast(syntax.kind()) {
64 Some(Self { syntax })
65 } else {
66 None
67 }
68 }
69 fn syntax(&self) -> &SyntaxToken { &self.syntax }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Hash)]
73pub struct RawString {
74 pub(crate) syntax: SyntaxToken,
75}
76impl std::fmt::Display for RawString {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 std::fmt::Display::fmt(&self.syntax, f)
79 }
80}
81impl AstToken for RawString {
82 fn can_cast(kind: SyntaxKind) -> bool { kind == RAW_STRING }
83 fn cast(syntax: SyntaxToken) -> Option<Self> {
84 if Self::can_cast(syntax.kind()) {
85 Some(Self { syntax })
86 } else {
87 None
88 }
89 }
90 fn syntax(&self) -> &SyntaxToken { &self.syntax }
91}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
new file mode 100644
index 000000000..d20c085aa
--- /dev/null
+++ b/crates/syntax/src/ast/make.rs
@@ -0,0 +1,402 @@
1//! This module contains free-standing functions for creating AST fragments out
2//! of smaller pieces.
3//!
4//! Note that all functions here intended to be stupid constructors, which just
5//! assemble a finish node from immediate children. If you want to do something
6//! smarter than that, it probably doesn't belong in this module.
7use itertools::Itertools;
8use stdx::format_to;
9
10use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
11
12pub fn name(text: &str) -> ast::Name {
13 ast_from_text(&format!("mod {};", text))
14}
15
16pub fn name_ref(text: &str) -> ast::NameRef {
17 ast_from_text(&format!("fn f() {{ {}; }}", text))
18}
19
20pub fn ty(text: &str) -> ast::Type {
21 ast_from_text(&format!("impl {} for D {{}};", text))
22}
23
24pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment {
25 ast_from_text(&format!("use {};", name_ref))
26}
27pub fn path_segment_self() -> ast::PathSegment {
28 ast_from_text("use self;")
29}
30pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path {
31 path_from_text(&format!("use {}", segment))
32}
33pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path {
34 path_from_text(&format!("{}::{}", qual, segment))
35}
36pub fn path_from_text(text: &str) -> ast::Path {
37 ast_from_text(text)
38}
39
40pub fn use_tree(
41 path: ast::Path,
42 use_tree_list: Option<ast::UseTreeList>,
43 alias: Option<ast::Rename>,
44 add_star: bool,
45) -> ast::UseTree {
46 let mut buf = "use ".to_string();
47 buf += &path.syntax().to_string();
48 if let Some(use_tree_list) = use_tree_list {
49 format_to!(buf, "::{}", use_tree_list);
50 }
51 if add_star {
52 buf += "::*";
53 }
54
55 if let Some(alias) = alias {
56 format_to!(buf, " {}", alias);
57 }
58 ast_from_text(&buf)
59}
60
61pub fn use_tree_list(use_trees: impl IntoIterator<Item = ast::UseTree>) -> ast::UseTreeList {
62 let use_trees = use_trees.into_iter().map(|it| it.syntax().clone()).join(", ");
63 ast_from_text(&format!("use {{{}}};", use_trees))
64}
65
66pub fn use_(use_tree: ast::UseTree) -> ast::Use {
67 ast_from_text(&format!("use {};", use_tree))
68}
69
70pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField {
71 return match expr {
72 Some(expr) => from_text(&format!("{}: {}", name, expr)),
73 None => from_text(&name.to_string()),
74 };
75
76 fn from_text(text: &str) -> ast::RecordExprField {
77 ast_from_text(&format!("fn f() {{ S {{ {}, }} }}", text))
78 }
79}
80
81pub fn record_field(name: ast::NameRef, ty: ast::Type) -> ast::RecordField {
82 ast_from_text(&format!("struct S {{ {}: {}, }}", name, ty))
83}
84
85pub fn block_expr(
86 stmts: impl IntoIterator<Item = ast::Stmt>,
87 tail_expr: Option<ast::Expr>,
88) -> ast::BlockExpr {
89 let mut buf = "{\n".to_string();
90 for stmt in stmts.into_iter() {
91 format_to!(buf, " {}\n", stmt);
92 }
93 if let Some(tail_expr) = tail_expr {
94 format_to!(buf, " {}\n", tail_expr)
95 }
96 buf += "}";
97 ast_from_text(&format!("fn f() {}", buf))
98}
99
100pub fn expr_unit() -> ast::Expr {
101 expr_from_text("()")
102}
103pub fn expr_empty_block() -> ast::Expr {
104 expr_from_text("{}")
105}
106pub fn expr_unimplemented() -> ast::Expr {
107 expr_from_text("unimplemented!()")
108}
109pub fn expr_unreachable() -> ast::Expr {
110 expr_from_text("unreachable!()")
111}
112pub fn expr_todo() -> ast::Expr {
113 expr_from_text("todo!()")
114}
115pub fn expr_path(path: ast::Path) -> ast::Expr {
116 expr_from_text(&path.to_string())
117}
118pub fn expr_continue() -> ast::Expr {
119 expr_from_text("continue")
120}
121pub fn expr_break() -> ast::Expr {
122 expr_from_text("break")
123}
124pub fn expr_return() -> ast::Expr {
125 expr_from_text("return")
126}
127pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr {
128 expr_from_text(&format!("match {} {}", expr, match_arm_list))
129}
130pub fn expr_if(condition: ast::Condition, then_branch: ast::BlockExpr) -> ast::Expr {
131 expr_from_text(&format!("if {} {}", condition, then_branch))
132}
133pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr {
134 let token = token(op);
135 expr_from_text(&format!("{}{}", token, expr))
136}
137pub fn expr_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr {
138 expr_from_text(&format!("{}{}", f, arg_list))
139}
140fn expr_from_text(text: &str) -> ast::Expr {
141 ast_from_text(&format!("const C: () = {};", text))
142}
143
144pub fn try_expr_from_text(text: &str) -> Option<ast::Expr> {
145 try_ast_from_text(&format!("const C: () = {};", text))
146}
147
148pub fn condition(expr: ast::Expr, pattern: Option<ast::Pat>) -> ast::Condition {
149 match pattern {
150 None => ast_from_text(&format!("const _: () = while {} {{}};", expr)),
151 Some(pattern) => {
152 ast_from_text(&format!("const _: () = while let {} = {} {{}};", pattern, expr))
153 }
154 }
155}
156
157pub fn arg_list(args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList {
158 ast_from_text(&format!("fn main() {{ ()({}) }}", args.into_iter().format(", ")))
159}
160
161pub fn ident_pat(name: ast::Name) -> ast::IdentPat {
162 return from_text(name.text());
163
164 fn from_text(text: &str) -> ast::IdentPat {
165 ast_from_text(&format!("fn f({}: ())", text))
166 }
167}
168
169pub fn wildcard_pat() -> ast::WildcardPat {
170 return from_text("_");
171
172 fn from_text(text: &str) -> ast::WildcardPat {
173 ast_from_text(&format!("fn f({}: ())", text))
174 }
175}
176
177/// Creates a tuple of patterns from an interator of patterns.
178///
179/// Invariant: `pats` must be length > 1
180///
181/// FIXME handle `pats` length == 1
182pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
183 let pats_str = pats.into_iter().map(|p| p.to_string()).join(", ");
184 return from_text(&format!("({})", pats_str));
185
186 fn from_text(text: &str) -> ast::TuplePat {
187 ast_from_text(&format!("fn f({}: ())", text))
188 }
189}
190
191pub fn tuple_struct_pat(
192 path: ast::Path,
193 pats: impl IntoIterator<Item = ast::Pat>,
194) -> ast::TupleStructPat {
195 let pats_str = pats.into_iter().join(", ");
196 return from_text(&format!("{}({})", path, pats_str));
197
198 fn from_text(text: &str) -> ast::TupleStructPat {
199 ast_from_text(&format!("fn f({}: ())", text))
200 }
201}
202
203pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) -> ast::RecordPat {
204 let pats_str = pats.into_iter().join(", ");
205 return from_text(&format!("{} {{ {} }}", path, pats_str));
206
207 fn from_text(text: &str) -> ast::RecordPat {
208 ast_from_text(&format!("fn f({}: ())", text))
209 }
210}
211
212/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise.
213pub fn path_pat(path: ast::Path) -> ast::Pat {
214 return from_text(&path.to_string());
215 fn from_text(text: &str) -> ast::Pat {
216 ast_from_text(&format!("fn f({}: ())", text))
217 }
218}
219
220pub fn match_arm(pats: impl IntoIterator<Item = ast::Pat>, expr: ast::Expr) -> ast::MatchArm {
221 let pats_str = pats.into_iter().join(" | ");
222 return from_text(&format!("{} => {}", pats_str, expr));
223
224 fn from_text(text: &str) -> ast::MatchArm {
225 ast_from_text(&format!("fn f() {{ match () {{{}}} }}", text))
226 }
227}
228
229pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
230 let arms_str = arms
231 .into_iter()
232 .map(|arm| {
233 let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like());
234 let comma = if needs_comma { "," } else { "" };
235 format!(" {}{}\n", arm.syntax(), comma)
236 })
237 .collect::<String>();
238 return from_text(&arms_str);
239
240 fn from_text(text: &str) -> ast::MatchArmList {
241 ast_from_text(&format!("fn f() {{ match () {{\n{}}} }}", text))
242 }
243}
244
245pub fn where_pred(
246 path: ast::Path,
247 bounds: impl IntoIterator<Item = ast::TypeBound>,
248) -> ast::WherePred {
249 let bounds = bounds.into_iter().join(" + ");
250 return from_text(&format!("{}: {}", path, bounds));
251
252 fn from_text(text: &str) -> ast::WherePred {
253 ast_from_text(&format!("fn f() where {} {{ }}", text))
254 }
255}
256
257pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::WhereClause {
258 let preds = preds.into_iter().join(", ");
259 return from_text(preds.as_str());
260
261 fn from_text(text: &str) -> ast::WhereClause {
262 ast_from_text(&format!("fn f() where {} {{ }}", text))
263 }
264}
265
266pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt {
267 let text = match initializer {
268 Some(it) => format!("let {} = {};", pattern, it),
269 None => format!("let {};", pattern),
270 };
271 ast_from_text(&format!("fn f() {{ {} }}", text))
272}
273pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt {
274 let semi = if expr.is_block_like() { "" } else { ";" };
275 ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi))
276}
277
278pub fn token(kind: SyntaxKind) -> SyntaxToken {
279 tokens::SOURCE_FILE
280 .tree()
281 .syntax()
282 .descendants_with_tokens()
283 .filter_map(|it| it.into_token())
284 .find(|it| it.kind() == kind)
285 .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
286}
287
288pub fn param(name: String, ty: String) -> ast::Param {
289 ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty))
290}
291
292pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList {
293 let args = pats.into_iter().join(", ");
294 ast_from_text(&format!("fn f({}) {{ }}", args))
295}
296
297pub fn visibility_pub_crate() -> ast::Visibility {
298 ast_from_text("pub(crate) struct S")
299}
300
301pub fn fn_(
302 visibility: Option<ast::Visibility>,
303 fn_name: ast::Name,
304 type_params: Option<ast::GenericParamList>,
305 params: ast::ParamList,
306 body: ast::BlockExpr,
307) -> ast::Fn {
308 let type_params =
309 if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() };
310 let visibility = match visibility {
311 None => String::new(),
312 Some(it) => format!("{} ", it),
313 };
314 ast_from_text(&format!("{}fn {}{}{} {}", visibility, fn_name, type_params, params, body))
315}
316
317fn ast_from_text<N: AstNode>(text: &str) -> N {
318 let parse = SourceFile::parse(text);
319 let node = match parse.tree().syntax().descendants().find_map(N::cast) {
320 Some(it) => it,
321 None => {
322 panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text)
323 }
324 };
325 let node = node.syntax().clone();
326 let node = unroot(node);
327 let node = N::cast(node).unwrap();
328 assert_eq!(node.syntax().text_range().start(), 0.into());
329 node
330}
331
332fn try_ast_from_text<N: AstNode>(text: &str) -> Option<N> {
333 let parse = SourceFile::parse(text);
334 let node = parse.tree().syntax().descendants().find_map(N::cast)?;
335 let node = node.syntax().clone();
336 let node = unroot(node);
337 let node = N::cast(node).unwrap();
338 assert_eq!(node.syntax().text_range().start(), 0.into());
339 Some(node)
340}
341
342fn unroot(n: SyntaxNode) -> SyntaxNode {
343 SyntaxNode::new_root(n.green().clone())
344}
345
346pub mod tokens {
347 use once_cell::sync::Lazy;
348
349 use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken};
350
351 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> =
352 Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true)\n;"));
353
354 pub fn single_space() -> SyntaxToken {
355 SOURCE_FILE
356 .tree()
357 .syntax()
358 .descendants_with_tokens()
359 .filter_map(|it| it.into_token())
360 .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ")
361 .unwrap()
362 }
363
364 pub fn whitespace(text: &str) -> SyntaxToken {
365 assert!(text.trim().is_empty());
366 let sf = SourceFile::parse(text).ok().unwrap();
367 sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
368 }
369
370 pub fn doc_comment(text: &str) -> SyntaxToken {
371 assert!(!text.trim().is_empty());
372 let sf = SourceFile::parse(text).ok().unwrap();
373 sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
374 }
375
376 pub fn literal(text: &str) -> SyntaxToken {
377 assert_eq!(text.trim(), text);
378 let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {}; }}", text));
379 lit.syntax().first_child_or_token().unwrap().into_token().unwrap()
380 }
381
382 pub fn single_newline() -> SyntaxToken {
383 SOURCE_FILE
384 .tree()
385 .syntax()
386 .descendants_with_tokens()
387 .filter_map(|it| it.into_token())
388 .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n")
389 .unwrap()
390 }
391
392 pub struct WsBuilder(SourceFile);
393
394 impl WsBuilder {
395 pub fn new(text: &str) -> WsBuilder {
396 WsBuilder(SourceFile::parse(text).ok().unwrap())
397 }
398 pub fn ws(&self) -> SyntaxToken {
399 self.0.syntax().first_child_or_token().unwrap().into_token().unwrap()
400 }
401 }
402}
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
new file mode 100644
index 000000000..50c1c157d
--- /dev/null
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -0,0 +1,485 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3
4use std::fmt;
5
6use itertools::Itertools;
7use parser::SyntaxKind;
8
9use crate::{
10 ast::{self, support, AstNode, NameOwner, SyntaxNode},
11 SmolStr, SyntaxElement, SyntaxToken, T,
12};
13
14impl ast::Name {
15 pub fn text(&self) -> &SmolStr {
16 text_of_first_token(self.syntax())
17 }
18}
19
20impl ast::NameRef {
21 pub fn text(&self) -> &SmolStr {
22 text_of_first_token(self.syntax())
23 }
24
25 pub fn as_tuple_field(&self) -> Option<usize> {
26 self.text().parse().ok()
27 }
28}
29
30fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
31 node.green().children().next().and_then(|it| it.into_token()).unwrap().text()
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub enum AttrKind {
36 Inner,
37 Outer,
38}
39
40impl ast::Attr {
41 pub fn as_simple_atom(&self) -> Option<SmolStr> {
42 if self.eq_token().is_some() || self.token_tree().is_some() {
43 return None;
44 }
45 self.simple_name()
46 }
47
48 pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
49 let tt = self.token_tree()?;
50 Some((self.simple_name()?, tt))
51 }
52
53 pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
54 let lit = self.literal()?;
55 let key = self.simple_name()?;
56 // FIXME: escape? raw string?
57 let value = lit.syntax().first_token()?.text().trim_matches('"').into();
58 Some((key, value))
59 }
60
61 pub fn simple_name(&self) -> Option<SmolStr> {
62 let path = self.path()?;
63 match (path.segment(), path.qualifier()) {
64 (Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()),
65 _ => None,
66 }
67 }
68
69 pub fn kind(&self) -> AttrKind {
70 let first_token = self.syntax().first_token();
71 let first_token_kind = first_token.as_ref().map(SyntaxToken::kind);
72 let second_token_kind =
73 first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind);
74
75 match (first_token_kind, second_token_kind) {
76 (Some(SyntaxKind::POUND), Some(T![!])) => AttrKind::Inner,
77 _ => AttrKind::Outer,
78 }
79 }
80}
81
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub enum PathSegmentKind {
84 Name(ast::NameRef),
85 Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
86 SelfKw,
87 SuperKw,
88 CrateKw,
89}
90
91impl ast::PathSegment {
92 pub fn parent_path(&self) -> ast::Path {
93 self.syntax()
94 .parent()
95 .and_then(ast::Path::cast)
96 .expect("segments are always nested in paths")
97 }
98
99 pub fn kind(&self) -> Option<PathSegmentKind> {
100 let res = if let Some(name_ref) = self.name_ref() {
101 PathSegmentKind::Name(name_ref)
102 } else {
103 match self.syntax().first_child_or_token()?.kind() {
104 T![self] => PathSegmentKind::SelfKw,
105 T![super] => PathSegmentKind::SuperKw,
106 T![crate] => PathSegmentKind::CrateKw,
107 T![<] => {
108 // <T> or <T as Trait>
109 // T is any TypeRef, Trait has to be a PathType
110 let mut type_refs =
111 self.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
112 let type_ref = type_refs.next().and_then(ast::Type::cast);
113 let trait_ref = type_refs.next().and_then(ast::PathType::cast);
114 PathSegmentKind::Type { type_ref, trait_ref }
115 }
116 _ => return None,
117 }
118 };
119 Some(res)
120 }
121}
122
123impl ast::Path {
124 pub fn parent_path(&self) -> Option<ast::Path> {
125 self.syntax().parent().and_then(ast::Path::cast)
126 }
127}
128
129impl ast::UseTreeList {
130 pub fn parent_use_tree(&self) -> ast::UseTree {
131 self.syntax()
132 .parent()
133 .and_then(ast::UseTree::cast)
134 .expect("UseTreeLists are always nested in UseTrees")
135 }
136}
137
138impl ast::Impl {
139 pub fn self_ty(&self) -> Option<ast::Type> {
140 match self.target() {
141 (Some(t), None) | (_, Some(t)) => Some(t),
142 _ => None,
143 }
144 }
145
146 pub fn trait_(&self) -> Option<ast::Type> {
147 match self.target() {
148 (Some(t), Some(_)) => Some(t),
149 _ => None,
150 }
151 }
152
153 fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) {
154 let mut types = support::children(self.syntax());
155 let first = types.next();
156 let second = types.next();
157 (first, second)
158 }
159}
160
161#[derive(Debug, Clone, PartialEq, Eq)]
162pub enum StructKind {
163 Record(ast::RecordFieldList),
164 Tuple(ast::TupleFieldList),
165 Unit,
166}
167
168impl StructKind {
169 fn from_node<N: AstNode>(node: &N) -> StructKind {
170 if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) {
171 StructKind::Record(nfdl)
172 } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) {
173 StructKind::Tuple(pfl)
174 } else {
175 StructKind::Unit
176 }
177 }
178}
179
180impl ast::Struct {
181 pub fn kind(&self) -> StructKind {
182 StructKind::from_node(self)
183 }
184}
185
186impl ast::RecordExprField {
187 pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
188 let candidate =
189 field_name.syntax().parent().and_then(ast::RecordExprField::cast).or_else(|| {
190 field_name.syntax().ancestors().nth(4).and_then(ast::RecordExprField::cast)
191 })?;
192 if candidate.field_name().as_ref() == Some(field_name) {
193 Some(candidate)
194 } else {
195 None
196 }
197 }
198
199 /// Deals with field init shorthand
200 pub fn field_name(&self) -> Option<ast::NameRef> {
201 if let Some(name_ref) = self.name_ref() {
202 return Some(name_ref);
203 }
204 if let Some(ast::Expr::PathExpr(expr)) = self.expr() {
205 let path = expr.path()?;
206 let segment = path.segment()?;
207 let name_ref = segment.name_ref()?;
208 if path.qualifier().is_none() {
209 return Some(name_ref);
210 }
211 }
212 None
213 }
214}
215
216pub enum NameOrNameRef {
217 Name(ast::Name),
218 NameRef(ast::NameRef),
219}
220
221impl fmt::Display for NameOrNameRef {
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 match self {
224 NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
225 NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
226 }
227 }
228}
229
230impl ast::RecordPatField {
231 /// Deals with field init shorthand
232 pub fn field_name(&self) -> Option<NameOrNameRef> {
233 if let Some(name_ref) = self.name_ref() {
234 return Some(NameOrNameRef::NameRef(name_ref));
235 }
236 if let Some(ast::Pat::IdentPat(pat)) = self.pat() {
237 let name = pat.name()?;
238 return Some(NameOrNameRef::Name(name));
239 }
240 None
241 }
242}
243
244impl ast::Variant {
245 pub fn parent_enum(&self) -> ast::Enum {
246 self.syntax()
247 .parent()
248 .and_then(|it| it.parent())
249 .and_then(ast::Enum::cast)
250 .expect("EnumVariants are always nested in Enums")
251 }
252 pub fn kind(&self) -> StructKind {
253 StructKind::from_node(self)
254 }
255}
256
257#[derive(Debug, Clone, PartialEq, Eq)]
258pub enum FieldKind {
259 Name(ast::NameRef),
260 Index(SyntaxToken),
261}
262
263impl ast::FieldExpr {
264 pub fn index_token(&self) -> Option<SyntaxToken> {
265 self.syntax
266 .children_with_tokens()
267 // FIXME: Accepting floats here to reject them in validation later
268 .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
269 .as_ref()
270 .and_then(SyntaxElement::as_token)
271 .cloned()
272 }
273
274 pub fn field_access(&self) -> Option<FieldKind> {
275 if let Some(nr) = self.name_ref() {
276 Some(FieldKind::Name(nr))
277 } else if let Some(tok) = self.index_token() {
278 Some(FieldKind::Index(tok))
279 } else {
280 None
281 }
282 }
283}
284
285pub struct SlicePatComponents {
286 pub prefix: Vec<ast::Pat>,
287 pub slice: Option<ast::Pat>,
288 pub suffix: Vec<ast::Pat>,
289}
290
291impl ast::SlicePat {
292 pub fn components(&self) -> SlicePatComponents {
293 let mut args = self.pats().peekable();
294 let prefix = args
295 .peeking_take_while(|p| match p {
296 ast::Pat::RestPat(_) => false,
297 ast::Pat::IdentPat(bp) => match bp.pat() {
298 Some(ast::Pat::RestPat(_)) => false,
299 _ => true,
300 },
301 ast::Pat::RefPat(rp) => match rp.pat() {
302 Some(ast::Pat::RestPat(_)) => false,
303 Some(ast::Pat::IdentPat(bp)) => match bp.pat() {
304 Some(ast::Pat::RestPat(_)) => false,
305 _ => true,
306 },
307 _ => true,
308 },
309 _ => true,
310 })
311 .collect();
312 let slice = args.next();
313 let suffix = args.collect();
314
315 SlicePatComponents { prefix, slice, suffix }
316 }
317}
318
319#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
320pub enum SelfParamKind {
321 /// self
322 Owned,
323 /// &self
324 Ref,
325 /// &mut self
326 MutRef,
327}
328
329impl ast::SelfParam {
330 pub fn kind(&self) -> SelfParamKind {
331 if self.amp_token().is_some() {
332 if self.mut_token().is_some() {
333 SelfParamKind::MutRef
334 } else {
335 SelfParamKind::Ref
336 }
337 } else {
338 SelfParamKind::Owned
339 }
340 }
341}
342
343#[derive(Clone, Debug, PartialEq, Eq, Hash)]
344pub enum TypeBoundKind {
345 /// Trait
346 PathType(ast::PathType),
347 /// for<'a> ...
348 ForType(ast::ForType),
349 /// 'a
350 Lifetime(SyntaxToken),
351}
352
353impl ast::TypeBound {
354 pub fn kind(&self) -> TypeBoundKind {
355 if let Some(path_type) = support::children(self.syntax()).next() {
356 TypeBoundKind::PathType(path_type)
357 } else if let Some(for_type) = support::children(self.syntax()).next() {
358 TypeBoundKind::ForType(for_type)
359 } else if let Some(lifetime) = self.lifetime_token() {
360 TypeBoundKind::Lifetime(lifetime)
361 } else {
362 unreachable!()
363 }
364 }
365}
366
367pub enum VisibilityKind {
368 In(ast::Path),
369 PubCrate,
370 PubSuper,
371 PubSelf,
372 Pub,
373}
374
375impl ast::Visibility {
376 pub fn kind(&self) -> VisibilityKind {
377 if let Some(path) = support::children(self.syntax()).next() {
378 VisibilityKind::In(path)
379 } else if self.crate_token().is_some() {
380 VisibilityKind::PubCrate
381 } else if self.super_token().is_some() {
382 VisibilityKind::PubSuper
383 } else if self.self_token().is_some() {
384 VisibilityKind::PubSelf
385 } else {
386 VisibilityKind::Pub
387 }
388 }
389}
390
391impl ast::MacroCall {
392 pub fn is_macro_rules(&self) -> Option<ast::Name> {
393 let name_ref = self.path()?.segment()?.name_ref()?;
394 if name_ref.text() == "macro_rules" {
395 self.name()
396 } else {
397 None
398 }
399 }
400
401 pub fn is_bang(&self) -> bool {
402 self.is_macro_rules().is_none()
403 }
404}
405
406impl ast::LifetimeParam {
407 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
408 self.syntax()
409 .children_with_tokens()
410 .filter_map(|it| it.into_token())
411 .skip_while(|x| x.kind() != T![:])
412 .filter(|it| it.kind() == T![lifetime])
413 }
414}
415
416impl ast::RangePat {
417 pub fn start(&self) -> Option<ast::Pat> {
418 self.syntax()
419 .children_with_tokens()
420 .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
421 .filter_map(|it| it.into_node())
422 .find_map(ast::Pat::cast)
423 }
424
425 pub fn end(&self) -> Option<ast::Pat> {
426 self.syntax()
427 .children_with_tokens()
428 .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
429 .filter_map(|it| it.into_node())
430 .find_map(ast::Pat::cast)
431 }
432}
433
434impl ast::TokenTree {
435 pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
436 self.syntax()
437 .first_child_or_token()?
438 .into_token()
439 .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['[']))
440 }
441
442 pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
443 self.syntax()
444 .last_child_or_token()?
445 .into_token()
446 .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']']))
447 }
448}
449
450impl ast::GenericParamList {
451 pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> {
452 self.generic_params().filter_map(|param| match param {
453 ast::GenericParam::LifetimeParam(it) => Some(it),
454 ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
455 })
456 }
457 pub fn type_params(&self) -> impl Iterator<Item = ast::TypeParam> {
458 self.generic_params().filter_map(|param| match param {
459 ast::GenericParam::TypeParam(it) => Some(it),
460 ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None,
461 })
462 }
463 pub fn const_params(&self) -> impl Iterator<Item = ast::ConstParam> {
464 self.generic_params().filter_map(|param| match param {
465 ast::GenericParam::ConstParam(it) => Some(it),
466 ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None,
467 })
468 }
469}
470
471impl ast::DocCommentsOwner for ast::SourceFile {}
472impl ast::DocCommentsOwner for ast::Fn {}
473impl ast::DocCommentsOwner for ast::Struct {}
474impl ast::DocCommentsOwner for ast::Union {}
475impl ast::DocCommentsOwner for ast::RecordField {}
476impl ast::DocCommentsOwner for ast::TupleField {}
477impl ast::DocCommentsOwner for ast::Enum {}
478impl ast::DocCommentsOwner for ast::Variant {}
479impl ast::DocCommentsOwner for ast::Trait {}
480impl ast::DocCommentsOwner for ast::Module {}
481impl ast::DocCommentsOwner for ast::Static {}
482impl ast::DocCommentsOwner for ast::Const {}
483impl ast::DocCommentsOwner for ast::TypeAlias {}
484impl ast::DocCommentsOwner for ast::Impl {}
485impl ast::DocCommentsOwner for ast::MacroCall {}
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
new file mode 100644
index 000000000..c5ef92733
--- /dev/null
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -0,0 +1,538 @@
1//! There are many AstNodes, but only a few tokens, so we hand-write them here.
2
3use std::{
4 borrow::Cow,
5 convert::{TryFrom, TryInto},
6};
7
8use rustc_lexer::unescape::{unescape_literal, Mode};
9
10use crate::{
11 ast::{AstToken, Comment, RawString, String, Whitespace},
12 TextRange, TextSize,
13};
14
15impl Comment {
16 pub fn kind(&self) -> CommentKind {
17 kind_by_prefix(self.text())
18 }
19
20 pub fn prefix(&self) -> &'static str {
21 for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
22 if *k == self.kind() && self.text().starts_with(prefix) {
23 return prefix;
24 }
25 }
26 unreachable!()
27 }
28}
29
30#[derive(Debug, PartialEq, Eq, Clone, Copy)]
31pub struct CommentKind {
32 pub shape: CommentShape,
33 pub doc: Option<CommentPlacement>,
34}
35
36#[derive(Debug, PartialEq, Eq, Clone, Copy)]
37pub enum CommentShape {
38 Line,
39 Block,
40}
41
42impl CommentShape {
43 pub fn is_line(self) -> bool {
44 self == CommentShape::Line
45 }
46
47 pub fn is_block(self) -> bool {
48 self == CommentShape::Block
49 }
50}
51
52#[derive(Debug, PartialEq, Eq, Clone, Copy)]
53pub enum CommentPlacement {
54 Inner,
55 Outer,
56}
57
58const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = {
59 use {CommentPlacement::*, CommentShape::*};
60 &[
61 ("////", CommentKind { shape: Line, doc: None }),
62 ("///", CommentKind { shape: Line, doc: Some(Outer) }),
63 ("//!", CommentKind { shape: Line, doc: Some(Inner) }),
64 ("/**", CommentKind { shape: Block, doc: Some(Outer) }),
65 ("/*!", CommentKind { shape: Block, doc: Some(Inner) }),
66 ("//", CommentKind { shape: Line, doc: None }),
67 ("/*", CommentKind { shape: Block, doc: None }),
68 ]
69};
70
71fn kind_by_prefix(text: &str) -> CommentKind {
72 if text == "/**/" {
73 return CommentKind { shape: CommentShape::Block, doc: None };
74 }
75 for (prefix, kind) in COMMENT_PREFIX_TO_KIND.iter() {
76 if text.starts_with(prefix) {
77 return *kind;
78 }
79 }
80 panic!("bad comment text: {:?}", text)
81}
82
83impl Whitespace {
84 pub fn spans_multiple_lines(&self) -> bool {
85 let text = self.text();
86 text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
87 }
88}
89
90pub struct QuoteOffsets {
91 pub quotes: (TextRange, TextRange),
92 pub contents: TextRange,
93}
94
95impl QuoteOffsets {
96 fn new(literal: &str) -> Option<QuoteOffsets> {
97 let left_quote = literal.find('"')?;
98 let right_quote = literal.rfind('"')?;
99 if left_quote == right_quote {
100 // `literal` only contains one quote
101 return None;
102 }
103
104 let start = TextSize::from(0);
105 let left_quote = TextSize::try_from(left_quote).unwrap() + TextSize::of('"');
106 let right_quote = TextSize::try_from(right_quote).unwrap();
107 let end = TextSize::of(literal);
108
109 let res = QuoteOffsets {
110 quotes: (TextRange::new(start, left_quote), TextRange::new(right_quote, end)),
111 contents: TextRange::new(left_quote, right_quote),
112 };
113 Some(res)
114 }
115}
116
117pub trait HasQuotes: AstToken {
118 fn quote_offsets(&self) -> Option<QuoteOffsets> {
119 let text = self.text().as_str();
120 let offsets = QuoteOffsets::new(text)?;
121 let o = self.syntax().text_range().start();
122 let offsets = QuoteOffsets {
123 quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o),
124 contents: offsets.contents + o,
125 };
126 Some(offsets)
127 }
128 fn open_quote_text_range(&self) -> Option<TextRange> {
129 self.quote_offsets().map(|it| it.quotes.0)
130 }
131
132 fn close_quote_text_range(&self) -> Option<TextRange> {
133 self.quote_offsets().map(|it| it.quotes.1)
134 }
135
136 fn text_range_between_quotes(&self) -> Option<TextRange> {
137 self.quote_offsets().map(|it| it.contents)
138 }
139}
140
141impl HasQuotes for String {}
142impl HasQuotes for RawString {}
143
144pub trait HasStringValue: HasQuotes {
145 fn value(&self) -> Option<Cow<'_, str>>;
146}
147
148impl HasStringValue for String {
149 fn value(&self) -> Option<Cow<'_, str>> {
150 let text = self.text().as_str();
151 let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
152
153 let mut buf = std::string::String::with_capacity(text.len());
154 let mut has_error = false;
155 unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char {
156 Ok(c) => buf.push(c),
157 Err(_) => has_error = true,
158 });
159
160 if has_error {
161 return None;
162 }
163 // FIXME: don't actually allocate for borrowed case
164 let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) };
165 Some(res)
166 }
167}
168
169impl HasStringValue for RawString {
170 fn value(&self) -> Option<Cow<'_, str>> {
171 let text = self.text().as_str();
172 let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
173 Some(Cow::Borrowed(text))
174 }
175}
176
177impl RawString {
178 pub fn map_range_up(&self, range: TextRange) -> Option<TextRange> {
179 let contents_range = self.text_range_between_quotes()?;
180 assert!(TextRange::up_to(contents_range.len()).contains_range(range));
181 Some(range + contents_range.start())
182 }
183}
184
185#[derive(Debug)]
186pub enum FormatSpecifier {
187 Open,
188 Close,
189 Integer,
190 Identifier,
191 Colon,
192 Fill,
193 Align,
194 Sign,
195 NumberSign,
196 Zero,
197 DollarSign,
198 Dot,
199 Asterisk,
200 QuestionMark,
201}
202
203pub trait HasFormatSpecifier: AstToken {
204 fn char_ranges(
205 &self,
206 ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>>;
207
208 fn lex_format_specifier<F>(&self, mut callback: F)
209 where
210 F: FnMut(TextRange, FormatSpecifier),
211 {
212 let char_ranges = if let Some(char_ranges) = self.char_ranges() {
213 char_ranges
214 } else {
215 return;
216 };
217 let mut chars = char_ranges.iter().peekable();
218
219 while let Some((range, first_char)) = chars.next() {
220 match first_char {
221 Ok('{') => {
222 // Format specifier, see syntax at https://doc.rust-lang.org/std/fmt/index.html#syntax
223 if let Some((_, Ok('{'))) = chars.peek() {
224 // Escaped format specifier, `{{`
225 chars.next();
226 continue;
227 }
228
229 callback(*range, FormatSpecifier::Open);
230
231 // check for integer/identifier
232 match chars
233 .peek()
234 .and_then(|next| next.1.as_ref().ok())
235 .copied()
236 .unwrap_or_default()
237 {
238 '0'..='9' => {
239 // integer
240 read_integer(&mut chars, &mut callback);
241 }
242 c if c == '_' || c.is_alphabetic() => {
243 // identifier
244 read_identifier(&mut chars, &mut callback);
245 }
246 _ => {}
247 }
248
249 if let Some((_, Ok(':'))) = chars.peek() {
250 skip_char_and_emit(&mut chars, FormatSpecifier::Colon, &mut callback);
251
252 // check for fill/align
253 let mut cloned = chars.clone().take(2);
254 let first = cloned
255 .next()
256 .and_then(|next| next.1.as_ref().ok())
257 .copied()
258 .unwrap_or_default();
259 let second = cloned
260 .next()
261 .and_then(|next| next.1.as_ref().ok())
262 .copied()
263 .unwrap_or_default();
264 match second {
265 '<' | '^' | '>' => {
266 // alignment specifier, first char specifies fillment
267 skip_char_and_emit(
268 &mut chars,
269 FormatSpecifier::Fill,
270 &mut callback,
271 );
272 skip_char_and_emit(
273 &mut chars,
274 FormatSpecifier::Align,
275 &mut callback,
276 );
277 }
278 _ => match first {
279 '<' | '^' | '>' => {
280 skip_char_and_emit(
281 &mut chars,
282 FormatSpecifier::Align,
283 &mut callback,
284 );
285 }
286 _ => {}
287 },
288 }
289
290 // check for sign
291 match chars
292 .peek()
293 .and_then(|next| next.1.as_ref().ok())
294 .copied()
295 .unwrap_or_default()
296 {
297 '+' | '-' => {
298 skip_char_and_emit(
299 &mut chars,
300 FormatSpecifier::Sign,
301 &mut callback,
302 );
303 }
304 _ => {}
305 }
306
307 // check for `#`
308 if let Some((_, Ok('#'))) = chars.peek() {
309 skip_char_and_emit(
310 &mut chars,
311 FormatSpecifier::NumberSign,
312 &mut callback,
313 );
314 }
315
316 // check for `0`
317 let mut cloned = chars.clone().take(2);
318 let first = cloned.next().and_then(|next| next.1.as_ref().ok()).copied();
319 let second = cloned.next().and_then(|next| next.1.as_ref().ok()).copied();
320
321 if first == Some('0') && second != Some('$') {
322 skip_char_and_emit(&mut chars, FormatSpecifier::Zero, &mut callback);
323 }
324
325 // width
326 match chars
327 .peek()
328 .and_then(|next| next.1.as_ref().ok())
329 .copied()
330 .unwrap_or_default()
331 {
332 '0'..='9' => {
333 read_integer(&mut chars, &mut callback);
334 if let Some((_, Ok('$'))) = chars.peek() {
335 skip_char_and_emit(
336 &mut chars,
337 FormatSpecifier::DollarSign,
338 &mut callback,
339 );
340 }
341 }
342 c if c == '_' || c.is_alphabetic() => {
343 read_identifier(&mut chars, &mut callback);
344 // can be either width (indicated by dollar sign, or type in which case
345 // the next sign has to be `}`)
346 let next =
347 chars.peek().and_then(|next| next.1.as_ref().ok()).copied();
348 match next {
349 Some('$') => skip_char_and_emit(
350 &mut chars,
351 FormatSpecifier::DollarSign,
352 &mut callback,
353 ),
354 Some('}') => {
355 skip_char_and_emit(
356 &mut chars,
357 FormatSpecifier::Close,
358 &mut callback,
359 );
360 continue;
361 }
362 _ => continue,
363 };
364 }
365 _ => {}
366 }
367
368 // precision
369 if let Some((_, Ok('.'))) = chars.peek() {
370 skip_char_and_emit(&mut chars, FormatSpecifier::Dot, &mut callback);
371
372 match chars
373 .peek()
374 .and_then(|next| next.1.as_ref().ok())
375 .copied()
376 .unwrap_or_default()
377 {
378 '*' => {
379 skip_char_and_emit(
380 &mut chars,
381 FormatSpecifier::Asterisk,
382 &mut callback,
383 );
384 }
385 '0'..='9' => {
386 read_integer(&mut chars, &mut callback);
387 if let Some((_, Ok('$'))) = chars.peek() {
388 skip_char_and_emit(
389 &mut chars,
390 FormatSpecifier::DollarSign,
391 &mut callback,
392 );
393 }
394 }
395 c if c == '_' || c.is_alphabetic() => {
396 read_identifier(&mut chars, &mut callback);
397 if chars.peek().and_then(|next| next.1.as_ref().ok()).copied()
398 != Some('$')
399 {
400 continue;
401 }
402 skip_char_and_emit(
403 &mut chars,
404 FormatSpecifier::DollarSign,
405 &mut callback,
406 );
407 }
408 _ => {
409 continue;
410 }
411 }
412 }
413
414 // type
415 match chars
416 .peek()
417 .and_then(|next| next.1.as_ref().ok())
418 .copied()
419 .unwrap_or_default()
420 {
421 '?' => {
422 skip_char_and_emit(
423 &mut chars,
424 FormatSpecifier::QuestionMark,
425 &mut callback,
426 );
427 }
428 c if c == '_' || c.is_alphabetic() => {
429 read_identifier(&mut chars, &mut callback);
430 }
431 _ => {}
432 }
433 }
434
435 if let Some((_, Ok('}'))) = chars.peek() {
436 skip_char_and_emit(&mut chars, FormatSpecifier::Close, &mut callback);
437 } else {
438 continue;
439 }
440 }
441 _ => {
442 while let Some((_, Ok(next_char))) = chars.peek() {
443 match next_char {
444 '{' => break,
445 _ => {}
446 }
447 chars.next();
448 }
449 }
450 };
451 }
452
453 fn skip_char_and_emit<'a, I, F>(
454 chars: &mut std::iter::Peekable<I>,
455 emit: FormatSpecifier,
456 callback: &mut F,
457 ) where
458 I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
459 F: FnMut(TextRange, FormatSpecifier),
460 {
461 let (range, _) = chars.next().unwrap();
462 callback(*range, emit);
463 }
464
465 fn read_integer<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
466 where
467 I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
468 F: FnMut(TextRange, FormatSpecifier),
469 {
470 let (mut range, c) = chars.next().unwrap();
471 assert!(c.as_ref().unwrap().is_ascii_digit());
472 while let Some((r, Ok(next_char))) = chars.peek() {
473 if next_char.is_ascii_digit() {
474 chars.next();
475 range = range.cover(*r);
476 } else {
477 break;
478 }
479 }
480 callback(range, FormatSpecifier::Integer);
481 }
482
483 fn read_identifier<'a, I, F>(chars: &mut std::iter::Peekable<I>, callback: &mut F)
484 where
485 I: Iterator<Item = &'a (TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>,
486 F: FnMut(TextRange, FormatSpecifier),
487 {
488 let (mut range, c) = chars.next().unwrap();
489 assert!(c.as_ref().unwrap().is_alphabetic() || *c.as_ref().unwrap() == '_');
490 while let Some((r, Ok(next_char))) = chars.peek() {
491 if *next_char == '_' || next_char.is_ascii_digit() || next_char.is_alphabetic() {
492 chars.next();
493 range = range.cover(*r);
494 } else {
495 break;
496 }
497 }
498 callback(range, FormatSpecifier::Identifier);
499 }
500 }
501}
502
503impl HasFormatSpecifier for String {
504 fn char_ranges(
505 &self,
506 ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> {
507 let text = self.text().as_str();
508 let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
509 let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start();
510
511 let mut res = Vec::with_capacity(text.len());
512 unescape_literal(text, Mode::Str, &mut |range, unescaped_char| {
513 res.push((
514 TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap())
515 + offset,
516 unescaped_char,
517 ))
518 });
519
520 Some(res)
521 }
522}
523
524impl HasFormatSpecifier for RawString {
525 fn char_ranges(
526 &self,
527 ) -> Option<Vec<(TextRange, Result<char, rustc_lexer::unescape::EscapeError>)>> {
528 let text = self.text().as_str();
529 let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
530 let offset = self.text_range_between_quotes()?.start() - self.syntax().text_range().start();
531
532 let mut res = Vec::with_capacity(text.len());
533 for (idx, c) in text.char_indices() {
534 res.push((TextRange::at(idx.try_into().unwrap(), TextSize::of(c)) + offset, Ok(c)));
535 }
536 Some(res)
537 }
538}
diff --git a/crates/syntax/src/ast/traits.rs b/crates/syntax/src/ast/traits.rs
new file mode 100644
index 000000000..0bdc22d95
--- /dev/null
+++ b/crates/syntax/src/ast/traits.rs
@@ -0,0 +1,141 @@
1//! Various traits that are implemented by ast nodes.
2//!
3//! The implementations are usually trivial, and live in generated.rs
4use itertools::Itertools;
5
6use crate::{
7 ast::{self, support, AstChildren, AstNode, AstToken},
8 syntax_node::SyntaxElementChildren,
9 SyntaxToken, T,
10};
11
12pub trait NameOwner: AstNode {
13 fn name(&self) -> Option<ast::Name> {
14 support::child(self.syntax())
15 }
16}
17
18pub trait VisibilityOwner: AstNode {
19 fn visibility(&self) -> Option<ast::Visibility> {
20 support::child(self.syntax())
21 }
22}
23
24pub trait LoopBodyOwner: AstNode {
25 fn loop_body(&self) -> Option<ast::BlockExpr> {
26 support::child(self.syntax())
27 }
28
29 fn label(&self) -> Option<ast::Label> {
30 support::child(self.syntax())
31 }
32}
33
34pub trait ArgListOwner: AstNode {
35 fn arg_list(&self) -> Option<ast::ArgList> {
36 support::child(self.syntax())
37 }
38}
39
40pub trait ModuleItemOwner: AstNode {
41 fn items(&self) -> AstChildren<ast::Item> {
42 support::children(self.syntax())
43 }
44}
45
46pub trait GenericParamsOwner: AstNode {
47 fn generic_param_list(&self) -> Option<ast::GenericParamList> {
48 support::child(self.syntax())
49 }
50
51 fn where_clause(&self) -> Option<ast::WhereClause> {
52 support::child(self.syntax())
53 }
54}
55
56pub trait TypeBoundsOwner: AstNode {
57 fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
58 support::child(self.syntax())
59 }
60
61 fn colon_token(&self) -> Option<SyntaxToken> {
62 support::token(self.syntax(), T![:])
63 }
64}
65
66pub trait AttrsOwner: AstNode {
67 fn attrs(&self) -> AstChildren<ast::Attr> {
68 support::children(self.syntax())
69 }
70 fn has_atom_attr(&self, atom: &str) -> bool {
71 self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
72 }
73}
74
75pub trait DocCommentsOwner: AstNode {
76 fn doc_comments(&self) -> CommentIter {
77 CommentIter { iter: self.syntax().children_with_tokens() }
78 }
79
80 fn doc_comment_text(&self) -> Option<String> {
81 self.doc_comments().doc_comment_text()
82 }
83}
84
85impl CommentIter {
86 pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> CommentIter {
87 CommentIter { iter: syntax_node.children_with_tokens() }
88 }
89
90 /// Returns the textual content of a doc comment block as a single string.
91 /// That is, strips leading `///` (+ optional 1 character of whitespace),
92 /// trailing `*/`, trailing whitespace and then joins the lines.
93 pub fn doc_comment_text(self) -> Option<String> {
94 let mut has_comments = false;
95 let docs = self
96 .filter(|comment| comment.kind().doc.is_some())
97 .map(|comment| {
98 has_comments = true;
99 let prefix_len = comment.prefix().len();
100
101 let line: &str = comment.text().as_str();
102
103 // Determine if the prefix or prefix + 1 char is stripped
104 let pos =
105 if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) {
106 prefix_len + ws.len_utf8()
107 } else {
108 prefix_len
109 };
110
111 let end = if comment.kind().shape.is_block() && line.ends_with("*/") {
112 line.len() - 2
113 } else {
114 line.len()
115 };
116
117 // Note that we do not trim the end of the line here
118 // since whitespace can have special meaning at the end
119 // of a line in markdown.
120 line[pos..end].to_owned()
121 })
122 .join("\n");
123
124 if has_comments {
125 Some(docs)
126 } else {
127 None
128 }
129 }
130}
131
132pub struct CommentIter {
133 iter: SyntaxElementChildren,
134}
135
136impl Iterator for CommentIter {
137 type Item = ast::Comment;
138 fn next(&mut self) -> Option<ast::Comment> {
139 self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
140 }
141}
diff --git a/crates/syntax/src/fuzz.rs b/crates/syntax/src/fuzz.rs
new file mode 100644
index 000000000..fbb97aa27
--- /dev/null
+++ b/crates/syntax/src/fuzz.rs
@@ -0,0 +1,73 @@
1//! FIXME: write short doc here
2
3use std::{
4 convert::TryInto,
5 str::{self, FromStr},
6};
7
8use text_edit::Indel;
9
10use crate::{validation, AstNode, SourceFile, TextRange};
11
12fn check_file_invariants(file: &SourceFile) {
13 let root = file.syntax();
14 validation::validate_block_structure(root);
15}
16
17pub fn check_parser(text: &str) {
18 let file = SourceFile::parse(text);
19 check_file_invariants(&file.tree());
20}
21
22#[derive(Debug, Clone)]
23pub struct CheckReparse {
24 text: String,
25 edit: Indel,
26 edited_text: String,
27}
28
29impl CheckReparse {
30 pub fn from_data(data: &[u8]) -> Option<Self> {
31 const PREFIX: &str = "fn main(){\n\t";
32 const SUFFIX: &str = "\n}";
33
34 let data = str::from_utf8(data).ok()?;
35 let mut lines = data.lines();
36 let delete_start = usize::from_str(lines.next()?).ok()? + PREFIX.len();
37 let delete_len = usize::from_str(lines.next()?).ok()?;
38 let insert = lines.next()?.to_string();
39 let text = lines.collect::<Vec<_>>().join("\n");
40 let text = format!("{}{}{}", PREFIX, text, SUFFIX);
41 text.get(delete_start..delete_start.checked_add(delete_len)?)?; // make sure delete is a valid range
42 let delete =
43 TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap());
44 let edited_text =
45 format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]);
46 let edit = Indel { delete, insert };
47 Some(CheckReparse { text, edit, edited_text })
48 }
49
50 pub fn run(&self) {
51 let parse = SourceFile::parse(&self.text);
52 let new_parse = parse.reparse(&self.edit);
53 check_file_invariants(&new_parse.tree());
54 assert_eq!(&new_parse.tree().syntax().text().to_string(), &self.edited_text);
55 let full_reparse = SourceFile::parse(&self.edited_text);
56 for (a, b) in
57 new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants())
58 {
59 if (a.kind(), a.text_range()) != (b.kind(), b.text_range()) {
60 eprint!("original:\n{:#?}", parse.tree().syntax());
61 eprint!("reparsed:\n{:#?}", new_parse.tree().syntax());
62 eprint!("full reparse:\n{:#?}", full_reparse.tree().syntax());
63 assert_eq!(
64 format!("{:?}", a),
65 format!("{:?}", b),
66 "different syntax tree produced by the full reparse"
67 );
68 }
69 }
70 // FIXME
71 // assert_eq!(new_file.errors(), full_reparse.errors());
72 }
73}
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
new file mode 100644
index 000000000..7f8da66af
--- /dev/null
+++ b/crates/syntax/src/lib.rs
@@ -0,0 +1,388 @@
1//! Syntax Tree library used throughout the rust analyzer.
2//!
3//! Properties:
4//! - easy and fast incremental re-parsing
5//! - graceful handling of errors
6//! - full-fidelity representation (*any* text can be precisely represented as
7//! a syntax tree)
8//!
9//! For more information, see the [RFC]. Current implementation is inspired by
10//! the [Swift] one.
11//!
12//! The most interesting modules here are `syntax_node` (which defines concrete
13//! syntax tree) and `ast` (which defines abstract syntax tree on top of the
14//! CST). The actual parser live in a separate `parser` crate, though the
15//! lexer lives in this crate.
16//!
17//! See `api_walkthrough` test in this file for a quick API tour!
18//!
19//! [RFC]: <https://github.com/rust-lang/rfcs/pull/2256>
20//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md>
21
22#[allow(unused)]
23macro_rules! eprintln {
24 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
25}
26
27mod syntax_node;
28mod syntax_error;
29mod parsing;
30mod validation;
31mod ptr;
32#[cfg(test)]
33mod tests;
34
35pub mod algo;
36pub mod ast;
37#[doc(hidden)]
38pub mod fuzz;
39
40use std::{marker::PhantomData, sync::Arc};
41
42use stdx::format_to;
43use text_edit::Indel;
44
45pub use crate::{
46 algo::InsertPosition,
47 ast::{AstNode, AstToken},
48 parsing::{lex_single_syntax_kind, lex_single_valid_syntax_kind, tokenize, Token},
49 ptr::{AstPtr, SyntaxNodePtr},
50 syntax_error::SyntaxError,
51 syntax_node::{
52 Direction, GreenNode, NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode,
53 SyntaxNodeChildren, SyntaxToken, SyntaxTreeBuilder,
54 },
55};
56pub use parser::{SyntaxKind, T};
57pub use rowan::{SmolStr, SyntaxText, TextRange, TextSize, TokenAtOffset, WalkEvent};
58
59/// `Parse` is the result of the parsing: a syntax tree and a collection of
60/// errors.
61///
62/// Note that we always produce a syntax tree, even for completely invalid
63/// files.
64#[derive(Debug, PartialEq, Eq)]
65pub struct Parse<T> {
66 green: GreenNode,
67 errors: Arc<Vec<SyntaxError>>,
68 _ty: PhantomData<fn() -> T>,
69}
70
71impl<T> Clone for Parse<T> {
72 fn clone(&self) -> Parse<T> {
73 Parse { green: self.green.clone(), errors: self.errors.clone(), _ty: PhantomData }
74 }
75}
76
77impl<T> Parse<T> {
78 fn new(green: GreenNode, errors: Vec<SyntaxError>) -> Parse<T> {
79 Parse { green, errors: Arc::new(errors), _ty: PhantomData }
80 }
81
82 pub fn syntax_node(&self) -> SyntaxNode {
83 SyntaxNode::new_root(self.green.clone())
84 }
85}
86
87impl<T: AstNode> Parse<T> {
88 pub fn to_syntax(self) -> Parse<SyntaxNode> {
89 Parse { green: self.green, errors: self.errors, _ty: PhantomData }
90 }
91
92 pub fn tree(&self) -> T {
93 T::cast(self.syntax_node()).unwrap()
94 }
95
96 pub fn errors(&self) -> &[SyntaxError] {
97 &*self.errors
98 }
99
100 pub fn ok(self) -> Result<T, Arc<Vec<SyntaxError>>> {
101 if self.errors.is_empty() {
102 Ok(self.tree())
103 } else {
104 Err(self.errors)
105 }
106 }
107}
108
109impl Parse<SyntaxNode> {
110 pub fn cast<N: AstNode>(self) -> Option<Parse<N>> {
111 if N::cast(self.syntax_node()).is_some() {
112 Some(Parse { green: self.green, errors: self.errors, _ty: PhantomData })
113 } else {
114 None
115 }
116 }
117}
118
119impl Parse<SourceFile> {
120 pub fn debug_dump(&self) -> String {
121 let mut buf = format!("{:#?}", self.tree().syntax());
122 for err in self.errors.iter() {
123 format_to!(buf, "error {:?}: {}\n", err.range(), err);
124 }
125 buf
126 }
127
128 pub fn reparse(&self, indel: &Indel) -> Parse<SourceFile> {
129 self.incremental_reparse(indel).unwrap_or_else(|| self.full_reparse(indel))
130 }
131
132 fn incremental_reparse(&self, indel: &Indel) -> Option<Parse<SourceFile>> {
133 // FIXME: validation errors are not handled here
134 parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map(
135 |(green_node, errors, _reparsed_range)| Parse {
136 green: green_node,
137 errors: Arc::new(errors),
138 _ty: PhantomData,
139 },
140 )
141 }
142
143 fn full_reparse(&self, indel: &Indel) -> Parse<SourceFile> {
144 let mut text = self.tree().syntax().text().to_string();
145 indel.apply(&mut text);
146 SourceFile::parse(&text)
147 }
148}
149
150/// `SourceFile` represents a parse tree for a single Rust file.
151pub use crate::ast::SourceFile;
152
153impl SourceFile {
154 pub fn parse(text: &str) -> Parse<SourceFile> {
155 let (green, mut errors) = parsing::parse_text(text);
156 let root = SyntaxNode::new_root(green.clone());
157
158 if cfg!(debug_assertions) {
159 validation::validate_block_structure(&root);
160 }
161
162 errors.extend(validation::validate(&root));
163
164 assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE);
165 Parse { green, errors: Arc::new(errors), _ty: PhantomData }
166 }
167}
168
169impl ast::Path {
170 /// Returns `text`, parsed as a path, but only if it has no errors.
171 pub fn parse(text: &str) -> Result<Self, ()> {
172 parsing::parse_text_fragment(text, parser::FragmentKind::Path)
173 }
174}
175
176impl ast::Pat {
177 /// Returns `text`, parsed as a pattern, but only if it has no errors.
178 pub fn parse(text: &str) -> Result<Self, ()> {
179 parsing::parse_text_fragment(text, parser::FragmentKind::Pattern)
180 }
181}
182
183impl ast::Expr {
184 /// Returns `text`, parsed as an expression, but only if it has no errors.
185 pub fn parse(text: &str) -> Result<Self, ()> {
186 parsing::parse_text_fragment(text, parser::FragmentKind::Expr)
187 }
188}
189
190impl ast::Item {
191 /// Returns `text`, parsed as an item, but only if it has no errors.
192 pub fn parse(text: &str) -> Result<Self, ()> {
193 parsing::parse_text_fragment(text, parser::FragmentKind::Item)
194 }
195}
196
197impl ast::Type {
198 /// Returns `text`, parsed as an type reference, but only if it has no errors.
199 pub fn parse(text: &str) -> Result<Self, ()> {
200 parsing::parse_text_fragment(text, parser::FragmentKind::Type)
201 }
202}
203
204/// Matches a `SyntaxNode` against an `ast` type.
205///
206/// # Example:
207///
208/// ```ignore
209/// match_ast! {
210/// match node {
211/// ast::CallExpr(it) => { ... },
212/// ast::MethodCallExpr(it) => { ... },
213/// ast::MacroCall(it) => { ... },
214/// _ => None,
215/// }
216/// }
217/// ```
218#[macro_export]
219macro_rules! match_ast {
220 (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
221
222 (match ($node:expr) {
223 $( ast::$ast:ident($it:ident) => $res:expr, )*
224 _ => $catch_all:expr $(,)?
225 }) => {{
226 $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
227 { $catch_all }
228 }};
229}
230
231/// This test does not assert anything and instead just shows off the crate's
232/// API.
233#[test]
234fn api_walkthrough() {
235 use ast::{ModuleItemOwner, NameOwner};
236
237 let source_code = "
238 fn foo() {
239 1 + 1
240 }
241 ";
242 // `SourceFile` is the main entry point.
243 //
244 // The `parse` method returns a `Parse` -- a pair of syntax tree and a list
245 // of errors. That is, syntax tree is constructed even in presence of errors.
246 let parse = SourceFile::parse(source_code);
247 assert!(parse.errors().is_empty());
248
249 // The `tree` method returns an owned syntax node of type `SourceFile`.
250 // Owned nodes are cheap: inside, they are `Rc` handles to the underling data.
251 let file: SourceFile = parse.tree();
252
253 // `SourceFile` is the root of the syntax tree. We can iterate file's items.
254 // Let's fetch the `foo` function.
255 let mut func = None;
256 for item in file.items() {
257 match item {
258 ast::Item::Fn(f) => func = Some(f),
259 _ => unreachable!(),
260 }
261 }
262 let func: ast::Fn = func.unwrap();
263
264 // Each AST node has a bunch of getters for children. All getters return
265 // `Option`s though, to account for incomplete code. Some getters are common
266 // for several kinds of node. In this case, a trait like `ast::NameOwner`
267 // usually exists. By convention, all ast types should be used with `ast::`
268 // qualifier.
269 let name: Option<ast::Name> = func.name();
270 let name = name.unwrap();
271 assert_eq!(name.text(), "foo");
272
273 // Let's get the `1 + 1` expression!
274 let body: ast::BlockExpr = func.body().unwrap();
275 let expr: ast::Expr = body.expr().unwrap();
276
277 // Enums are used to group related ast nodes together, and can be used for
278 // matching. However, because there are no public fields, it's possible to
279 // match only the top level enum: that is the price we pay for increased API
280 // flexibility
281 let bin_expr: &ast::BinExpr = match &expr {
282 ast::Expr::BinExpr(e) => e,
283 _ => unreachable!(),
284 };
285
286 // Besides the "typed" AST API, there's an untyped CST one as well.
287 // To switch from AST to CST, call `.syntax()` method:
288 let expr_syntax: &SyntaxNode = expr.syntax();
289
290 // Note how `expr` and `bin_expr` are in fact the same node underneath:
291 assert!(expr_syntax == bin_expr.syntax());
292
293 // To go from CST to AST, `AstNode::cast` function is used:
294 let _expr: ast::Expr = match ast::Expr::cast(expr_syntax.clone()) {
295 Some(e) => e,
296 None => unreachable!(),
297 };
298
299 // The two properties each syntax node has is a `SyntaxKind`:
300 assert_eq!(expr_syntax.kind(), SyntaxKind::BIN_EXPR);
301
302 // And text range:
303 assert_eq!(expr_syntax.text_range(), TextRange::new(32.into(), 37.into()));
304
305 // You can get node's text as a `SyntaxText` object, which will traverse the
306 // tree collecting token's text:
307 let text: SyntaxText = expr_syntax.text();
308 assert_eq!(text.to_string(), "1 + 1");
309
310 // There's a bunch of traversal methods on `SyntaxNode`:
311 assert_eq!(expr_syntax.parent().as_ref(), Some(body.syntax()));
312 assert_eq!(body.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
313 assert_eq!(
314 expr_syntax.next_sibling_or_token().map(|it| it.kind()),
315 Some(SyntaxKind::WHITESPACE)
316 );
317
318 // As well as some iterator helpers:
319 let f = expr_syntax.ancestors().find_map(ast::Fn::cast);
320 assert_eq!(f, Some(func));
321 assert!(expr_syntax.siblings_with_tokens(Direction::Next).any(|it| it.kind() == T!['}']));
322 assert_eq!(
323 expr_syntax.descendants_with_tokens().count(),
324 8, // 5 tokens `1`, ` `, `+`, ` `, `!`
325 // 2 child literal expressions: `1`, `1`
326 // 1 the node itself: `1 + 1`
327 );
328
329 // There's also a `preorder` method with a more fine-grained iteration control:
330 let mut buf = String::new();
331 let mut indent = 0;
332 for event in expr_syntax.preorder_with_tokens() {
333 match event {
334 WalkEvent::Enter(node) => {
335 let text = match &node {
336 NodeOrToken::Node(it) => it.text().to_string(),
337 NodeOrToken::Token(it) => it.text().to_string(),
338 };
339 format_to!(buf, "{:indent$}{:?} {:?}\n", " ", text, node.kind(), indent = indent);
340 indent += 2;
341 }
342 WalkEvent::Leave(_) => indent -= 2,
343 }
344 }
345 assert_eq!(indent, 0);
346 assert_eq!(
347 buf.trim(),
348 r#"
349"1 + 1" BIN_EXPR
350 "1" LITERAL
351 "1" INT_NUMBER
352 " " WHITESPACE
353 "+" PLUS
354 " " WHITESPACE
355 "1" LITERAL
356 "1" INT_NUMBER
357"#
358 .trim()
359 );
360
361 // To recursively process the tree, there are three approaches:
362 // 1. explicitly call getter methods on AST nodes.
363 // 2. use descendants and `AstNode::cast`.
364 // 3. use descendants and `match_ast!`.
365 //
366 // Here's how the first one looks like:
367 let exprs_cast: Vec<String> = file
368 .syntax()
369 .descendants()
370 .filter_map(ast::Expr::cast)
371 .map(|expr| expr.syntax().text().to_string())
372 .collect();
373
374 // An alternative is to use a macro.
375 let mut exprs_visit = Vec::new();
376 for node in file.syntax().descendants() {
377 match_ast! {
378 match node {
379 ast::Expr(it) => {
380 let res = it.syntax().text().to_string();
381 exprs_visit.push(res);
382 },
383 _ => (),
384 }
385 }
386 }
387 assert_eq!(exprs_cast, exprs_visit);
388}
diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs
new file mode 100644
index 000000000..68a39eb21
--- /dev/null
+++ b/crates/syntax/src/parsing.rs
@@ -0,0 +1,59 @@
1//! Lexing, bridging to parser (which does the actual parsing) and
2//! incremental reparsing.
3
4mod lexer;
5mod text_token_source;
6mod text_tree_sink;
7mod reparsing;
8
9use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode};
10use text_token_source::TextTokenSource;
11use text_tree_sink::TextTreeSink;
12
13pub use lexer::*;
14
15pub(crate) use self::reparsing::incremental_reparse;
16use parser::SyntaxKind;
17
18pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
19 let (tokens, lexer_errors) = tokenize(&text);
20
21 let mut token_source = TextTokenSource::new(text, &tokens);
22 let mut tree_sink = TextTreeSink::new(text, &tokens);
23
24 parser::parse(&mut token_source, &mut tree_sink);
25
26 let (tree, mut parser_errors) = tree_sink.finish();
27 parser_errors.extend(lexer_errors);
28
29 (tree, parser_errors)
30}
31
32/// Returns `text` parsed as a `T` provided there are no parse errors.
33pub(crate) fn parse_text_fragment<T: AstNode>(
34 text: &str,
35 fragment_kind: parser::FragmentKind,
36) -> Result<T, ()> {
37 let (tokens, lexer_errors) = tokenize(&text);
38 if !lexer_errors.is_empty() {
39 return Err(());
40 }
41
42 let mut token_source = TextTokenSource::new(text, &tokens);
43 let mut tree_sink = TextTreeSink::new(text, &tokens);
44
45 // TextTreeSink assumes that there's at least some root node to which it can attach errors and
46 // tokens. We arbitrarily give it a SourceFile.
47 use parser::TreeSink;
48 tree_sink.start_node(SyntaxKind::SOURCE_FILE);
49 parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind);
50 tree_sink.finish_node();
51
52 let (tree, parser_errors) = tree_sink.finish();
53 use parser::TokenSource;
54 if !parser_errors.is_empty() || token_source.current().kind != SyntaxKind::EOF {
55 return Err(());
56 }
57
58 SyntaxNode::new_root(tree).first_child().and_then(T::cast).ok_or(())
59}
diff --git a/crates/syntax/src/parsing/lexer.rs b/crates/syntax/src/parsing/lexer.rs
new file mode 100644
index 000000000..fa3be1016
--- /dev/null
+++ b/crates/syntax/src/parsing/lexer.rs
@@ -0,0 +1,244 @@
1//! Lexer analyzes raw input string and produces lexemes (tokens).
2//! It is just a bridge to `rustc_lexer`.
3
4use rustc_lexer::{LiteralKind as LK, RawStrError};
5
6use std::convert::TryInto;
7
8use crate::{
9 SyntaxError,
10 SyntaxKind::{self, *},
11 TextRange, TextSize, T,
12};
13
14/// A token of Rust source.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct Token {
17 /// The kind of token.
18 pub kind: SyntaxKind,
19 /// The length of the token.
20 pub len: TextSize,
21}
22
23/// Break a string up into its component tokens.
24/// Beware that it checks for shebang first and its length contributes to resulting
25/// tokens offsets.
26pub fn tokenize(text: &str) -> (Vec<Token>, Vec<SyntaxError>) {
27 // non-empty string is a precondtion of `rustc_lexer::strip_shebang()`.
28 if text.is_empty() {
29 return Default::default();
30 }
31
32 let mut tokens = Vec::new();
33 let mut errors = Vec::new();
34
35 let mut offset = match rustc_lexer::strip_shebang(text) {
36 Some(shebang_len) => {
37 tokens.push(Token { kind: SHEBANG, len: shebang_len.try_into().unwrap() });
38 shebang_len
39 }
40 None => 0,
41 };
42
43 let text_without_shebang = &text[offset..];
44
45 for rustc_token in rustc_lexer::tokenize(text_without_shebang) {
46 let token_len: TextSize = rustc_token.len.try_into().unwrap();
47 let token_range = TextRange::at(offset.try_into().unwrap(), token_len);
48
49 let (syntax_kind, err_message) =
50 rustc_token_kind_to_syntax_kind(&rustc_token.kind, &text[token_range]);
51
52 tokens.push(Token { kind: syntax_kind, len: token_len });
53
54 if let Some(err_message) = err_message {
55 errors.push(SyntaxError::new(err_message, token_range));
56 }
57
58 offset += rustc_token.len;
59 }
60
61 (tokens, errors)
62}
63
64/// Returns `SyntaxKind` and `Option<SyntaxError>` of the first token
65/// encountered at the beginning of the string.
66///
67/// Returns `None` if the string contains zero *or two or more* tokens.
68/// The token is malformed if the returned error is not `None`.
69///
70/// Beware that unescape errors are not checked at tokenization time.
71pub fn lex_single_syntax_kind(text: &str) -> Option<(SyntaxKind, Option<SyntaxError>)> {
72 lex_first_token(text)
73 .filter(|(token, _)| token.len == TextSize::of(text))
74 .map(|(token, error)| (token.kind, error))
75}
76
77/// The same as `lex_single_syntax_kind()` but returns only `SyntaxKind` and
78/// returns `None` if any tokenization error occured.
79///
80/// Beware that unescape errors are not checked at tokenization time.
81pub fn lex_single_valid_syntax_kind(text: &str) -> Option<SyntaxKind> {
82 lex_first_token(text)
83 .filter(|(token, error)| !error.is_some() && token.len == TextSize::of(text))
84 .map(|(token, _error)| token.kind)
85}
86
87/// Returns `SyntaxKind` and `Option<SyntaxError>` of the first token
88/// encountered at the beginning of the string.
89///
90/// Returns `None` if the string contains zero tokens or if the token was parsed
91/// with an error.
92/// The token is malformed if the returned error is not `None`.
93///
94/// Beware that unescape errors are not checked at tokenization time.
95fn lex_first_token(text: &str) -> Option<(Token, Option<SyntaxError>)> {
96 // non-empty string is a precondtion of `rustc_lexer::first_token()`.
97 if text.is_empty() {
98 return None;
99 }
100
101 let rustc_token = rustc_lexer::first_token(text);
102 let (syntax_kind, err_message) = rustc_token_kind_to_syntax_kind(&rustc_token.kind, text);
103
104 let token = Token { kind: syntax_kind, len: rustc_token.len.try_into().unwrap() };
105 let optional_error = err_message
106 .map(|err_message| SyntaxError::new(err_message, TextRange::up_to(TextSize::of(text))));
107
108 Some((token, optional_error))
109}
110
111/// Returns `SyntaxKind` and an optional tokenize error message.
112fn rustc_token_kind_to_syntax_kind(
113 rustc_token_kind: &rustc_lexer::TokenKind,
114 token_text: &str,
115) -> (SyntaxKind, Option<&'static str>) {
116 // A note on an intended tradeoff:
117 // We drop some useful infromation here (see patterns with double dots `..`)
118 // Storing that info in `SyntaxKind` is not possible due to its layout requirements of
119 // being `u16` that come from `rowan::SyntaxKind`.
120
121 let syntax_kind = {
122 match rustc_token_kind {
123 rustc_lexer::TokenKind::LineComment => COMMENT,
124
125 rustc_lexer::TokenKind::BlockComment { terminated: true } => COMMENT,
126 rustc_lexer::TokenKind::BlockComment { terminated: false } => {
127 return (
128 COMMENT,
129 Some("Missing trailing `*/` symbols to terminate the block comment"),
130 );
131 }
132
133 rustc_lexer::TokenKind::Whitespace => WHITESPACE,
134
135 rustc_lexer::TokenKind::Ident => {
136 if token_text == "_" {
137 UNDERSCORE
138 } else {
139 SyntaxKind::from_keyword(token_text).unwrap_or(IDENT)
140 }
141 }
142
143 rustc_lexer::TokenKind::RawIdent => IDENT,
144 rustc_lexer::TokenKind::Literal { kind, .. } => return match_literal_kind(&kind),
145
146 rustc_lexer::TokenKind::Lifetime { starts_with_number: false } => LIFETIME,
147 rustc_lexer::TokenKind::Lifetime { starts_with_number: true } => {
148 return (LIFETIME, Some("Lifetime name cannot start with a number"))
149 }
150
151 rustc_lexer::TokenKind::Semi => T![;],
152 rustc_lexer::TokenKind::Comma => T![,],
153 rustc_lexer::TokenKind::Dot => T![.],
154 rustc_lexer::TokenKind::OpenParen => T!['('],
155 rustc_lexer::TokenKind::CloseParen => T![')'],
156 rustc_lexer::TokenKind::OpenBrace => T!['{'],
157 rustc_lexer::TokenKind::CloseBrace => T!['}'],
158 rustc_lexer::TokenKind::OpenBracket => T!['['],
159 rustc_lexer::TokenKind::CloseBracket => T![']'],
160 rustc_lexer::TokenKind::At => T![@],
161 rustc_lexer::TokenKind::Pound => T![#],
162 rustc_lexer::TokenKind::Tilde => T![~],
163 rustc_lexer::TokenKind::Question => T![?],
164 rustc_lexer::TokenKind::Colon => T![:],
165 rustc_lexer::TokenKind::Dollar => T![$],
166 rustc_lexer::TokenKind::Eq => T![=],
167 rustc_lexer::TokenKind::Not => T![!],
168 rustc_lexer::TokenKind::Lt => T![<],
169 rustc_lexer::TokenKind::Gt => T![>],
170 rustc_lexer::TokenKind::Minus => T![-],
171 rustc_lexer::TokenKind::And => T![&],
172 rustc_lexer::TokenKind::Or => T![|],
173 rustc_lexer::TokenKind::Plus => T![+],
174 rustc_lexer::TokenKind::Star => T![*],
175 rustc_lexer::TokenKind::Slash => T![/],
176 rustc_lexer::TokenKind::Caret => T![^],
177 rustc_lexer::TokenKind::Percent => T![%],
178 rustc_lexer::TokenKind::Unknown => ERROR,
179 }
180 };
181
182 return (syntax_kind, None);
183
184 fn match_literal_kind(kind: &rustc_lexer::LiteralKind) -> (SyntaxKind, Option<&'static str>) {
185 #[rustfmt::skip]
186 let syntax_kind = match *kind {
187 LK::Int { empty_int: false, .. } => INT_NUMBER,
188 LK::Int { empty_int: true, .. } => {
189 return (INT_NUMBER, Some("Missing digits after the integer base prefix"))
190 }
191
192 LK::Float { empty_exponent: false, .. } => FLOAT_NUMBER,
193 LK::Float { empty_exponent: true, .. } => {
194 return (FLOAT_NUMBER, Some("Missing digits after the exponent symbol"))
195 }
196
197 LK::Char { terminated: true } => CHAR,
198 LK::Char { terminated: false } => {
199 return (CHAR, Some("Missing trailing `'` symbol to terminate the character literal"))
200 }
201
202 LK::Byte { terminated: true } => BYTE,
203 LK::Byte { terminated: false } => {
204 return (BYTE, Some("Missing trailing `'` symbol to terminate the byte literal"))
205 }
206
207 LK::Str { terminated: true } => STRING,
208 LK::Str { terminated: false } => {
209 return (STRING, Some("Missing trailing `\"` symbol to terminate the string literal"))
210 }
211
212
213 LK::ByteStr { terminated: true } => BYTE_STRING,
214 LK::ByteStr { terminated: false } => {
215 return (BYTE_STRING, Some("Missing trailing `\"` symbol to terminate the byte string literal"))
216 }
217
218 LK::RawStr { err, .. } => match err {
219 None => RAW_STRING,
220 Some(RawStrError::InvalidStarter { .. }) => return (RAW_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw string literal")),
221 Some(RawStrError::NoTerminator { expected, found, .. }) => if expected == found {
222 return (RAW_STRING, Some("Missing trailing `\"` to terminate the raw string literal"))
223 } else {
224 return (RAW_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw string literal"))
225
226 },
227 Some(RawStrError::TooManyDelimiters { .. }) => return (RAW_STRING, Some("Too many `#` symbols: raw strings may be delimited by up to 65535 `#` symbols")),
228 },
229 LK::RawByteStr { err, .. } => match err {
230 None => RAW_BYTE_STRING,
231 Some(RawStrError::InvalidStarter { .. }) => return (RAW_BYTE_STRING, Some("Missing `\"` symbol after `#` symbols to begin the raw byte string literal")),
232 Some(RawStrError::NoTerminator { expected, found, .. }) => if expected == found {
233 return (RAW_BYTE_STRING, Some("Missing trailing `\"` to terminate the raw byte string literal"))
234 } else {
235 return (RAW_BYTE_STRING, Some("Missing trailing `\"` with `#` symbols to terminate the raw byte string literal"))
236
237 },
238 Some(RawStrError::TooManyDelimiters { .. }) => return (RAW_BYTE_STRING, Some("Too many `#` symbols: raw byte strings may be delimited by up to 65535 `#` symbols")),
239 },
240 };
241
242 (syntax_kind, None)
243 }
244}
diff --git a/crates/syntax/src/parsing/reparsing.rs b/crates/syntax/src/parsing/reparsing.rs
new file mode 100644
index 000000000..4149f856a
--- /dev/null
+++ b/crates/syntax/src/parsing/reparsing.rs
@@ -0,0 +1,455 @@
1//! Implementation of incremental re-parsing.
2//!
3//! We use two simple strategies for this:
4//! - if the edit modifies only a single token (like changing an identifier's
5//! letter), we replace only this token.
6//! - otherwise, we search for the nearest `{}` block which contains the edit
7//! and try to parse only this block.
8
9use parser::Reparser;
10use text_edit::Indel;
11
12use crate::{
13 algo,
14 parsing::{
15 lexer::{lex_single_syntax_kind, tokenize, Token},
16 text_token_source::TextTokenSource,
17 text_tree_sink::TextTreeSink,
18 },
19 syntax_node::{GreenNode, GreenToken, NodeOrToken, SyntaxElement, SyntaxNode},
20 SyntaxError,
21 SyntaxKind::*,
22 TextRange, TextSize, T,
23};
24
25pub(crate) fn incremental_reparse(
26 node: &SyntaxNode,
27 edit: &Indel,
28 errors: Vec<SyntaxError>,
29) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
30 if let Some((green, new_errors, old_range)) = reparse_token(node, &edit) {
31 return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
32 }
33
34 if let Some((green, new_errors, old_range)) = reparse_block(node, &edit) {
35 return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
36 }
37 None
38}
39
40fn reparse_token<'node>(
41 root: &'node SyntaxNode,
42 edit: &Indel,
43) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
44 let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone();
45 let prev_token_kind = prev_token.kind();
46 match prev_token_kind {
47 WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
48 if prev_token_kind == WHITESPACE || prev_token_kind == COMMENT {
49 // removing a new line may extends previous token
50 let deleted_range = edit.delete - prev_token.text_range().start();
51 if prev_token.text()[deleted_range].contains('\n') {
52 return None;
53 }
54 }
55
56 let mut new_text = get_text_after_edit(prev_token.clone().into(), &edit);
57 let (new_token_kind, new_err) = lex_single_syntax_kind(&new_text)?;
58
59 if new_token_kind != prev_token_kind
60 || (new_token_kind == IDENT && is_contextual_kw(&new_text))
61 {
62 return None;
63 }
64
65 // Check that edited token is not a part of the bigger token.
66 // E.g. if for source code `bruh"str"` the user removed `ruh`, then
67 // `b` no longer remains an identifier, but becomes a part of byte string literal
68 if let Some(next_char) = root.text().char_at(prev_token.text_range().end()) {
69 new_text.push(next_char);
70 let token_with_next_char = lex_single_syntax_kind(&new_text);
71 if let Some((_kind, _error)) = token_with_next_char {
72 return None;
73 }
74 new_text.pop();
75 }
76
77 let new_token =
78 GreenToken::new(rowan::SyntaxKind(prev_token_kind.into()), new_text.into());
79 Some((
80 prev_token.replace_with(new_token),
81 new_err.into_iter().collect(),
82 prev_token.text_range(),
83 ))
84 }
85 _ => None,
86 }
87}
88
89fn reparse_block<'node>(
90 root: &'node SyntaxNode,
91 edit: &Indel,
92) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
93 let (node, reparser) = find_reparsable_node(root, edit.delete)?;
94 let text = get_text_after_edit(node.clone().into(), edit);
95
96 let (tokens, new_lexer_errors) = tokenize(&text);
97 if !is_balanced(&tokens) {
98 return None;
99 }
100
101 let mut token_source = TextTokenSource::new(&text, &tokens);
102 let mut tree_sink = TextTreeSink::new(&text, &tokens);
103 reparser.parse(&mut token_source, &mut tree_sink);
104
105 let (green, mut new_parser_errors) = tree_sink.finish();
106 new_parser_errors.extend(new_lexer_errors);
107
108 Some((node.replace_with(green), new_parser_errors, node.text_range()))
109}
110
111fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String {
112 let edit = Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone());
113
114 let mut text = match element {
115 NodeOrToken::Token(token) => token.text().to_string(),
116 NodeOrToken::Node(node) => node.text().to_string(),
117 };
118 edit.apply(&mut text);
119 text
120}
121
122fn is_contextual_kw(text: &str) -> bool {
123 matches!(text, "auto" | "default" | "union")
124}
125
126fn find_reparsable_node(node: &SyntaxNode, range: TextRange) -> Option<(SyntaxNode, Reparser)> {
127 let node = algo::find_covering_element(node, range);
128
129 let mut ancestors = match node {
130 NodeOrToken::Token(it) => it.parent().ancestors(),
131 NodeOrToken::Node(it) => it.ancestors(),
132 };
133 ancestors.find_map(|node| {
134 let first_child = node.first_child_or_token().map(|it| it.kind());
135 let parent = node.parent().map(|it| it.kind());
136 Reparser::for_node(node.kind(), first_child, parent).map(|r| (node, r))
137 })
138}
139
140fn is_balanced(tokens: &[Token]) -> bool {
141 if tokens.is_empty()
142 || tokens.first().unwrap().kind != T!['{']
143 || tokens.last().unwrap().kind != T!['}']
144 {
145 return false;
146 }
147 let mut balance = 0usize;
148 for t in &tokens[1..tokens.len() - 1] {
149 match t.kind {
150 T!['{'] => balance += 1,
151 T!['}'] => {
152 balance = match balance.checked_sub(1) {
153 Some(b) => b,
154 None => return false,
155 }
156 }
157 _ => (),
158 }
159 }
160 balance == 0
161}
162
163fn merge_errors(
164 old_errors: Vec<SyntaxError>,
165 new_errors: Vec<SyntaxError>,
166 range_before_reparse: TextRange,
167 edit: &Indel,
168) -> Vec<SyntaxError> {
169 let mut res = Vec::new();
170
171 for old_err in old_errors {
172 let old_err_range = old_err.range();
173 if old_err_range.end() <= range_before_reparse.start() {
174 res.push(old_err);
175 } else if old_err_range.start() >= range_before_reparse.end() {
176 let inserted_len = TextSize::of(&edit.insert);
177 res.push(old_err.with_range((old_err_range + inserted_len) - edit.delete.len()));
178 // Note: extra parens are intentional to prevent uint underflow, HWAB (here was a bug)
179 }
180 }
181 res.extend(new_errors.into_iter().map(|new_err| {
182 // fighting borrow checker with a variable ;)
183 let offseted_range = new_err.range() + range_before_reparse.start();
184 new_err.with_range(offseted_range)
185 }));
186 res
187}
188
189#[cfg(test)]
190mod tests {
191 use test_utils::{assert_eq_text, extract_range};
192
193 use super::*;
194 use crate::{AstNode, Parse, SourceFile};
195
196 fn do_check(before: &str, replace_with: &str, reparsed_len: u32) {
197 let (range, before) = extract_range(before);
198 let edit = Indel::replace(range, replace_with.to_owned());
199 let after = {
200 let mut after = before.clone();
201 edit.apply(&mut after);
202 after
203 };
204
205 let fully_reparsed = SourceFile::parse(&after);
206 let incrementally_reparsed: Parse<SourceFile> = {
207 let before = SourceFile::parse(&before);
208 let (green, new_errors, range) =
209 incremental_reparse(before.tree().syntax(), &edit, before.errors.to_vec()).unwrap();
210 assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
211 Parse::new(green, new_errors)
212 };
213
214 assert_eq_text!(
215 &format!("{:#?}", fully_reparsed.tree().syntax()),
216 &format!("{:#?}", incrementally_reparsed.tree().syntax()),
217 );
218 assert_eq!(fully_reparsed.errors(), incrementally_reparsed.errors());
219 }
220
221 #[test] // FIXME: some test here actually test token reparsing
222 fn reparse_block_tests() {
223 do_check(
224 r"
225fn foo() {
226 let x = foo + <|>bar<|>
227}
228",
229 "baz",
230 3,
231 );
232 do_check(
233 r"
234fn foo() {
235 let x = foo<|> + bar<|>
236}
237",
238 "baz",
239 25,
240 );
241 do_check(
242 r"
243struct Foo {
244 f: foo<|><|>
245}
246",
247 ",\n g: (),",
248 14,
249 );
250 do_check(
251 r"
252fn foo {
253 let;
254 1 + 1;
255 <|>92<|>;
256}
257",
258 "62",
259 31, // FIXME: reparse only int literal here
260 );
261 do_check(
262 r"
263mod foo {
264 fn <|><|>
265}
266",
267 "bar",
268 11,
269 );
270
271 do_check(
272 r"
273trait Foo {
274 type <|>Foo<|>;
275}
276",
277 "Output",
278 3,
279 );
280 do_check(
281 r"
282impl IntoIterator<Item=i32> for Foo {
283 f<|><|>
284}
285",
286 "n next(",
287 9,
288 );
289 do_check(r"use a::b::{foo,<|>,bar<|>};", "baz", 10);
290 do_check(
291 r"
292pub enum A {
293 Foo<|><|>
294}
295",
296 "\nBar;\n",
297 11,
298 );
299 do_check(
300 r"
301foo!{a, b<|><|> d}
302",
303 ", c[3]",
304 8,
305 );
306 do_check(
307 r"
308fn foo() {
309 vec![<|><|>]
310}
311",
312 "123",
313 14,
314 );
315 do_check(
316 r"
317extern {
318 fn<|>;<|>
319}
320",
321 " exit(code: c_int)",
322 11,
323 );
324 }
325
326 #[test]
327 fn reparse_token_tests() {
328 do_check(
329 r"<|><|>
330fn foo() -> i32 { 1 }
331",
332 "\n\n\n \n",
333 1,
334 );
335 do_check(
336 r"
337fn foo() -> <|><|> {}
338",
339 " \n",
340 2,
341 );
342 do_check(
343 r"
344fn <|>foo<|>() -> i32 { 1 }
345",
346 "bar",
347 3,
348 );
349 do_check(
350 r"
351fn foo<|><|>foo() { }
352",
353 "bar",
354 6,
355 );
356 do_check(
357 r"
358fn foo /* <|><|> */ () {}
359",
360 "some comment",
361 6,
362 );
363 do_check(
364 r"
365fn baz <|><|> () {}
366",
367 " \t\t\n\n",
368 2,
369 );
370 do_check(
371 r"
372fn baz <|><|> () {}
373",
374 " \t\t\n\n",
375 2,
376 );
377 do_check(
378 r"
379/// foo <|><|>omment
380mod { }
381",
382 "c",
383 14,
384 );
385 do_check(
386 r#"
387fn -> &str { "Hello<|><|>" }
388"#,
389 ", world",
390 7,
391 );
392 do_check(
393 r#"
394fn -> &str { // "Hello<|><|>"
395"#,
396 ", world",
397 10,
398 );
399 do_check(
400 r##"
401fn -> &str { r#"Hello<|><|>"#
402"##,
403 ", world",
404 10,
405 );
406 do_check(
407 r"
408#[derive(<|>Copy<|>)]
409enum Foo {
410
411}
412",
413 "Clone",
414 4,
415 );
416 }
417
418 #[test]
419 fn reparse_str_token_with_error_unchanged() {
420 do_check(r#""<|>Unclosed<|> string literal"#, "Still unclosed", 24);
421 }
422
423 #[test]
424 fn reparse_str_token_with_error_fixed() {
425 do_check(r#""unterinated<|><|>"#, "\"", 12);
426 }
427
428 #[test]
429 fn reparse_block_with_error_in_middle_unchanged() {
430 do_check(
431 r#"fn main() {
432 if {}
433 32 + 4<|><|>
434 return
435 if {}
436 }"#,
437 "23",
438 105,
439 )
440 }
441
442 #[test]
443 fn reparse_block_with_error_in_middle_fixed() {
444 do_check(
445 r#"fn main() {
446 if {}
447 32 + 4<|><|>
448 return
449 if {}
450 }"#,
451 ";",
452 105,
453 )
454 }
455}
diff --git a/crates/syntax/src/parsing/text_token_source.rs b/crates/syntax/src/parsing/text_token_source.rs
new file mode 100644
index 000000000..df866dc2b
--- /dev/null
+++ b/crates/syntax/src/parsing/text_token_source.rs
@@ -0,0 +1,84 @@
1//! See `TextTokenSource` docs.
2
3use parser::TokenSource;
4
5use crate::{parsing::lexer::Token, SyntaxKind::EOF, TextRange, TextSize};
6
7/// Implementation of `parser::TokenSource` that takes tokens from source code text.
8pub(crate) struct TextTokenSource<'t> {
9 text: &'t str,
10 /// token and its start position (non-whitespace/comment tokens)
11 /// ```non-rust
12 /// struct Foo;
13 /// ^------^--^-
14 /// | | \________
15 /// | \____ \
16 /// | \ |
17 /// (struct, 0) (Foo, 7) (;, 10)
18 /// ```
19 /// `[(struct, 0), (Foo, 7), (;, 10)]`
20 token_offset_pairs: Vec<(Token, TextSize)>,
21
22 /// Current token and position
23 curr: (parser::Token, usize),
24}
25
26impl<'t> TokenSource for TextTokenSource<'t> {
27 fn current(&self) -> parser::Token {
28 self.curr.0
29 }
30
31 fn lookahead_nth(&self, n: usize) -> parser::Token {
32 mk_token(self.curr.1 + n, &self.token_offset_pairs)
33 }
34
35 fn bump(&mut self) {
36 if self.curr.0.kind == EOF {
37 return;
38 }
39
40 let pos = self.curr.1 + 1;
41 self.curr = (mk_token(pos, &self.token_offset_pairs), pos);
42 }
43
44 fn is_keyword(&self, kw: &str) -> bool {
45 self.token_offset_pairs
46 .get(self.curr.1)
47 .map(|(token, offset)| &self.text[TextRange::at(*offset, token.len)] == kw)
48 .unwrap_or(false)
49 }
50}
51
52fn mk_token(pos: usize, token_offset_pairs: &[(Token, TextSize)]) -> parser::Token {
53 let (kind, is_jointed_to_next) = match token_offset_pairs.get(pos) {
54 Some((token, offset)) => (
55 token.kind,
56 token_offset_pairs
57 .get(pos + 1)
58 .map(|(_, next_offset)| offset + token.len == *next_offset)
59 .unwrap_or(false),
60 ),
61 None => (EOF, false),
62 };
63 parser::Token { kind, is_jointed_to_next }
64}
65
66impl<'t> TextTokenSource<'t> {
67 /// Generate input from tokens(expect comment and whitespace).
68 pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> TextTokenSource<'t> {
69 let token_offset_pairs: Vec<_> = raw_tokens
70 .iter()
71 .filter_map({
72 let mut len = 0.into();
73 move |token| {
74 let pair = if token.kind.is_trivia() { None } else { Some((*token, len)) };
75 len += token.len;
76 pair
77 }
78 })
79 .collect();
80
81 let first = mk_token(0, &token_offset_pairs);
82 TextTokenSource { text, token_offset_pairs, curr: (first, 0) }
83 }
84}
diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs
new file mode 100644
index 000000000..c1b5f246d
--- /dev/null
+++ b/crates/syntax/src/parsing/text_tree_sink.rs
@@ -0,0 +1,183 @@
1//! FIXME: write short doc here
2
3use std::mem;
4
5use parser::{ParseError, TreeSink};
6
7use crate::{
8 parsing::Token,
9 syntax_node::GreenNode,
10 SmolStr, SyntaxError,
11 SyntaxKind::{self, *},
12 SyntaxTreeBuilder, TextRange, TextSize,
13};
14
15/// Bridges the parser with our specific syntax tree representation.
16///
17/// `TextTreeSink` also handles attachment of trivia (whitespace) to nodes.
18pub(crate) struct TextTreeSink<'a> {
19 text: &'a str,
20 tokens: &'a [Token],
21 text_pos: TextSize,
22 token_pos: usize,
23 state: State,
24 inner: SyntaxTreeBuilder,
25}
26
27enum State {
28 PendingStart,
29 Normal,
30 PendingFinish,
31}
32
33impl<'a> TreeSink for TextTreeSink<'a> {
34 fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
35 match mem::replace(&mut self.state, State::Normal) {
36 State::PendingStart => unreachable!(),
37 State::PendingFinish => self.inner.finish_node(),
38 State::Normal => (),
39 }
40 self.eat_trivias();
41 let n_tokens = n_tokens as usize;
42 let len = self.tokens[self.token_pos..self.token_pos + n_tokens]
43 .iter()
44 .map(|it| it.len)
45 .sum::<TextSize>();
46 self.do_token(kind, len, n_tokens);
47 }
48
49 fn start_node(&mut self, kind: SyntaxKind) {
50 match mem::replace(&mut self.state, State::Normal) {
51 State::PendingStart => {
52 self.inner.start_node(kind);
53 // No need to attach trivias to previous node: there is no
54 // previous node.
55 return;
56 }
57 State::PendingFinish => self.inner.finish_node(),
58 State::Normal => (),
59 }
60
61 let n_trivias =
62 self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count();
63 let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
64 let mut trivia_end =
65 self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextSize>();
66
67 let n_attached_trivias = {
68 let leading_trivias = leading_trivias.iter().rev().map(|it| {
69 let next_end = trivia_end - it.len;
70 let range = TextRange::new(next_end, trivia_end);
71 trivia_end = next_end;
72 (it.kind, &self.text[range])
73 });
74 n_attached_trivias(kind, leading_trivias)
75 };
76 self.eat_n_trivias(n_trivias - n_attached_trivias);
77 self.inner.start_node(kind);
78 self.eat_n_trivias(n_attached_trivias);
79 }
80
81 fn finish_node(&mut self) {
82 match mem::replace(&mut self.state, State::PendingFinish) {
83 State::PendingStart => unreachable!(),
84 State::PendingFinish => self.inner.finish_node(),
85 State::Normal => (),
86 }
87 }
88
89 fn error(&mut self, error: ParseError) {
90 self.inner.error(error, self.text_pos)
91 }
92}
93
94impl<'a> TextTreeSink<'a> {
95 pub(super) fn new(text: &'a str, tokens: &'a [Token]) -> Self {
96 Self {
97 text,
98 tokens,
99 text_pos: 0.into(),
100 token_pos: 0,
101 state: State::PendingStart,
102 inner: SyntaxTreeBuilder::default(),
103 }
104 }
105
106 pub(super) fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
107 match mem::replace(&mut self.state, State::Normal) {
108 State::PendingFinish => {
109 self.eat_trivias();
110 self.inner.finish_node()
111 }
112 State::PendingStart | State::Normal => unreachable!(),
113 }
114
115 self.inner.finish_raw()
116 }
117
118 fn eat_trivias(&mut self) {
119 while let Some(&token) = self.tokens.get(self.token_pos) {
120 if !token.kind.is_trivia() {
121 break;
122 }
123 self.do_token(token.kind, token.len, 1);
124 }
125 }
126
127 fn eat_n_trivias(&mut self, n: usize) {
128 for _ in 0..n {
129 let token = self.tokens[self.token_pos];
130 assert!(token.kind.is_trivia());
131 self.do_token(token.kind, token.len, 1);
132 }
133 }
134
135 fn do_token(&mut self, kind: SyntaxKind, len: TextSize, n_tokens: usize) {
136 let range = TextRange::at(self.text_pos, len);
137 let text: SmolStr = self.text[range].into();
138 self.text_pos += len;
139 self.token_pos += n_tokens;
140 self.inner.token(kind, text);
141 }
142}
143
144fn n_attached_trivias<'a>(
145 kind: SyntaxKind,
146 trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
147) -> usize {
148 match kind {
149 MACRO_CALL | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT | MODULE
150 | RECORD_FIELD | STATIC => {
151 let mut res = 0;
152 let mut trivias = trivias.enumerate().peekable();
153
154 while let Some((i, (kind, text))) = trivias.next() {
155 match kind {
156 WHITESPACE => {
157 if text.contains("\n\n") {
158 // we check whether the next token is a doc-comment
159 // and skip the whitespace in this case
160 if let Some((peek_kind, peek_text)) =
161 trivias.peek().map(|(_, pair)| pair)
162 {
163 if *peek_kind == COMMENT
164 && peek_text.starts_with("///")
165 && !peek_text.starts_with("////")
166 {
167 continue;
168 }
169 }
170 break;
171 }
172 }
173 COMMENT => {
174 res = i + 1;
175 }
176 _ => (),
177 }
178 }
179 res
180 }
181 _ => 0,
182 }
183}
diff --git a/crates/syntax/src/ptr.rs b/crates/syntax/src/ptr.rs
new file mode 100644
index 000000000..ca7957747
--- /dev/null
+++ b/crates/syntax/src/ptr.rs
@@ -0,0 +1,105 @@
1//! FIXME: write short doc here
2
3use std::{
4 hash::{Hash, Hasher},
5 iter::successors,
6 marker::PhantomData,
7};
8
9use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange};
10
11/// A pointer to a syntax node inside a file. It can be used to remember a
12/// specific node across reparses of the same file.
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct SyntaxNodePtr {
15 pub(crate) range: TextRange,
16 kind: SyntaxKind,
17}
18
19impl SyntaxNodePtr {
20 pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
21 SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
22 }
23
24 pub fn to_node(&self, root: &SyntaxNode) -> SyntaxNode {
25 assert!(root.parent().is_none());
26 successors(Some(root.clone()), |node| {
27 node.children().find(|it| it.text_range().contains_range(self.range))
28 })
29 .find(|it| it.text_range() == self.range && it.kind() == self.kind)
30 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
31 }
32
33 pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
34 if !N::can_cast(self.kind) {
35 return None;
36 }
37 Some(AstPtr { raw: self, _ty: PhantomData })
38 }
39}
40
41/// Like `SyntaxNodePtr`, but remembers the type of node
42#[derive(Debug)]
43pub struct AstPtr<N: AstNode> {
44 raw: SyntaxNodePtr,
45 _ty: PhantomData<fn() -> N>,
46}
47
48impl<N: AstNode> Clone for AstPtr<N> {
49 fn clone(&self) -> AstPtr<N> {
50 AstPtr { raw: self.raw.clone(), _ty: PhantomData }
51 }
52}
53
54impl<N: AstNode> Eq for AstPtr<N> {}
55
56impl<N: AstNode> PartialEq for AstPtr<N> {
57 fn eq(&self, other: &AstPtr<N>) -> bool {
58 self.raw == other.raw
59 }
60}
61
62impl<N: AstNode> Hash for AstPtr<N> {
63 fn hash<H: Hasher>(&self, state: &mut H) {
64 self.raw.hash(state)
65 }
66}
67
68impl<N: AstNode> AstPtr<N> {
69 pub fn new(node: &N) -> AstPtr<N> {
70 AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }
71 }
72
73 pub fn to_node(&self, root: &SyntaxNode) -> N {
74 let syntax_node = self.raw.to_node(root);
75 N::cast(syntax_node).unwrap()
76 }
77
78 pub fn syntax_node_ptr(&self) -> SyntaxNodePtr {
79 self.raw.clone()
80 }
81
82 pub fn cast<U: AstNode>(self) -> Option<AstPtr<U>> {
83 if !U::can_cast(self.raw.kind) {
84 return None;
85 }
86 Some(AstPtr { raw: self.raw, _ty: PhantomData })
87 }
88}
89
90impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr {
91 fn from(ptr: AstPtr<N>) -> SyntaxNodePtr {
92 ptr.raw
93 }
94}
95
96#[test]
97fn test_local_syntax_ptr() {
98 use crate::{ast, AstNode, SourceFile};
99
100 let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap();
101 let field = file.syntax().descendants().find_map(ast::RecordField::cast).unwrap();
102 let ptr = SyntaxNodePtr::new(field.syntax());
103 let field_syntax = ptr.to_node(file.syntax());
104 assert_eq!(field.syntax(), &field_syntax);
105}
diff --git a/crates/syntax/src/syntax_error.rs b/crates/syntax/src/syntax_error.rs
new file mode 100644
index 000000000..7c4511fec
--- /dev/null
+++ b/crates/syntax/src/syntax_error.rs
@@ -0,0 +1,44 @@
1//! See docs for `SyntaxError`.
2
3use std::fmt;
4
5use crate::{TextRange, TextSize};
6
7/// Represents the result of unsuccessful tokenization, parsing
8/// or tree validation.
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct SyntaxError(String, TextRange);
11
12// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
13// It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
14// but it was not removed by a mistake.
15//
16// So, we need to find a place where to stick validation for attributes in match clauses.
17// Code before refactor:
18// InvalidMatchInnerAttr => {
19// write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
20// }
21
22impl SyntaxError {
23 pub fn new(message: impl Into<String>, range: TextRange) -> Self {
24 Self(message.into(), range)
25 }
26 pub fn new_at_offset(message: impl Into<String>, offset: TextSize) -> Self {
27 Self(message.into(), TextRange::empty(offset))
28 }
29
30 pub fn range(&self) -> TextRange {
31 self.1
32 }
33
34 pub fn with_range(mut self, range: TextRange) -> Self {
35 self.1 = range;
36 self
37 }
38}
39
40impl fmt::Display for SyntaxError {
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 self.0.fmt(f)
43 }
44}
diff --git a/crates/syntax/src/syntax_node.rs b/crates/syntax/src/syntax_node.rs
new file mode 100644
index 000000000..b2abcbfbb
--- /dev/null
+++ b/crates/syntax/src/syntax_node.rs
@@ -0,0 +1,77 @@
1//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
2//!
3//! The CST includes comments and whitespace, provides a single node type,
4//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
5//!
6//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
7//! module just wraps its API.
8
9use rowan::{GreenNodeBuilder, Language};
10
11use crate::{Parse, SmolStr, SyntaxError, SyntaxKind, TextSize};
12
13pub use rowan::GreenNode;
14
15pub(crate) use rowan::GreenToken;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub enum RustLanguage {}
19impl Language for RustLanguage {
20 type Kind = SyntaxKind;
21
22 fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
23 SyntaxKind::from(raw.0)
24 }
25
26 fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind {
27 rowan::SyntaxKind(kind.into())
28 }
29}
30
31pub type SyntaxNode = rowan::SyntaxNode<RustLanguage>;
32pub type SyntaxToken = rowan::SyntaxToken<RustLanguage>;
33pub type SyntaxElement = rowan::SyntaxElement<RustLanguage>;
34pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<RustLanguage>;
35pub type SyntaxElementChildren = rowan::SyntaxElementChildren<RustLanguage>;
36
37pub use rowan::{Direction, NodeOrToken};
38
39#[derive(Default)]
40pub struct SyntaxTreeBuilder {
41 errors: Vec<SyntaxError>,
42 inner: GreenNodeBuilder<'static>,
43}
44
45impl SyntaxTreeBuilder {
46 pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
47 let green = self.inner.finish();
48 (green, self.errors)
49 }
50
51 pub fn finish(self) -> Parse<SyntaxNode> {
52 let (green, errors) = self.finish_raw();
53 if cfg!(debug_assertions) {
54 let node = SyntaxNode::new_root(green.clone());
55 crate::validation::validate_block_structure(&node);
56 }
57 Parse::new(green, errors)
58 }
59
60 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {
61 let kind = RustLanguage::kind_to_raw(kind);
62 self.inner.token(kind, text)
63 }
64
65 pub fn start_node(&mut self, kind: SyntaxKind) {
66 let kind = RustLanguage::kind_to_raw(kind);
67 self.inner.start_node(kind)
68 }
69
70 pub fn finish_node(&mut self) {
71 self.inner.finish_node()
72 }
73
74 pub fn error(&mut self, error: parser::ParseError, text_pos: TextSize) {
75 self.errors.push(SyntaxError::new_at_offset(*error.0, text_pos))
76 }
77}
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
new file mode 100644
index 000000000..8c217dfe0
--- /dev/null
+++ b/crates/syntax/src/tests.rs
@@ -0,0 +1,280 @@
1use std::{
2 fmt::Write,
3 fs,
4 path::{Path, PathBuf},
5};
6
7use expect_test::expect_file;
8use rayon::prelude::*;
9use test_utils::project_dir;
10
11use crate::{fuzz, tokenize, SourceFile, SyntaxError, TextRange, TextSize, Token};
12
13#[test]
14fn lexer_tests() {
15 // FIXME:
16 // * Add tests for unicode escapes in byte-character and [raw]-byte-string literals
17 // * Add tests for unescape errors
18
19 dir_tests(&test_data_dir(), &["lexer/ok"], "txt", |text, path| {
20 let (tokens, errors) = tokenize(text);
21 assert_errors_are_absent(&errors, path);
22 dump_tokens_and_errors(&tokens, &errors, text)
23 });
24 dir_tests(&test_data_dir(), &["lexer/err"], "txt", |text, path| {
25 let (tokens, errors) = tokenize(text);
26 assert_errors_are_present(&errors, path);
27 dump_tokens_and_errors(&tokens, &errors, text)
28 });
29}
30
31#[test]
32fn parse_smoke_test() {
33 let code = r##"
34fn main() {
35 println!("Hello, world!")
36}
37 "##;
38
39 let parse = SourceFile::parse(code);
40 // eprintln!("{:#?}", parse.syntax_node());
41 assert!(parse.ok().is_ok());
42}
43
44#[test]
45fn parser_tests() {
46 dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], "rast", |text, path| {
47 let parse = SourceFile::parse(text);
48 let errors = parse.errors();
49 assert_errors_are_absent(&errors, path);
50 parse.debug_dump()
51 });
52 dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], "rast", |text, path| {
53 let parse = SourceFile::parse(text);
54 let errors = parse.errors();
55 assert_errors_are_present(&errors, path);
56 parse.debug_dump()
57 });
58}
59
60#[test]
61fn expr_parser_tests() {
62 fragment_parser_dir_test(
63 &["parser/fragments/expr/ok"],
64 &["parser/fragments/expr/err"],
65 crate::ast::Expr::parse,
66 );
67}
68
69#[test]
70fn path_parser_tests() {
71 fragment_parser_dir_test(
72 &["parser/fragments/path/ok"],
73 &["parser/fragments/path/err"],
74 crate::ast::Path::parse,
75 );
76}
77
78#[test]
79fn pattern_parser_tests() {
80 fragment_parser_dir_test(
81 &["parser/fragments/pattern/ok"],
82 &["parser/fragments/pattern/err"],
83 crate::ast::Pat::parse,
84 );
85}
86
87#[test]
88fn item_parser_tests() {
89 fragment_parser_dir_test(
90 &["parser/fragments/item/ok"],
91 &["parser/fragments/item/err"],
92 crate::ast::Item::parse,
93 );
94}
95
96#[test]
97fn type_parser_tests() {
98 fragment_parser_dir_test(
99 &["parser/fragments/type/ok"],
100 &["parser/fragments/type/err"],
101 crate::ast::Type::parse,
102 );
103}
104
105#[test]
106fn parser_fuzz_tests() {
107 for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) {
108 fuzz::check_parser(&text)
109 }
110}
111
112#[test]
113fn reparse_fuzz_tests() {
114 for (_, text) in collect_rust_files(&test_data_dir(), &["reparse/fuzz-failures"]) {
115 let check = fuzz::CheckReparse::from_data(text.as_bytes()).unwrap();
116 println!("{:?}", check);
117 check.run();
118 }
119}
120
121/// Test that Rust-analyzer can parse and validate the rust-analyzer
122/// FIXME: Use this as a benchmark
123#[test]
124fn self_hosting_parsing() {
125 let dir = project_dir().join("crates");
126 let files = walkdir::WalkDir::new(dir)
127 .into_iter()
128 .filter_entry(|entry| {
129 // Get all files which are not in the crates/syntax/test_data folder
130 !entry.path().components().any(|component| component.as_os_str() == "test_data")
131 })
132 .map(|e| e.unwrap())
133 .filter(|entry| {
134 // Get all `.rs ` files
135 !entry.path().is_dir() && (entry.path().extension().unwrap_or_default() == "rs")
136 })
137 .map(|entry| entry.into_path())
138 .collect::<Vec<_>>();
139 assert!(
140 files.len() > 100,
141 "self_hosting_parsing found too few files - is it running in the right directory?"
142 );
143
144 let errors = files
145 .into_par_iter()
146 .filter_map(|file| {
147 let text = read_text(&file);
148 match SourceFile::parse(&text).ok() {
149 Ok(_) => None,
150 Err(err) => Some((file, err)),
151 }
152 })
153 .collect::<Vec<_>>();
154
155 if !errors.is_empty() {
156 let errors = errors
157 .into_iter()
158 .map(|(path, err)| format!("{}: {:?}\n", path.display(), err))
159 .collect::<String>();
160 panic!("Parsing errors:\n{}\n", errors);
161 }
162}
163
164fn test_data_dir() -> PathBuf {
165 project_dir().join("crates/syntax/test_data")
166}
167
168fn assert_errors_are_present(errors: &[SyntaxError], path: &Path) {
169 assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display());
170}
171fn assert_errors_are_absent(errors: &[SyntaxError], path: &Path) {
172 assert_eq!(
173 errors,
174 &[] as &[SyntaxError],
175 "There should be no errors in the file {:?}",
176 path.display(),
177 );
178}
179
180fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str) -> String {
181 let mut acc = String::new();
182 let mut offset: TextSize = 0.into();
183 for token in tokens {
184 let token_len = token.len;
185 let token_text = &text[TextRange::at(offset, token.len)];
186 offset += token.len;
187 writeln!(acc, "{:?} {:?} {:?}", token.kind, token_len, token_text).unwrap();
188 }
189 for err in errors {
190 writeln!(acc, "> error{:?} token({:?}) msg({})", err.range(), &text[err.range()], err)
191 .unwrap();
192 }
193 acc
194}
195
196fn fragment_parser_dir_test<T, F>(ok_paths: &[&str], err_paths: &[&str], f: F)
197where
198 T: crate::AstNode,
199 F: Fn(&str) -> Result<T, ()>,
200{
201 dir_tests(&test_data_dir(), ok_paths, "rast", |text, path| {
202 if let Ok(node) = f(text) {
203 format!("{:#?}", crate::ast::AstNode::syntax(&node))
204 } else {
205 panic!("Failed to parse '{:?}'", path);
206 }
207 });
208 dir_tests(&test_data_dir(), err_paths, "rast", |text, path| {
209 if let Ok(_) = f(text) {
210 panic!("'{:?}' successfully parsed when it should have errored", path);
211 } else {
212 "ERROR\n".to_owned()
213 }
214 });
215}
216
217/// Calls callback `f` with input code and file paths for each `.rs` file in `test_data_dir`
218/// subdirectories defined by `paths`.
219///
220/// If the content of the matching output file differs from the output of `f()`
221/// the test will fail.
222///
223/// If there is no matching output file it will be created and filled with the
224/// output of `f()`, but the test will fail.
225fn dir_tests<F>(test_data_dir: &Path, paths: &[&str], outfile_extension: &str, f: F)
226where
227 F: Fn(&str, &Path) -> String,
228{
229 for (path, input_code) in collect_rust_files(test_data_dir, paths) {
230 let actual = f(&input_code, &path);
231 let path = path.with_extension(outfile_extension);
232 expect_file![path].assert_eq(&actual)
233 }
234}
235
236/// Collects all `.rs` files from `dir` subdirectories defined by `paths`.
237fn collect_rust_files(root_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, String)> {
238 paths
239 .iter()
240 .flat_map(|path| {
241 let path = root_dir.to_owned().join(path);
242 rust_files_in_dir(&path).into_iter()
243 })
244 .map(|path| {
245 let text = read_text(&path);
246 (path, text)
247 })
248 .collect()
249}
250
251/// Collects paths to all `.rs` files from `dir` in a sorted `Vec<PathBuf>`.
252fn rust_files_in_dir(dir: &Path) -> Vec<PathBuf> {
253 let mut acc = Vec::new();
254 for file in fs::read_dir(&dir).unwrap() {
255 let file = file.unwrap();
256 let path = file.path();
257 if path.extension().unwrap_or_default() == "rs" {
258 acc.push(path);
259 }
260 }
261 acc.sort();
262 acc
263}
264
265/// Read file and normalize newlines.
266///
267/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
268///
269/// ```
270/// let s = "
271/// ";
272/// assert_eq!(s.as_bytes(), &[10]);
273/// ```
274///
275/// so this should always be correct.
276fn read_text(path: &Path) -> String {
277 fs::read_to_string(path)
278 .unwrap_or_else(|_| panic!("File at {:?} should be valid", path))
279 .replace("\r\n", "\n")
280}
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
new file mode 100644
index 000000000..2dddaf09a
--- /dev/null
+++ b/crates/syntax/src/validation.rs
@@ -0,0 +1,303 @@
1//! FIXME: write short doc here
2
3mod block;
4
5use crate::{
6 ast, match_ast, AstNode, SyntaxError,
7 SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST, FN, INT_NUMBER, STRING, TYPE_ALIAS},
8 SyntaxNode, SyntaxToken, TextSize, T,
9};
10use rustc_lexer::unescape::{
11 self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
12};
13use std::convert::TryFrom;
14
15fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str {
16 use unescape::EscapeError as EE;
17
18 #[rustfmt::skip]
19 let err_message = match err {
20 EE::ZeroChars => {
21 "Literal must not be empty"
22 }
23 EE::MoreThanOneChar => {
24 "Literal must be one character long"
25 }
26 EE::LoneSlash => {
27 "Character must be escaped: `\\`"
28 }
29 EE::InvalidEscape => {
30 "Invalid escape"
31 }
32 EE::BareCarriageReturn | EE::BareCarriageReturnInRawString => {
33 "Character must be escaped: `\r`"
34 }
35 EE::EscapeOnlyChar => {
36 "Escape character `\\` must be escaped itself"
37 }
38 EE::TooShortHexEscape => {
39 "ASCII hex escape code must have exactly two digits"
40 }
41 EE::InvalidCharInHexEscape => {
42 "ASCII hex escape code must contain only hex characters"
43 }
44 EE::OutOfRangeHexEscape => {
45 "ASCII hex escape code must be at most 0x7F"
46 }
47 EE::NoBraceInUnicodeEscape => {
48 "Missing `{` to begin the unicode escape"
49 }
50 EE::InvalidCharInUnicodeEscape => {
51 "Unicode escape must contain only hex characters and underscores"
52 }
53 EE::EmptyUnicodeEscape => {
54 "Unicode escape must not be empty"
55 }
56 EE::UnclosedUnicodeEscape => {
57 "Missing `}` to terminate the unicode escape"
58 }
59 EE::LeadingUnderscoreUnicodeEscape => {
60 "Unicode escape code must not begin with an underscore"
61 }
62 EE::OverlongUnicodeEscape => {
63 "Unicode escape code must have at most 6 digits"
64 }
65 EE::LoneSurrogateUnicodeEscape => {
66 "Unicode escape code must not be a surrogate"
67 }
68 EE::OutOfRangeUnicodeEscape => {
69 "Unicode escape code must be at most 0x10FFFF"
70 }
71 EE::UnicodeEscapeInByte => {
72 "Byte literals must not contain unicode escapes"
73 }
74 EE::NonAsciiCharInByte | EE::NonAsciiCharInByteString => {
75 "Byte literals must not contain non-ASCII characters"
76 }
77 };
78
79 err_message
80}
81
82pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
83 // FIXME:
84 // * Add unescape validation of raw string literals and raw byte string literals
85 // * Add validation of doc comments are being attached to nodes
86
87 let mut errors = Vec::new();
88 for node in root.descendants() {
89 match_ast! {
90 match node {
91 ast::Literal(it) => validate_literal(it, &mut errors),
92 ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors),
93 ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors),
94 ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors),
95 ast::Visibility(it) => validate_visibility(it, &mut errors),
96 ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
97 ast::PathSegment(it) => validate_path_keywords(it, &mut errors),
98 _ => (),
99 }
100 }
101 }
102 errors
103}
104
105fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
106 // FIXME: move this function to outer scope (https://github.com/rust-analyzer/rust-analyzer/pull/2834#discussion_r366196658)
107 fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
108 text.rfind(end_delimiter).and_then(|end| text.get(prefix_len..end))
109 }
110
111 let token = literal.token();
112 let text = token.text().as_str();
113
114 // FIXME: lift this lambda refactor to `fn` (https://github.com/rust-analyzer/rust-analyzer/pull/2834#discussion_r366199205)
115 let mut push_err = |prefix_len, (off, err): (usize, unescape::EscapeError)| {
116 let off = token.text_range().start() + TextSize::try_from(off + prefix_len).unwrap();
117 acc.push(SyntaxError::new_at_offset(rustc_unescape_error_to_string(err), off));
118 };
119
120 match token.kind() {
121 BYTE => {
122 if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
123 push_err(2, e);
124 }
125 }
126 CHAR => {
127 if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
128 push_err(1, e);
129 }
130 }
131 BYTE_STRING => {
132 if let Some(without_quotes) = unquote(text, 2, '"') {
133 unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
134 if let Err(err) = char {
135 push_err(2, (range.start, err));
136 }
137 })
138 }
139 }
140 STRING => {
141 if let Some(without_quotes) = unquote(text, 1, '"') {
142 unescape_literal(without_quotes, Mode::Str, &mut |range, char| {
143 if let Err(err) = char {
144 push_err(1, (range.start, err));
145 }
146 })
147 }
148 }
149 _ => (),
150 }
151}
152
153pub(crate) fn validate_block_structure(root: &SyntaxNode) {
154 let mut stack = Vec::new();
155 for node in root.descendants() {
156 match node.kind() {
157 T!['{'] => stack.push(node),
158 T!['}'] => {
159 if let Some(pair) = stack.pop() {
160 assert_eq!(
161 node.parent(),
162 pair.parent(),
163 "\nunpaired curleys:\n{}\n{:#?}\n",
164 root.text(),
165 root,
166 );
167 assert!(
168 node.next_sibling().is_none() && pair.prev_sibling().is_none(),
169 "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
170 node,
171 root.text(),
172 node.text(),
173 );
174 }
175 }
176 _ => (),
177 }
178 }
179}
180
181fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<SyntaxError>) {
182 if let Some(int_token) = int_token(name_ref) {
183 if int_token.text().chars().any(|c| !c.is_digit(10)) {
184 errors.push(SyntaxError::new(
185 "Tuple (struct) field access is only allowed through \
186 decimal integers with no underscores or suffix",
187 int_token.text_range(),
188 ));
189 }
190 }
191
192 fn int_token(name_ref: Option<ast::NameRef>) -> Option<SyntaxToken> {
193 name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER)
194 }
195}
196
197fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) {
198 let parent = match vis.syntax().parent() {
199 Some(it) => it,
200 None => return,
201 };
202 match parent.kind() {
203 FN | CONST | TYPE_ALIAS => (),
204 _ => return,
205 }
206
207 let impl_def = match parent.parent().and_then(|it| it.parent()).and_then(ast::Impl::cast) {
208 Some(it) => it,
209 None => return,
210 };
211 if impl_def.trait_().is_some() {
212 errors.push(SyntaxError::new("Unnecessary visibility qualifier", vis.syntax.text_range()));
213 }
214}
215
216fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) {
217 if expr.op_kind() == Some(ast::RangeOp::Inclusive) && expr.end().is_none() {
218 errors.push(SyntaxError::new(
219 "An inclusive range must have an end expression",
220 expr.syntax().text_range(),
221 ));
222 }
223}
224
225fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxError>) {
226 use ast::PathSegmentKind;
227
228 let path = segment.parent_path();
229 let is_path_start = segment.coloncolon_token().is_none() && path.qualifier().is_none();
230
231 if let Some(token) = segment.self_token() {
232 if !is_path_start {
233 errors.push(SyntaxError::new(
234 "The `self` keyword is only allowed as the first segment of a path",
235 token.text_range(),
236 ));
237 }
238 } else if let Some(token) = segment.crate_token() {
239 if !is_path_start || use_prefix(path).is_some() {
240 errors.push(SyntaxError::new(
241 "The `crate` keyword is only allowed as the first segment of a path",
242 token.text_range(),
243 ));
244 }
245 } else if let Some(token) = segment.super_token() {
246 if !all_supers(&path) {
247 errors.push(SyntaxError::new(
248 "The `super` keyword may only be preceded by other `super`s",
249 token.text_range(),
250 ));
251 return;
252 }
253
254 let mut curr_path = path;
255 while let Some(prefix) = use_prefix(curr_path) {
256 if !all_supers(&prefix) {
257 errors.push(SyntaxError::new(
258 "The `super` keyword may only be preceded by other `super`s",
259 token.text_range(),
260 ));
261 return;
262 }
263 curr_path = prefix;
264 }
265 }
266
267 fn use_prefix(mut path: ast::Path) -> Option<ast::Path> {
268 for node in path.syntax().ancestors().skip(1) {
269 match_ast! {
270 match node {
271 ast::UseTree(it) => if let Some(tree_path) = it.path() {
272 // Even a top-level path exists within a `UseTree` so we must explicitly
273 // allow our path but disallow anything else
274 if tree_path != path {
275 return Some(tree_path);
276 }
277 },
278 ast::UseTreeList(_it) => continue,
279 ast::Path(parent) => path = parent,
280 _ => return None,
281 }
282 };
283 }
284 return None;
285 }
286
287 fn all_supers(path: &ast::Path) -> bool {
288 let segment = match path.segment() {
289 Some(it) => it,
290 None => return false,
291 };
292
293 if segment.kind() != Some(PathSegmentKind::SuperKw) {
294 return false;
295 }
296
297 if let Some(ref subpath) = path.qualifier() {
298 return all_supers(subpath);
299 }
300
301 return true;
302 }
303}
diff --git a/crates/syntax/src/validation/block.rs b/crates/syntax/src/validation/block.rs
new file mode 100644
index 000000000..ad9901468
--- /dev/null
+++ b/crates/syntax/src/validation/block.rs
@@ -0,0 +1,22 @@
1//! Logic for validating block expressions i.e. `ast::BlockExpr`.
2
3use crate::{
4 ast::{self, AstNode, AttrsOwner},
5 SyntaxError,
6 SyntaxKind::*,
7};
8
9pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
10 if let Some(parent) = block.syntax().parent() {
11 match parent.kind() {
12 FN | EXPR_STMT | BLOCK_EXPR => return,
13 _ => {}
14 }
15 }
16 errors.extend(block.attrs().map(|attr| {
17 SyntaxError::new(
18 "A block in this position cannot accept inner attributes",
19 attr.syntax().text_range(),
20 )
21 }))
22}