Skip to content

Commit 26010eb

Browse files
authored
Merge pull request #7 from mystor/hide_helpers
Hide helper traits from calling code
2 parents eb369ed + 5db9364 commit 26010eb

File tree

4 files changed

+76
-46
lines changed

4 files changed

+76
-46
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
on: [push]
1+
on: [push, pull_request]
22

33
name: Continuous integration
44

src/expand.rs

+23-27
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,48 @@ use quote::{format_ident, quote};
44
use syn::{Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Result};
55

66
pub fn derive(input: &DeriveInput) -> Result<TokenStream> {
7-
match &input.data {
7+
let impls = match &input.data {
88
Data::Struct(data) => impl_struct(input, data),
99
Data::Enum(data) => impl_enum(input, data),
1010
Data::Union(_) => Err(Error::new_spanned(input, "Unions are not supported")),
11-
}
11+
}?;
12+
13+
let helpers = specialization();
14+
let dummy_const = format_ident!("_DERIVE_Display_FOR_{}", input.ident);
15+
Ok(quote! {
16+
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
17+
const #dummy_const: () = {
18+
#helpers
19+
#impls
20+
};
21+
})
1222
}
1323

1424
#[cfg(feature = "std")]
1525
fn specialization() -> TokenStream {
1626
quote! {
1727
trait DisplayToDisplayDoc {
18-
fn get_display(&self) -> Self;
28+
fn __displaydoc_display(&self) -> &Self;
1929
}
2030

21-
impl<T: core::fmt::Display> DisplayToDisplayDoc for &T {
22-
fn get_display(&self) -> Self {
31+
impl<T: core::fmt::Display> DisplayToDisplayDoc for T {
32+
fn __displaydoc_display(&self) -> &Self {
2333
self
2434
}
2535
}
2636

2737
trait PathToDisplayDoc {
28-
fn get_display(&self) -> std::path::Display<'_>;
38+
fn __displaydoc_display(&self) -> std::path::Display<'_>;
2939
}
3040

3141
impl PathToDisplayDoc for std::path::Path {
32-
fn get_display(&self) -> std::path::Display<'_> {
42+
fn __displaydoc_display(&self) -> std::path::Display<'_> {
3343
self.display()
3444
}
3545
}
3646

3747
impl PathToDisplayDoc for std::path::PathBuf {
38-
fn get_display(&self) -> std::path::Display<'_> {
48+
fn __displaydoc_display(&self) -> std::path::Display<'_> {
3949
self.display()
4050
}
4151
}
@@ -74,13 +84,7 @@ fn impl_struct(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
7484
}
7585
});
7686

77-
let needed_traits = specialization();
78-
79-
Ok(quote! {
80-
#needed_traits
81-
82-
#display
83-
})
87+
Ok(quote! { #display })
8488
}
8589

8690
fn impl_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
@@ -93,7 +97,7 @@ fn impl_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
9397
.map(|variant| attr::display(&variant.attrs))
9498
.collect::<Result<Vec<_>>>()?;
9599

96-
let display = if displays.iter().any(Option::is_some) {
100+
if displays.iter().any(Option::is_some) {
97101
let arms = data
98102
.variants
99103
.iter()
@@ -115,7 +119,7 @@ fn impl_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
115119
})
116120
})
117121
.collect::<Result<Vec<_>>>()?;
118-
Some(quote! {
122+
Ok(quote! {
119123
impl #impl_generics core::fmt::Display for #ty #ty_generics #where_clause {
120124
fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
121125
#[allow(unused_variables)]
@@ -126,14 +130,6 @@ fn impl_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
126130
}
127131
})
128132
} else {
129-
return Err(Error::new_spanned(input, "Missing doc comments"));
130-
};
131-
132-
let needed_traits = specialization();
133-
134-
Ok(quote! {
135-
#needed_traits
136-
137-
#display
138-
})
133+
Err(Error::new_spanned(input, "Missing doc comments"))
134+
}
139135
}

src/fmt.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ use proc_macro2::TokenStream;
33
use quote::quote_spanned;
44
use syn::{Ident, LitStr};
55

6-
#[cfg(feature = "std")]
7-
const IS_STD: bool = true;
8-
#[cfg(not(feature = "std"))]
9-
const IS_STD: bool = false;
10-
116
macro_rules! peek_next {
127
($read:ident) => {
138
match $read.chars().next() {
@@ -49,8 +44,8 @@ impl Display {
4944

5045
let next = peek_next!(read);
5146

52-
let arg = if IS_STD && next == '}' {
53-
quote_spanned!(span=> , (&#ident).get_display())
47+
let arg = if cfg!(feature = "std") && next == '}' {
48+
quote_spanned!(span=> , #ident.__displaydoc_display())
5449
} else {
5550
quote_spanned!(span=> , #ident)
5651
};
@@ -120,11 +115,33 @@ mod tests {
120115
assert(
121116
"{v} {v:?} {0} {0:?}",
122117
"{} {:?} {} {:?}",
123-
", ( & v ) . get_display ( ) , v , ( & _0 ) . get_display ( ) , _0",
118+
", v . __displaydoc_display ( ) , v , _0 . __displaydoc_display ( ) , _0",
119+
);
120+
assert(
121+
"error {var}",
122+
"error {}",
123+
", var . __displaydoc_display ( )",
124+
);
125+
126+
assert(
127+
"The path {0}",
128+
"The path {}",
129+
", _0 . __displaydoc_display ( )",
130+
);
131+
assert("The path {0:?}", "The path {:?}", ", _0");
132+
}
133+
134+
#[test]
135+
#[cfg_attr(feature = "std", ignore)]
136+
fn test_nostd_expand() {
137+
assert(
138+
"{v} {v:?} {0} {0:?}",
139+
"{} {:?} {} {:?}",
140+
", v , v , _0 , _0",
124141
);
125-
assert("error {var}", "error {}", ", ( & var ) . get_display ( )");
142+
assert("error {var}", "error {}", ", var");
126143

127-
// assert("The path {0.display()}", "The path {}", "0.display()");
128-
// assert("The path {0.display():?}", "The path {:?}", "0.display()");
144+
assert("The path {0}", "The path {}", ", _0");
145+
assert("The path {0:?}", "The path {:?}", ", _0");
129146
}
130147
}

tests/happy.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
use displaydoc::Display;
2-
// use std::path::PathBuf;
2+
3+
#[cfg(feature = "std")]
4+
use std::path::PathBuf;
5+
6+
#[derive(Display)]
7+
/// Just a basic struct {thing}
8+
struct HappyStruct {
9+
thing: &'static str,
10+
}
311

412
#[derive(Display)]
513
enum Happy {
@@ -18,8 +26,10 @@ enum Happy {
1826
/// Variant5 just has {0} many problems
1927
/// but multi line comments aren't one of them
2028
Variant5(u32),
21-
// /// The path {0.display()}
22-
// Variant6(PathBuf),
29+
30+
/// The path {0}
31+
#[cfg(feature = "std")]
32+
Variant6(PathBuf),
2333
}
2434

2535
fn assert_display<T: std::fmt::Display>(input: T, expected: &'static str) {
@@ -37,8 +47,15 @@ fn does_it_print() {
3747
"Variant4 wants to have a lot of lines\n\n Lets see how this works out for it",
3848
);
3949
assert_display(Happy::Variant5(2), "Variant5 just has 2 many problems");
40-
// assert_display(
41-
// Happy::Variant6(PathBuf::from("/var/log/happy")),
42-
// "The path /var/log/happy",
43-
// );
50+
51+
assert_display(HappyStruct { thing: "hi" }, "Just a basic struct hi");
52+
}
53+
54+
#[test]
55+
#[cfg(feature = "std")]
56+
fn does_it_print_path() {
57+
assert_display(
58+
Happy::Variant6(PathBuf::from("/var/log/happy")),
59+
"The path /var/log/happy",
60+
);
4461
}

0 commit comments

Comments
 (0)