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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// lib.rs
use quote::quote;
use syn::FnArg;
use syn::Ident;
use syn::Pat;
extern crate proc_macro;
#[derive(Debug, Clone)]
pub struct FnArgInfo {
pub arg_name: String,
pub type_name: String,
// pub fn_arg_doc: Vec<String>,
}
impl FnArgInfo {
pub fn new(arg: syn::FnArg) -> Option<FnArgInfo> {
// 过滤掉 self 参数(仅处理普通参数)
if let FnArg::Typed(pat_type) = arg {
// 提取参数名称(模式中的标识符)
let arg_name = {
if let Pat::Ident(pat_ident) = &*pat_type.pat {
&pat_ident.ident
} else {
// 处理非标识符参数(如元组、结构体等,这里简化处理)
&Ident::new("unknown_arg", proc_macro2::Span::call_site())
}
};
// 提取参数类型
let arg_type = &pat_type.ty;
// let doc = {
// pat_type
// .attrs
// .iter()
// .filter_map(|attr| {
// if attr.path().is_ident("about") {
// // 解析 #[about = "..."]
// if let syn::Meta::NameValue(meta_nv) = &attr.meta {
// if let syn::Expr::Lit(expr_lit) = &meta_nv.value {
// if let syn::Lit::Str(litstr) = &expr_lit.lit {
// return Some(litstr.value());
// }
// }
// }
// }
// None
// })
// .collect::<Vec<String>>()
// };
return Some(FnArgInfo {
arg_name: arg_name.to_string(),
type_name: quote!(#arg_type)
.to_string()
.trim_matches(|x| x == ' ')
.replace(" ", "")
.to_string(),
// fn_arg_doc: doc,
});
}
return None;
}
/// 生成 cmd_arg_str -> rust_typed_value.
/// String -> T.
/// returns.0 -> auto_name
/// returns.1 -> the let exprs.
/// returns.0 == "__arg_0___converted";
/// returns.1 ==
/// "
/// let __arg_0__ = app._user_inputed_cmd_args.get(0).unwrap().clone();
/// let __arg_0___converted: String =
/// <String as ::aslip::from_arg_sttr::FromArgStr>::from_arg_str(&__arg_0__)
/// .unwrap()
/// .clone();
/// ";
pub fn gen_type_converter_code(&self, index: usize) -> (String, String) {
if self.is_colection_type() {
self.gen_vec_type_convet(index)
} else {
self.gen_single_type(index)
}
}
fn auto_name(&self, index: usize) -> String {
// format!("arg_{}_{}", index, self.type_name.to_lowercase())
format!("__arg_{}", index,)
}
pub fn is_colection_type(&self) -> bool {
let collection_types = ["Vec", "HashSet", "BTreeSet", "VecDeque"];
let type_name: &str = &self.type_name.replace(" ", "");
for x in collection_types {
if type_name.starts_with(x) {
return true;
}
}
return false;
}
fn gen_single_type(&self, index: usize) -> (String, String) {
// __arg_0__
let arg_str_variable_name = self.auto_name(index);
// __arg_0_converted
let _converted_variable_name = arg_str_variable_name.clone() + "_converted";
{
let ty = &self.type_name;
let converted = format!(
r###"
// let {_converted_variable_name}: {ty} = aslip::single_type_converter::<{ty}>(&app, "{arg_name}", {index});
let {_converted_variable_name}: {ty} = aslip::from_arg_sttr::single_type_converter::<{ty}>(&app, "{arg_name}", {index});
"###,
arg_name = self.arg_name,
);
return (_converted_variable_name.clone(), converted);
}
}
fn gen_vec_type_convet(&self, index: usize) -> (String, String) {
// __arg_0__
let arg_str_variable_name = self.auto_name(index);
// __arg_0___converted
let _converted_variable_name = arg_str_variable_name.clone() + "_converted";
let final_code: String = {
let ty = self.type_name.replace(" ", "");
let inner_ty = get_inner_ty(&ty);
let a = format!("[{}...]", self.arg_name);
let expect_msg = format!("需要参数: {}", a);
format!(
r###"
let {_converted_variable_name}: {ty} = {{
let tail_args: &[String] = app._user_inputed_cmd_args.get({index}..).expect( "{expect_msg}");
let re: {ty} = aslip::from_arg_sttr::vec_type_converter::<{inner_ty}>(tail_args);
re
}};
"###
)
};
return (_converted_variable_name, final_code);
}
}
/// "Vec<u8>" -> "u8"
/// 注意: 这港剧说并不支持 Vec<Option<u8>> 这样的类型嵌套,只支持 Vec<u8> 这样的, Result<O,E> 这种也是不支持的。
pub fn get_inner_ty(s: &str) -> String {
let mut re = String::new();
let mut inner_started = false;
'outer: for x in s.chars() {
match x {
'<' => {
if inner_started {
break 'outer;
}
inner_started = true
}
'>' => break 'outer,
a => {
if inner_started {
re.push(a);
}
}
}
}
return re;
}