]>
git.proxmox.com Git - rustc.git/blob - vendor/clap_derive/src/utils/ty.rs
1 //! Special types handling
3 use super::spanned
::Sp
;
6 spanned
::Spanned
, GenericArgument
, Path
, PathArguments
, PathArguments
::AngleBracketed
,
7 PathSegment
, Type
, TypePath
,
10 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
23 pub fn from_syn_ty(ty
: &syn
::Type
) -> Sp
<Self> {
25 let t
= |kind
| Sp
::new(kind
, ty
.span());
29 } else if let Some(vt
) = get_vec_ty(ty
, Vec
, VecVec
) {
31 } else if let Some(subty
) = subty_if_name(ty
, "Option") {
32 if is_generic_ty(subty
, "Option") {
34 } else if let Some(vt
) = get_vec_ty(subty
, OptionVec
, OptionVecVec
) {
44 pub fn as_str(&self) -> &'
static str {
47 Self::Vec
=> "Vec<T>",
48 Self::Option
=> "Option<T>",
49 Self::OptionOption
=> "Option<Option<T>>",
50 Self::OptionVec
=> "Option<Vec<T>>",
51 Self::VecVec
=> "Vec<Vec<T>>",
52 Self::OptionVecVec
=> "Option<Vec<Vec<T>>>",
53 Self::Other
=> "...other...",
58 pub fn inner_type(field_ty
: &syn
::Type
) -> &syn
::Type
{
59 let ty
= Ty
::from_syn_ty(field_ty
);
61 Ty
::Vec
| Ty
::Option
=> sub_type(field_ty
).unwrap_or(field_ty
),
62 Ty
::OptionOption
| Ty
::OptionVec
| Ty
::VecVec
=> {
63 sub_type(field_ty
).and_then(sub_type
).unwrap_or(field_ty
)
65 Ty
::OptionVecVec
=> sub_type(field_ty
)
73 pub fn sub_type(ty
: &syn
::Type
) -> Option
<&syn
::Type
> {
74 subty_if(ty
, |_
| true)
77 fn only_last_segment(mut ty
: &syn
::Type
) -> Option
<&PathSegment
> {
78 while let syn
::Type
::Group(syn
::TypeGroup { elem, .. }
) = ty
{
89 }) => only_one(segments
.iter()),
95 fn subty_if
<F
>(ty
: &syn
::Type
, f
: F
) -> Option
<&syn
::Type
>
97 F
: FnOnce(&PathSegment
) -> bool
,
100 .filter(|segment
| f(segment
))
101 .and_then(|segment
| {
102 if let AngleBracketed(args
) = &segment
.arguments
{
103 only_one(args
.args
.iter()).and_then(|genneric
| {
104 if let GenericArgument
::Type(ty
) = genneric
{
116 pub fn subty_if_name
<'a
>(ty
: &'a syn
::Type
, name
: &str) -> Option
<&'a syn
::Type
> {
117 subty_if(ty
, |seg
| seg
.ident
== name
)
120 pub fn is_simple_ty(ty
: &syn
::Type
, name
: &str) -> bool
{
121 only_last_segment(ty
)
123 if let PathArguments
::None
= segment
.arguments
{
124 segment
.ident
== name
132 fn is_generic_ty(ty
: &syn
::Type
, name
: &str) -> bool
{
133 subty_if_name(ty
, name
).is_some()
136 fn is_unit_ty(ty
: &syn
::Type
) -> bool
{
137 if let syn
::Type
::Tuple(tuple
) = ty
{
138 tuple
.elems
.is_empty()
144 fn only_one
<I
, T
>(mut iter
: I
) -> Option
<T
>
146 I
: Iterator
<Item
= T
>,
148 iter
.next().filter(|_
| iter
.next().is_none())
151 #[cfg(feature = "unstable-v5")]
152 fn get_vec_ty(ty
: &Type
, vec_ty
: Ty
, vecvec_ty
: Ty
) -> Option
<Ty
> {
153 subty_if_name(ty
, "Vec").map(|subty
| {
154 if is_generic_ty(subty
, "Vec") {
162 #[cfg(not(feature = "unstable-v5"))]
163 fn get_vec_ty(ty
: &Type
, vec_ty
: Ty
, _vecvec_ty
: Ty
) -> Option
<Ty
> {
164 is_generic_ty(ty
, "Vec").then_some(vec_ty
)