Skip to content

Commit d6bbbe2

Browse files
authored
Merge pull request #961 from dtolnay/hidden
Do nonexhaustive detection based on doc(hidden) attribute
2 parents 72c006c + dffc40d commit d6bbbe2

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

codegen/src/parse.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ const SYN_CRATE_ROOT: &str = "../src/lib.rs";
1717
const TOKEN_SRC: &str = "../src/token.rs";
1818
const IGNORED_MODS: &[&str] = &["fold", "visit", "visit_mut"];
1919
const EXTRA_TYPES: &[&str] = &["Lifetime"];
20-
const NONEXHAUSTIVE: &str = "__Nonexhaustive";
2120

2221
// NOTE: BTreeMap is used here instead of HashMap to have deterministic output.
2322
type ItemLookup = BTreeMap<Ident, AstItem>;
@@ -63,7 +62,7 @@ fn introspect_item(item: &AstItem, items: &ItemLookup, tokens: &TokenLookup) ->
6362
ident: item.ast.ident.to_string(),
6463
features,
6564
data: types::Data::Enum(introspect_enum(data, items, tokens)),
66-
exhaustive: data.variants.iter().all(|v| v.ident != NONEXHAUSTIVE),
65+
exhaustive: !data.variants.iter().any(|v| is_doc_hidden(&v.attrs)),
6766
},
6867
Data::Struct(ref data) => types::Node {
6968
ident: item.ast.ident.to_string(),
@@ -85,7 +84,7 @@ fn introspect_enum(item: &DataEnum, items: &ItemLookup, tokens: &TokenLookup) ->
8584
item.variants
8685
.iter()
8786
.filter_map(|variant| {
88-
if variant.ident == NONEXHAUSTIVE {
87+
if is_doc_hidden(&variant.attrs) {
8988
return None;
9089
}
9190
let fields = match &variant.fields {
@@ -215,6 +214,20 @@ fn is_pub(vis: &Visibility) -> bool {
215214
}
216215
}
217216

217+
fn is_doc_hidden(attrs: &[Attribute]) -> bool {
218+
for attr in attrs {
219+
if attr.path.is_ident("doc") {
220+
if parsing::parse_doc_hidden_attr
221+
.parse2(attr.tokens.clone())
222+
.is_ok()
223+
{
224+
return true;
225+
}
226+
}
227+
}
228+
false
229+
}
230+
218231
fn first_arg(params: &PathArguments) -> &syn::Type {
219232
let data = match *params {
220233
PathArguments::AngleBracketed(ref data) => data,
@@ -331,11 +344,12 @@ mod parsing {
331344

332345
// A single variant of an ast_enum_of_structs!
333346
struct EosVariant {
347+
attrs: Vec<Attribute>,
334348
name: Ident,
335349
member: Option<Path>,
336350
}
337351
fn eos_variant(input: ParseStream) -> Result<EosVariant> {
338-
input.call(Attribute::parse_outer)?;
352+
let attrs = input.call(Attribute::parse_outer)?;
339353
let variant: Ident = input.parse()?;
340354
let member = if input.peek(token::Paren) {
341355
let content;
@@ -347,6 +361,7 @@ mod parsing {
347361
};
348362
input.parse::<Token![,]>()?;
349363
Ok(EosVariant {
364+
attrs,
350365
name: variant,
351366
member,
352367
})
@@ -371,10 +386,11 @@ mod parsing {
371386

372387
let enum_item = {
373388
let variants = variants.iter().map(|v| {
374-
let name = v.name.clone();
389+
let attrs = &v.attrs;
390+
let name = &v.name;
375391
match v.member {
376-
Some(ref member) => quote!(#name(#member)),
377-
None => quote!(#name),
392+
Some(ref member) => quote!(#(#attrs)* #name(#member)),
393+
None => quote!(#(#attrs)* #name),
378394
}
379395
});
380396
parse_quote! {
@@ -390,6 +406,7 @@ mod parsing {
390406
}
391407

392408
mod kw {
409+
syn::custom_keyword!(hidden);
393410
syn::custom_keyword!(macro_rules);
394411
syn::custom_keyword!(Token);
395412
}
@@ -489,6 +506,13 @@ mod parsing {
489506
}
490507
Ok(None)
491508
}
509+
510+
pub fn parse_doc_hidden_attr(input: ParseStream) -> Result<()> {
511+
let content;
512+
parenthesized!(content in input);
513+
content.parse::<kw::hidden>()?;
514+
Ok(())
515+
}
492516
}
493517

494518
fn clone_features(features: &[Attribute]) -> Vec<Attribute> {

0 commit comments

Comments
 (0)