Merge pull request #19408 from Veykril/push-wtnxzulsovxy

refactor: Reduce codegen burden for generated syntax
This commit is contained in:
Lukas Wirth 2025-03-21 11:32:43 +00:00 committed by GitHub
commit 9c01af0a86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 2844 additions and 464 deletions

View File

@ -336,7 +336,7 @@ enum Command {
}
impl <> $crate::cmp::PartialOrd for Command< > where {
fn partial_cmp(&self , other: &Self ) -> $crate::option::Option::Option<$crate::cmp::Ordering> {
fn partial_cmp(&self , other: &Self ) -> $crate::option::Option<$crate::cmp::Ordering> {
match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) {
$crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
match (self , other) {

View File

@ -969,7 +969,7 @@ fn partial_ord_expand(
span,
);
quote! {span =>
fn partial_cmp(&self, other: &Self) -> #krate::option::Option::Option<#krate::cmp::Ordering> {
fn partial_cmp(&self, other: &Self) -> #krate::option::Option<#krate::cmp::Ordering> {
#body
}
}

View File

@ -852,7 +852,7 @@ fn highlight_name_ref_by_syntax(
}
}
ASSOC_TYPE_ARG => SymbolKind::TypeAlias.into(),
USE_BOUND_GENERIC_ARG => SymbolKind::TypeParam.into(),
USE_BOUND_GENERIC_ARGS => SymbolKind::TypeParam.into(),
_ => default.into(),
}
}

View File

@ -35,6 +35,8 @@ mod shortcuts;
mod syntax_kind;
mod token_set;
pub use T_ as T;
#[cfg(test)]
mod tests;

View File

@ -1,6 +1,7 @@
//! Defines [`SyntaxKind`] -- a fieldless enum of all possible syntactic
//! constructs of the Rust language.
#[rustfmt::skip]
mod generated;
use crate::Edition;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,7 @@ use crate::{
SyntaxKind::{self, *},
SyntaxToken,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
use std::{fmt, hash};
pub struct Byte {
pub(crate) syntax: SyntaxToken,
}
@ -26,8 +25,21 @@ impl AstToken for Byte {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for Byte {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Byte").field("syntax", &self.syntax).finish()
}
}
impl Clone for Byte {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for Byte {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for Byte {}
impl PartialEq for Byte {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct ByteString {
pub(crate) syntax: SyntaxToken,
}
@ -47,8 +59,21 @@ impl AstToken for ByteString {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for ByteString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ByteString").field("syntax", &self.syntax).finish()
}
}
impl Clone for ByteString {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for ByteString {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for ByteString {}
impl PartialEq for ByteString {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct CString {
pub(crate) syntax: SyntaxToken,
}
@ -68,8 +93,21 @@ impl AstToken for CString {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for CString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CString").field("syntax", &self.syntax).finish()
}
}
impl Clone for CString {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for CString {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for CString {}
impl PartialEq for CString {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct Char {
pub(crate) syntax: SyntaxToken,
}
@ -89,8 +127,21 @@ impl AstToken for Char {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for Char {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Char").field("syntax", &self.syntax).finish()
}
}
impl Clone for Char {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for Char {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for Char {}
impl PartialEq for Char {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct Comment {
pub(crate) syntax: SyntaxToken,
}
@ -110,8 +161,21 @@ impl AstToken for Comment {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for Comment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Comment").field("syntax", &self.syntax).finish()
}
}
impl Clone for Comment {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for Comment {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for Comment {}
impl PartialEq for Comment {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct FloatNumber {
pub(crate) syntax: SyntaxToken,
}
@ -131,8 +195,21 @@ impl AstToken for FloatNumber {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for FloatNumber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FloatNumber").field("syntax", &self.syntax).finish()
}
}
impl Clone for FloatNumber {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for FloatNumber {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for FloatNumber {}
impl PartialEq for FloatNumber {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct Ident {
pub(crate) syntax: SyntaxToken,
}
@ -152,8 +229,21 @@ impl AstToken for Ident {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Ident").field("syntax", &self.syntax).finish()
}
}
impl Clone for Ident {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for Ident {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for Ident {}
impl PartialEq for Ident {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct IntNumber {
pub(crate) syntax: SyntaxToken,
}
@ -173,8 +263,21 @@ impl AstToken for IntNumber {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for IntNumber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IntNumber").field("syntax", &self.syntax).finish()
}
}
impl Clone for IntNumber {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for IntNumber {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for IntNumber {}
impl PartialEq for IntNumber {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct String {
pub(crate) syntax: SyntaxToken,
}
@ -194,8 +297,21 @@ impl AstToken for String {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
impl fmt::Debug for String {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("String").field("syntax", &self.syntax).finish()
}
}
impl Clone for String {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for String {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for String {}
impl PartialEq for String {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}
pub struct Whitespace {
pub(crate) syntax: SyntaxToken,
}
@ -215,3 +331,18 @@ impl AstToken for Whitespace {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
impl fmt::Debug for Whitespace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Whitespace").field("syntax", &self.syntax).finish()
}
}
impl Clone for Whitespace {
fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
}
impl hash::Hash for Whitespace {
fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
}
impl Eq for Whitespace {}
impl PartialEq for Whitespace {
fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
}

View File

@ -21,7 +21,7 @@ impl flags::Codegen {
pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> {
match self.codegen_type.unwrap_or_default() {
flags::CodegenType::All => {
diagnostics_docs::generate(self.check);
grammar::generate(self.check);
assists_doc_tests::generate(self.check);
parser_inline_tests::generate(self.check);
feature_docs::generate(self.check)

View File

@ -67,7 +67,6 @@ fn generate_tokens(grammar: &AstSrc) -> String {
let name = format_ident!("{}", token);
let kind = format_ident!("{}", to_upper_snake_case(token));
quote! {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct #name {
pub(crate) syntax: SyntaxToken,
}
@ -83,6 +82,29 @@ fn generate_tokens(grammar: &AstSrc) -> String {
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
impl fmt::Debug for #name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(#token).field("syntax", &self.syntax).finish()
}
}
impl Clone for #name {
fn clone(&self) -> Self {
Self { syntax: self.syntax.clone() }
}
}
impl hash::Hash for #name {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.syntax.hash(state);
}
}
impl Eq for #name {}
impl PartialEq for #name {
fn eq(&self, other: &Self) -> bool {
self.syntax == other.syntax
}
}
}
});
@ -90,7 +112,10 @@ fn generate_tokens(grammar: &AstSrc) -> String {
crate::flags::CodegenType::Grammar,
reformat(
quote! {
use std::{fmt, hash};
use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
#(#tokens)*
}
.to_string(),
@ -104,6 +129,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
.nodes
.iter()
.map(|node| {
let node_str_name = &node.name;
let name = format_ident!("{}", node.name);
let kind = format_ident!("{}", to_upper_snake_case(&node.name));
let traits = node
@ -149,7 +175,6 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
(
quote! {
#[pretty_doc_comment_placeholder_workaround]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct #name {
pub(crate) syntax: SyntaxNode,
}
@ -180,6 +205,31 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
#[inline]
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl hash::Hash for #name {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.syntax.hash(state);
}
}
impl Eq for #name {}
impl PartialEq for #name {
fn eq(&self, other: &Self) -> bool {
self.syntax == other.syntax
}
}
impl Clone for #name {
fn clone(&self) -> Self {
Self { syntax: self.syntax.clone() }
}
}
impl fmt::Debug for #name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish()
}
}
},
)
})
@ -265,6 +315,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
.sorted_by_key(|(name, _)| *name)
.map(|(trait_name, nodes)| {
let name = format_ident!("Any{}", trait_name);
let node_str_name = name.to_string();
let trait_name = format_ident!("{}", trait_name);
let kinds: Vec<_> = nodes
.iter()
@ -274,13 +325,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
(
quote! {
#[pretty_doc_comment_placeholder_workaround]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct #name {
pub(crate) syntax: SyntaxNode,
}
impl ast::#trait_name for #name {}
},
quote! {
impl #name {
#[inline]
pub fn new<T: ast::#trait_name>(node: T) -> #name {
@ -289,6 +336,9 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
}
}
}
},
quote! {
impl ast::#trait_name for #name {}
impl AstNode for #name {
#[inline]
fn can_cast(kind: SyntaxKind) -> bool {
@ -304,6 +354,31 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
}
}
impl hash::Hash for #name {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.syntax.hash(state);
}
}
impl Eq for #name {}
impl PartialEq for #name {
fn eq(&self, other: &Self) -> bool {
self.syntax == other.syntax
}
}
impl Clone for #name {
fn clone(&self) -> Self {
Self { syntax: self.syntax.clone() }
}
}
impl fmt::Debug for #name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(#node_str_name).field("syntax", &self.syntax).finish()
}
}
#(
impl From<#nodes> for #name {
#[inline]
@ -346,6 +421,8 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
let ast = quote! {
#![allow(non_snake_case)]
use std::{fmt, hash};
use crate::{
SyntaxNode, SyntaxToken, SyntaxKind::{self, *},
ast::{self, AstNode, AstChildren, support},
@ -476,7 +553,6 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
// FIXME: This generates enum kinds?
let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
let ast = quote! {
@ -484,7 +560,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
use crate::Edition;
/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Debug)]
#[repr(u16)]
pub enum SyntaxKind {
// Technical SyntaxKinds: they appear temporally during parsing,
@ -585,7 +661,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
}
#[macro_export]
macro_rules! T {
macro_rules! T_ {
#([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)*
#([#strict_keywords_tokens] => { $crate::SyntaxKind::#strict_keywords_variants };)*
#([#contextual_keywords_tokens] => { $crate::SyntaxKind::#contextual_keywords_variants };)*
@ -596,6 +672,38 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
[string] => { $crate::SyntaxKind::STRING };
[shebang] => { $crate::SyntaxKind::SHEBANG };
}
impl ::core::marker::Copy for SyntaxKind {}
impl ::core::clone::Clone for SyntaxKind {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl ::core::cmp::PartialEq for SyntaxKind {
#[inline]
fn eq(&self, other: &Self) -> bool {
(*self as u16) == (*other as u16)
}
}
impl ::core::cmp::Eq for SyntaxKind {}
impl ::core::cmp::PartialOrd for SyntaxKind {
#[inline]
fn partial_cmp(&self, other: &Self) -> core::option::Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl ::core::cmp::Ord for SyntaxKind {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(*self as u16).cmp(&(*other as u16))
}
}
impl ::core::hash::Hash for SyntaxKind {
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
::core::mem::discriminant(self).hash(state);
}
}
};
add_preamble(crate::flags::CodegenType::Grammar, reformat(ast.to_string()))

View File

@ -12,6 +12,7 @@ pub(crate) struct KindsSrc {
pub(crate) literals: &'static [&'static str],
pub(crate) tokens: &'static [&'static str],
pub(crate) nodes: &'static [&'static str],
pub(crate) _enums: &'static [&'static str],
pub(crate) edition_dependent_keywords: &'static [(&'static str, Edition)],
}
@ -206,13 +207,21 @@ pub(crate) fn generate_kind_src(
let nodes = nodes
.iter()
.map(|it| &it.name)
.chain(enums.iter().map(|it| &it.name))
.map(|it| to_upper_snake_case(it))
.map(String::leak)
.map(|it| &*it)
.collect();
let nodes = Vec::leak(nodes);
nodes.sort();
let enums = enums
.iter()
.map(|it| &it.name)
.map(|it| to_upper_snake_case(it))
.map(String::leak)
.map(|it| &*it)
.collect();
let enums = Vec::leak(enums);
enums.sort();
let keywords = Vec::leak(keywords);
let contextual_keywords = Vec::leak(contextual_keywords);
let edition_dependent_keywords = Vec::leak(edition_dependent_keywords);
@ -224,6 +233,7 @@ pub(crate) fn generate_kind_src(
KindsSrc {
punct: PUNCT,
nodes,
_enums: enums,
keywords,
contextual_keywords,
edition_dependent_keywords,