1use crate::utils::normalize_return_type;
2use crate::{docs::get_doc_lines, types::TypeIdent};
3use quote::ToTokens;
4use std::{collections::BTreeSet, convert::TryFrom};
5use syn::{FnArg, ForeignItemFn};
6
7#[derive(Debug, Default)]
9pub struct FunctionList(BTreeSet<Function>);
10
11impl FunctionList {
12 pub fn add_function(&mut self, function_decl: &str) {
13 self.0.insert(Function::new(function_decl));
14 }
15
16 pub fn iter(&self) -> std::collections::btree_set::Iter<'_, Function> {
17 self.0.iter()
18 }
19
20 pub fn new() -> Self {
21 Self(BTreeSet::new())
22 }
23}
24
25impl IntoIterator for FunctionList {
26 type Item = Function;
27 type IntoIter = std::collections::btree_set::IntoIter<Function>;
28
29 fn into_iter(self) -> Self::IntoIter {
30 self.0.into_iter()
31 }
32}
33
34impl<'a> IntoIterator for &'a FunctionList {
35 type Item = &'a Function;
36 type IntoIter = std::collections::btree_set::Iter<'a, Function>;
37
38 fn into_iter(self) -> Self::IntoIter {
39 self.0.iter()
40 }
41}
42
43#[derive(Debug, Eq, PartialEq)]
44pub struct Function {
45 pub name: String,
46 pub doc_lines: Vec<String>,
47 pub args: Vec<FunctionArg>,
48 pub return_type: Option<TypeIdent>,
49 pub is_async: bool,
50}
51
52impl Function {
53 pub fn new(decl: &str) -> Self {
54 let item =
55 syn::parse_str::<ForeignItemFn>(decl).expect("Cannot parse function declaration");
56
57 let name = item.sig.ident.to_string();
58 let doc_lines = get_doc_lines(&item.attrs);
59 let args = item
60 .sig
61 .inputs
62 .iter()
63 .map(|input| match input {
64 FnArg::Receiver(_) => panic!(
65 "Methods are not supported. Found `self` in function declaration: {:?}",
66 item
67 ),
68 FnArg::Typed(arg) => FunctionArg {
69 name: arg.pat.to_token_stream().to_string(),
70 ty: TypeIdent::try_from(arg.ty.as_ref()).unwrap_or_else(|e| {
71 panic!("Invalid argument type for function {}: {}", name, e)
72 }),
73 },
74 })
75 .collect();
76 let return_type = normalize_return_type(&item.sig.output).map(|return_type| {
77 TypeIdent::try_from(return_type)
78 .unwrap_or_else(|_| panic!("Invalid return type for function {}", name))
79 });
80 let is_async = item.sig.asyncness.is_some();
81
82 Self {
83 name,
84 doc_lines,
85 args,
86 return_type,
87 is_async,
88 }
89 }
90}
91
92impl Ord for Function {
93 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
94 self.name.cmp(&other.name)
95 }
96}
97
98impl PartialOrd for Function {
99 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
100 self.name.partial_cmp(&other.name)
101 }
102}
103
104#[derive(Debug, Eq, PartialEq)]
105pub struct FunctionArg {
106 pub name: String,
107 pub ty: TypeIdent,
108}