aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_tools
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_tools')
-rw-r--r--crates/ra_tools/src/boilerplate_gen.rs87
1 files changed, 50 insertions, 37 deletions
diff --git a/crates/ra_tools/src/boilerplate_gen.rs b/crates/ra_tools/src/boilerplate_gen.rs
index 486a3fdec..01d092d48 100644
--- a/crates/ra_tools/src/boilerplate_gen.rs
+++ b/crates/ra_tools/src/boilerplate_gen.rs
@@ -37,41 +37,72 @@ fn generate_ast(grammar: &Grammar) -> Result<String> {
37 ast_node.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); 37 ast_node.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
38 let name = format_ident!("{}", name); 38 let name = format_ident!("{}", name);
39 39
40 let kinds = if variants.is_empty() { vec![name.clone()] } else { variants.clone() } 40 let adt = if variants.is_empty() {
41 .into_iter() 41 let kind = format_ident!("{}", name.to_string().to_shouty_snake_case());
42 .map(|name| format_ident!("{}", name.to_string().to_shouty_snake_case())) 42 quote! {
43 .collect::<Vec<_>>(); 43 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
44 pub struct #name {
45 pub(crate) syntax: SyntaxNode,
46 }
44 47
45 let variants = if variants.is_empty() { 48 impl AstNode for #name {
46 None 49 fn can_cast(kind: SyntaxKind) -> bool {
50 match kind {
51 #kind => true,
52 _ => false,
53 }
54 }
55 fn cast(syntax: SyntaxNode) -> Option<Self> {
56 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
57 }
58 fn syntax(&self) -> &SyntaxNode { &self.syntax }
59 }
60 }
47 } else { 61 } else {
48 let kind_enum = format_ident!("{}Kind", name); 62 let kinds = variants
49 Some(quote!( 63 .iter()
50 pub enum #kind_enum { 64 .map(|name| format_ident!("{}", name.to_string().to_shouty_snake_case()))
65 .collect::<Vec<_>>();
66
67 quote! {
68 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
69 pub enum #name {
51 #(#variants(#variants),)* 70 #(#variants(#variants),)*
52 } 71 }
53 72
54 #( 73 #(
55 impl From<#variants> for #name { 74 impl From<#variants> for #name {
56 fn from(node: #variants) -> #name { 75 fn from(node: #variants) -> #name {
57 #name { syntax: node.syntax } 76 #name::#variants(node)
58 } 77 }
59 } 78 }
60 )* 79 )*
61 80
62 impl #name { 81 impl AstNode for #name {
63 pub fn kind(&self) -> #kind_enum { 82 fn can_cast(kind: SyntaxKind) -> bool {
64 let syntax = self.syntax.clone(); 83 match kind {
65 match syntax.kind() { 84 #(#kinds)|* => true,
85 _ => false,
86 }
87 }
88 fn cast(syntax: SyntaxNode) -> Option<Self> {
89 let res = match syntax.kind() {
66 #( 90 #(
67 #kinds => 91 #kinds => #name::#variants(#variants { syntax }),
68 #kind_enum::#variants(#variants { syntax }), 92 )*
93 _ => return None,
94 };
95 Some(res)
96 }
97 fn syntax(&self) -> &SyntaxNode {
98 match self {
99 #(
100 #name::#variants(it) => &it.syntax,
69 )* 101 )*
70 _ => unreachable!(),
71 } 102 }
72 } 103 }
73 } 104 }
74 )) 105 }
75 }; 106 };
76 107
77 let traits = ast_node.traits.iter().map(|trait_name| { 108 let traits = ast_node.traits.iter().map(|trait_name| {
@@ -105,25 +136,7 @@ fn generate_ast(grammar: &Grammar) -> Result<String> {
105 }); 136 });
106 137
107 quote! { 138 quote! {
108 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 139 #adt
109 pub struct #name {
110 pub(crate) syntax: SyntaxNode,
111 }
112
113 impl AstNode for #name {
114 fn can_cast(kind: SyntaxKind) -> bool {
115 match kind {
116 #(#kinds)|* => true,
117 _ => false,
118 }
119 }
120 fn cast(syntax: SyntaxNode) -> Option<Self> {
121 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
122 }
123 fn syntax(&self) -> &SyntaxNode { &self.syntax }
124 }
125
126 #variants
127 140
128 #(#traits)* 141 #(#traits)*
129 142