1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
use syn::{parse_quote, Visibility};
// If `vis` describes a visibility relative to some module scope, returns the
// same visibility as described from a module contained within that scope.
//
// quote! {
// #vis #A;
// mod #name {
// // Same visibility as super::A.
// #vis_super #B;
// }
// }
//
// Note if you are considering copying this implementation into another crate:
// please try not to. Visibilities in Rust are confusing and subtle, especially
// around visibility specifiers of items declared inside of a function body.
// This function is not a robust implementation of the transformation that it
// claims to implement. Always first try to restructure your code to avoid
// needing this logic.
pub fn vis_super(vis: &Visibility) -> Visibility {
match vis {
Visibility::Public(vis) => {
// pub -> pub
parse_quote!(#vis)
}
Visibility::Restricted(vis) => {
if vis.path.segments[0].ident == "self" {
// pub(self) -> pub(in super)
// pub(in self::super) -> pub(in super::super)
let path = vis.path.segments.iter().skip(1);
parse_quote!(pub(in super #(::#path)*))
} else if vis.path.segments[0].ident == "super" {
// pub(super) -> pub(in super::super)
// pub(in super::super) -> pub(in super::super::super)
let path = &vis.path;
parse_quote!(pub(in super::#path))
} else {
// pub(crate) -> pub(crate)
// pub(in crate::path) -> pub(in crate::path)
parse_quote!(#vis)
}
}
Visibility::Inherited => {
// private -> pub(super)
parse_quote!(pub(super))
}
}
}