-
Notifications
You must be signed in to change notification settings - Fork 68
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
FromAttributes derive macro is underdocumented. #156
Comments
For example, having input like #[my_attribute]
struct Foo{}
/// My doccomment
struct Bar{}
#[my_attribute]
/// Both attribute and a doccomment
struct Baz; how do I parse it into #[derive(FromAttributes)]
struct MyAttrs {
my_attribute: Option<()>,
doc: Option<String>,
} I tried to juggle |
Thanks for calling this out - I added Primarily, #[my_crate(opt1, opt2 = "foo")]
pub struct Bar; That would parse into a struct like this: #[derive(FromAttributes)]
#[darling(attributes(my_crate))]
struct Options {
opt1: Flag,
opt2: String,
} The advantage of using #[my_crate(opt1)]
#[my_crate(opt2 = "foo")]
pub struct Bar;
#[my_crate(opt2 = "foo")]
#[my_crate(opt1)]
pub struct Bar;
#[my_crate(opt2 = "foo", opt1)]
pub struct Bar;
// et cetera For your specific use-case, there's a problem: If this example is accurate, then I think you're looking for #[derive(FromDeriveInput)]
#[darling(forward_attrs(my_attribute, doc)]
struct Options {
attrs: Vec<Attribute>
} Would that work for you? |
How's this for an example to put in the docs? ExampleThis is an illustrative example of using #[derive(Default, FromAttributes)]
#[darling(attributes(aspect), default)]
pub struct MethodOpts {
trace: bool,
role: Option<string>,
}
pub struct AspectOpts {
methods: util::WithOriginal<MethodOpts, ImplItemMethod>
}
impl TryFrom<ItemImpl> for AspectOps {
type Error = darling::Error;
fn try_from(item_impl: ItemImpl) -> darling::Result<Self> {
let mut methods = vec![];
let mut errors = vec![];
for item in item_impl.items {
if let ImplItem::Method(method) = item {
match MethodOpts::from_attributes(&method.attrs) {
Ok(opts) => methods.push(WithOriginal::new(opts, method)),
Err(e) => errors.push(e),
}
}
}
if !errors.is_empty() {
return Err(darling::Error::multiple(errors));
}
Ok(Self { methods })
}
}
#[proc_macro_attribute]
pub fn aspect(input: TokenStream) -> TokenStream {
let impl_item: ItemImpl = syn::parse_macro_input!(input);
let options = match AspectOps::try_from(impl_item) {
Ok(ops) => ops,
Err(e) => {
return e.write_errors().into();
}
};
// at this point, darling's role is done; use `options.methods` to step
// through each of the methods, adding the necessary code for the aspects
// that were selected.
} In another crate, this can now be consumed as follows: #[aspect]
impl MyController {
#[aspect(trace)]
pub fn create(user: UserId, new_resource: Resource) -> Result<ResourceId, MyCreateError> {
// elided
}
pub fn get(user: UserId, id: ResourceId) -> Result<ResourceId, MyGetError> {
// elided
}
#[aspect(trace, role = "owner")]
pub fn delete(user: UserId, id: ResourceId) -> Result<(), MyDeleteError> {
// elided
}
} |
Maybe empty attribute sets like #[derive(FromAttributes)]
#[darling(attributes(my_crate))]
struct Options {
} should also be supported? It should return Also capturing the doccomment using Darling is counterintuitive. Shall I use
Maybe the scope should be extended to "declaratively parse everything that can be in #[] and is obtained from |
It looks like a second, more advanced example. I think it should be prepended by something trivial-ish. |
Isn't there too many #[derive(MyCrate)]
#[opt1]
#[opt2="foo"]
pub struct Bar;
#[derive(MyCrate)]
#[opt1]
#[opt2="foo"]
pub struct Bar;
#[derive(MyCrate)]
#[opt2="foo"]
#[opt1]
pub struct Bar; without annoying repetition of #[derive(FromAttributes)]
#[darling(root)]
struct Options {
opt1: Flag,
opt2: String,
} . It may also be useful for capturing foreign attributes (defined not by your crate, but "spying" on somebody else's attributes). Being able to flatten them into one structure may be nice: #[my_crate(opt2 = "foo")]
#[my_crate(opt1)]
#[other_crate(opt3="bar")]
#[freestanding_attribute]
pub struct Bar; #[derive(FromAttributes)]
#[darling(attributes(my_crate))]
struct Options {
opt1: Flag,
opt2: String,
#[darling(override_attribute="other_crate")]
opt3: Option<String>,
#[darling(root, rename="freestanding_attribute")]
f_a: Flag,
} |
Do you have something in mind? Most simpler cases should be done with Let's set the empty-attribute case aside (or file a new issue specifically for it).
If deriving
This is a very reasonable question. When I don't plan to broaden the scope.
|
I just saw the type I got at hand was |
Where is it? Does |
README's opening phrase:
From this one can assume that any attributes can be Darling-ized, just like almost any JSON can be Serde-ized. This scope limitation should be documented early and explicitly. |
Something like the opening example in README, but using |
I'd be happy to accept a PR including this in the documentation; I haven't used the
Was there a parent
I don't know that I agree this rises to the level of a scope limitation, as others have found value with the crate as-is. Even if you choose not to use its derivations, you can use its traits to model how to parse information from the AST. |
No, as it is not a proc macro at all. It is just
Obviously, the crate provide value as is for many use cases. It is already used in other part of the project (in a proc_macro crate, in It is understandable if Darling does not support parsing something like |
This is a good analogy; it's possible for |
There's a bit more documentation for this now, and the larger conversation wandered in a direction that doesn't seem related to the original, so I'm going to close this out. |
Used naively, it just bails with
error: FromAttributes without attributes collects nothing
and there seems to be no solid example of both the code and input sample, neither in README nor on docs.rs.The text was updated successfully, but these errors were encountered: