-
Notifications
You must be signed in to change notification settings - Fork 2
Add document-unstable default-feature
#23
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
Changes from 2 commits
ff73d8a
34fc2b0
2ac6d59
cd8265d
80876f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| fn main() { | ||
| println!("cargo:rustc-check-cfg=cfg(instability_exclude_unstable_docs)"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,12 +64,24 @@ impl UnstableAttribute { | |
| .into_iter() | ||
| .map(|ident| quote! { #[allow(#ident)] }); | ||
|
|
||
| #[cfg(not(instability_exclude_unstable_docs))] | ||
| let (cfg, not_cfg) = ( | ||
| quote! { #[cfg(any(doc, feature = #feature_flag))] }, | ||
| quote! { #[cfg(not(any(doc, feature = #feature_flag)))] }, | ||
| ); | ||
|
|
||
| #[cfg(instability_exclude_unstable_docs)] | ||
| let (cfg, not_cfg) = ( | ||
| quote! { #[cfg(feature = #feature_flag)] }, | ||
| quote! { #[cfg(not(feature = #feature_flag))] }, | ||
| ); | ||
|
|
||
| quote! { | ||
| #[cfg(any(doc, feature = #feature_flag))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = #feature_flag)))] | ||
| #item | ||
|
|
||
| #[cfg(not(any(doc, feature = #feature_flag)))] | ||
| #not_cfg | ||
| #(#allows)* | ||
| #hidden_item | ||
| } | ||
|
|
@@ -78,8 +90,15 @@ impl UnstableAttribute { | |
| pub fn expand_impl(&self, mut item: impl Stability + ToTokens) -> TokenStream { | ||
| let feature_flag = self.feature_flag(); | ||
| self.add_doc(&mut item); | ||
|
|
||
| #[cfg(not(instability_exclude_unstable_docs))] | ||
| let cfg = quote! { #[cfg(any(doc, feature = #feature_flag))] }; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same note about variable name here as above and adding 5 extra lines (including the newline) to avoid repeating 5 lines. |
||
|
|
||
| #[cfg(instability_exclude_unstable_docs)] | ||
| let cfg = quote! { #[cfg(feature = #feature_flag)] }; | ||
|
|
||
| quote! { | ||
| #[cfg(any(doc, feature = #feature_flag))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = #feature_flag)))] | ||
| #item | ||
| } | ||
|
|
@@ -107,6 +126,7 @@ impl UnstableAttribute { | |
| .map_or(String::from("unstable"), |name| format!("unstable-{name}")) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use pretty_assertions::assert_eq; | ||
|
|
@@ -144,6 +164,20 @@ mod tests { | |
| const WITH_FEATURES_DOC: &str = "# Stability\n\n**This API is marked as unstable** and is only available when the `unstable-experimental`\ncrate feature is enabled. This comes with no stability guarantees, and could be changed\nor removed at any time."; | ||
| const ISSUE_DOC: &str = "The tracking issue is: `#123`."; | ||
|
|
||
| fn cfg_attributes(feature: &str) -> (TokenStream, TokenStream) { | ||
| #[cfg(not(instability_exclude_unstable_docs))] | ||
| return ( | ||
| quote! { #[cfg(any(doc, feature = #feature))] }, | ||
| quote! { #[cfg(not(any(doc, feature = #feature)))] }, | ||
| ); | ||
|
|
||
| #[cfg(instability_exclude_unstable_docs)] | ||
| return ( | ||
| quote! { #[cfg(feature = #feature)] }, | ||
| quote! { #[cfg(not(feature = #feature))] }, | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn expand_with_feature() { | ||
| let item: syn::ItemType = parse_quote! { pub type Foo = Bar; }; | ||
|
|
@@ -152,13 +186,15 @@ mod tests { | |
| issue: None, | ||
| }; | ||
| let tokens = unstable.expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable-experimental"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable-experimental"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable-experimental")))] | ||
| #[doc = #WITH_FEATURES_DOC] | ||
| pub type Foo = Bar; | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable-experimental")))] | ||
| #not_cfg | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a general rule, I like tests to be fairly linear and simple when possible. I don't like to have to think about an expectation being several different things based on a flag like this. Often this means not calling any code that has logic like this and being WET (Write Everything Twice) instead of DRY. Here that means adding an extra It's possible that we might need to introduce something like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm absolutely on the same page about that
Would be awesome to have something like that. Unfortunately, I don't see a way to pass feature flags to
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this is something that falls at the edges of my knowledge, so solutions are very much about exploring rather than synthesizing. Making the tests simple and easy to understand / fix when they break is the main point of this. I'm fine with the extra CI to do this (unless there's some obvious other way that would make it possible to run this without that needed). That can definitely be out of scope for getting this PR over the line and something to think about for later. |
||
| #[allow(dead_code)] | ||
| #[doc = #WITH_FEATURES_DOC] | ||
| pub(crate) type Foo = Bar; | ||
|
|
@@ -174,14 +210,16 @@ mod tests { | |
| issue: Some("#123".to_string()), | ||
| }; | ||
| let tokens = unstable.expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| #[doc = #ISSUE_DOC] | ||
| pub type Foo = Bar; | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| #[doc = #ISSUE_DOC] | ||
|
|
@@ -194,13 +232,15 @@ mod tests { | |
| fn expand_public_type() { | ||
| let item: syn::ItemType = parse_quote! { pub type Foo = Bar; }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub type Foo = Bar; | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) type Foo = Bar; | ||
|
|
@@ -216,15 +256,17 @@ mod tests { | |
| } | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub struct Foo { | ||
| pub field: i32, | ||
| } | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) struct Foo { | ||
|
|
@@ -243,16 +285,18 @@ mod tests { | |
| } | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub enum Foo { | ||
| A, | ||
| B, | ||
| } | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) enum Foo { | ||
|
|
@@ -269,13 +313,15 @@ mod tests { | |
| pub fn foo() {} | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub fn foo() {} | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) fn foo() {} | ||
|
|
@@ -291,15 +337,17 @@ mod tests { | |
| } | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub trait Foo { | ||
| fn bar(&self); | ||
| } | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) trait Foo { | ||
|
|
@@ -315,13 +363,15 @@ mod tests { | |
| pub const FOO: i32 = 42; | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub const FOO: i32 = 42; | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) const FOO: i32 = 42; | ||
|
|
@@ -335,13 +385,15 @@ mod tests { | |
| pub static FOO: i32 = 42; | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub static FOO: i32 = 42; | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) static FOO: i32 = 42; | ||
|
|
@@ -357,15 +409,17 @@ mod tests { | |
| } | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub mod foo { | ||
| pub fn bar() {} | ||
| } | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(dead_code)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) mod foo { | ||
|
|
@@ -381,13 +435,15 @@ mod tests { | |
| pub use crate::foo::bar; | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand(item); | ||
|
|
||
| let (cfg, not_cfg) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub use crate::foo::bar; | ||
|
|
||
| #[cfg(not(any(doc, feature = "unstable")))] | ||
| #not_cfg | ||
| #[allow(unused_imports)] | ||
| #[doc = #DEFAULT_DOC] | ||
| pub(crate) use crate::foo::bar; | ||
|
|
@@ -401,8 +457,10 @@ mod tests { | |
| impl Default for crate::foo::Foo {} | ||
| }; | ||
| let tokens = UnstableAttribute::default().expand_impl(item); | ||
|
|
||
| let (cfg, _) = cfg_attributes("unstable"); | ||
| let expected = quote! { | ||
| #[cfg(any(doc, feature = "unstable"))] | ||
| #cfg | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] | ||
| #[doc = #DEFAULT_DOC] | ||
| impl Default for crate::foo::Foo {} | ||
|
|
||
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.
There's a couple of things which confused me on initially reading this:
#[cfg]macro. This actually caught me on the initial reading of this (I'm pretty sure I read it on a phone), so not a hypothetical misunderstanding, an actual one. A longer name here would help this a bit.if cfg!(instability_exclude_unstable_docs) { quote! { ... } } else quote! { ... }and remove that indirection.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.
Agreed - tried to come up with a better naming
I see - unfortunately we cannot just inline the cfg-gating on
instability_disable_unstable_docs- it would be emitted in the resulting code which is not what we want here