1use itertools::Itertools;
2use solang_parser::pt::FunctionDefinition;
3use toml::{Value, value::Table};
4
5pub fn function_signature(func: &FunctionDefinition) -> String {
8 let func_name = func.name.as_ref().map_or(func.ty.to_string(), |n| n.name.to_owned());
9 if func.params.is_empty() {
10 return func_name;
11 }
12
13 format!(
14 "{}({})",
15 func_name,
16 func.params
17 .iter()
18 .map(|p| p.1.as_ref().map(|p| p.ty.to_string()).unwrap_or_default())
19 .join(",")
20 )
21}
22
23pub(crate) fn merge_toml_table(table: &mut Table, override_table: Table) {
25 for (key, override_value) in override_table {
26 match table.get_mut(&key) {
27 Some(Value::Table(inner_table)) => {
28 if let Value::Table(inner_override) = override_value {
30 merge_toml_table(inner_table, inner_override);
31 }
32 }
33 Some(Value::Array(inner_array)) => {
34 if let Value::Array(inner_override) = override_value {
36 for entry in inner_override {
37 if !inner_array.contains(&entry) {
38 inner_array.push(entry);
39 }
40 }
41 }
42 }
43 _ => {
44 table.insert(key, override_value);
45 }
46 };
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use solang_parser::{
54 parse,
55 pt::{ContractPart, SourceUnit, SourceUnitPart},
56 };
57
58 #[test]
59 fn test_function_signature_no_params() {
60 let (source_unit, _) = parse(
61 r#"
62 contract Test {
63 function foo() public {}
64 }
65 "#,
66 0,
67 )
68 .unwrap();
69
70 let func = extract_function(&source_unit);
71 assert_eq!(function_signature(func), "foo");
72 }
73
74 #[test]
75 fn test_function_signature_with_params() {
76 let (source_unit, _) = parse(
77 r#"
78 contract Test {
79 function transfer(address to, uint256 amount) public {}
80 }
81 "#,
82 0,
83 )
84 .unwrap();
85
86 let func = extract_function(&source_unit);
87 assert_eq!(function_signature(func), "transfer(address,uint256)");
88 }
89
90 #[test]
91 fn test_function_signature_constructor() {
92 let (source_unit, _) = parse(
93 r#"
94 contract Test {
95 constructor(address owner) {}
96 }
97 "#,
98 0,
99 )
100 .unwrap();
101
102 let func = extract_function(&source_unit);
103 assert_eq!(function_signature(func), "constructor(address)");
104 }
105
106 fn extract_function(source_unit: &SourceUnit) -> &FunctionDefinition {
108 for part in &source_unit.0 {
109 if let SourceUnitPart::ContractDefinition(contract) = part {
110 for part in &contract.parts {
111 if let ContractPart::FunctionDefinition(func) = part {
112 return func;
113 }
114 }
115 }
116 }
117 panic!("No function found in source unit");
118 }
119}