Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions crates/uv-dev/src/generate_env_vars_reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,27 +80,31 @@ fn generate() -> String {
// Partition and sort environment variables into UV_ and external variables.
let (uv_vars, external_vars): (BTreeSet<_>, BTreeSet<_>) = EnvVars::metadata()
.iter()
.partition(|(var, _)| var.starts_with("UV_"));
.partition(|(var, _, _)| var.starts_with("UV_"));

output.push_str("uv defines and respects the following environment variables:\n\n");

for (var, doc) in uv_vars {
output.push_str(&render(var, doc));
for (var, doc, added_in) in uv_vars {
output.push_str(&render(var, doc, added_in));
}

output.push_str("\n\n## Externally defined variables\n\n");
output.push_str("uv also reads the following externally defined environment variables:\n\n");

for (var, doc) in external_vars {
output.push_str(&render(var, doc));
for (var, doc, added_in) in external_vars {
output.push_str(&render(var, doc, added_in));
}

output
}

/// Render an environment variable and its documentation.
fn render(var: &str, doc: &str) -> String {
format!("### `{var}`\n\n{doc}\n\n")
fn render(var: &str, doc: &str, added_in: Option<&str>) -> String {
if let Some(added_in) = added_in {
format!("### `{var}`\n<small class=\"added-in\">added in `{added_in}`</small>\n\n{doc}\n\n")
} else {
format!("### `{var}`\n\n{doc}\n\n")
}
}

#[cfg(test)]
Expand Down
29 changes: 23 additions & 6 deletions crates/uv-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ fn get_env_var_pattern_from_attr(attrs: &[Attribute]) -> Option<String> {
.map(|lit_str| lit_str.value())
}

fn get_added_in(attrs: &[Attribute]) -> Option<String> {
attrs
.iter()
.find(|a| a.path().is_ident("attr_added_in"))
.and_then(|attr| attr.parse_args::<LitStr>().ok())
.map(|lit_str| lit_str.value())
}

fn is_hidden(attrs: &[Attribute]) -> bool {
attrs.iter().any(|attr| attr.path().is_ident("attr_hidden"))
}
Expand All @@ -92,6 +100,7 @@ pub fn attribute_env_vars_metadata(_attr: TokenStream, input: TokenStream) -> To
.filter_map(|item| match item {
ImplItem::Const(item) if !is_hidden(&item.attrs) => {
let doc = get_doc_comment(&item.attrs);
let added_in = get_added_in(&item.attrs);
let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(lit),
..
Expand All @@ -100,13 +109,14 @@ pub fn attribute_env_vars_metadata(_attr: TokenStream, input: TokenStream) -> To
return None;
};
let name = lit.value();
Some((name, doc))
Some((name, doc, added_in))
}
ImplItem::Fn(item) if !is_hidden(&item.attrs) => {
// Extract the environment variable patterns.
if let Some(pattern) = get_env_var_pattern_from_attr(&item.attrs) {
let doc = get_doc_comment(&item.attrs);
Some((pattern, doc))
let added_in = get_added_in(&item.attrs);
Some((pattern, doc, added_in))
} else {
None // Skip if pattern extraction fails.
}
Expand All @@ -116,9 +126,11 @@ pub fn attribute_env_vars_metadata(_attr: TokenStream, input: TokenStream) -> To
.collect();

let struct_name = &ast.self_ty;
let pairs = constants.iter().map(|(name, doc)| {
quote! {
(#name, #doc)
let pairs = constants.iter().map(|(name, doc, added_in)| {
if let Some(added_in) = added_in {
quote! { (#name, #doc, Some(#added_in)) }
} else {
quote! { (#name, #doc, None) }
}
});

Expand All @@ -127,7 +139,7 @@ pub fn attribute_env_vars_metadata(_attr: TokenStream, input: TokenStream) -> To

impl #struct_name {
/// Returns a list of pairs of env var and their documentation defined in this impl block.
pub fn metadata<'a>() -> &'a [(&'static str, &'static str)] {
pub fn metadata<'a>() -> &'a [(&'static str, &'static str, Option<&'static str>)] {
&[#(#pairs),*]
}
}
Expand All @@ -145,3 +157,8 @@ pub fn attr_hidden(_attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn attr_env_var_pattern(_attr: TokenStream, item: TokenStream) -> TokenStream {
item
}

#[proc_macro_attribute]
pub fn attr_added_in(_attr: TokenStream, item: TokenStream) -> TokenStream {
item
}
Loading
Loading