Skip to content

Commit 75a9453

Browse files
committed
wip
1 parent 88fff7a commit 75a9453

9 files changed

Lines changed: 1275 additions & 1176 deletions

File tree

Cargo.lock

Lines changed: 70 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ can-dbc = "8.0.1"
2929
embedded-can = "0.4.1"
3030
heck = "0.5.0"
3131
prettyplease = "0.2.37"
32-
quote = "1.0"
32+
proc-macro2 = "1.0.92"
33+
quote = "1.0.44"
3334
syn = "2.0.114"
35+
template-quote = "0.4.2"
3436
typed-builder = "0.23.0"
3537

3638
[dev-dependencies]
@@ -48,6 +50,7 @@ unused_qualifications = "warn"
4850
[lints.clippy]
4951
cargo = { level = "warn", priority = -1 }
5052
pedantic = { level = "warn", priority = -1 }
53+
multiple_crate_versions = "allow"
5154
cast_possible_truncation = "allow"
5255
cast_precision_loss = "allow"
5356
missing_errors_doc = "allow"

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ bless-generate: (cargo-install 'cargo-insta')
3333
# Generate all snapshots, including forced (.gitignore-d) ones
3434
bless-generate-all:
3535
rm -rf tests-snapshots
36-
FORCE_INSTA=1 {{just}} bless-generate
36+
FORCE_INSTA=1 {{just}} bless-generate bless-compile
3737

3838
# Build the project
3939
build:

src/feature_config.rs

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use std::fmt::Display;
2-
use std::io::Write;
3-
4-
use anyhow::{Error, Result};
1+
use proc_macro2::TokenStream;
2+
use template_quote::quote;
53

64
/// Configuration for including features in the code generator.
75
///
@@ -20,31 +18,41 @@ pub enum FeatureConfig<'a> {
2018
}
2119

2220
impl FeatureConfig<'_> {
23-
pub(crate) fn fmt_attr(&self, w: &mut impl Write, attr: impl Display) -> Result<()> {
21+
/// Generate an attribute token stream (like `#[derive(Debug)]`).
22+
/// The closure is only called when the feature is enabled, so expensive codegen can be skipped when `Never`.
23+
pub(crate) fn attr<F>(&self, f: F) -> TokenStream
24+
where
25+
F: FnOnce() -> TokenStream,
26+
{
2427
match self {
25-
FeatureConfig::Always => writeln!(w, "#[{attr}]")?,
26-
FeatureConfig::Gated(gate) => writeln!(w, "#[cfg_attr(feature = {gate:?}, {attr})]")?,
27-
FeatureConfig::Never => {}
28+
FeatureConfig::Always => {
29+
let tokens = f();
30+
quote! { #[#tokens] }
31+
}
32+
FeatureConfig::Gated(gate) => {
33+
let tokens = f();
34+
quote! { #[cfg_attr(feature = #gate, #tokens)] }
35+
}
36+
FeatureConfig::Never => quote! {},
2837
}
29-
Ok(())
3038
}
3139

32-
pub(crate) fn fmt_cfg<W: Write, E: Into<Error>>(
33-
&self,
34-
mut w: W,
35-
f: impl FnOnce(W) -> Result<(), E>,
36-
) -> Result<()> {
40+
/// Generate a token stream optionally wrapped in a cfg attribute.
41+
/// The closure is only called when the feature is enabled, so expensive codegen can be skipped when `Never`.
42+
pub(crate) fn if_cfg<F>(&self, f: F) -> TokenStream
43+
where
44+
F: FnOnce() -> TokenStream,
45+
{
3746
match self {
38-
// If config is Never, return immediately without calling `f`
39-
FeatureConfig::Never => return Ok(()),
40-
// If config is Gated, prepend `f` with a cfg guard
47+
FeatureConfig::Always => f(),
4148
FeatureConfig::Gated(gate) => {
42-
writeln!(w, "#[cfg(feature = {gate:?})]")?;
49+
let tokens = f();
50+
quote! {
51+
#[cfg(feature = #gate)]
52+
#tokens
53+
}
4354
}
44-
// Otherwise, just call `f`
45-
FeatureConfig::Always => {}
55+
FeatureConfig::Never => quote! {},
4656
}
47-
48-
f(w).map_err(Into::into)
4957
}
5058
}

0 commit comments

Comments
 (0)