@@ -2,7 +2,7 @@ mod options_metadata;
2
2
3
3
use proc_macro:: TokenStream ;
4
4
use quote:: quote;
5
- use syn:: { parse_macro_input, DeriveInput } ;
5
+ use syn:: { parse_macro_input, Attribute , DeriveInput , ImplItem , ItemImpl , LitStr } ;
6
6
7
7
#[ proc_macro_derive( OptionsMetadata , attributes( option, doc, option_group) ) ]
8
8
pub fn derive_options_metadata ( input : TokenStream ) -> TokenStream {
@@ -49,3 +49,92 @@ fn impl_combine(ast: &DeriveInput) -> TokenStream {
49
49
} ;
50
50
gen. into ( )
51
51
}
52
+
53
+ fn get_doc_comment ( attrs : & [ Attribute ] ) -> String {
54
+ attrs
55
+ . iter ( )
56
+ . filter_map ( |attr| {
57
+ if attr. path ( ) . is_ident ( "doc" ) {
58
+ if let syn:: Meta :: NameValue ( meta) = & attr. meta {
59
+ if let syn:: Expr :: Lit ( expr) = & meta. value {
60
+ if let syn:: Lit :: Str ( str) = & expr. lit {
61
+ return Some ( str. value ( ) . trim ( ) . to_string ( ) ) ;
62
+ }
63
+ }
64
+ }
65
+ }
66
+ None
67
+ } )
68
+ . collect :: < Vec < _ > > ( )
69
+ . join ( "\n " )
70
+ }
71
+
72
+ fn get_env_var_pattern_from_attr ( attrs : & [ Attribute ] ) -> Option < String > {
73
+ attrs
74
+ . iter ( )
75
+ . find ( |attr| attr. path ( ) . is_ident ( "attr_env_var_pattern" ) )
76
+ . and_then ( |attr| attr. parse_args :: < LitStr > ( ) . ok ( ) )
77
+ . map ( |lit_str| lit_str. value ( ) )
78
+ }
79
+
80
+ fn is_hidden ( attrs : & [ Attribute ] ) -> bool {
81
+ attrs. iter ( ) . any ( |attr| attr. path ( ) . is_ident ( "attr_hidden" ) )
82
+ }
83
+
84
+ /// This attribute is used to generate environment variables metadata for [`uv_static::EnvVars`].
85
+ #[ proc_macro_attribute]
86
+ pub fn attribute_env_vars_metadata ( _attr : TokenStream , input : TokenStream ) -> TokenStream {
87
+ let ast = parse_macro_input ! ( input as ItemImpl ) ;
88
+
89
+ let constants: Vec < _ > = ast
90
+ . items
91
+ . iter ( )
92
+ . filter_map ( |item| match item {
93
+ ImplItem :: Const ( item) if !is_hidden ( & item. attrs ) => {
94
+ let name = item. ident . to_string ( ) ;
95
+ let doc = get_doc_comment ( & item. attrs ) ;
96
+ Some ( ( name, doc) )
97
+ }
98
+ ImplItem :: Fn ( item) if !is_hidden ( & item. attrs ) => {
99
+ // Extract the environment variable patterns.
100
+ if let Some ( pattern) = get_env_var_pattern_from_attr ( & item. attrs ) {
101
+ let doc = get_doc_comment ( & item. attrs ) ;
102
+ Some ( ( pattern, doc) )
103
+ } else {
104
+ None // Skip if pattern extraction fails.
105
+ }
106
+ }
107
+ _ => None ,
108
+ } )
109
+ . collect ( ) ;
110
+
111
+ let struct_name = & ast. self_ty ;
112
+ let pairs = constants. iter ( ) . map ( |( name, doc) | {
113
+ quote ! {
114
+ ( #name, #doc)
115
+ }
116
+ } ) ;
117
+
118
+ let expanded = quote ! {
119
+ #ast
120
+
121
+ impl #struct_name {
122
+ /// Returns a list of pairs of env var and their documentation defined in this impl block.
123
+ pub fn metadata<' a>( ) -> & ' a [ ( & ' static str , & ' static str ) ] {
124
+ & [ #( #pairs) , * ]
125
+ }
126
+ }
127
+ } ;
128
+
129
+ expanded. into ( )
130
+ }
131
+
132
+ #[ proc_macro_attribute]
133
+ pub fn attr_hidden ( _attr : TokenStream , item : TokenStream ) -> TokenStream {
134
+ item
135
+ }
136
+
137
+ #[ proc_macro_attribute]
138
+ pub fn attr_env_var_pattern ( _attr : TokenStream , item : TokenStream ) -> TokenStream {
139
+ item
140
+ }
0 commit comments