fix(solc): fix fields for `UserDoc` and `DevDoc` (#1355)
* fix(solc): fix fields for UserDoc and DevDoc * solc: unify userdoc notice fields
This commit is contained in:
parent
0abc3ca39a
commit
5ee4092bd3
|
@ -1366,6 +1366,10 @@ pub struct UserDoc {
|
||||||
pub kind: Option<String>,
|
pub kind: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
pub methods: BTreeMap<String, UserDocNotice>,
|
pub methods: BTreeMap<String, UserDocNotice>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub events: BTreeMap<String, UserDocNotice>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub errors: BTreeMap<String, Vec<UserDocNotice>>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub notice: Option<String>,
|
pub notice: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -1375,7 +1379,7 @@ pub struct UserDoc {
|
||||||
pub enum UserDocNotice {
|
pub enum UserDocNotice {
|
||||||
// NOTE: this a variant used for constructors on older solc versions
|
// NOTE: this a variant used for constructors on older solc versions
|
||||||
Constructor(String),
|
Constructor(String),
|
||||||
Method { notice: String },
|
Notice { notice: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
|
@ -1392,6 +1396,10 @@ pub struct DevDoc {
|
||||||
pub custom_experimental: Option<String>,
|
pub custom_experimental: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
pub methods: BTreeMap<String, MethodDoc>,
|
pub methods: BTreeMap<String, MethodDoc>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub events: BTreeMap<String, EventDoc>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub errors: BTreeMap<String, Vec<ErrorDoc>>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -1402,8 +1410,24 @@ pub struct MethodDoc {
|
||||||
pub details: Option<String>,
|
pub details: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
pub params: BTreeMap<String, String>,
|
pub params: BTreeMap<String, String>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub returns: BTreeMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
|
pub struct EventDoc {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub r#return: Option<String>,
|
pub details: Option<String>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub params: BTreeMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
|
pub struct ErrorDoc {
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub details: Option<String>,
|
||||||
|
#[serde(default, skip_serializing_if = "::std::collections::BTreeMap::is_empty")]
|
||||||
|
pub params: BTreeMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
|
|
|
@ -10,8 +10,8 @@ use std::{
|
||||||
use ethers_core::types::Address;
|
use ethers_core::types::Address;
|
||||||
use ethers_solc::{
|
use ethers_solc::{
|
||||||
artifacts::{
|
artifacts::{
|
||||||
BytecodeHash, Libraries, ModelCheckerEngine::CHC, ModelCheckerSettings, UserDoc,
|
BytecodeHash, DevDoc, ErrorDoc, EventDoc, Libraries, MethodDoc, ModelCheckerEngine::CHC,
|
||||||
UserDocNotice,
|
ModelCheckerSettings, UserDoc, UserDocNotice,
|
||||||
},
|
},
|
||||||
cache::{SolFilesCache, SOLIDITY_FILES_CACHE_FILENAME},
|
cache::{SolFilesCache, SOLIDITY_FILES_CACHE_FILENAME},
|
||||||
project_util::*,
|
project_util::*,
|
||||||
|
@ -1677,10 +1677,12 @@ fn can_parse_notice() {
|
||||||
version: None,
|
version: None,
|
||||||
kind: None,
|
kind: None,
|
||||||
methods: BTreeMap::from([
|
methods: BTreeMap::from([
|
||||||
("abc()".to_string(), UserDocNotice::Method { notice: "hello".to_string() }),
|
("abc()".to_string(), UserDocNotice::Notice { notice: "hello".to_string() }),
|
||||||
("xyz()".to_string(), UserDocNotice::Method { notice: "hello".to_string() }),
|
("xyz()".to_string(), UserDocNotice::Notice { notice: "hello".to_string() }),
|
||||||
("constructor".to_string(), UserDocNotice::Constructor("hello".to_string())),
|
("constructor".to_string(), UserDocNotice::Constructor("hello".to_string())),
|
||||||
]),
|
]),
|
||||||
|
events: BTreeMap::new(),
|
||||||
|
errors: BTreeMap::new(),
|
||||||
notice: None
|
notice: None
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -1699,15 +1701,201 @@ fn can_parse_notice() {
|
||||||
version: Some(1),
|
version: Some(1),
|
||||||
kind: Some("user".to_string()),
|
kind: Some("user".to_string()),
|
||||||
methods: BTreeMap::from([
|
methods: BTreeMap::from([
|
||||||
("abc()".to_string(), UserDocNotice::Method { notice: "hello".to_string() }),
|
("abc()".to_string(), UserDocNotice::Notice { notice: "hello".to_string() }),
|
||||||
("xyz()".to_string(), UserDocNotice::Method { notice: "hello".to_string() }),
|
("xyz()".to_string(), UserDocNotice::Notice { notice: "hello".to_string() }),
|
||||||
("constructor".to_string(), UserDocNotice::Method { notice: "hello".to_string() }),
|
("constructor".to_string(), UserDocNotice::Notice { notice: "hello".to_string() }),
|
||||||
]),
|
]),
|
||||||
|
events: BTreeMap::new(),
|
||||||
|
errors: BTreeMap::new(),
|
||||||
notice: None
|
notice: None
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_doc() {
|
||||||
|
let mut project = TempProject::<ConfigurableArtifacts>::dapptools().unwrap();
|
||||||
|
project.project_mut().artifacts.additional_values.userdoc = true;
|
||||||
|
project.project_mut().artifacts.additional_values.devdoc = true;
|
||||||
|
project.project_mut().solc_config.settings = project.project_mut().artifacts.settings();
|
||||||
|
|
||||||
|
let contract = r#"
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
pragma solidity ^0.8.0;
|
||||||
|
|
||||||
|
/// @title Not an ERC20.
|
||||||
|
/// @author Notadev
|
||||||
|
/// @notice Do not use this.
|
||||||
|
/// @dev This is not an ERC20 implementation.
|
||||||
|
/// @custom:experimental This is an experimental contract.
|
||||||
|
interface INotERC20 {
|
||||||
|
/// @notice Transfer tokens.
|
||||||
|
/// @dev Transfer `amount` tokens to account `to`.
|
||||||
|
/// @param to Target account.
|
||||||
|
/// @param amount Transfer amount.
|
||||||
|
/// @return A boolean value indicating whether the operation succeeded.
|
||||||
|
function transfer(address to, uint256 amount) external returns (bool);
|
||||||
|
|
||||||
|
/// @notice Transfer some tokens.
|
||||||
|
/// @dev Emitted when transfer.
|
||||||
|
/// @param from Source account.
|
||||||
|
/// @param to Target account.
|
||||||
|
/// @param value Transfer amount.
|
||||||
|
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||||
|
|
||||||
|
/// @notice Insufficient balance for transfer.
|
||||||
|
/// @dev Needed `required` but only `available` available.
|
||||||
|
/// @param available Balance available.
|
||||||
|
/// @param required Requested amount to transfer.
|
||||||
|
error InsufficientBalance(uint256 available, uint256 required);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract NotERC20 is INotERC20 {
|
||||||
|
/// @inheritdoc INotERC20
|
||||||
|
function transfer(address to, uint256 amount) external returns (bool) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
project.add_source("Contract", contract).unwrap();
|
||||||
|
|
||||||
|
let mut compiled = project.compile().unwrap();
|
||||||
|
assert!(!compiled.has_compiler_errors());
|
||||||
|
assert!(!compiled.is_unchanged());
|
||||||
|
|
||||||
|
assert!(compiled.find("INotERC20").is_some());
|
||||||
|
let contract = compiled.remove("INotERC20").unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
contract.userdoc,
|
||||||
|
Some(UserDoc {
|
||||||
|
version: Some(1),
|
||||||
|
kind: Some("user".to_string()),
|
||||||
|
notice: Some("Do not use this.".to_string()),
|
||||||
|
methods: BTreeMap::from([(
|
||||||
|
"transfer(address,uint256)".to_string(),
|
||||||
|
UserDocNotice::Notice { notice: "Transfer tokens.".to_string() }
|
||||||
|
),]),
|
||||||
|
events: BTreeMap::from([(
|
||||||
|
"Transfer(address,address,uint256)".to_string(),
|
||||||
|
UserDocNotice::Notice { notice: "Transfer some tokens.".to_string() }
|
||||||
|
),]),
|
||||||
|
errors: BTreeMap::from([(
|
||||||
|
"InsufficientBalance(uint256,uint256)".to_string(),
|
||||||
|
vec![UserDocNotice::Notice {
|
||||||
|
notice: "Insufficient balance for transfer.".to_string()
|
||||||
|
}]
|
||||||
|
),]),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
contract.devdoc,
|
||||||
|
Some(DevDoc {
|
||||||
|
version: Some(1),
|
||||||
|
kind: Some("dev".to_string()),
|
||||||
|
author: Some("Notadev".to_string()),
|
||||||
|
details: Some("This is not an ERC20 implementation.".to_string()),
|
||||||
|
custom_experimental: Some("This is an experimental contract.".to_string()),
|
||||||
|
methods: BTreeMap::from([(
|
||||||
|
"transfer(address,uint256)".to_string(),
|
||||||
|
MethodDoc {
|
||||||
|
details: Some("Transfer `amount` tokens to account `to`.".to_string()),
|
||||||
|
params: BTreeMap::from([
|
||||||
|
("to".to_string(), "Target account.".to_string()),
|
||||||
|
("amount".to_string(), "Transfer amount.".to_string())
|
||||||
|
]),
|
||||||
|
returns: BTreeMap::from([(
|
||||||
|
"_0".to_string(),
|
||||||
|
"A boolean value indicating whether the operation succeeded.".to_string()
|
||||||
|
),])
|
||||||
|
}
|
||||||
|
),]),
|
||||||
|
events: BTreeMap::from([(
|
||||||
|
"Transfer(address,address,uint256)".to_string(),
|
||||||
|
EventDoc {
|
||||||
|
details: Some("Emitted when transfer.".to_string()),
|
||||||
|
params: BTreeMap::from([
|
||||||
|
("from".to_string(), "Source account.".to_string()),
|
||||||
|
("to".to_string(), "Target account.".to_string()),
|
||||||
|
("value".to_string(), "Transfer amount.".to_string()),
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
),]),
|
||||||
|
errors: BTreeMap::from([(
|
||||||
|
"InsufficientBalance(uint256,uint256)".to_string(),
|
||||||
|
vec![ErrorDoc {
|
||||||
|
details: Some("Needed `required` but only `available` available.".to_string()),
|
||||||
|
params: BTreeMap::from([
|
||||||
|
("available".to_string(), "Balance available.".to_string()),
|
||||||
|
("required".to_string(), "Requested amount to transfer.".to_string())
|
||||||
|
]),
|
||||||
|
}]
|
||||||
|
),]),
|
||||||
|
title: Some("Not an ERC20.".to_string())
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(compiled.find("NotERC20").is_some());
|
||||||
|
let contract = compiled.remove("NotERC20").unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
contract.userdoc,
|
||||||
|
Some(UserDoc {
|
||||||
|
version: Some(1),
|
||||||
|
kind: Some("user".to_string()),
|
||||||
|
notice: None,
|
||||||
|
methods: BTreeMap::from([(
|
||||||
|
"transfer(address,uint256)".to_string(),
|
||||||
|
UserDocNotice::Notice { notice: "Transfer tokens.".to_string() }
|
||||||
|
),]),
|
||||||
|
events: BTreeMap::from([(
|
||||||
|
"Transfer(address,address,uint256)".to_string(),
|
||||||
|
UserDocNotice::Notice { notice: "Transfer some tokens.".to_string() }
|
||||||
|
),]),
|
||||||
|
errors: BTreeMap::from([(
|
||||||
|
"InsufficientBalance(uint256,uint256)".to_string(),
|
||||||
|
vec![UserDocNotice::Notice {
|
||||||
|
notice: "Insufficient balance for transfer.".to_string()
|
||||||
|
}]
|
||||||
|
),]),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
contract.devdoc,
|
||||||
|
Some(DevDoc {
|
||||||
|
version: Some(1),
|
||||||
|
kind: Some("dev".to_string()),
|
||||||
|
author: None,
|
||||||
|
details: None,
|
||||||
|
custom_experimental: None,
|
||||||
|
methods: BTreeMap::from([(
|
||||||
|
"transfer(address,uint256)".to_string(),
|
||||||
|
MethodDoc {
|
||||||
|
details: Some("Transfer `amount` tokens to account `to`.".to_string()),
|
||||||
|
params: BTreeMap::from([
|
||||||
|
("to".to_string(), "Target account.".to_string()),
|
||||||
|
("amount".to_string(), "Transfer amount.".to_string())
|
||||||
|
]),
|
||||||
|
returns: BTreeMap::from([(
|
||||||
|
"_0".to_string(),
|
||||||
|
"A boolean value indicating whether the operation succeeded.".to_string()
|
||||||
|
),])
|
||||||
|
}
|
||||||
|
),]),
|
||||||
|
events: BTreeMap::new(),
|
||||||
|
errors: BTreeMap::from([(
|
||||||
|
"InsufficientBalance(uint256,uint256)".to_string(),
|
||||||
|
vec![ErrorDoc {
|
||||||
|
details: Some("Needed `required` but only `available` available.".to_string()),
|
||||||
|
params: BTreeMap::from([
|
||||||
|
("available".to_string(), "Balance available.".to_string()),
|
||||||
|
("required".to_string(), "Requested amount to transfer.".to_string())
|
||||||
|
]),
|
||||||
|
}]
|
||||||
|
),]),
|
||||||
|
title: None
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_relative_cache_entries() {
|
fn test_relative_cache_entries() {
|
||||||
let project = TempProject::dapptools().unwrap();
|
let project = TempProject::dapptools().unwrap();
|
||||||
|
|
Loading…
Reference in New Issue