Repository: gakonst/ethers-rs (rust)

Issue:
Abigen: Conflicting struct and method definitions
**Version**
Latest `master` branch (`184cffa`).

**Description**
If the lowercase versions of two functions names do not conflict but the snake case versions do conflict, Abigen generates conflicting method names and FnNameCall structs.

For example, the following fails to compile with `duplicate definitions with name 'foo_bar'`

```rust
abigen!(
    Test,
    r#"[
        function fooBar()
        function FOO_BAR()
    ]"#,
);
```

Pull request description:
fix(abigen): support functions with different casing
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Bug fixes and new features should include tests.

Contributors guide: https://github.com/gakonst/ethers-rs/blob/master/CONTRIBUTING.md

The contributors guide includes instructions for running rustfmt and building the
documentation.
-->

## Motivation
Close #958
<!--
Explain the context and why you're making that change. What is the problem
you're trying to solve? In some cases there is not a problem and this can be
thought of as being the motivation for your change.
-->

## Solution
Previously we used `to_lowercase` as the identifier to determine if there are duplicated function calls, this ignored cases like `fooBar` and `FOO_BAR`. Instead we use snake_case as baseline now to catch these as well.
<!--
Summarize the solution and provide any necessary context needed to understand
the code change.
-->

## PR Checklist

- [x] Added Tests
- [ ] Added Documentation
- [ ] Updated the changelog


Patch:
diff --git a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs
index 212ebdb8..720d7b1e 100644
--- a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs
+++ b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs
@@ -342,7 +342,7 @@ impl Context {
         let mut all_functions = HashMap::new();
         for function in self.abi.functions() {
             all_functions
-                .entry(function.name.to_lowercase())
+                .entry(util::safe_snake_case_ident(&function.name))
                 .or_insert_with(Vec::new)
                 .push(function);
         }


Test patch:
diff --git a/ethers-contract/tests/abigen.rs b/ethers-contract/tests/abigen.rs
index 1aa57525..04570190 100644
--- a/ethers-contract/tests/abigen.rs
+++ b/ethers-contract/tests/abigen.rs
@@ -427,6 +427,23 @@ fn can_generate_nested_types() {
     assert_eq!(call, decoded_call);
 }
 
+#[test]
+fn can_handle_different_calls() {
+    abigen!(
+        Test,
+        r#"[
+        function fooBar()
+        function FOO_BAR()
+    ]"#,
+    );
+
+    let (client, _mock) = Provider::mocked();
+    let contract = Test::new(Address::default(), Arc::new(client));
+
+    let _ = contract.fooBar();
+    let _ = contract.FOO_BAR();
+}
+
 #[test]
 fn can_handle_case_sensitive_calls() {
     abigen!(