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
use std::ops::Deref;
use proc_macro2::TokenStream;
use quote::quote;
use smallvec::{smallvec, SmallVec};
use crate::models::code::{IdentPath, ModulePath};
/// Represents a type ready to be resolved and rendered for a specific module.
///
/// It contains information like the actual path to the type, a list of generics
/// and a list of usings to add to the module.
#[derive(Debug, Clone)]
pub struct PathData {
/// Actual path of the target type.
pub path: IdentPath,
/// Usings to add for this target type.
pub usings: SmallVec<[String; 1]>,
/// Generics of this target type.
pub generics: SmallVec<[IdentPath; 1]>,
}
impl PathData {
/// Create a new [`PathData`] instance from the passed `path`.
#[must_use]
pub fn from_path(path: IdentPath) -> Self {
Self {
path,
usings: smallvec![],
generics: smallvec![],
}
}
/// Add a generic argument to the path data.
#[must_use]
pub fn with_generic(mut self, path: IdentPath) -> Self {
self.generics.push(path);
self
}
/// Add a using to the path data.
#[must_use]
pub fn with_using<P: Into<String>>(mut self, path: P) -> Self {
self.usings.push(path.into());
self
}
/// Make the path data to an included path data instead of a absolute one.
#[must_use]
pub fn into_included(self) -> Self {
if self.path.module().is_some() {
let using = format!("{}", &self.path);
let (ident, _, _) = self.path.into_parts();
Self::from_path(IdentPath::from_ident(ident)).with_using(using)
} else {
self
}
}
/// Resolves the target type relative to the passed module `path` and
/// returns the rendered type as [`TokenStream`].
#[must_use]
pub fn resolve_relative_to(&self, path: &ModulePath) -> TokenStream {
let mut ret = self.path.relative_to(path);
if !self.generics.is_empty() {
ret.extend(quote!(<));
for (idx, x) in self.generics.iter().enumerate() {
if idx > 0 {
ret.extend(quote!(,));
}
ret.extend(x.relative_to(path));
}
ret.extend(quote!(>));
}
ret
}
}
impl Deref for PathData {
type Target = IdentPath;
fn deref(&self) -> &Self::Target {
&self.path
}
}