mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Scale token generation back
This commit is contained in:
parent
779f06ed77
commit
8d71a6bf0c
9 changed files with 136 additions and 547 deletions
|
@ -3,10 +3,7 @@
|
|||
//! 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 std::collections::{BTreeSet, HashSet};
|
||||
|
||||
use proc_macro2::{Punct, Spacing};
|
||||
use quote::{format_ident, quote};
|
||||
|
@ -26,10 +23,6 @@ pub fn generate_syntax(mode: Mode) -> Result<()> {
|
|||
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(())
|
||||
}
|
||||
|
||||
|
@ -40,147 +33,7 @@ struct ElementKinds {
|
|||
has_tokens: bool,
|
||||
}
|
||||
|
||||
fn generate_tokens(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 tokens = all_token_kinds.iter().filter_map(|kind_str| {
|
||||
if kind_str.ends_with("_KW") {
|
||||
return None;
|
||||
}
|
||||
let kind_str = &**kind_str;
|
||||
let kind = format_ident!("{}", kind_str);
|
||||
let name = format_ident!("{}", to_pascal_case(kind_str));
|
||||
let res = quote! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct #name {
|
||||
pub(crate) syntax: SyntaxToken,
|
||||
}
|
||||
|
||||
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 { kind == #kind }
|
||||
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
||||
}
|
||||
};
|
||||
Some(res)
|
||||
});
|
||||
|
||||
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()));
|
||||
|
@ -207,19 +60,9 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let is_token = token_kinds.contains(&ty.to_string());
|
||||
if is_token {
|
||||
let method_name = format_ident!("{}_token", method_name);
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
support::token(&self.syntax)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
quote! {
|
||||
pub fn #method_name(&self) -> Option<#ty> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -338,8 +181,6 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
|
|||
T,
|
||||
};
|
||||
|
||||
use super::tokens::*;
|
||||
|
||||
#(#nodes)*
|
||||
#(#enums)*
|
||||
#(#displays)*
|
||||
|
@ -456,6 +297,8 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> {
|
|||
macro_rules! T {
|
||||
#((#punctuation_values) => { $crate::SyntaxKind::#punctuation };)*
|
||||
#((#all_keywords_idents) => { $crate::SyntaxKind::#all_keywords };)*
|
||||
(lifetime) => { $crate::SyntaxKind::LIFETIME };
|
||||
(ident) => { $crate::SyntaxKind::IDENT };
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -535,8 +378,21 @@ impl Field<'_> {
|
|||
"')'" => "r_paren",
|
||||
"'['" => "l_brack",
|
||||
"']'" => "r_brack",
|
||||
"<" => "l_angle",
|
||||
">" => "r_angle",
|
||||
"=" => "eq",
|
||||
"!" => "excl",
|
||||
"*" => "star",
|
||||
"&" => "amp",
|
||||
"_" => "underscore",
|
||||
"." => "dot",
|
||||
".." => "dotdot",
|
||||
"..." => "dotdotdot",
|
||||
"=>" => "fat_arrow",
|
||||
"@" => "at",
|
||||
":" => "colon",
|
||||
"::" => "coloncolon",
|
||||
"#" => "pound",
|
||||
_ => name,
|
||||
};
|
||||
format_ident!("{}_token", name)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue