mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
remove ast::*Kind enums
With the new owned trees, we don't need an indirection here
This commit is contained in:
parent
ba2836245b
commit
39e444d701
3 changed files with 398 additions and 391 deletions
File diff suppressed because it is too large
Load diff
|
@ -186,8 +186,8 @@ fn api_walkthrough() {
|
||||||
// Let's fetch the `foo` function.
|
// Let's fetch the `foo` function.
|
||||||
let mut func = None;
|
let mut func = None;
|
||||||
for item in file.items() {
|
for item in file.items() {
|
||||||
match item.kind() {
|
match item {
|
||||||
ast::ModuleItemKind::FnDef(f) => func = Some(f),
|
ast::ModuleItem::FnDef(f) => func = Some(f),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,12 +206,12 @@ fn api_walkthrough() {
|
||||||
let block: ast::Block = func.body().unwrap();
|
let block: ast::Block = func.body().unwrap();
|
||||||
let expr: ast::Expr = block.expr().unwrap();
|
let expr: ast::Expr = block.expr().unwrap();
|
||||||
|
|
||||||
// "Enum"-like nodes are represented using the "kind" pattern. It allows us
|
// Enums are used to group related ast nodes together, and can be used for
|
||||||
// to match exhaustively against all flavors of nodes, while maintaining
|
// matching. However, because there are no public fields, it's possible to
|
||||||
// internal representation flexibility. The drawback is that one can't write
|
// match only the top level enum: that is the price we pay for increased API
|
||||||
// nested matches as one pattern.
|
// flexibility
|
||||||
let bin_expr: ast::BinExpr = match expr.kind() {
|
let bin_expr: &ast::BinExpr = match &expr {
|
||||||
ast::ExprKind::BinExpr(e) => e,
|
ast::Expr::BinExpr(e) => e,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,41 +37,72 @@ fn generate_ast(grammar: &Grammar) -> Result<String> {
|
||||||
ast_node.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
|
ast_node.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
|
||||||
let name = format_ident!("{}", name);
|
let name = format_ident!("{}", name);
|
||||||
|
|
||||||
let kinds = if variants.is_empty() { vec![name.clone()] } else { variants.clone() }
|
let adt = if variants.is_empty() {
|
||||||
.into_iter()
|
let kind = format_ident!("{}", name.to_string().to_shouty_snake_case());
|
||||||
.map(|name| format_ident!("{}", name.to_string().to_shouty_snake_case()))
|
quote! {
|
||||||
.collect::<Vec<_>>();
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct #name {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
|
||||||
let variants = if variants.is_empty() {
|
impl AstNode for #name {
|
||||||
None
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
|
match kind {
|
||||||
|
#kind => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let kind_enum = format_ident!("{}Kind", name);
|
let kinds = variants
|
||||||
Some(quote!(
|
.iter()
|
||||||
pub enum #kind_enum {
|
.map(|name| format_ident!("{}", name.to_string().to_shouty_snake_case()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum #name {
|
||||||
#(#variants(#variants),)*
|
#(#variants(#variants),)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#(
|
#(
|
||||||
impl From<#variants> for #name {
|
impl From<#variants> for #name {
|
||||||
fn from(node: #variants) -> #name {
|
fn from(node: #variants) -> #name {
|
||||||
#name { syntax: node.syntax }
|
#name::#variants(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
||||||
impl #name {
|
impl AstNode for #name {
|
||||||
pub fn kind(&self) -> #kind_enum {
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
let syntax = self.syntax.clone();
|
match kind {
|
||||||
match syntax.kind() {
|
#(#kinds)|* => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
let res = match syntax.kind() {
|
||||||
#(
|
#(
|
||||||
#kinds =>
|
#kinds => #name::#variants(#variants { syntax }),
|
||||||
#kind_enum::#variants(#variants { syntax }),
|
)*
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
#(
|
||||||
|
#name::#variants(it) => &it.syntax,
|
||||||
)*
|
)*
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let traits = ast_node.traits.iter().map(|trait_name| {
|
let traits = ast_node.traits.iter().map(|trait_name| {
|
||||||
|
@ -105,25 +136,7 @@ fn generate_ast(grammar: &Grammar) -> Result<String> {
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#adt
|
||||||
pub struct #name {
|
|
||||||
pub(crate) syntax: SyntaxNode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AstNode for #name {
|
|
||||||
fn can_cast(kind: SyntaxKind) -> bool {
|
|
||||||
match kind {
|
|
||||||
#(#kinds)|* => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
|
||||||
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
|
||||||
}
|
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
|
||||||
}
|
|
||||||
|
|
||||||
#variants
|
|
||||||
|
|
||||||
#(#traits)*
|
#(#traits)*
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue