aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_syntax/src/ast.rs114
-rw-r--r--crates/ra_syntax/src/ast/tokens.rs62
-rw-r--r--xtask/src/codegen/gen_syntax.rs298
3 files changed, 380 insertions, 94 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 26fafb469..1ac0201b8 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -11,7 +11,10 @@ pub mod make;
11use std::marker::PhantomData; 11use std::marker::PhantomData;
12 12
13use crate::{ 13use crate::{
14 syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken}, 14 syntax_node::{
15 NodeOrToken, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren,
16 SyntaxToken,
17 },
15 SmolStr, SyntaxKind, 18 SmolStr, SyntaxKind,
16}; 19};
17 20
@@ -30,16 +33,24 @@ pub use self::{
30/// conversion itself has zero runtime cost: ast and syntax nodes have exactly 33/// 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 34/// the same representation: a pointer to the tree root and a pointer to the
32/// node itself. 35/// node itself.
33pub trait AstNode: std::fmt::Display { 36pub trait AstNode: AstElement {
34 fn can_cast(kind: SyntaxKind) -> bool 37 fn can_cast(kind: SyntaxKind) -> bool
35 where 38 where
36 Self: Sized; 39 Self: Sized;
37 40
38 fn cast(syntax: SyntaxNode) -> Option<Self> 41 fn cast_or_return(syntax: SyntaxNode) -> Result<Self, SyntaxNode>
39 where 42 where
40 Self: Sized; 43 Self: Sized;
41 44
45 fn cast(syntax: SyntaxNode) -> Option<Self>
46 where
47 Self: Sized,
48 {
49 <Self as AstNode>::cast_or_return(syntax).ok()
50 }
51
42 fn syntax(&self) -> &SyntaxNode; 52 fn syntax(&self) -> &SyntaxNode;
53 fn into_syntax(self) -> SyntaxNode;
43} 54}
44 55
45#[test] 56#[test]
@@ -48,16 +59,51 @@ fn assert_ast_is_object_safe() {
48} 59}
49 60
50/// Like `AstNode`, but wraps tokens rather than interior nodes. 61/// Like `AstNode`, but wraps tokens rather than interior nodes.
51pub trait AstToken { 62pub trait AstToken: AstElement {
52 fn cast(token: SyntaxToken) -> Option<Self> 63 fn can_cast(token: SyntaxKind) -> bool
53 where 64 where
54 Self: Sized; 65 Self: Sized;
66
67 fn cast_or_return(syntax: SyntaxToken) -> Result<Self, SyntaxToken>
68 where
69 Self: Sized;
70
71 fn cast(syntax: SyntaxToken) -> Option<Self>
72 where
73 Self: Sized,
74 {
75 <Self as AstToken>::cast_or_return(syntax).ok()
76 }
77
55 fn syntax(&self) -> &SyntaxToken; 78 fn syntax(&self) -> &SyntaxToken;
79 fn into_syntax(self) -> SyntaxToken;
80
56 fn text(&self) -> &SmolStr { 81 fn text(&self) -> &SmolStr {
57 self.syntax().text() 82 self.syntax().text()
58 } 83 }
59} 84}
60 85
86/// Like `AstNode`, but wraps either nodes or tokens rather than interior nodes.
87pub trait AstElement: std::fmt::Display {
88 fn can_cast_element(kind: SyntaxKind) -> bool
89 where
90 Self: Sized;
91
92 fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement>
93 where
94 Self: Sized;
95
96 fn cast_element(syntax: SyntaxElement) -> Option<Self>
97 where
98 Self: Sized,
99 {
100 <Self as AstElement>::cast_or_return_element(syntax).ok()
101 }
102
103 fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken>;
104 fn into_syntax_element(self) -> SyntaxElement;
105}
106
61/// An iterator over `SyntaxNode` children of a particular AST type. 107/// An iterator over `SyntaxNode` children of a particular AST type.
62#[derive(Debug, Clone)] 108#[derive(Debug, Clone)]
63pub struct AstChildren<N> { 109pub struct AstChildren<N> {
@@ -86,6 +132,64 @@ fn children<P: AstNode + ?Sized, C: AstNode>(parent: &P) -> AstChildren<C> {
86 AstChildren::new(parent.syntax()) 132 AstChildren::new(parent.syntax())
87} 133}
88 134
135/// An iterator over `SyntaxToken` children of a particular AST type.
136#[derive(Debug, Clone)]
137pub struct AstChildTokens<N> {
138 inner: SyntaxElementChildren,
139 ph: PhantomData<N>,
140}
141
142impl<N> AstChildTokens<N> {
143 fn new(parent: &SyntaxNode) -> Self {
144 AstChildTokens { inner: parent.children_with_tokens(), ph: PhantomData }
145 }
146}
147
148impl<N: AstToken> Iterator for AstChildTokens<N> {
149 type Item = N;
150 fn next(&mut self) -> Option<N> {
151 self.inner.by_ref().filter_map(|x| x.into_token()).find_map(N::cast)
152 }
153}
154
155fn child_token_opt<P: AstNode + ?Sized, C: AstToken>(parent: &P) -> Option<C> {
156 child_tokens(parent).next()
157}
158
159fn child_tokens<P: AstNode + ?Sized, C: AstToken>(parent: &P) -> AstChildTokens<C> {
160 AstChildTokens::new(parent.syntax())
161}
162
163/// An iterator over `SyntaxNode` children of a particular AST type.
164#[derive(Debug, Clone)]
165pub struct AstChildElements<N> {
166 inner: SyntaxElementChildren,
167 ph: PhantomData<N>,
168}
169
170impl<N> AstChildElements<N> {
171 fn new(parent: &SyntaxNode) -> Self {
172 AstChildElements { inner: parent.children_with_tokens(), ph: PhantomData }
173 }
174}
175
176impl<N: AstElement> Iterator for AstChildElements<N> {
177 type Item = N;
178 fn next(&mut self) -> Option<N> {
179 self.inner.by_ref().find_map(N::cast_element)
180 }
181}
182
183#[allow(dead_code)]
184fn child_element_opt<P: AstNode + ?Sized, C: AstElement>(parent: &P) -> Option<C> {
185 child_elements(parent).next()
186}
187
188#[allow(dead_code)]
189fn child_elements<P: AstNode + ?Sized, C: AstElement>(parent: &P) -> AstChildElements<C> {
190 AstChildElements::new(parent.syntax())
191}
192
89#[test] 193#[test]
90fn test_doc_comment_none() { 194fn test_doc_comment_none() {
91 let file = SourceFile::parse( 195 let file = SourceFile::parse(
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs
index 1a51b8d3b..e8320b57e 100644
--- a/crates/ra_syntax/src/ast/tokens.rs
+++ b/crates/ra_syntax/src/ast/tokens.rs
@@ -1,26 +1,10 @@
1//! There are many AstNodes, but only a few tokens, so we hand-write them here. 1//! There are many AstNodes, but only a few tokens, so we hand-write them here.
2 2
3use crate::{ 3use crate::{
4 ast::AstToken, 4 ast::{AstToken, Comment, RawString, String, Whitespace},
5 SyntaxKind::{COMMENT, RAW_STRING, STRING, WHITESPACE}, 5 TextRange, TextUnit,
6 SyntaxToken, TextRange, TextUnit,
7}; 6};
8 7
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct Comment(SyntaxToken);
11
12impl AstToken for Comment {
13 fn cast(token: SyntaxToken) -> Option<Self> {
14 match token.kind() {
15 COMMENT => Some(Comment(token)),
16 _ => None,
17 }
18 }
19 fn syntax(&self) -> &SyntaxToken {
20 &self.0
21 }
22}
23
24impl Comment { 8impl Comment {
25 pub fn kind(&self) -> CommentKind { 9 pub fn kind(&self) -> CommentKind {
26 kind_by_prefix(self.text()) 10 kind_by_prefix(self.text())
@@ -89,20 +73,6 @@ fn prefix_by_kind(kind: CommentKind) -> &'static str {
89 unreachable!() 73 unreachable!()
90} 74}
91 75
92pub struct Whitespace(SyntaxToken);
93
94impl AstToken for Whitespace {
95 fn cast(token: SyntaxToken) -> Option<Self> {
96 match token.kind() {
97 WHITESPACE => Some(Whitespace(token)),
98 _ => None,
99 }
100 }
101 fn syntax(&self) -> &SyntaxToken {
102 &self.0
103 }
104}
105
106impl Whitespace { 76impl Whitespace {
107 pub fn spans_multiple_lines(&self) -> bool { 77 pub fn spans_multiple_lines(&self) -> bool {
108 let text = self.text(); 78 let text = self.text();
@@ -168,20 +138,6 @@ pub trait HasStringValue: HasQuotes {
168 fn value(&self) -> Option<std::string::String>; 138 fn value(&self) -> Option<std::string::String>;
169} 139}
170 140
171pub struct String(SyntaxToken);
172
173impl AstToken for String {
174 fn cast(token: SyntaxToken) -> Option<Self> {
175 match token.kind() {
176 STRING => Some(String(token)),
177 _ => None,
178 }
179 }
180 fn syntax(&self) -> &SyntaxToken {
181 &self.0
182 }
183}
184
185impl HasStringValue for String { 141impl HasStringValue for String {
186 fn value(&self) -> Option<std::string::String> { 142 fn value(&self) -> Option<std::string::String> {
187 let text = self.text().as_str(); 143 let text = self.text().as_str();
@@ -201,20 +157,6 @@ impl HasStringValue for String {
201 } 157 }
202} 158}
203 159
204pub struct RawString(SyntaxToken);
205
206impl AstToken for RawString {
207 fn cast(token: SyntaxToken) -> Option<Self> {
208 match token.kind() {
209 RAW_STRING => Some(RawString(token)),
210 _ => None,
211 }
212 }
213 fn syntax(&self) -> &SyntaxToken {
214 &self.0
215 }
216}
217
218impl HasStringValue for RawString { 160impl HasStringValue for RawString {
219 fn value(&self) -> Option<std::string::String> { 161 fn value(&self) -> Option<std::string::String> {
220 let text = self.text().as_str(); 162 let text = self.text().as_str();
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index 32afd47bc..c730c75ee 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -5,6 +5,8 @@
5 5
6use proc_macro2::{Punct, Spacing}; 6use proc_macro2::{Punct, Spacing};
7use quote::{format_ident, quote}; 7use quote::{format_ident, quote};
8use std::borrow::Cow;
9use std::collections::{BTreeSet, HashMap, HashSet};
8 10
9use crate::{ 11use crate::{
10 ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, 12 ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC},
@@ -18,13 +20,125 @@ pub fn generate_syntax(mode: Mode) -> Result<()> {
18 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; 20 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
19 21
20 let ast_file = project_root().join(codegen::AST); 22 let ast_file = project_root().join(codegen::AST);
21 let ast = generate_ast(AST_SRC)?; 23 let ast = generate_ast(KINDS_SRC, AST_SRC)?;
22 update(ast_file.as_path(), &ast, mode)?; 24 update(ast_file.as_path(), &ast, mode)?;
23 25
24 Ok(()) 26 Ok(())
25} 27}
26 28
27fn generate_ast(grammar: AstSrc<'_>) -> Result<String> { 29#[derive(Debug, Default, Clone)]
30struct ElementKinds {
31 kinds: BTreeSet<proc_macro2::Ident>,
32 has_nodes: bool,
33 has_tokens: bool,
34}
35
36fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
37 let all_token_kinds: Vec<_> = kinds
38 .punct
39 .into_iter()
40 .map(|(_, kind)| kind)
41 .copied()
42 .map(|x| x.into())
43 .chain(
44 kinds
45 .keywords
46 .into_iter()
47 .chain(kinds.contextual_keywords.into_iter())
48 .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))),
49 )
50 .chain(kinds.literals.into_iter().copied().map(|x| x.into()))
51 .chain(kinds.tokens.into_iter().copied().map(|x| x.into()))
52 .collect();
53
54 let mut element_kinds_map = HashMap::new();
55 for kind in &all_token_kinds {
56 let kind = &**kind;
57 let name = to_pascal_case(kind);
58 element_kinds_map.insert(
59 name,
60 ElementKinds {
61 kinds: Some(format_ident!("{}", kind)).into_iter().collect(),
62 has_nodes: false,
63 has_tokens: true,
64 },
65 );
66 }
67
68 for kind in kinds.nodes {
69 let name = to_pascal_case(kind);
70 element_kinds_map.insert(
71 name,
72 ElementKinds {
73 kinds: Some(format_ident!("{}", *kind)).into_iter().collect(),
74 has_nodes: true,
75 has_tokens: false,
76 },
77 );
78 }
79
80 for en in grammar.enums {
81 let mut element_kinds: ElementKinds = Default::default();
82 for variant in en.variants {
83 if let Some(variant_element_kinds) = element_kinds_map.get(*variant) {
84 element_kinds.kinds.extend(variant_element_kinds.kinds.iter().cloned());
85 element_kinds.has_tokens |= variant_element_kinds.has_tokens;
86 element_kinds.has_nodes |= variant_element_kinds.has_nodes;
87 } else {
88 panic!("Enum variant has type that does not exist or was not declared before the enum: {}", *variant);
89 }
90 }
91 element_kinds_map.insert(en.name.to_string(), element_kinds);
92 }
93
94 let tokens = all_token_kinds.iter().map(|kind_str| {
95 let kind_str = &**kind_str;
96 let kind = format_ident!("{}", kind_str);
97 let name = format_ident!("{}", to_pascal_case(kind_str));
98 quote! {
99 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
100 pub struct #name(SyntaxToken);
101
102 impl std::fmt::Display for #name {
103 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
104 std::fmt::Display::fmt(self.syntax(), f)
105 }
106 }
107
108 impl AstToken for #name {
109 fn can_cast(kind: SyntaxKind) -> bool {
110 match kind {
111 #kind => true,
112 _ => false,
113 }
114 }
115 fn cast_or_return(syntax: SyntaxToken) -> Result<Self, SyntaxToken> {
116 if Self::can_cast(syntax.kind()) { Ok(Self(syntax)) } else { Err(syntax) }
117 }
118 fn syntax(&self) -> &SyntaxToken { &self.0 }
119 fn into_syntax(self) -> SyntaxToken { self.0 }
120 }
121
122 impl AstElement for #name {
123 fn can_cast_element(kind: SyntaxKind) -> bool {
124 match kind {
125 #kind => true,
126 _ => false,
127 }
128 }
129 fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement> {
130 if Self::can_cast_element(syntax.kind()) { Ok(Self(syntax.into_token().unwrap())) } else { Err(syntax) }
131 }
132 fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken> {
133 NodeOrToken::Token(&self.0)
134 }
135 fn into_syntax_element(self) -> SyntaxElement {
136 NodeOrToken::Token(self.0)
137 }
138 }
139 }
140 });
141
28 let nodes = grammar.nodes.iter().map(|node| { 142 let nodes = grammar.nodes.iter().map(|node| {
29 let name = format_ident!("{}", node.name); 143 let name = format_ident!("{}", node.name);
30 let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); 144 let kind = format_ident!("{}", to_upper_snake_case(&name.to_string()));
@@ -42,20 +156,28 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
42 FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, 156 FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty,
43 FieldSrc::Shorthand => name, 157 FieldSrc::Shorthand => name,
44 }; 158 };
159 let element_kinds = &element_kinds_map.get(*ty).unwrap_or_else(|| panic!("type not found: {}", *ty));
160 let iter = if !element_kinds.has_tokens {
161 format_ident!("AstChildren")
162 } else if !element_kinds.has_nodes {
163 format_ident!("AstChildTokens")
164 } else {
165 format_ident!("AstChildElements")
166 };
45 let ty = format_ident!("{}", ty); 167 let ty = format_ident!("{}", ty);
46 168
47 match field { 169 match field {
48 FieldSrc::Many(_) => { 170 FieldSrc::Many(_) => {
49 quote! { 171 quote! {
50 pub fn #method_name(&self) -> AstChildren<#ty> { 172 pub fn #method_name(&self) -> #iter<#ty> {
51 AstChildren::new(&self.syntax) 173 #iter::new(&self.syntax)
52 } 174 }
53 } 175 }
54 } 176 }
55 FieldSrc::Optional(_) | FieldSrc::Shorthand => { 177 FieldSrc::Optional(_) | FieldSrc::Shorthand => {
56 quote! { 178 quote! {
57 pub fn #method_name(&self) -> Option<#ty> { 179 pub fn #method_name(&self) -> Option<#ty> {
58 AstChildren::new(&self.syntax).next() 180 #iter::new(&self.syntax).next()
59 } 181 }
60 } 182 }
61 } 183 }
@@ -81,11 +203,31 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
81 _ => false, 203 _ => false,
82 } 204 }
83 } 205 }
84 fn cast(syntax: SyntaxNode) -> Option<Self> { 206 fn cast_or_return(syntax: SyntaxNode) -> Result<Self, SyntaxNode> {
85 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } 207 if Self::can_cast(syntax.kind()) { Ok(Self { syntax }) } else { Err(syntax) }
86 } 208 }
87 fn syntax(&self) -> &SyntaxNode { &self.syntax } 209 fn syntax(&self) -> &SyntaxNode { &self.syntax }
210 fn into_syntax(self) -> SyntaxNode { self.syntax }
88 } 211 }
212
213 impl AstElement for #name {
214 fn can_cast_element(kind: SyntaxKind) -> bool {
215 match kind {
216 #kind => true,
217 _ => false,
218 }
219 }
220 fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement> {
221 if Self::can_cast_element(syntax.kind()) { Ok(Self { syntax: syntax.into_node().unwrap() }) } else { Err(syntax) }
222 }
223 fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken> {
224 NodeOrToken::Node(&self.syntax)
225 }
226 fn into_syntax_element(self) -> SyntaxElement {
227 NodeOrToken::Node(self.syntax)
228 }
229 }
230
89 #(#traits)* 231 #(#traits)*
90 232
91 impl #name { 233 impl #name {
@@ -96,16 +238,71 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
96 238
97 let enums = grammar.enums.iter().map(|en| { 239 let enums = grammar.enums.iter().map(|en| {
98 let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); 240 let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
241 let element_kinds = &element_kinds_map[&en.name.to_string()];
99 let name = format_ident!("{}", en.name); 242 let name = format_ident!("{}", en.name);
100 let kinds = variants 243 let kinds = en.variants
101 .iter() 244 .iter()
102 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string()))) 245 .map(|name| {
246 element_kinds_map[*name].kinds.iter().collect::<Vec<_>>()
247 })
103 .collect::<Vec<_>>(); 248 .collect::<Vec<_>>();
104 let traits = en.traits.iter().map(|trait_name| { 249 let traits = en.traits.iter().map(|trait_name| {
105 let trait_name = format_ident!("{}", trait_name); 250 let trait_name = format_ident!("{}", trait_name);
106 quote!(impl ast::#trait_name for #name {}) 251 quote!(impl ast::#trait_name for #name {})
107 }); 252 });
108 253
254 let all_kinds = &element_kinds.kinds;
255
256 let specific_ast_trait = if element_kinds.has_nodes != element_kinds.has_tokens {
257 let (ast_trait, syntax_type) = if element_kinds.has_tokens {
258 (
259 quote!(AstToken),
260 quote!(SyntaxToken),
261 )
262 } else {
263 (
264 quote!(AstNode),
265 quote!(SyntaxNode),
266 )
267 };
268
269 quote! {
270 impl #ast_trait for #name {
271 fn can_cast(kind: SyntaxKind) -> bool {
272 match kind {
273 #(#all_kinds)|* => true,
274 _ => false,
275 }
276 }
277 #[allow(unreachable_patterns)]
278 fn cast_or_return(syntax: #syntax_type) -> Result<Self, #syntax_type> {
279 match syntax.kind() {
280 #(
281 #(#kinds)|* => #variants::cast_or_return(syntax).map(|x| #name::#variants(x)),
282 )*
283 _ => Err(syntax),
284 }
285 }
286 fn syntax(&self) -> &#syntax_type {
287 match self {
288 #(
289 #name::#variants(it) => it.syntax(),
290 )*
291 }
292 }
293 fn into_syntax(self) -> #syntax_type {
294 match self {
295 #(
296 #name::#variants(it) => it.into_syntax(),
297 )*
298 }
299 }
300 }
301 }
302 } else {
303 Default::default()
304 };
305
109 quote! { 306 quote! {
110 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 307 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
111 pub enum #name { 308 pub enum #name {
@@ -122,44 +319,71 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
122 319
123 impl std::fmt::Display for #name { 320 impl std::fmt::Display for #name {
124 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 321 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
125 std::fmt::Display::fmt(self.syntax(), f) 322 match self {
323 #(
324 #name::#variants(it) => std::fmt::Display::fmt(it, f),
325 )*
326 }
126 } 327 }
127 } 328 }
128 329
129 impl AstNode for #name { 330 #specific_ast_trait
130 fn can_cast(kind: SyntaxKind) -> bool { 331
332 impl AstElement for #name {
333 fn can_cast_element(kind: SyntaxKind) -> bool {
131 match kind { 334 match kind {
132 #(#kinds)|* => true, 335 #(#all_kinds)|* => true,
133 _ => false, 336 _ => false,
134 } 337 }
135 } 338 }
136 fn cast(syntax: SyntaxNode) -> Option<Self> { 339 #[allow(unreachable_patterns)]
137 let res = match syntax.kind() { 340 fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement> {
341 match syntax.kind() {
342 #(
343 #(#kinds)|* => #variants::cast_or_return_element(syntax).map(|x| #name::#variants(x)),
344 )*
345 _ => Err(syntax),
346 }
347 }
348 fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken> {
349 match self {
138 #( 350 #(
139 #kinds => #name::#variants(#variants { syntax }), 351 #name::#variants(it) => it.syntax_element(),
140 )* 352 )*
141 _ => return None, 353 }
142 };
143 Some(res)
144 } 354 }
145 fn syntax(&self) -> &SyntaxNode { 355 fn into_syntax_element(self) -> SyntaxElement {
146 match self { 356 match self {
147 #( 357 #(
148 #name::#variants(it) => &it.syntax, 358 #name::#variants(it) => it.into_syntax_element(),
149 )* 359 )*
150 } 360 }
151 } 361 }
152 } 362 }
363
153 #(#traits)* 364 #(#traits)*
154 } 365 }
155 }); 366 });
156 367
368 let defined_nodes: HashSet<_> = grammar.nodes.iter().map(|node| node.name).collect();
369
370 for node in kinds
371 .nodes
372 .iter()
373 .map(|kind| to_pascal_case(*kind))
374 .filter(|name| !defined_nodes.contains(&**name))
375 {
376 eprintln!("Warning: node {} not defined in ast source", node);
377 }
378
157 let ast = quote! { 379 let ast = quote! {
380 #[allow(unused_imports)]
158 use crate::{ 381 use crate::{
159 SyntaxNode, SyntaxKind::{self, *}, 382 SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
160 ast::{self, AstNode, AstChildren}, 383 ast::{self, AstNode, AstToken, AstElement, AstChildren, AstChildTokens, AstChildElements},
161 }; 384 };
162 385
386 #(#tokens)*
163 #(#nodes)* 387 #(#nodes)*
164 #(#enums)* 388 #(#enums)*
165 }; 389 };
@@ -282,12 +506,12 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> {
282 506
283fn to_upper_snake_case(s: &str) -> String { 507fn to_upper_snake_case(s: &str) -> String {
284 let mut buf = String::with_capacity(s.len()); 508 let mut buf = String::with_capacity(s.len());
285 let mut prev_is_upper = None; 509 let mut prev = false;
286 for c in s.chars() { 510 for c in s.chars() {
287 if c.is_ascii_uppercase() && prev_is_upper == Some(false) { 511 if c.is_ascii_uppercase() && prev {
288 buf.push('_') 512 buf.push('_')
289 } 513 }
290 prev_is_upper = Some(c.is_ascii_uppercase()); 514 prev = true;
291 515
292 buf.push(c.to_ascii_uppercase()); 516 buf.push(c.to_ascii_uppercase());
293 } 517 }
@@ -296,14 +520,30 @@ fn to_upper_snake_case(s: &str) -> String {
296 520
297fn to_lower_snake_case(s: &str) -> String { 521fn to_lower_snake_case(s: &str) -> String {
298 let mut buf = String::with_capacity(s.len()); 522 let mut buf = String::with_capacity(s.len());
299 let mut prev_is_upper = None; 523 let mut prev = false;
300 for c in s.chars() { 524 for c in s.chars() {
301 if c.is_ascii_uppercase() && prev_is_upper == Some(false) { 525 if c.is_ascii_uppercase() && prev {
302 buf.push('_') 526 buf.push('_')
303 } 527 }
304 prev_is_upper = Some(c.is_ascii_uppercase()); 528 prev = true;
305 529
306 buf.push(c.to_ascii_lowercase()); 530 buf.push(c.to_ascii_lowercase());
307 } 531 }
308 buf 532 buf
309} 533}
534
535fn to_pascal_case(s: &str) -> String {
536 let mut buf = String::with_capacity(s.len());
537 let mut prev_is_underscore = true;
538 for c in s.chars() {
539 if c == '_' {
540 prev_is_underscore = true;
541 } else if prev_is_underscore {
542 buf.push(c.to_ascii_uppercase());
543 prev_is_underscore = false;
544 } else {
545 buf.push(c.to_ascii_lowercase());
546 }
547 }
548 buf
549}