-
Notifications
You must be signed in to change notification settings - Fork 169
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
RUST-2103 Update the rest of actions to document options #1272
RUST-2103 Update the rest of actions to document options #1272
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing in here changed, just moved to its own file.
($span:expr, $($message:tt)+) => {{ | ||
return Error::new($span, format!($($message)+)).into_compile_error().into(); | ||
}}; | ||
crate::action_impl::action_impl(attrs, input) | ||
} | ||
|
||
/// Enables rustdoc links to types that link individually to each type | ||
/// component. | ||
#[proc_macro_attribute] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has to be attached to a fn at the toplevel module for whatever reason, hence the wrapper rather than just re-exporting.
impl_in.to_token_stream().into() | ||
} | ||
|
||
pub(crate) struct OptionSettersArgs { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously for the macro_magic
custom args I was keeping every token individually and laboriously reconstructing the original in ToTokens
, which was a giant hassle with any sort of change. I realized that it's much easier to just keep a clone of the entire input token stream and then only have struct members for the bits actually needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deeplink
and options_doc
are unchanged.
@@ -30,7 +38,7 @@ impl Database { | |||
/// returned cursor will be a [`SessionCursor`]. If [`with_type`](Aggregate::with_type) was | |||
/// called, the returned cursor will be generic over the `T` specified. | |||
#[deeplink] | |||
#[options_doc(aggregate_setters)] | |||
#[options_doc(aggregate)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the name is translated into a mangled representation, it's effectively in its own namespace and won't clash with anything. Having it be the same name as the fn it's attached to seemed reasonable, the _setters
suffix wasn't doing anything helpful.
range_options: RangeOptions, | ||
); | ||
} | ||
#[option_setters(EncryptOptions, skip = [query_type])] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's one of the fun corner cases! The Encrypt
action is shared across both encrypt
and encrypt_expression
; we want to expose the query_type
option for the former, both in code and documentation, but not the latter. So:
- For the generic
impl
block, the generated setter forquery_type
is skipped, and it's manually implemented forEncrypt<'_, Value>
only. - For the generated documentation for
encrypt
, the manually written setter forquery_type
is added to the list - For the generated documentation for
encrypt_expr
, it isn't
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somewhat tangential, but this led me to find a niche corner case that can lead to bad behavior when using with_options
in a call to encrypt_expression
:
let options = EncryptOptions::builder()
.contention_factor(0)
.range_options(range_options)
.build();
let result = client_encryption
.encrypt_expression(...)
.with_options(options)
.await?;
The call to encrypt_expression
sets the query_type
to the correct value on the options internally, but chaining with_options
wipes this value, and the following error is returned: EncryptExpression may only be used for range queries
.
We should add the following validation to the IntoFuture
impl for Encrypt<Expression>
:
- if
query_type
is set toSome(<string not equal to "range">)
, return an error indicating thatquery_type
cannot be set viawith_options
for calls toencrypt_expression
- if
query_type
is set toNone
, manually re-set the value toSome("range")
as the user inadvertently overrode it by the call towith_options
I can make a follow-up PR to fix this; we're also missing a TypedBuilder
impl for EncryptOptions
so I'll add that too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! Follow up PR makes sense, thank you :)
@@ -130,6 +134,7 @@ pub struct Shutdown { | |||
pub(crate) immediate: bool, | |||
} | |||
|
|||
#[export_doc(shutdown)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another corner case: we want to generate documentation for the options for shutdown
, but there's no corresponding options object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the updated docs look great!
range_options: RangeOptions, | ||
); | ||
} | ||
#[option_setters(EncryptOptions, skip = [query_type])] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somewhat tangential, but this led me to find a niche corner case that can lead to bad behavior when using with_options
in a call to encrypt_expression
:
let options = EncryptOptions::builder()
.contention_factor(0)
.range_options(range_options)
.build();
let result = client_encryption
.encrypt_expression(...)
.with_options(options)
.await?;
The call to encrypt_expression
sets the query_type
to the correct value on the options internally, but chaining with_options
wipes this value, and the following error is returned: EncryptExpression may only be used for range queries
.
We should add the following validation to the IntoFuture
impl for Encrypt<Expression>
:
- if
query_type
is set toSome(<string not equal to "range">)
, return an error indicating thatquery_type
cannot be set viawith_options
for calls toencrypt_expression
- if
query_type
is set toNone
, manually re-set the value toSome("range")
as the user inadvertently overrode it by the call towith_options
I can make a follow-up PR to fix this; we're also missing a TypedBuilder
impl for EncryptOptions
so I'll add that too.
RUST-2103
This did involve one more rework of how the macros handle things (sorry!); with that, there's now a family of three related macros:
option_setters
: takes the path to an options struct and generates setters for the fields of that struct in theimpl
block to which it's attached. Can be optionally told to skip setters for some of the fields.export_doc
: generates a notional named "doc item" for use byoptions_doc
from animpl
block. Can be optionally told to add entries to the doc item that aren't present in the code of theimpl
.options_doc
: consumes a "doc item" to add rustdoc listing option setters to afn
. Can be optionally told it's a sync fn to adjust the rustdoc output. (unchanged from last PR)With this split, I think it's both easier to read and understand (no more multiline kwarg macro invocations) and it much better handles edge cases, of which we have surprisingly many.
Oh, and I also split up the contents of
macros/src/lib.rs
since that had gotten quite big.