Skip to content

Commit

Permalink
feat(codegen,css_formatter): autogenerate property formattting boiler…
Browse files Browse the repository at this point in the history
…plate (#1452)
  • Loading branch information
faultyserver authored Jan 7, 2024
1 parent 166cbab commit b16b630
Showing 1 changed file with 70 additions and 29 deletions.
99 changes: 70 additions & 29 deletions xtask/codegen/src/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ fn generate_formatter(repo: &GitRepo, language_kind: LanguageKind) {
modules.insert(repo, &path);

let node_id = Ident::new(&name, Span::call_site());
let node_fields_id = Ident::new(&format!("{name}Fields"), Span::call_site());
let format_id = Ident::new(&format!("Format{name}"), Span::call_site());

let qualified_format_id = {
Expand Down Expand Up @@ -358,18 +359,49 @@ fn generate_formatter(repo: &GitRepo, language_kind: LanguageKind) {
}
},
NodeKind::Node => {
quote! {
use crate::prelude::*;
// TODO: This is CSS-specific and would be nice to handle in a
// per-language generator somehow.
if language_kind == LanguageKind::Css
&& matches!(
get_node_concept(&kind, &module.dialect, &language_kind, &name),
NodeConcept::Property
)
{
quote! {
use crate::prelude::*;

use biome_rowan::AstNode;
use #syntax_crate_ident::#node_id;
use #syntax_crate_ident::{#node_id, #node_fields_id};
use biome_formatter::write;

#[derive(Debug, Clone, Default)]
pub(crate) struct #format_id;
#[derive(Debug, Clone, Default)]
pub(crate) struct #format_id;

impl FormatNodeRule<#node_id> for #format_id {
fn fmt_fields(&self, node: &#node_id, f: &mut #formatter_ident) -> FormatResult<()> {
let #node_fields_id {
name,
colon_token,
value
} = node.as_fields();

write!(f, [name.format(), colon_token.format(), space(), value.format()])
}
}
}
} else {
quote! {
use crate::prelude::*;

use biome_rowan::AstNode;
use #syntax_crate_ident::#node_id;

#[derive(Debug, Clone, Default)]
pub(crate) struct #format_id;

impl FormatNodeRule<#node_id> for #format_id {
fn fmt_fields(&self, node: &#node_id, f: &mut #formatter_ident) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
impl FormatNodeRule<#node_id> for #format_id {
fn fmt_fields(&self, node: &#node_id, f: &mut #formatter_ident) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
}
}
}
}
Expand Down Expand Up @@ -642,25 +674,13 @@ impl NodeModuleInformation {
}
}

/// Convert an AstNode name to a path / Rust module name
fn name_to_module(kind: &NodeKind, in_name: &str, language: LanguageKind) -> NodeModuleInformation {
let mut upper_case_indices = in_name.match_indices(|c: char| c.is_uppercase());

assert!(matches!(upper_case_indices.next(), Some((0, _))));

let (second_upper_start, _) = upper_case_indices.next().expect("Node name malformed");
let (mut dialect_prefix, mut name) = in_name.split_at(second_upper_start);

// AnyJsX
if dialect_prefix == "Any" {
let (third_upper_start, _) = upper_case_indices.next().expect("Node name malformed");
(dialect_prefix, name) = name.split_at(third_upper_start - dialect_prefix.len());
}

let dialect = NodeDialect::from_str(dialect_prefix);

// Classify nodes by concept
let concept = if matches!(kind, NodeKind::Bogus) {
fn get_node_concept(
kind: &NodeKind,
dialect: &NodeDialect,
language: &LanguageKind,
name: &str,
) -> NodeConcept {
if matches!(kind, NodeKind::Bogus) {
NodeConcept::Bogus
} else if matches!(kind, NodeKind::List { .. }) {
NodeConcept::List
Expand Down Expand Up @@ -761,7 +781,28 @@ fn name_to_module(kind: &NodeKind, in_name: &str, language: LanguageKind) -> Nod
_ => NodeConcept::Auxiliary,
},
}
};
}
}

/// Convert an AstNode name to a path / Rust module name
fn name_to_module(kind: &NodeKind, in_name: &str, language: LanguageKind) -> NodeModuleInformation {
let mut upper_case_indices = in_name.match_indices(|c: char| c.is_uppercase());

assert!(matches!(upper_case_indices.next(), Some((0, _))));

let (second_upper_start, _) = upper_case_indices.next().expect("Node name malformed");
let (mut dialect_prefix, mut name) = in_name.split_at(second_upper_start);

// AnyJsX
if dialect_prefix == "Any" {
let (third_upper_start, _) = upper_case_indices.next().expect("Node name malformed");
(dialect_prefix, name) = name.split_at(third_upper_start - dialect_prefix.len());
}

let dialect = NodeDialect::from_str(dialect_prefix);

// Classify nodes by concept
let concept = get_node_concept(kind, &dialect, &language, name);

// Convert the names from CamelCase to snake_case
let mut stem = String::new();
Expand Down

0 comments on commit b16b630

Please sign in to comment.