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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
mod definition;
pub(crate) use definition::Definition;
mod details;
pub(crate) use details::Details;
mod index;
pub use index::Index;
mod map;
pub use map::Map;
mod group;
pub(crate) use group::Group;
use syn::{
punctuated::Punctuated, AngleBracketedGenericArguments, GenericArgument, GenericParam, Generics, Path, PathArguments, PathSegment, Token, Type, TypePath
};
use crate::syn_util;
/// The details of a type alias.
#[derive(Debug, Clone, Copy)]
pub struct Alias<'m> {
map: &'m Map,
index: Index,
details: &'m Details,
}
impl<'m> Alias<'m> {
pub(crate) fn new(map: &'m Map, index: Index, details: &'m Details) -> Self {
Self { map, index, details }
}
/// The [Index] of this alias.
pub fn index(&self) -> Index {
self.index
}
/// Is this alias for a type parameter?
/// Only lone type parameters are included (i.e. `T`, but not `Vec<T>`).
pub fn is_generic_parameter_type(&self) -> bool {
if let Type::Path(type_path) = &self.details.aliased_type {
let mut iter = self.details.parameters.params.iter();
if let (Some(GenericParam::Type(single)), None) = (iter.next(), iter.next()) {
return type_path.path.is_ident(&single.ident);
}
}
false
}
/// The generic parameters required for this type alias.
/// For example, this item has two type parameters:
/// ```rust,ignore
/// struct Either<A, B> {
/// A(Box<A>),
/// B(Box<B>),
/// }
/// ```
/// But reusing these parameters on the alias to the type in variant `A` will fail,
/// as parameter `B` is unused by the aliased type:
/// ```rust,ignore
/// type Alias<A, B> = Box<A>;
/// ```
/// ```text,ignore
/// type parameter `B` is unused
/// ```
/// This method returns only the generic parameters used by the alias.
pub fn parameters(&self) -> &Generics {
&self.details.parameters
}
/// Returns this alias formatted as a [PathSegment], without generic parameters
pub fn path_segment_no_generics(&self) -> PathSegment {
PathSegment {
ident: self.index.ident(),
arguments: PathArguments::None,
}
}
/// Returns this alias formatted as a [PathSegment], with unsubstituted generic
/// arguments if applicable.
pub fn path_segment(&self) -> PathSegment {
let mut segment = self.path_segment_no_generics();
segment.arguments = PathArguments::AngleBracketed(AngleBracketedGenericArguments {
colon2_token: None,
lt_token: Default::default(),
args: syn_util::generic_params_to_arguments(self.parameters()),
gt_token: Default::default(),
});
segment
}
/// The original type being aliased
pub fn aliased_type(&self) -> &Type {
&self.details.aliased_type
}
/// The type arguments on the original aliased type.
/// e.g. `i32, u64` for `my_crate::MyType<i32, i64>`
pub fn aliased_type_arguments(&self) -> Option<&Punctuated<GenericArgument, Token![,]>> {
if let Type::Path(type_path) = self.aliased_type() {
if let Some(last_segment) = type_path.path.segments.last() {
if let PathArguments::AngleBracketed(angle_bracketed) = &last_segment.arguments {
return Some(&angle_bracketed.args);
}
}
}
None
}
/// Creates a qualified [Path] to the alias with no generic arguments
pub fn path(&self) -> Path {
let mut path = self.map.group().path();
path.segments.push(self.path_segment_no_generics());
path
}
/// Creates a qualified [TypePath] to the alias, with generic arguments.
pub fn type_path(&self) -> TypePath {
let mut path = self.map.group().path();
path.segments.push(self.path_segment());
TypePath { qself: None, path }
}
/// Creates a qualified [Type] of the alias.
pub fn ty(&self) -> Type {
Type::Path(self.type_path())
}
}