Repository: gakonst/ethers-rs
Pull request #849 (2022-01-31 21:50:29)

fix(solc): can parse secondary source locations
<!--
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
Apparently the `secondarySourceLocations` only contains a `message` field, which is at odds with the docs https://docs.soliditylang.org/en/v0.8.11/using-the-compiler.html#compiler-api

```text
            "secondarySourceLocations": Array([
                Object({
                    "message": String(
                        "Candidate: function require(bool)",
                    ),
                }),
                Object({
                    "message": String(
                        "Candidate: function require(bool, string memory)",
                    ),
                }),
            ]),

```

<!--
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
Change types so that error can now be parsed correctly
```console
TypeError: No matching declaration found after argument-dependent lookup.
 --> /private/var/folders/l5/lprhf87s6xv8djgd017f0b2h0000gn/T/tmp_dapp1Wk7S5/src/Contract.sol:6:13:
  |
6 |             require(address(0), "Error");
  |             ^^^^^^^
Note: Candidate: function require(bool)
Note: Candidate: function require(bool, string memory)

```
<!--
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-solc/src/artifacts.rs b/ethers-solc/src/artifacts.rs
index 5977b43c..3df38461 100644
--- a/ethers-solc/src/artifacts.rs
+++ b/ethers-solc/src/artifacts.rs
@@ -1733,7 +1733,7 @@ pub struct Error {
     #[serde(default, skip_serializing_if = "Option::is_none")]
     pub source_location: Option<SourceLocation>,
     #[serde(default, skip_serializing_if = "Vec::is_empty")]
-    pub secondary_source_locations: Vec<SourceLocation>,
+    pub secondary_source_locations: Vec<SecondarySourceLocation>,
     pub r#type: String,
     pub component: String,
     pub severity: Severity,
@@ -1845,6 +1845,13 @@ pub struct SourceLocation {
     pub file: String,
     pub start: i32,
     pub end: i32,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
+pub struct SecondarySourceLocation {
+    pub file: Option<String>,
+    pub start: Option<i32>,
+    pub end: Option<i32>,
     pub message: Option<String>,
 }
 


Test patch:
diff --git a/ethers-solc/tests/project.rs b/ethers-solc/tests/project.rs
index f7b362d7..e095b01e 100644
--- a/ethers-solc/tests/project.rs
+++ b/ethers-solc/tests/project.rs
@@ -378,3 +378,26 @@ fn can_flatten_file_with_duplicates() {
     assert_eq!(result.matches("contract FooBar {").count(), 1);
     assert_eq!(result.matches(";").count(), 1);
 }
+
+#[test]
+fn can_detect_type_error() {
+    let project = TempProject::<MinimalCombinedArtifacts>::dapptools().unwrap();
+
+    project
+        .add_source(
+            "Contract",
+            r#"
+    pragma solidity ^0.8.10;
+
+   contract Contract {
+        function xyz() public {
+            require(address(0), "Error");
+        }
+   }
+   "#,
+        )
+        .unwrap();
+
+    let compiled = project.compile().unwrap();
+    assert!(compiled.has_compiler_errors());
+}