Skip to content

Commit

Permalink
Generate docs for the field contained in a transparent value
Browse files Browse the repository at this point in the history
Most `#[turbo_tasks::value(transparent)]` types leave their inner value
as private. I think this okay, but because rustdoc hides private fields
by default, it makes it hard to understand at a glance the contained
value, without scrolling down to the `impl` of `VcValueType`.

This auto-generates documentation for these types.
  • Loading branch information
bgw committed May 3, 2024
1 parent 5397453 commit 776c923
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 18 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/turbo-tasks-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ anyhow = { workspace = true }
proc-macro-error = "1.0.4"
proc-macro2 = { workspace = true }
quote = { workspace = true }
regex = { workspace = true }
syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] }
turbo-tasks-macros-shared = { workspace = true }
68 changes: 50 additions & 18 deletions crates/turbo-tasks-macros/src/value_macro.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::sync::OnceLock;

use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::quote;
use quote::{quote, ToTokens};
use regex::Regex;
use syn::{
parse::{Parse, ParseStream},
parse_macro_input,
parse_macro_input, parse_quote,
punctuated::Punctuated,
spanned::Spanned,
Error, Fields, FieldsUnnamed, Generics, Item, ItemEnum, ItemStruct, Lit, LitStr, Meta,
Expand Down Expand Up @@ -189,7 +192,7 @@ impl Parse for ValueArguments {
}

pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
let item = parse_macro_input!(input as Item);
let mut item = parse_macro_input!(input as Item);
let ValueArguments {
serialization_mode,
into_mode,
Expand All @@ -198,6 +201,49 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
transparent,
} = parse_macro_input!(args as ValueArguments);

let mut inner_type = None;
if transparent {
if let Item::Struct(ItemStruct {
attrs,
fields: Fields::Unnamed(FieldsUnnamed { unnamed, .. }),
..
}) = &mut item
{
if unnamed.len() == 1 {
let field = unnamed.iter().next().unwrap();
inner_type = Some(field.ty.clone());

// generate a type string to add to the docs
let inner_type_string = inner_type.to_token_stream().to_string();

// HACK: proc_macro2 inserts whitespace between every token. It's ugly, so
// remove it, assuming these whitespace aren't syntatically important. Using
// prettyplease (or similar) would be more correct, but slower and add another
// dependency.
static WHITESPACE_RE: OnceLock<Regex> = OnceLock::new();
// Remove whitespace, as long as there is a non-word character (e.g. `>` or `,`)
// on either side. Try not to remove whitespace between `dyn Trait`.
let whitespace_re = WHITESPACE_RE.get_or_init(|| {
Regex::new(r"\b \B|\B \b|\B \B").expect("WHITESPACE_RE is valid")
});
let inner_type_string = whitespace_re.replace_all(&inner_type_string, "");

// Add a couple blank lines in case there's already a doc comment we're
// effectively appending to. If there's not, rustdoc will strip
// the leading whitespace.
let doc_str = format!(
"\n\nThis is a [transparent value type][::turbo_tasks::value#transparent] \
wrapping [`{}`].",
inner_type_string,
);

attrs.push(parse_quote! {
#[doc = #doc_str]
});
}
}
}

let ident = match &item {
Item::Enum(ItemEnum { ident, .. }) => ident,
Item::Struct(ItemStruct { ident, .. }) => ident,
Expand All @@ -211,20 +257,6 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
}
};

let mut inner_type = None;
if transparent {
if let Item::Struct(ItemStruct {
fields: Fields::Unnamed(FieldsUnnamed { unnamed, .. }),
..
}) = &item
{
if unnamed.len() == 1 {
let field = unnamed.iter().next().unwrap();
inner_type = Some(&field.ty);
}
}
}

let cell_mode = match cell_mode {
CellMode::New => quote! {
turbo_tasks::VcCellNewMode<#ident>
Expand All @@ -234,7 +266,7 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream {
},
};

let (cell_prefix, cell_access_content, read) = if let Some(inner_type) = inner_type {
let (cell_prefix, cell_access_content, read) = if let Some(inner_type) = &inner_type {
(
quote! { pub },
quote! {
Expand Down

0 comments on commit 776c923

Please sign in to comment.