Skip to content

Commit 0a11ec7

Browse files
committed
feat(dtoken): private fields
Signed-off-by: Jean Mertz <git@jeanmertz.com>
1 parent 80e9be4 commit 0a11ec7

File tree

2 files changed

+96
-18
lines changed

2 files changed

+96
-18
lines changed

crates/dtoken/src/build.rs

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,23 @@ use proc_macro2::{Ident, Span, TokenStream};
1212
use quote::{quote, ToTokens};
1313
use tinyjson::JsonValue;
1414

15-
pub fn build(path: impl AsRef<str>) -> Result<(), BuildError> {
16-
write(&parse_content(&read_file(path)?)?)
15+
#[derive(Default)]
16+
pub struct Config {
17+
/// List of field names to give a private visibility modifier.
18+
///
19+
/// This currently does not do any object traversal. If this list contains a value "foo", then
20+
/// any field named "foo", regardless of the depth in the JSON object, will be set to private.
21+
pub private_fields: Vec<String>,
1722
}
1823

19-
pub fn build_merge(paths: &[impl AsRef<str>]) -> Result<(), BuildError> {
24+
pub fn build(path: impl AsRef<str>, opts: Config) -> Result<(), BuildError> {
25+
write(&parse_content(&read_file(path)?)?, opts)
26+
}
27+
28+
pub fn build_merge(paths: &[impl AsRef<str>], opts: Config) -> Result<(), BuildError> {
2029
let map = parse_content_merge(paths.iter().map(read_file).collect::<Result<Vec<_>, _>>()?)?;
2130

22-
write(&map)
31+
write(&map, opts)
2332
}
2433

2534
fn read_file(path: impl AsRef<str>) -> Result<String, BuildError> {
@@ -76,9 +85,9 @@ fn parse_content_merge(contents: Vec<String>) -> Result<HashMap<String, JsonValu
7685
Ok(map)
7786
}
7887

79-
fn write(map: &HashMap<String, JsonValue>) -> Result<(), BuildError> {
88+
fn write(map: &HashMap<String, JsonValue>, opts: Config) -> Result<(), BuildError> {
8089
let tokens = DesignTokens::from_map(map)?;
81-
let code = generate(&tokens);
90+
let code = generate(&tokens, opts);
8291

8392
let output = Path::new(&std::env::var("OUT_DIR")?).join("design_tokens.rs");
8493

@@ -312,24 +321,25 @@ fn convert_number(n: &str) -> Result<JsonValue, BuildError> {
312321
Err(BuildError::Parse(Error::ExpectedNumber))
313322
}
314323

315-
fn generate(tokens: &DesignTokens) -> TokenStream {
316-
Generator::new(tokens).generate()
324+
fn generate(tokens: &DesignTokens, opts: Config) -> TokenStream {
325+
Generator::new(tokens, opts).generate()
317326
}
318327

319328
struct Generator {
320329
root: Group,
330+
opts: Config,
321331
}
322332

323333
impl Generator {
324-
fn new(tokens: &DesignTokens) -> Self {
334+
fn new(tokens: &DesignTokens, opts: Config) -> Self {
325335
let root = Group {
326336
items: tokens.items.clone(),
327337
description: Some("Root-level Design Tokens type".to_owned()),
328338
default_type: None,
329339
extensions: HashMap::new(),
330340
};
331341

332-
Self { root }
342+
Self { root, opts }
333343
}
334344

335345
fn generate(&self) -> TokenStream {
@@ -410,13 +420,20 @@ impl Generator {
410420
nested.push(group);
411421
}
412422

423+
let mut visibilities = vec![];
413424
let mut fields = vec![];
414425
let mut types = vec![];
415426
let mut descs = vec![];
416427
for (name, token_or_group) in &items {
417428
let (field, kind) = self.struct_field(name, token_or_group);
418429
let desc = token_or_group.description().unwrap_or_default();
430+
let visibility = if self.opts.private_fields.contains(name) {
431+
quote! {}
432+
} else {
433+
quote! { pub }
434+
};
419435

436+
visibilities.push(visibility);
420437
fields.push(field);
421438
types.push(kind);
422439
descs.push(if desc.is_empty() {
@@ -445,7 +462,7 @@ impl Generator {
445462
pub struct #group_name {
446463
#(
447464
#descs
448-
pub #fields: #types,
465+
#visibilities #fields: #types,
449466
)*
450467
}
451468

@@ -599,8 +616,7 @@ fn rustfmt(path: &Path) -> Result<(), BuildError> {
599616

600617
Command::new(std::env::var("RUSTFMT").unwrap_or_else(|_| "rustfmt".to_string()))
601618
.args(["--emit", "files"])
602-
// .args(["--config", "format_strings=true,edition=2024,struct_lit_width=0,struct_lit_single_line=false,struct_variant_width=false"])
603-
.args(["--config", "format_strings=true"])
619+
.args(["--config", "format_strings=true,max_width=120"])
604620
.arg(path)
605621
.output()
606622
.map_err(BuildError::Fmt)?;
@@ -645,7 +661,7 @@ mod tests {
645661
let map: HashMap<String, JsonValue> = parse_content(case).unwrap();
646662
let tokens = DesignTokens::from_map(&map).unwrap();
647663

648-
let tokens = generate(&tokens);
664+
let tokens = generate(&tokens, Config::default());
649665
let abstract_file: File =
650666
syn::parse2(tokens.clone()).unwrap_or_else(|err| panic!("{err}:\n\n{tokens}"));
651667
let code = prettyplease::unparse(&abstract_file);
@@ -672,7 +688,7 @@ mod tests {
672688
let map: HashMap<String, JsonValue> = parse_content(case).unwrap();
673689
let tokens = DesignTokens::from_map(&map).unwrap();
674690

675-
let tokens = generate(&tokens);
691+
let tokens = generate(&tokens, Config::default());
676692
let abstract_file: File =
677693
syn::parse2(tokens.clone()).unwrap_or_else(|err| panic!("{err}:\n\n{tokens}"));
678694
let code = prettyplease::unparse(&abstract_file);
@@ -702,7 +718,7 @@ mod tests {
702718
let map: HashMap<String, JsonValue> = parse_content(case).unwrap();
703719
let tokens = DesignTokens::from_map(&map).unwrap();
704720

705-
let tokens = generate(&tokens);
721+
let tokens = generate(&tokens, Config::default());
706722
let abstract_file: File =
707723
syn::parse2(tokens.clone()).unwrap_or_else(|err| panic!("{err}:\n\n{tokens}"));
708724
let code = prettyplease::unparse(&abstract_file);
@@ -733,7 +749,7 @@ mod tests {
733749
let map: HashMap<String, JsonValue> = parse_content(case).unwrap();
734750
let tokens = DesignTokens::from_map(&map).unwrap();
735751

736-
let tokens = generate(&tokens);
752+
let tokens = generate(&tokens, Config::default());
737753
let abstract_file: File =
738754
syn::parse2(tokens.clone()).unwrap_or_else(|err| panic!("{err}:\n\n{tokens}"));
739755
let code = prettyplease::unparse(&abstract_file);
@@ -784,11 +800,44 @@ mod tests {
784800
let map = parse_content_merge(contents.iter().map(ToString::to_string).collect()).unwrap();
785801
let tokens = DesignTokens::from_map(&map).unwrap();
786802

787-
let tokens = generate(&tokens);
803+
let tokens = generate(&tokens, Config::default());
788804
let abstract_file: File =
789805
syn::parse2(tokens.clone()).unwrap_or_else(|err| panic!("{err}:\n\n{tokens}"));
790806
let code = prettyplease::unparse(&abstract_file);
791807

792808
insta::assert_snapshot!("merged content", code.to_string());
793809
}
810+
811+
#[cfg(any(
812+
not(any(feature = "ason", feature = "toml", feature = "jsonc")),
813+
all(feature = "ason", feature = "toml", feature = "jsonc")
814+
))]
815+
#[test]
816+
fn test_private_fields() {
817+
let content = indoc! {r#"
818+
{
819+
"group name": {
820+
"token name": {
821+
"$value": 1234,
822+
"$type": "number"
823+
}
824+
},
825+
"alias name": {
826+
"$value": "{group name.token name}"
827+
}
828+
}
829+
"#};
830+
831+
let map = parse_content(content).unwrap();
832+
let tokens = DesignTokens::from_map(&map).unwrap();
833+
let opts = Config {
834+
private_fields: vec!["group name".to_owned()],
835+
};
836+
let tokens = generate(&tokens, opts);
837+
let abstract_file: File =
838+
syn::parse2(tokens.clone()).unwrap_or_else(|err| panic!("{err}:\n\n{tokens}"));
839+
let code = prettyplease::unparse(&abstract_file);
840+
841+
insta::assert_snapshot!("private fields", code);
842+
}
794843
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
source: crates/dtoken/src/build.rs
3+
expression: code
4+
---
5+
#[allow(clippy::allow_attributes, clippy::too_many_lines)]
6+
pub fn design_tokens() -> design_tokens::DesignTokens {
7+
design_tokens::DesignTokens {
8+
alias_name: dtoken::types::number::Number(1234f64),
9+
group_name: design_tokens::group_name::GroupName {
10+
token_name: dtoken::types::number::Number(1234f64),
11+
},
12+
}
13+
}
14+
#[allow(clippy::allow_attributes, clippy::module_inception)]
15+
pub mod design_tokens {
16+
///Root-level Design Tokens type
17+
#[derive(Debug)]
18+
pub struct DesignTokens {
19+
pub alias_name: dtoken::types::number::Number,
20+
group_name: group_name::GroupName,
21+
}
22+
#[allow(clippy::allow_attributes, clippy::module_inception)]
23+
pub mod group_name {
24+
#[derive(Debug)]
25+
pub struct GroupName {
26+
pub token_name: dtoken::types::number::Number,
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)