Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close #109: Add crate_module_path #111

Merged
merged 1 commit into from
Aug 26, 2023
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- `#[builder(crate_module_path = ...)]` for overcoming cases where the derive
macro is used in another crate's macro (see issue #109)

## 0.15.2 - 2023-08-03
### Fixed
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ use core::ops::FnOnce;
/// but it won't be a link. If you turn this on, the builder type and its `build` method will get
/// sane defaults. The field methods on the builder will be undocumented by default.
///
/// - `crate_module_path`: This is only needed when `typed_builder` is reexported from another
/// crate - which usually happens when another macro uses it. In that case, it is the
/// reponsibility of that macro to set the `crate_module_path` to the _unquoted_ module path from
/// which the `typed_builder` crate can be accessed, so that the `TypedBuilder` macro will be
/// able to access the typed declared in it.
///
/// Defaults to `#[builder(crate_module_path=::typed_builder)]`.
///
/// - The following subsections:
/// - `builder_method(...)`: customize the builder method that creates the builder type
/// - `builder_type(...)`: customize the builder type
Expand Down
4 changes: 2 additions & 2 deletions typed-builder-macro/src/field_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,11 @@ impl SetterSettings {
Ok(())
}
"prefix" => {
self.prefix = Some(expr_to_lit_string(&*assign.right)?);
self.prefix = Some(expr_to_lit_string(&assign.right)?);
Ok(())
}
"suffix" => {
self.suffix = Some(expr_to_lit_string(&*assign.right)?);
self.suffix = Some(expr_to_lit_string(&assign.right)?);
Ok(())
}
_ => Err(Error::new_spanned(&assign, format!("Unknown parameter {:?}", name))),
Expand Down
59 changes: 38 additions & 21 deletions typed-builder-macro/src/struct_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,25 +405,18 @@ impl<'a> StructInfo<'a> {
paren_token: None,
lifetimes: None,
modifier: syn::TraitBoundModifier::None,
path: syn::Path {
leading_colon: Some(syn::token::PathSep::default()),
segments: [
syn::PathSegment {
ident: Ident::new("typed_builder", Span::call_site()),
arguments: syn::PathArguments::None,
},
syn::PathSegment {
ident: Ident::new("Optional", Span::call_site()),
arguments: syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: Default::default(),
args: [syn::GenericArgument::Type(field.ty.clone())].into_iter().collect(),
gt_token: Default::default(),
}),
},
]
.into_iter()
.collect(),
path: {
let mut path = self.builder_attr.crate_module_path.clone();
path.segments.push(syn::PathSegment {
ident: Ident::new("Optional", Span::call_site()),
arguments: syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
colon2_token: None,
lt_token: Default::default(),
args: [syn::GenericArgument::Type(field.ty.clone())].into_iter().collect(),
gt_token: Default::default(),
}),
});
path
},
};
let mut generic_param: syn::TypeParam = field.generic_ident.clone().into();
Expand Down Expand Up @@ -463,7 +456,8 @@ impl<'a> StructInfo<'a> {
if field.builder_attr.setter.skip.is_some() {
quote!(let #name = #default;)
} else {
quote!(let #name = ::typed_builder::Optional::into_value(#name, || #default);)
let crate_module_path = &self.builder_attr.crate_module_path;
quote!(let #name = #crate_module_path::Optional::into_value(#name, || #default);)
}
} else {
quote!(let #name = #name.0;)
Expand Down Expand Up @@ -619,7 +613,7 @@ impl BuildMethodSettings {
}
}

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct TypeBuilderAttr<'a> {
/// Whether to show docs for the `TypeBuilder` type (rather than hiding them).
pub doc: bool,
Expand All @@ -634,6 +628,21 @@ pub struct TypeBuilderAttr<'a> {
pub build_method: BuildMethodSettings,

pub field_defaults: FieldBuilderAttr<'a>,

pub crate_module_path: syn::Path,
}

impl Default for TypeBuilderAttr<'_> {
fn default() -> Self {
Self {
doc: Default::default(),
builder_method: Default::default(),
builder_type: Default::default(),
build_method: Default::default(),
field_defaults: Default::default(),
crate_module_path: syn::parse_quote!(::typed_builder),
}
}
}

impl<'a> TypeBuilderAttr<'a> {
Expand Down Expand Up @@ -678,6 +687,14 @@ impl<'a> TypeBuilderAttr<'a> {
)
};
match name.as_str() {
"crate_module_path" => {
if let syn::Expr::Path(crate_module_path) = assign.right.as_ref() {
self.crate_module_path = crate_module_path.path.clone();
Ok(())
} else {
Err(Error::new_spanned(&assign.right, "crate_module_path must be a path"))
}
}
"builder_method_doc" => Err(gen_structure_depracation_error("builder_method", "doc")),
"builder_type_doc" => Err(gen_structure_depracation_error("builder_type", "doc")),
"build_method_doc" => Err(gen_structure_depracation_error("build_method", "doc")),
Expand Down
4 changes: 2 additions & 2 deletions typed-builder-macro/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ pub fn expr_to_lit_string(expr: &syn::Expr) -> Result<String, Error> {
match expr {
syn::Expr::Lit(lit) => match &lit.lit {
syn::Lit::Str(str) => Ok(str.value()),
_ => return Err(Error::new_spanned(expr, "attribute only allows str values")),
_ => Err(Error::new_spanned(expr, "attribute only allows str values")),
},
_ => return Err(Error::new_spanned(expr, "attribute only allows str values")),
_ => Err(Error::new_spanned(expr, "attribute only allows str values")),
}
}
Loading