mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Merge #3915
3915: Prettify generated code r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
30f0ad159a
8 changed files with 7154 additions and 9746 deletions
|
@ -21,7 +21,7 @@ pub use self::{
|
|||
AttrKind, FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind,
|
||||
TypeBoundKind, VisibilityKind,
|
||||
},
|
||||
generated::*,
|
||||
generated::{nodes::*, tokens::*},
|
||||
tokens::*,
|
||||
traits::*,
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
4177
crates/ra_syntax/src/ast/generated/nodes.rs
Normal file
4177
crates/ra_syntax/src/ast/generated/nodes.rs
Normal file
File diff suppressed because it is too large
Load diff
2808
crates/ra_syntax/src/ast/generated/tokens.rs
Normal file
2808
crates/ra_syntax/src/ast/generated/tokens.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -227,6 +227,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
|
|||
pub(crate) struct AstSrc<'a> {
|
||||
pub(crate) nodes: &'a [AstNodeSrc<'a>],
|
||||
pub(crate) enums: &'a [AstEnumSrc<'a>],
|
||||
pub(crate) token_enums: &'a [AstEnumSrc<'a>],
|
||||
}
|
||||
|
||||
pub(crate) struct AstNodeSrc<'a> {
|
||||
|
@ -753,6 +754,13 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
// macro calls are parsed as expression statements */
|
||||
}
|
||||
|
||||
enum FieldDefList {
|
||||
RecordFieldDefList,
|
||||
TupleFieldDefList,
|
||||
}
|
||||
},
|
||||
|
||||
token_enums: &ast_enums! {
|
||||
enum LeftDelimiter { LParen, LBrack, LCurly }
|
||||
enum RightDelimiter { RParen, RBrack, RCurly }
|
||||
enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq}
|
||||
|
@ -817,10 +825,5 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
Ident,
|
||||
IntNumber
|
||||
}
|
||||
|
||||
enum FieldDefList {
|
||||
RecordFieldDefList,
|
||||
TupleFieldDefList,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -22,8 +22,9 @@ const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
|
|||
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok";
|
||||
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err";
|
||||
|
||||
pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs";
|
||||
pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs";
|
||||
const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs";
|
||||
const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs";
|
||||
const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs";
|
||||
|
||||
const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
|
||||
const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs";
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
|
||||
//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`.
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{BTreeSet, HashSet},
|
||||
};
|
||||
|
||||
use proc_macro2::{Punct, Spacing};
|
||||
use quote::{format_ident, quote};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
|
||||
use crate::{
|
||||
ast_src::{AstSrc, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC},
|
||||
|
@ -19,9 +22,13 @@ pub fn generate_syntax(mode: Mode) -> Result<()> {
|
|||
let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
|
||||
update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
|
||||
|
||||
let ast_file = project_root().join(codegen::AST);
|
||||
let ast = generate_ast(KINDS_SRC, AST_SRC)?;
|
||||
update(ast_file.as_path(), &ast, mode)?;
|
||||
let ast_nodes_file = project_root().join(codegen::AST_NODES);
|
||||
let contents = generate_nodes(KINDS_SRC, AST_SRC)?;
|
||||
update(ast_nodes_file.as_path(), &contents, mode)?;
|
||||
|
||||
let ast_tokens_file = project_root().join(codegen::AST_TOKENS);
|
||||
let contents = generate_tokens(KINDS_SRC, AST_SRC)?;
|
||||
update(ast_tokens_file.as_path(), &contents, mode)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -33,7 +40,7 @@ struct ElementKinds {
|
|||
has_tokens: bool,
|
||||
}
|
||||
|
||||
fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||
fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||
let all_token_kinds: Vec<_> = kinds
|
||||
.punct
|
||||
.into_iter()
|
||||
|
@ -51,46 +58,6 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
.chain(kinds.tokens.into_iter().copied().map(|x| x.into()))
|
||||
.collect();
|
||||
|
||||
let mut element_kinds_map = HashMap::new();
|
||||
for kind in &all_token_kinds {
|
||||
let kind = &**kind;
|
||||
let name = to_pascal_case(kind);
|
||||
element_kinds_map.insert(
|
||||
name,
|
||||
ElementKinds {
|
||||
kinds: Some(format_ident!("{}", kind)).into_iter().collect(),
|
||||
has_nodes: false,
|
||||
has_tokens: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for kind in kinds.nodes {
|
||||
let name = to_pascal_case(kind);
|
||||
element_kinds_map.insert(
|
||||
name,
|
||||
ElementKinds {
|
||||
kinds: Some(format_ident!("{}", *kind)).into_iter().collect(),
|
||||
has_nodes: true,
|
||||
has_tokens: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for en in grammar.enums {
|
||||
let mut element_kinds: ElementKinds = Default::default();
|
||||
for variant in en.variants {
|
||||
if let Some(variant_element_kinds) = element_kinds_map.get(*variant) {
|
||||
element_kinds.kinds.extend(variant_element_kinds.kinds.iter().cloned());
|
||||
element_kinds.has_tokens |= variant_element_kinds.has_tokens;
|
||||
element_kinds.has_nodes |= variant_element_kinds.has_nodes;
|
||||
} else {
|
||||
panic!("Enum variant has type that does not exist or was not declared before the enum: {}", *variant);
|
||||
}
|
||||
}
|
||||
element_kinds_map.insert(en.name.to_string(), element_kinds);
|
||||
}
|
||||
|
||||
let tokens = all_token_kinds.iter().map(|kind_str| {
|
||||
let kind_str = &**kind_str;
|
||||
let kind = format_ident!("{}", kind_str);
|
||||
|
@ -108,12 +75,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
|
||||
impl AstToken for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#kind => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == #kind }
|
||||
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
||||
}
|
||||
|
@ -122,6 +84,99 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
});
|
||||
|
||||
let enums = grammar.token_enums.iter().map(|en| {
|
||||
let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>();
|
||||
let name = format_ident!("{}", en.name);
|
||||
let kinds = variants
|
||||
.iter()
|
||||
.map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
|
||||
.collect::<Vec<_>>();
|
||||
assert!(en.traits.is_empty());
|
||||
|
||||
quote! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum #name {
|
||||
#(#variants(#variants),)*
|
||||
}
|
||||
|
||||
#(
|
||||
impl From<#variants> for #name {
|
||||
fn from(node: #variants) -> #name {
|
||||
#name::#variants(node)
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
impl std::fmt::Display for #name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl AstToken for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#(#kinds)|* => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||
let res = match syntax.kind() {
|
||||
#(
|
||||
#kinds => #name::#variants(#variants { syntax }),
|
||||
)*
|
||||
_ => return None,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken {
|
||||
match self {
|
||||
#(
|
||||
#name::#variants(it) => &it.syntax,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
crate::reformat(quote! {
|
||||
use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken};
|
||||
|
||||
#(#tokens)*
|
||||
#(#enums)*
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
||||
let all_token_kinds: Vec<_> = kinds
|
||||
.punct
|
||||
.into_iter()
|
||||
.map(|(_, kind)| kind)
|
||||
.copied()
|
||||
.map(|x| x.into())
|
||||
.chain(
|
||||
kinds
|
||||
.keywords
|
||||
.into_iter()
|
||||
.chain(kinds.contextual_keywords.into_iter())
|
||||
.map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))),
|
||||
)
|
||||
.chain(kinds.literals.into_iter().copied().map(|x| x.into()))
|
||||
.chain(kinds.tokens.into_iter().copied().map(|x| x.into()))
|
||||
.collect();
|
||||
|
||||
let mut token_kinds = HashSet::new();
|
||||
for kind in &all_token_kinds {
|
||||
let kind = &**kind;
|
||||
let name = to_pascal_case(kind);
|
||||
token_kinds.insert(name);
|
||||
}
|
||||
|
||||
for en in grammar.token_enums {
|
||||
token_kinds.insert(en.name.to_string());
|
||||
}
|
||||
|
||||
let nodes = grammar.nodes.iter().map(|node| {
|
||||
let name = format_ident!("{}", node.name);
|
||||
let kind = format_ident!("{}", to_upper_snake_case(&name.to_string()));
|
||||
|
@ -151,7 +206,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
}
|
||||
FieldSrc::Optional(_) | FieldSrc::Shorthand => {
|
||||
let is_token = element_kinds_map[&ty.to_string()].has_tokens;
|
||||
let is_token = token_kinds.contains(&ty.to_string());
|
||||
if is_token {
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
|
@ -175,18 +230,9 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for #name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl AstNode for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#kind => true,
|
||||
_ => false,
|
||||
}
|
||||
kind == #kind
|
||||
}
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
||||
|
@ -214,48 +260,6 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
quote!(impl ast::#trait_name for #name {})
|
||||
});
|
||||
|
||||
let element_kinds = &element_kinds_map[&en.name.to_string()];
|
||||
assert!(
|
||||
element_kinds.has_nodes ^ element_kinds.has_tokens,
|
||||
"{}: {:#?}",
|
||||
name,
|
||||
element_kinds
|
||||
);
|
||||
let specific_ast_trait = {
|
||||
let (ast_trait, syntax_type) = if element_kinds.has_tokens {
|
||||
(quote!(AstToken), quote!(SyntaxToken))
|
||||
} else {
|
||||
(quote!(AstNode), quote!(SyntaxNode))
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl #ast_trait for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#(#kinds)|* => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: #syntax_type) -> Option<Self> {
|
||||
let res = match syntax.kind() {
|
||||
#(
|
||||
#kinds => #name::#variants(#variants { syntax }),
|
||||
)*
|
||||
_ => return None,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
fn syntax(&self) -> &#syntax_type {
|
||||
match self {
|
||||
#(
|
||||
#name::#variants(it) => &it.syntax,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum #name {
|
||||
|
@ -270,18 +274,50 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
)*
|
||||
|
||||
impl std::fmt::Display for #name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
impl AstNode for #name {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
#(#kinds)|* => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
let res = match syntax.kind() {
|
||||
#(
|
||||
#kinds => #name::#variants(#variants { syntax }),
|
||||
)*
|
||||
_ => return None,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
match self {
|
||||
#(
|
||||
#name::#variants(it) => &it.syntax,
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#specific_ast_trait
|
||||
|
||||
#(#traits)*
|
||||
}
|
||||
});
|
||||
|
||||
let displays = grammar
|
||||
.enums
|
||||
.iter()
|
||||
.map(|it| format_ident!("{}", it.name))
|
||||
.chain(grammar.nodes.iter().map(|it| format_ident!("{}", it.name)))
|
||||
.map(|name| {
|
||||
quote! {
|
||||
impl std::fmt::Display for #name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let defined_nodes: HashSet<_> = grammar.nodes.iter().map(|node| node.name).collect();
|
||||
|
||||
for node in kinds
|
||||
|
@ -294,15 +330,16 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
|
||||
let ast = quote! {
|
||||
#[allow(unused_imports)]
|
||||
use crate::{
|
||||
SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *},
|
||||
ast::{self, AstNode, AstToken, AstChildren, support},
|
||||
SyntaxNode, SyntaxKind::{self, *},
|
||||
ast::{self, AstNode, AstChildren, support},
|
||||
};
|
||||
|
||||
#(#tokens)*
|
||||
use super::tokens::*;
|
||||
|
||||
#(#nodes)*
|
||||
#(#enums)*
|
||||
#(#displays)*
|
||||
};
|
||||
|
||||
let pretty = crate::reformat(ast)?;
|
||||
|
|
|
@ -67,6 +67,7 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> {
|
|||
let mut rustfmt = Command::new("rustup")
|
||||
.args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"])
|
||||
.arg(project_root().join("rustfmt.toml"))
|
||||
.args(&["--config", "fn_single_line=true"])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()?;
|
||||
|
|
Loading…
Reference in a new issue