diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 8a0e3d27b21..d536bb1e7d6 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -17,7 +17,7 @@ use crate::{
 
 pub use self::{
     expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
-    generated::{nodes::*, tokens::*},
+    generated::*,
     node_ext::{
         AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
         StructKind, TypeBoundKind, VisibilityKind,
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index f5199e09f21..ba55f1c427c 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1,6 +1,37 @@
 //! This file is actually hand-written, but the submodules are indeed generated.
+#[rustfmt::skip]
+mod nodes;
+#[rustfmt::skip]
+mod tokens;
 
-#[rustfmt::skip]
-pub(super) mod nodes;
-#[rustfmt::skip]
-pub(super) mod tokens;
+use crate::{
+    AstNode,
+    SyntaxKind::{self, *},
+    SyntaxNode,
+};
+
+pub use {nodes::*, tokens::*};
+
+// Stmt is the only nested enum, so it's easier to just hand-write it
+impl AstNode for Stmt {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        match kind {
+            LET_STMT | EXPR_STMT => true,
+            _ => false,
+        }
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            LET_STMT => Stmt::LetStmt(LetStmt { syntax }),
+            EXPR_STMT => Stmt::ExprStmt(ExprStmt { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            Stmt::LetStmt(it) => &it.syntax,
+            Stmt::ExprStmt(it) => &it.syntax,
+        }
+    }
+}
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs
index 286be1032b8..8ef72fec71e 100644
--- a/crates/ra_syntax/src/ast/generated/nodes.rs
+++ b/crates/ra_syntax/src/ast/generated/nodes.rs
@@ -3380,28 +3380,6 @@ impl From<LetStmt> for Stmt {
 impl From<ExprStmt> for Stmt {
     fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) }
 }
-impl AstNode for Stmt {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            LET_STMT | EXPR_STMT => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        let res = match syntax.kind() {
-            LET_STMT => Stmt::LetStmt(LetStmt { syntax }),
-            EXPR_STMT => Stmt::ExprStmt(ExprStmt { syntax }),
-            _ => return None,
-        };
-        Some(res)
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        match self {
-            Stmt::LetStmt(it) => &it.syntax,
-            Stmt::ExprStmt(it) => &it.syntax,
-        }
-    }
-}
 impl std::fmt::Display for Item {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index d6a72ccc06c..e3d4269f6e4 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -153,25 +153,10 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> {
                 quote!(impl ast::#trait_name for #name {})
             });
 
-            (
+            let ast_node = if en.name == "Stmt" {
+                quote! {}
+            } else {
                 quote! {
-                    #[pretty_doc_comment_placeholder_workaround]
-                    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-                    pub enum #name {
-                        #(#variants(#variants),)*
-                    }
-
-                    #(#traits)*
-                },
-                quote! {
-                    #(
-                    impl From<#variants> for #name {
-                        fn from(node: #variants) -> #name {
-                            #name::#variants(node)
-                        }
-                    }
-                    )*
-
                     impl AstNode for #name {
                         fn can_cast(kind: SyntaxKind) -> bool {
                             match kind {
@@ -196,6 +181,28 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> {
                             }
                         }
                     }
+                }
+            };
+
+            (
+                quote! {
+                    #[pretty_doc_comment_placeholder_workaround]
+                    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+                    pub enum #name {
+                        #(#variants(#variants),)*
+                    }
+
+                    #(#traits)*
+                },
+                quote! {
+                    #(
+                        impl From<#variants> for #name {
+                            fn from(node: #variants) -> #name {
+                                #name::#variants(node)
+                            }
+                        }
+                    )*
+                    #ast_node
                 },
             )
         })
@@ -497,13 +504,7 @@ fn lower(grammar: &Grammar) -> AstSrc {
     let mut res = AstSrc::default();
     res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()];
 
-    let nodes = grammar
-        .iter()
-        .filter(|&node| match grammar[node].rule {
-            Rule::Node(it) if it == node => false,
-            _ => true,
-        })
-        .collect::<Vec<_>>();
+    let nodes = grammar.iter().collect::<Vec<_>>();
 
     for &node in &nodes {
         let name = grammar[node].name.clone();