From 8cb207e93ae05ce3c3092cdbebb29b56fdaaacbb Mon Sep 17 00:00:00 2001 From: Astrodevs CI Date: Thu, 17 Aug 2023 19:46:55 +0000 Subject: [PATCH 01/27] chore: create branch chore/70-references-rust-crate-from-ast-staging --- remove-me-ed5dccf7608a4c40bb11.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 remove-me-ed5dccf7608a4c40bb11.txt diff --git a/remove-me-ed5dccf7608a4c40bb11.txt b/remove-me-ed5dccf7608a4c40bb11.txt new file mode 100644 index 00000000..75bea5bc --- /dev/null +++ b/remove-me-ed5dccf7608a4c40bb11.txt @@ -0,0 +1 @@ +ed5dccf7608a4c40bb11 From afd8ef160662fe95120ab2fea02796fc8e9cab4c Mon Sep 17 00:00:00 2001 From: Astrodevs CI Date: Thu, 17 Aug 2023 19:47:09 +0000 Subject: [PATCH 02/27] chore: create branch chore/70-references-rust-crate-from-ast/71-create-references-structure-staging --- remove-me-6963cf31313545279b31.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 remove-me-6963cf31313545279b31.txt diff --git a/remove-me-6963cf31313545279b31.txt b/remove-me-6963cf31313545279b31.txt new file mode 100644 index 00000000..50262245 --- /dev/null +++ b/remove-me-6963cf31313545279b31.txt @@ -0,0 +1 @@ +6963cf31313545279b31 From e1873204acb3b2b16c2ff82fe61ededdf9ddf671 Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Wed, 30 Aug 2023 15:29:44 -0400 Subject: [PATCH 03/27] feat(libs/ast-references): added first version of the references structure --- libs/ast-references/.gitignore | 10 + libs/ast-references/Cargo.lock | 7 + libs/ast-references/Cargo.toml | 8 + libs/ast-references/src/lib.rs | 27 +++ libs/ast-references/src/references.rs | 0 libs/ast-references/src/types.rs | 7 + .../src/types/contract_reference.rs | 147 ++++++++++++ .../src/types/enum_reference.rs | 210 ++++++++++++++++++ .../src/types/file_reference.rs | 124 +++++++++++ .../src/types/function_reference.rs | 76 +++++++ libs/ast-references/src/types/location.rs | 144 ++++++++++++ .../src/types/property_reference.rs | 79 +++++++ .../src/types/struct_reference.rs | 156 +++++++++++++ remove-me-6963cf31313545279b31.txt | 1 - 14 files changed, 995 insertions(+), 1 deletion(-) create mode 100644 libs/ast-references/.gitignore create mode 100644 libs/ast-references/Cargo.lock create mode 100644 libs/ast-references/Cargo.toml create mode 100644 libs/ast-references/src/lib.rs create mode 100644 libs/ast-references/src/references.rs create mode 100644 libs/ast-references/src/types.rs create mode 100644 libs/ast-references/src/types/contract_reference.rs create mode 100644 libs/ast-references/src/types/enum_reference.rs create mode 100644 libs/ast-references/src/types/file_reference.rs create mode 100644 libs/ast-references/src/types/function_reference.rs create mode 100644 libs/ast-references/src/types/location.rs create mode 100644 libs/ast-references/src/types/property_reference.rs create mode 100644 libs/ast-references/src/types/struct_reference.rs delete mode 100644 remove-me-6963cf31313545279b31.txt diff --git a/libs/ast-references/.gitignore b/libs/ast-references/.gitignore new file mode 100644 index 00000000..71ab9a43 --- /dev/null +++ b/libs/ast-references/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb \ No newline at end of file diff --git a/libs/ast-references/Cargo.lock b/libs/ast-references/Cargo.lock new file mode 100644 index 00000000..631c60fc --- /dev/null +++ b/libs/ast-references/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ast-references" +version = "0.1.0" diff --git a/libs/ast-references/Cargo.toml b/libs/ast-references/Cargo.toml new file mode 100644 index 00000000..0c98f5eb --- /dev/null +++ b/libs/ast-references/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ast-references" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/libs/ast-references/src/lib.rs b/libs/ast-references/src/lib.rs new file mode 100644 index 00000000..c1ed3f05 --- /dev/null +++ b/libs/ast-references/src/lib.rs @@ -0,0 +1,27 @@ +mod types; +use std::cell::RefCell; +use std::rc::Rc; + +use types::contract_reference::ContractReference; +use types::location::{Location, Bound}; + +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +pub fn parse () -> ContractReference { + let file = Rc::new(RefCell::new(types::file_reference::FileReference::new("".to_string()))); + ContractReference::new("".to_string(), Location::new("".to_string(), Bound { line: 0, column: 0}, Bound { line: 0, column: 0}), &file) + +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/libs/ast-references/src/references.rs b/libs/ast-references/src/references.rs new file mode 100644 index 00000000..e69de29b diff --git a/libs/ast-references/src/types.rs b/libs/ast-references/src/types.rs new file mode 100644 index 00000000..35b40e16 --- /dev/null +++ b/libs/ast-references/src/types.rs @@ -0,0 +1,7 @@ +pub mod contract_reference; +pub mod enum_reference; +pub mod file_reference; +pub mod function_reference; +pub mod location; +pub mod property_reference; +pub mod struct_reference; \ No newline at end of file diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs new file mode 100644 index 00000000..dfcdc95b --- /dev/null +++ b/libs/ast-references/src/types/contract_reference.rs @@ -0,0 +1,147 @@ +/** + * ContractReference.rs + * Definition of ContractReference struct + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::rc::Rc; +use std::cell::RefCell; +use crate::types::location::Location; +use crate::types::file_reference::FileReference; +use crate::types::struct_reference::StructReference; +use crate::types::function_reference::FunctionReference; +use crate::types::property_reference::PropertyReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct ContractReference { + pub name: String, + pub location: Location, + pub file: Rc>, + pub structs: Vec>>, + pub functions: Vec>>, + pub properties: Vec>>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + +impl ContractReference { + pub fn new(name: String, location: Location, file: &Rc>) -> ContractReference { + ContractReference { + name: name, + location: location, + file: file.clone(), + structs: Vec::new(), + functions: Vec::new(), + properties: Vec::new(), + } + } + + pub fn add_struct(&mut self, strct: &Rc>) { + self.structs.push(strct.clone()); + } + + pub fn add_function(&mut self, function: &Rc>) { + self.functions.push(function.clone()); + } + + pub fn add_property(&mut self, property: &Rc>) { + self.properties.push(property.clone()); + } +} + +impl fmt::Display for ContractReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Contract {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for ContractReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Contract {} at {}", self.name, self.location) + } +} + +impl PartialEq for ContractReference { + fn eq(&self, other: &ContractReference) -> bool { + self.name == other.name && self.location == other.location && self.file == other.file + } +} + +impl Eq for ContractReference {} + +impl Hash for ContractReference { + fn hash(&self, state: &mut H) { + self.name.hash(state); + self.location.hash(state); + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + +#[cfg(test)] +mod tests { + use std::cell::RefCell; + + use crate::types::location::Bound; + + use super::*; + + #[test] + fn new_good_construct() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file); + + assert_eq!(result.file, file); + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "File.test"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + } + + #[test] + fn add_struct() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let strct = Rc::new(RefCell::new(StructReference::new("TestStruct".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), Some(&file)))); + + (*result).borrow_mut().add_struct(&strct); + + assert_eq!(result.borrow().structs.len(), 1); + assert_eq!(result.borrow().structs[0], strct); + } + + #[test] + fn add_function() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let function = Rc::new(RefCell::new(FunctionReference::new("TestFunction".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &result))); + + (*result).borrow_mut().add_function(&function); + + assert_eq!(result.borrow().functions.len(), 1); + assert_eq!(result.borrow().functions[0], function); + } + + #[test] + fn add_property() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let property = Rc::new(RefCell::new(PropertyReference::new("TestProperty".to_string(), "uint256".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &result))); + + (*result).borrow_mut().add_property(&property); + + assert_eq!(result.borrow().properties.len(), 1); + assert_eq!(result.borrow().properties[0], property); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/enum_reference.rs b/libs/ast-references/src/types/enum_reference.rs new file mode 100644 index 00000000..546fe864 --- /dev/null +++ b/libs/ast-references/src/types/enum_reference.rs @@ -0,0 +1,210 @@ +use std::cell::RefCell; +/** + * EnumReference.rs + * Definition of EnumReference struct + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::rc::Rc; +use crate::types::location::Location; +use crate::types::file_reference::FileReference; +use crate::types::contract_reference::ContractReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct EnumValueReference { + pub name: String, + pub location: Location, +} + +pub struct EnumReference { + pub name: String, + pub location: Location, + pub values : Vec, + pub contract: Option>>, + pub file: Option>>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + + impl EnumReference { + pub fn new(name: String, location: Location, contract: Option<&Rc>>, file: Option<&Rc>>) -> EnumReference { + EnumReference { + name: name, + location: location, + values: Vec::new(), + contract: match contract { + Some(c) => Some(c.clone()), + None => None, + }, + file: match file { + Some(f) => Some(f.clone()), + None => None, + }, + } + } + + pub fn add_value(&mut self, name: String, location: Location) { + self.values.push(EnumValueReference { + name: name, + location: location, + }); + } + } + +impl fmt::Display for EnumReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Enum {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for EnumReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Enum {} at {}", self.name, self.location) + } +} + +impl PartialEq for EnumReference { + fn eq(&self, other: &EnumReference) -> bool { + self.name == other.name && self.location == other.location && self.values == other.values && self.file == other.file + } +} + +impl PartialEq for EnumValueReference { + fn eq(&self, other: &EnumValueReference) -> bool { + self.name == other.name && self.location == other.location + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + +#[cfg(test)] +mod tests { + use crate::types::location::Bound; + + use super::*; + + #[test] + fn new_good_construct() { + let result = EnumReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.values.is_empty()); + } + + #[test] + fn new_contract_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let contract = ContractReference::new( + "Contract".to_string(), + Location::new( + "File.test".to_string(), + Bound::new(0, 0), + Bound::new(0, 0), + ), + &file, + ); + let result = EnumReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + Some(&Rc::new(RefCell::new(contract))), + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.values.is_empty()); + + assert_eq!(result.contract.as_ref().unwrap().borrow().name, "Contract"); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.file, "File.test".to_string()); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.column, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.column, 0); + } + + #[test] + fn new_standalone_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = EnumReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + Some(&file), + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.values.is_empty()); + + assert_eq!(result.file.as_ref().unwrap().borrow().path, "File.test"); + } + + #[test] + fn add_value() { + let mut result = EnumReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + result.add_value( + String::from("TestValue"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + ); + + assert_eq!(result.values.len(), 1); + assert_eq!(result.values[0].name, "TestValue"); + assert_eq!(result.values[0].location.file, "test.sol"); + assert_eq!(result.values[0].location.start.line, 0); + assert_eq!(result.values[0].location.start.column, 0); + assert_eq!(result.values[0].location.end.line, 0); + assert_eq!(result.values[0].location.end.column, 0); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/file_reference.rs b/libs/ast-references/src/types/file_reference.rs new file mode 100644 index 00000000..b149bdc9 --- /dev/null +++ b/libs/ast-references/src/types/file_reference.rs @@ -0,0 +1,124 @@ +use std::cell::RefCell; +/** + * FileReference.rs + * Definition of FileReference struct + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::rc::Rc; +use crate::types::contract_reference::ContractReference; +use crate::types::struct_reference::StructReference; +use crate::types::enum_reference::EnumReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct FileReference { + pub path: String, + pub contracts: Vec>>, + pub structs: Vec>>, + pub enums: Vec>>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + +impl FileReference { + pub fn new(path: String) -> FileReference { + FileReference { + path: path, + contracts: Vec::new(), + structs: Vec::new(), + enums: Vec::new(), + } + } + + pub fn add_contract(&mut self, contract: ContractReference) { + self.contracts.push(Rc::new(RefCell::new(contract))); + } + + pub fn add_struct(&mut self, strct: StructReference) { + self.structs.push(Rc::new(RefCell::new(strct))); + } + + pub fn add_enum(&mut self, enm: EnumReference) { + self.enums.push(Rc::new(RefCell::new(enm))); + } +} + +impl fmt::Display for FileReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "File {}", self.path) + } +} + +impl fmt::Debug for FileReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "File {}", self.path) + } +} + +impl PartialEq for FileReference { + fn eq(&self, other: &FileReference) -> bool { + self.path == other.path + } +} + +impl Eq for FileReference {} + +impl Hash for FileReference { + fn hash(&self, state: &mut H) { + self.path.hash(state); + } +} + + +/****************************************************************************** + * Tests * + *****************************************************************************/ + + #[cfg(test)] + mod tests { + use std::cell::RefCell; + use crate::types::location::{Bound, Location}; + + use super::*; + + #[test] + fn new_good_construct() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + + assert_eq!(file.borrow().path, "File.test"); + } + + #[test] + fn add_contract() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let contract = ContractReference::new("Contract".to_string(), Location::new("File.test".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &file); + file.borrow_mut().add_contract(contract); + + assert_eq!(file.borrow().contracts.len(), 1); + } + + #[test] + fn add_struct() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let strct = StructReference::new("Struct".to_string(), Location::new("File.test".to_string(), Bound::new(0, 0), Bound::new(0, 0)), None, Some(&file)); + file.borrow_mut().add_struct(strct); + + assert_eq!(file.borrow().structs.len(), 1); + } + + #[test] + fn add_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let enm = EnumReference::new("Enum".to_string(), Location::new("File.test".to_string(), Bound::new(0, 0), Bound::new(0, 0)), None, Some(&file)); + file.borrow_mut().add_enum(enm); + + assert_eq!(file.borrow().enums.len(), 1); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/function_reference.rs b/libs/ast-references/src/types/function_reference.rs new file mode 100644 index 00000000..7c8e11df --- /dev/null +++ b/libs/ast-references/src/types/function_reference.rs @@ -0,0 +1,76 @@ +use std::cell::RefCell; +/** + * FunctionReference.rs + * Definition of FuntionReference struct + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::rc::Rc; +use crate::types::location::Location; +use crate::types::contract_reference::ContractReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct FunctionReference { + pub name: String, + pub location: Location, + pub contract: Rc>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + + impl FunctionReference { + pub fn new(name: String, location: Location, contract: &Rc>) -> FunctionReference { + FunctionReference { + name: name, + location: location, + contract: contract.clone(), + } + } + } + +impl fmt::Display for FunctionReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Function {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for FunctionReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Function {} at {} in contract {:?}", self.name, self.location, self.contract) + } +} + +impl PartialEq for FunctionReference { + fn eq(&self, other: &FunctionReference) -> bool { + self.name == other.name && self.location == other.location && self.contract == other.contract + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + + #[cfg(test)] + mod tests { + use std::cell::RefCell; + use crate::types::{location::{Bound, Location}, file_reference::FileReference}; + + use super::*; + + #[test] + fn new_good_construct() { + let file = Rc::new(RefCell::new(FileReference::new("Test.sol".to_string()))); + let contract = Rc::new(RefCell::new(ContractReference::new("contract".to_string(), Location::new("Test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &file))); + let function = FunctionReference::new("function".to_string(), Location::new("Test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &contract); + + assert_eq!(function.name, "function".to_string()); + assert_eq!(function.location, Location::new("Test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0))); + assert_eq!(function.contract, contract); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/location.rs b/libs/ast-references/src/types/location.rs new file mode 100644 index 00000000..9a7b9939 --- /dev/null +++ b/libs/ast-references/src/types/location.rs @@ -0,0 +1,144 @@ +/** + * Location.rs + * Definition of Location and Bound structs + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::hash::{Hash, Hasher}; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct Bound { + pub line: u32, + pub column: u32, +} + +pub struct Location { + pub file: String, // path of the file + pub start: Bound, + pub end: Bound, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + +impl Bound { + pub fn new(line: u32, column: u32) -> Bound { + Bound { + line: line, + column: column, + } + } +} + +impl Location { + pub fn new(file: String, start: Bound, end: Bound) -> Location { + Location { + file: file, + start: start, + end: end, + } + } +} + +impl fmt::Display for Location { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:({}:{}-{}:{})", self.file, self.start.line, self.start.column, self.end.line, self.end.column) + } +} + +impl fmt::Debug for Location { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:({}:{}-{}:{})", self.file, self.start.line, self.start.column, self.end.line, self.end.column) + } +} + +impl PartialEq for Location { + fn eq(&self, other: &Location) -> bool { + self.file == other.file && self.start == other.start && self.end == other.end + } +} + +impl PartialEq for Bound { + fn eq(&self, other: &Bound) -> bool { + self.line == other.line && self.column == other.column + } +} + +impl Eq for Location {} + +impl Hash for Location { + fn hash(&self, state: &mut H) { + self.file.hash(state); + self.start.hash(state); + self.end.hash(state); + + } +} + +impl Hash for Bound { + fn hash(&self, state: &mut H) { + self.line.hash(state); + self.column.hash(state); + } +} + +impl Clone for Location { + fn clone(&self) -> Location { + Location { + file: self.file.clone(), + start: Bound { + line: self.start.line, + column: self.start.column, + }, + end: Bound { + line: self.end.line, + column: self.end.column, + }, + } + } +} + +impl Default for Location { + fn default() -> Location { + Location { + file: String::new(), + start: Bound { + line: 0, + column: 0, + }, + end: Bound { + line: 0, + column: 0, + }, + } + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn new_good_construct() { + let result = Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ); + + assert_eq!(result.file, "test.sol"); + assert_eq!(result.start.line, 0); + assert_eq!(result.start.column, 0); + assert_eq!(result.end.line, 0); + assert_eq!(result.end.column, 0); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/property_reference.rs b/libs/ast-references/src/types/property_reference.rs new file mode 100644 index 00000000..e967bd9f --- /dev/null +++ b/libs/ast-references/src/types/property_reference.rs @@ -0,0 +1,79 @@ +use std::cell::RefCell; +/** + * PropertyReference.rs + * Definition of PropertyReference struct + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::rc::Rc; +use crate::types::location::Location; +use crate::types::contract_reference::ContractReference; + + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct PropertyReference { + pub name: String, + pub prop_type: String, + pub location: Location, + pub contract: Rc>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + + impl PropertyReference { + pub fn new(name: String, prop_type: String, location: Location, contract: &Rc>) -> PropertyReference { + PropertyReference { + name: name, + prop_type, + location: location, + contract: contract.clone(), + } + } + } + +impl fmt::Display for PropertyReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Property {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for PropertyReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Property {} at {} in contract {:?}", self.name, self.location, self.contract) + } +} + +impl PartialEq for PropertyReference { + fn eq(&self, other: &PropertyReference) -> bool { + self.name == other.name && self.location == other.location && self.contract == other.contract + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + + #[cfg(test)] + mod tests { + use std::cell::RefCell; + use crate::types::{location::{Bound, Location}, file_reference::FileReference}; + + use super::*; + + #[test] + fn new_good_construct() { + let file = Rc::new(RefCell::new(FileReference::new("test.sol".to_string()))); + let contract = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &file))); + let property = PropertyReference::new("test".to_string(), "uint256".to_string(), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &contract); + assert_eq!(property.name, "test"); + assert_eq!(property.prop_type, "uint256"); + assert_eq!(property.location, Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0))); + assert_eq!(property.contract, contract); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/struct_reference.rs b/libs/ast-references/src/types/struct_reference.rs new file mode 100644 index 00000000..89332755 --- /dev/null +++ b/libs/ast-references/src/types/struct_reference.rs @@ -0,0 +1,156 @@ +use std::cell::RefCell; +/** + * StructReference.rs + * Definition of StructReference struct + * author: 0xMemoryGrinder +*/ + +use std::fmt; +use std::rc::Rc; +use crate::types::location::Location; +use crate::types::file_reference::FileReference; +use crate::types::contract_reference::ContractReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct StructReference { + pub name: String, + pub location: Location, + pub contract: Option>>, + pub file: Option>>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + + impl StructReference { + pub fn new(name: String, location: Location, contract: Option<&Rc>>, file: Option<&Rc>>) -> StructReference { + StructReference { + name: name, + location: location, + contract: match contract { + Some(c) => Some(c.clone()), + None => None, + }, + file: match file { + Some(f) => Some(f.clone()), + None => None, + }, + } + } + } + +impl fmt::Display for StructReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Struct {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for StructReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Struct {} at {}", self.name, self.location) + } +} + +impl PartialEq for StructReference { + fn eq(&self, other: &StructReference) -> bool { + self.name == other.name && self.location == other.location && self.contract == other.contract && self.file == other.file + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + +#[cfg(test)] +mod tests { + use crate::types::location::Bound; + + use super::*; + + #[test] + fn new_good_construct() { + let result = StructReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + } + + #[test] + fn new_contract_struct() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let contract = ContractReference::new( + "Contract".to_string(), + Location::new( + "File.test".to_string(), + Bound::new(0, 0), + Bound::new(0, 0), + ), + &file, + ); + let result = StructReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + Some(&Rc::new(RefCell::new(contract))), + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + + assert_eq!(result.contract.as_ref().unwrap().borrow().name, "Contract"); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.file, "File.test".to_string()); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.column, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.column, 0); + } + + #[test] + fn new_standalone_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = StructReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + Some(&file), + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + + assert_eq!(result.file.as_ref().unwrap().borrow().path, "File.test"); + } +} \ No newline at end of file diff --git a/remove-me-6963cf31313545279b31.txt b/remove-me-6963cf31313545279b31.txt deleted file mode 100644 index 50262245..00000000 --- a/remove-me-6963cf31313545279b31.txt +++ /dev/null @@ -1 +0,0 @@ -6963cf31313545279b31 From 91d3c53409f528fcbe34fdfeed8196d7bd87b644 Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:53:08 -0400 Subject: [PATCH 04/27] refactor(libs/ast-references): remove useless file and boilerplate code --- libs/ast-references/src/lib.rs | 28 +-------------------------- libs/ast-references/src/references.rs | 0 2 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 libs/ast-references/src/references.rs diff --git a/libs/ast-references/src/lib.rs b/libs/ast-references/src/lib.rs index c1ed3f05..cd408564 100644 --- a/libs/ast-references/src/lib.rs +++ b/libs/ast-references/src/lib.rs @@ -1,27 +1 @@ -mod types; -use std::cell::RefCell; -use std::rc::Rc; - -use types::contract_reference::ContractReference; -use types::location::{Location, Bound}; - -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -pub fn parse () -> ContractReference { - let file = Rc::new(RefCell::new(types::file_reference::FileReference::new("".to_string()))); - ContractReference::new("".to_string(), Location::new("".to_string(), Bound { line: 0, column: 0}, Bound { line: 0, column: 0}), &file) - -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +pub mod types; diff --git a/libs/ast-references/src/references.rs b/libs/ast-references/src/references.rs deleted file mode 100644 index e69de29b..00000000 From 2e2f071d498e018e2e56d6c81303bc50e1240351 Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Sat, 2 Sep 2023 11:54:52 -0400 Subject: [PATCH 05/27] feat(libs/ast-references): added error and event structs --- libs/ast-references/Cargo.lock | 57 +++++ libs/ast-references/Cargo.toml | 2 + libs/ast-references/src/types.rs | 2 + .../src/types/contract_reference.rs | 39 ++++ .../src/types/enum_reference.rs | 4 +- .../src/types/error_reference.rs | 220 ++++++++++++++++++ .../src/types/event_reference.rs | 220 ++++++++++++++++++ .../src/types/file_reference.rs | 33 +++ 8 files changed, 575 insertions(+), 2 deletions(-) create mode 100644 libs/ast-references/src/types/error_reference.rs create mode 100644 libs/ast-references/src/types/event_reference.rs diff --git a/libs/ast-references/Cargo.lock b/libs/ast-references/Cargo.lock index 631c60fc..eebcaf3b 100644 --- a/libs/ast-references/Cargo.lock +++ b/libs/ast-references/Cargo.lock @@ -5,3 +5,60 @@ version = 3 [[package]] name = "ast-references" version = "0.1.0" +dependencies = [ + "proc-macro2", + "syn-solidity", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397f229dc34c7b8231b6ef85502f9ca4e3425b8625e6d403bb74779e6b1917b5" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" diff --git a/libs/ast-references/Cargo.toml b/libs/ast-references/Cargo.toml index 0c98f5eb..ef975a21 100644 --- a/libs/ast-references/Cargo.toml +++ b/libs/ast-references/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +proc-macro2 = { version = "1.0.66", features = ["span-locations"]} +syn-solidity = { version = "0.3.1", features = ["visit"] } \ No newline at end of file diff --git a/libs/ast-references/src/types.rs b/libs/ast-references/src/types.rs index 35b40e16..b3454cee 100644 --- a/libs/ast-references/src/types.rs +++ b/libs/ast-references/src/types.rs @@ -1,5 +1,7 @@ pub mod contract_reference; pub mod enum_reference; +pub mod error_reference; +pub mod event_reference; pub mod file_reference; pub mod function_reference; pub mod location; diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index dfcdc95b..e9424faa 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -14,6 +14,9 @@ use crate::types::struct_reference::StructReference; use crate::types::function_reference::FunctionReference; use crate::types::property_reference::PropertyReference; +use super::error_reference::ErrorReference; +use super::event_reference::EventReference; + /****************************************************************************** * Types * *****************************************************************************/ @@ -25,6 +28,8 @@ pub struct ContractReference { pub structs: Vec>>, pub functions: Vec>>, pub properties: Vec>>, + pub errors: Vec>>, + pub events: Vec>>, } /****************************************************************************** @@ -40,6 +45,8 @@ impl ContractReference { structs: Vec::new(), functions: Vec::new(), properties: Vec::new(), + errors: Vec::new(), + events: Vec::new(), } } @@ -54,6 +61,14 @@ impl ContractReference { pub fn add_property(&mut self, property: &Rc>) { self.properties.push(property.clone()); } + + pub fn add_error(&mut self, error: &Rc>) { + self.errors.push(error.clone()); + } + + pub fn add_event(&mut self, event: &Rc>) { + self.events.push(event.clone()); + } } impl fmt::Display for ContractReference { @@ -144,4 +159,28 @@ mod tests { assert_eq!(result.borrow().properties.len(), 1); assert_eq!(result.borrow().properties[0], property); } + + #[test] + fn add_error() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let error = Rc::new(RefCell::new(ErrorReference::new("TestError".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + + (*result).borrow_mut().add_error(&error); + + assert_eq!(result.borrow().errors.len(), 1); + assert_eq!(result.borrow().errors[0], error); + } + + #[test] + fn add_event() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let event = Rc::new(RefCell::new(EventReference::new("TestEvent".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + + (*result).borrow_mut().add_event(&event); + + assert_eq!(result.borrow().events.len(), 1); + assert_eq!(result.borrow().events[0], event); + } } \ No newline at end of file diff --git a/libs/ast-references/src/types/enum_reference.rs b/libs/ast-references/src/types/enum_reference.rs index 546fe864..5fb40685 100644 --- a/libs/ast-references/src/types/enum_reference.rs +++ b/libs/ast-references/src/types/enum_reference.rs @@ -1,12 +1,12 @@ -use std::cell::RefCell; /** * EnumReference.rs * Definition of EnumReference struct * author: 0xMemoryGrinder -*/ + */ use std::fmt; use std::rc::Rc; +use std::cell::RefCell; use crate::types::location::Location; use crate::types::file_reference::FileReference; use crate::types::contract_reference::ContractReference; diff --git a/libs/ast-references/src/types/error_reference.rs b/libs/ast-references/src/types/error_reference.rs new file mode 100644 index 00000000..5aebd82e --- /dev/null +++ b/libs/ast-references/src/types/error_reference.rs @@ -0,0 +1,220 @@ +/** + * ErrorReference.rs + * Definition of ErrorReference struct + * author: 0xMemoryGrinder + */ + +use std::fmt; +use std::rc::Rc; +use std::cell::RefCell; +use syn_solidity::{Type, Storage}; +use crate::types::location::Location; +use crate::types::file_reference::FileReference; +use crate::types::contract_reference::ContractReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct ErrorParameterReference { + pub name: String, + pub ty: Type, + pub storage: Option, + pub location: Location, +} + +pub struct ErrorReference { + pub name: String, + pub location: Location, + pub parameters : Vec, + pub contract: Option>>, + pub file: Option>>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + + impl ErrorReference { + pub fn new(name: String, location: Location, contract: Option<&Rc>>, file: Option<&Rc>>) -> ErrorReference { + ErrorReference { + name: name, + location: location, + parameters: Vec::new(), + contract: match contract { + Some(c) => Some(c.clone()), + None => None, + }, + file: match file { + Some(f) => Some(f.clone()), + None => None, + }, + } + } + + pub fn add_value(&mut self, name: String, ty: Type, storage: Option, location: Location) { + self.parameters.push(ErrorParameterReference { + name: name, + ty: ty, + storage: storage, + location: location, + }); + } + } + +impl fmt::Display for ErrorReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Error {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for ErrorReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Error {} at {}", self.name, self.location) + } +} + +impl PartialEq for ErrorReference { + fn eq(&self, other: &ErrorReference) -> bool { + self.name == other.name && self.location == other.location && self.parameters == other.parameters && self.file == other.file + } +} + +impl PartialEq for ErrorParameterReference { + fn eq(&self, other: &ErrorParameterReference) -> bool { + self.name == other.name && self.location == other.location && self.ty == other.ty && self.storage == other.storage + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + +#[cfg(test)] +mod tests { + use std::num::NonZeroU16; + use proc_macro2::Span; + + use crate::types::location::Bound; + + use super::*; + + #[test] + fn new_good_construct() { + let result = ErrorReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.parameters.is_empty()); + } + + #[test] + fn new_contract_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let contract = ContractReference::new( + "Contract".to_string(), + Location::new( + "File.test".to_string(), + Bound::new(0, 0), + Bound::new(0, 0), + ), + &file, + ); + let result = ErrorReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + Some(&Rc::new(RefCell::new(contract))), + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.parameters.is_empty()); + + assert_eq!(result.contract.as_ref().unwrap().borrow().name, "Contract"); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.file, "File.test".to_string()); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.column, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.column, 0); + } + + #[test] + fn new_standalone_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = ErrorReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + Some(&file), + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.parameters.is_empty()); + + assert_eq!(result.file.as_ref().unwrap().borrow().path, "File.test"); + } + + #[test] + fn add_value() { + let mut result = ErrorReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + result.add_value( + String::from("TestValue"), + Type::Uint(Span::call_site(), NonZeroU16::new(256)), + None, + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + ); + + assert_eq!(result.parameters.len(), 1); + assert_eq!(result.parameters[0].name, "TestValue"); + assert_eq!(result.parameters[0].location.file, "test.sol"); + assert_eq!(result.parameters[0].location.start.line, 0); + assert_eq!(result.parameters[0].location.start.column, 0); + assert_eq!(result.parameters[0].location.end.line, 0); + assert_eq!(result.parameters[0].location.end.column, 0); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/event_reference.rs b/libs/ast-references/src/types/event_reference.rs new file mode 100644 index 00000000..da23bcc8 --- /dev/null +++ b/libs/ast-references/src/types/event_reference.rs @@ -0,0 +1,220 @@ +/** + * EventReference.rs + * Definition of EventReference struct + * author: 0xMemoryGrinder + */ + +use std::fmt; +use std::rc::Rc; +use std::cell::RefCell; +use syn_solidity::{Type, Storage}; +use crate::types::location::Location; +use crate::types::file_reference::FileReference; +use crate::types::contract_reference::ContractReference; + +/****************************************************************************** + * Types * + *****************************************************************************/ + +pub struct EventParameterReference { + pub name: String, + pub ty: Type, + pub storage: Option, + pub location: Location, +} + +pub struct EventReference { + pub name: String, + pub location: Location, + pub parameters : Vec, + pub contract: Option>>, + pub file: Option>>, +} + +/****************************************************************************** + * Methods / Trait implementation * + *****************************************************************************/ + + impl EventReference { + pub fn new(name: String, location: Location, contract: Option<&Rc>>, file: Option<&Rc>>) -> EventReference { + EventReference { + name: name, + location: location, + parameters: Vec::new(), + contract: match contract { + Some(c) => Some(c.clone()), + None => None, + }, + file: match file { + Some(f) => Some(f.clone()), + None => None, + }, + } + } + + pub fn add_value(&mut self, name: String, ty: Type, storage: Option, location: Location) { + self.parameters.push(EventParameterReference { + name: name, + ty: ty, + storage: storage, + location: location, + }); + } + } + +impl fmt::Display for EventReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Event {} at {}", self.name, self.location) + } +} + +impl fmt::Debug for EventReference { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Event {} at {}", self.name, self.location) + } +} + +impl PartialEq for EventReference { + fn eq(&self, other: &EventReference) -> bool { + self.name == other.name && self.location == other.location && self.parameters == other.parameters && self.file == other.file + } +} + +impl PartialEq for EventParameterReference { + fn eq(&self, other: &EventParameterReference) -> bool { + self.name == other.name && self.location == other.location && self.ty == other.ty && self.storage == other.storage + } +} + +/****************************************************************************** + * Tests * + *****************************************************************************/ + +#[cfg(test)] +mod tests { + use std::num::NonZeroU16; + use proc_macro2::Span; + + use crate::types::location::Bound; + + use super::*; + + #[test] + fn new_good_construct() { + let result = EventReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.parameters.is_empty()); + } + + #[test] + fn new_contract_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let contract = ContractReference::new( + "Contract".to_string(), + Location::new( + "File.test".to_string(), + Bound::new(0, 0), + Bound::new(0, 0), + ), + &file, + ); + let result = EventReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + Some(&Rc::new(RefCell::new(contract))), + None, + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.parameters.is_empty()); + + assert_eq!(result.contract.as_ref().unwrap().borrow().name, "Contract"); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.file, "File.test".to_string()); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.start.column, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.line, 0); + assert_eq!(result.contract.as_ref().unwrap().borrow().location.end.column, 0); + } + + #[test] + fn new_standalone_enum() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let result = EventReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + Some(&file), + ); + + assert_eq!(result.name, "Test"); + assert_eq!(result.location.file, "test.sol"); + assert_eq!(result.location.start.line, 0); + assert_eq!(result.location.start.column, 0); + assert_eq!(result.location.end.line, 0); + assert_eq!(result.location.end.column, 0); + assert!(result.parameters.is_empty()); + + assert_eq!(result.file.as_ref().unwrap().borrow().path, "File.test"); + } + + #[test] + fn add_value() { + let mut result = EventReference::new( + String::from("Test"), + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + None, + None, + ); + + result.add_value( + String::from("TestValue"), + Type::Uint(Span::call_site(), NonZeroU16::new(256)), + None, + Location::new( + String::from("test.sol"), + Bound::new(0, 0), + Bound::new(0, 0), + ), + ); + + assert_eq!(result.parameters.len(), 1); + assert_eq!(result.parameters[0].name, "TestValue"); + assert_eq!(result.parameters[0].location.file, "test.sol"); + assert_eq!(result.parameters[0].location.start.line, 0); + assert_eq!(result.parameters[0].location.start.column, 0); + assert_eq!(result.parameters[0].location.end.line, 0); + assert_eq!(result.parameters[0].location.end.column, 0); + } +} \ No newline at end of file diff --git a/libs/ast-references/src/types/file_reference.rs b/libs/ast-references/src/types/file_reference.rs index b149bdc9..dca2983f 100644 --- a/libs/ast-references/src/types/file_reference.rs +++ b/libs/ast-references/src/types/file_reference.rs @@ -12,6 +12,9 @@ use crate::types::contract_reference::ContractReference; use crate::types::struct_reference::StructReference; use crate::types::enum_reference::EnumReference; +use super::error_reference::ErrorReference; +use super::event_reference::EventReference; + /****************************************************************************** * Types * *****************************************************************************/ @@ -21,6 +24,8 @@ pub struct FileReference { pub contracts: Vec>>, pub structs: Vec>>, pub enums: Vec>>, + pub errors: Vec>>, + pub events: Vec>>, } /****************************************************************************** @@ -34,6 +39,8 @@ impl FileReference { contracts: Vec::new(), structs: Vec::new(), enums: Vec::new(), + errors: Vec::new(), + events: Vec::new(), } } @@ -48,6 +55,14 @@ impl FileReference { pub fn add_enum(&mut self, enm: EnumReference) { self.enums.push(Rc::new(RefCell::new(enm))); } + + pub fn add_error(&mut self, error: ErrorReference) { + self.errors.push(Rc::new(RefCell::new(error))); + } + + pub fn add_event(&mut self, event: EventReference) { + self.events.push(Rc::new(RefCell::new(event))); + } } impl fmt::Display for FileReference { @@ -121,4 +136,22 @@ impl Hash for FileReference { assert_eq!(file.borrow().enums.len(), 1); } + + #[test] + fn add_error() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let error = ErrorReference::new("Error".to_string(), Location::new("File.test".to_string(), Bound::new(0, 0), Bound::new(0, 0)), None, None); + file.borrow_mut().add_error(error); + + assert_eq!(file.borrow().errors.len(), 1); + } + + #[test] + fn add_event() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let event = EventReference::new("Event".to_string(), Location::new("File.test".to_string(), Bound::new(0, 0), Bound::new(0, 0)), None, None); + file.borrow_mut().add_event(event); + + assert_eq!(file.borrow().events.len(), 1); + } } \ No newline at end of file From 5899910c00c21a6d2979830ebbe560652ba59d3f Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Sat, 2 Sep 2023 12:06:46 -0400 Subject: [PATCH 06/27] feat(libs/ast-references): added function type --- .../src/types/contract_reference.rs | 14 +++++++++++++- .../src/types/error_reference.rs | 2 +- .../src/types/function_reference.rs | 18 ++++++++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index e9424faa..ab3780d0 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -106,6 +106,8 @@ impl Hash for ContractReference { mod tests { use std::cell::RefCell; + use syn_solidity::kw::function; + use crate::types::location::Bound; use super::*; @@ -140,7 +142,17 @@ mod tests { fn add_function() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let function = Rc::new(RefCell::new(FunctionReference::new("TestFunction".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &result))); + let function = Rc::new( + RefCell::new( + FunctionReference::new( + "TestFunction".to_string(), + syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), + Location::new( + "File.test".to_string(), + Bound {line: 0, column: 0}, + Bound { line: 0, column: 0} + ), + &result))); (*result).borrow_mut().add_function(&function); diff --git a/libs/ast-references/src/types/error_reference.rs b/libs/ast-references/src/types/error_reference.rs index 5aebd82e..d3d84363 100644 --- a/libs/ast-references/src/types/error_reference.rs +++ b/libs/ast-references/src/types/error_reference.rs @@ -201,7 +201,7 @@ mod tests { result.add_value( String::from("TestValue"), Type::Uint(Span::call_site(), NonZeroU16::new(256)), - None, + None, Location::new( String::from("test.sol"), Bound::new(0, 0), diff --git a/libs/ast-references/src/types/function_reference.rs b/libs/ast-references/src/types/function_reference.rs index 7c8e11df..24f3d082 100644 --- a/libs/ast-references/src/types/function_reference.rs +++ b/libs/ast-references/src/types/function_reference.rs @@ -7,6 +7,8 @@ use std::cell::RefCell; use std::fmt; use std::rc::Rc; +use syn_solidity::FunctionKind; + use crate::types::location::Location; use crate::types::contract_reference::ContractReference; @@ -16,6 +18,7 @@ use crate::types::contract_reference::ContractReference; pub struct FunctionReference { pub name: String, + pub kind: FunctionKind, pub location: Location, pub contract: Rc>, } @@ -25,9 +28,10 @@ pub struct FunctionReference { *****************************************************************************/ impl FunctionReference { - pub fn new(name: String, location: Location, contract: &Rc>) -> FunctionReference { + pub fn new(name: String, kind: FunctionKind, location: Location, contract: &Rc>) -> FunctionReference { FunctionReference { name: name, + kind: kind, location: location, contract: contract.clone(), } @@ -59,6 +63,9 @@ impl PartialEq for FunctionReference { #[cfg(test)] mod tests { use std::cell::RefCell; + use proc_macro2::Span; + use syn_solidity::kw::function; + use crate::types::{location::{Bound, Location}, file_reference::FileReference}; use super::*; @@ -67,7 +74,14 @@ impl PartialEq for FunctionReference { fn new_good_construct() { let file = Rc::new(RefCell::new(FileReference::new("Test.sol".to_string()))); let contract = Rc::new(RefCell::new(ContractReference::new("contract".to_string(), Location::new("Test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &file))); - let function = FunctionReference::new("function".to_string(), Location::new("Test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &contract); + let function = FunctionReference::new( + "function".to_string(), + FunctionKind::Function(function(Span::call_site())), + Location::new("Test.sol".to_string(), + Bound::new(0, 0), + Bound::new(0, 0)), + &contract + ); assert_eq!(function.name, "function".to_string()); assert_eq!(function.location, Location::new("Test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0))); From 62ba8d1a4ac6cc4d97b8a88de9c6100f25e859f0 Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Sat, 2 Sep 2023 12:13:08 -0400 Subject: [PATCH 07/27] feat(libs/ast-references): property type is now a comprehensive enum --- .../src/types/contract_reference.rs | 5 +++-- .../src/types/property_reference.rs | 18 +++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index ab3780d0..f79634aa 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -106,7 +106,8 @@ impl Hash for ContractReference { mod tests { use std::cell::RefCell; - use syn_solidity::kw::function; + use proc_macro2::Span; + use syn_solidity::{kw::function, Type}; use crate::types::location::Bound; @@ -164,7 +165,7 @@ mod tests { fn add_property() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let property = Rc::new(RefCell::new(PropertyReference::new("TestProperty".to_string(), "uint256".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &result))); + let property = Rc::new(RefCell::new(PropertyReference::new("TestProperty".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &result))); (*result).borrow_mut().add_property(&property); diff --git a/libs/ast-references/src/types/property_reference.rs b/libs/ast-references/src/types/property_reference.rs index e967bd9f..7fd65844 100644 --- a/libs/ast-references/src/types/property_reference.rs +++ b/libs/ast-references/src/types/property_reference.rs @@ -1,12 +1,14 @@ -use std::cell::RefCell; /** * PropertyReference.rs * Definition of PropertyReference struct * author: 0xMemoryGrinder -*/ + */ use std::fmt; use std::rc::Rc; +use std::cell::RefCell; +use syn_solidity::Type; + use crate::types::location::Location; use crate::types::contract_reference::ContractReference; @@ -17,7 +19,7 @@ use crate::types::contract_reference::ContractReference; pub struct PropertyReference { pub name: String, - pub prop_type: String, + pub ty: Type, pub location: Location, pub contract: Rc>, } @@ -27,10 +29,10 @@ pub struct PropertyReference { *****************************************************************************/ impl PropertyReference { - pub fn new(name: String, prop_type: String, location: Location, contract: &Rc>) -> PropertyReference { + pub fn new(name: String, ty: Type, location: Location, contract: &Rc>) -> PropertyReference { PropertyReference { name: name, - prop_type, + ty, location: location, contract: contract.clone(), } @@ -62,6 +64,8 @@ impl PartialEq for PropertyReference { #[cfg(test)] mod tests { use std::cell::RefCell; + use proc_macro2::Span; + use crate::types::{location::{Bound, Location}, file_reference::FileReference}; use super::*; @@ -70,9 +74,9 @@ impl PartialEq for PropertyReference { fn new_good_construct() { let file = Rc::new(RefCell::new(FileReference::new("test.sol".to_string()))); let contract = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &file))); - let property = PropertyReference::new("test".to_string(), "uint256".to_string(), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &contract); + let property = PropertyReference::new("test".to_string(), Type::Bool(Span::call_site()), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &contract); assert_eq!(property.name, "test"); - assert_eq!(property.prop_type, "uint256"); + assert_eq!(property.ty, Type::Bool(Span::call_site())); assert_eq!(property.location, Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0))); assert_eq!(property.contract, contract); } From d18b07e3963d7ab38c789ac500daaa5352a54ea0 Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Sat, 2 Sep 2023 12:23:15 -0400 Subject: [PATCH 08/27] refactor(libs/ast-references): renamed PropertyReference to VariableReference to be more generic and use it outside a contract scope --- libs/ast-references/src/types.rs | 2 +- .../src/types/contract_reference.rs | 8 +-- .../src/types/file_reference.rs | 26 ++++++++-- ...rty_reference.rs => variable_reference.rs} | 50 +++++++++++++------ 4 files changed, 63 insertions(+), 23 deletions(-) rename libs/ast-references/src/types/{property_reference.rs => variable_reference.rs} (57%) diff --git a/libs/ast-references/src/types.rs b/libs/ast-references/src/types.rs index b3454cee..9ebda400 100644 --- a/libs/ast-references/src/types.rs +++ b/libs/ast-references/src/types.rs @@ -5,5 +5,5 @@ pub mod event_reference; pub mod file_reference; pub mod function_reference; pub mod location; -pub mod property_reference; +pub mod variable_reference; pub mod struct_reference; \ No newline at end of file diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index f79634aa..b4fe290a 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -12,7 +12,7 @@ use crate::types::location::Location; use crate::types::file_reference::FileReference; use crate::types::struct_reference::StructReference; use crate::types::function_reference::FunctionReference; -use crate::types::property_reference::PropertyReference; +use crate::types::variable_reference::VariableReference; use super::error_reference::ErrorReference; use super::event_reference::EventReference; @@ -27,7 +27,7 @@ pub struct ContractReference { pub file: Rc>, pub structs: Vec>>, pub functions: Vec>>, - pub properties: Vec>>, + pub properties: Vec>>, pub errors: Vec>>, pub events: Vec>>, } @@ -58,7 +58,7 @@ impl ContractReference { self.functions.push(function.clone()); } - pub fn add_property(&mut self, property: &Rc>) { + pub fn add_property(&mut self, property: &Rc>) { self.properties.push(property.clone()); } @@ -165,7 +165,7 @@ mod tests { fn add_property() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let property = Rc::new(RefCell::new(PropertyReference::new("TestProperty".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &result))); + let property = Rc::new(RefCell::new(VariableReference::new("TestProperty".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); (*result).borrow_mut().add_property(&property); diff --git a/libs/ast-references/src/types/file_reference.rs b/libs/ast-references/src/types/file_reference.rs index dca2983f..e0d572e4 100644 --- a/libs/ast-references/src/types/file_reference.rs +++ b/libs/ast-references/src/types/file_reference.rs @@ -8,12 +8,12 @@ use std::cell::RefCell; use std::fmt; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use crate::types::contract_reference::ContractReference; -use crate::types::struct_reference::StructReference; -use crate::types::enum_reference::EnumReference; - +use super::contract_reference::ContractReference; +use super::struct_reference::StructReference; +use super::enum_reference::EnumReference; use super::error_reference::ErrorReference; use super::event_reference::EventReference; +use super::variable_reference::VariableReference; /****************************************************************************** * Types * @@ -26,6 +26,7 @@ pub struct FileReference { pub enums: Vec>>, pub errors: Vec>>, pub events: Vec>>, + pub variables: Vec>>, } /****************************************************************************** @@ -41,6 +42,7 @@ impl FileReference { enums: Vec::new(), errors: Vec::new(), events: Vec::new(), + variables: Vec::new(), } } @@ -63,6 +65,10 @@ impl FileReference { pub fn add_event(&mut self, event: EventReference) { self.events.push(Rc::new(RefCell::new(event))); } + + pub fn add_variable(&mut self, variable: VariableReference) { + self.variables.push(Rc::new(RefCell::new(variable))); + } } impl fmt::Display for FileReference { @@ -99,6 +105,9 @@ impl Hash for FileReference { #[cfg(test)] mod tests { use std::cell::RefCell; + use proc_macro2::Span; + use syn_solidity::Type; + use crate::types::location::{Bound, Location}; use super::*; @@ -154,4 +163,13 @@ impl Hash for FileReference { assert_eq!(file.borrow().events.len(), 1); } + + #[test] + fn add_variable() { + let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); + let variable = VariableReference::new("Variable".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound::new(0, 0), Bound::new(0, 0)), None, None); + file.borrow_mut().add_variable(variable); + + assert_eq!(file.borrow().variables.len(), 1); + } } \ No newline at end of file diff --git a/libs/ast-references/src/types/property_reference.rs b/libs/ast-references/src/types/variable_reference.rs similarity index 57% rename from libs/ast-references/src/types/property_reference.rs rename to libs/ast-references/src/types/variable_reference.rs index 7fd65844..aa54f13a 100644 --- a/libs/ast-references/src/types/property_reference.rs +++ b/libs/ast-references/src/types/variable_reference.rs @@ -1,6 +1,6 @@ /** - * PropertyReference.rs - * Definition of PropertyReference struct + * VariableReference.rs + * Definition of VariableReference struct * author: 0xMemoryGrinder */ @@ -12,47 +12,57 @@ use syn_solidity::Type; use crate::types::location::Location; use crate::types::contract_reference::ContractReference; +use super::file_reference::FileReference; + /****************************************************************************** * Types * *****************************************************************************/ -pub struct PropertyReference { +pub struct VariableReference { pub name: String, pub ty: Type, pub location: Location, - pub contract: Rc>, + pub contract: Option>>, + pub file: Option>>, } /****************************************************************************** * Methods / Trait implementation * *****************************************************************************/ - impl PropertyReference { - pub fn new(name: String, ty: Type, location: Location, contract: &Rc>) -> PropertyReference { - PropertyReference { + impl VariableReference { + pub fn new(name: String, ty: Type, location: Location, contract: Option<&Rc>>, file: Option<&Rc>>) -> VariableReference { + VariableReference { name: name, ty, location: location, - contract: contract.clone(), + contract: match contract { + Some(c) => Some(c.clone()), + None => None, + }, + file: match file { + Some(f) => Some(f.clone()), + None => None, + }, } } } -impl fmt::Display for PropertyReference { +impl fmt::Display for VariableReference { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Property {} at {}", self.name, self.location) } } -impl fmt::Debug for PropertyReference { +impl fmt::Debug for VariableReference { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Property {} at {} in contract {:?}", self.name, self.location, self.contract) } } -impl PartialEq for PropertyReference { - fn eq(&self, other: &PropertyReference) -> bool { +impl PartialEq for VariableReference { + fn eq(&self, other: &VariableReference) -> bool { self.name == other.name && self.location == other.location && self.contract == other.contract } } @@ -74,10 +84,22 @@ impl PartialEq for PropertyReference { fn new_good_construct() { let file = Rc::new(RefCell::new(FileReference::new("test.sol".to_string()))); let contract = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &file))); - let property = PropertyReference::new("test".to_string(), Type::Bool(Span::call_site()), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), &contract); + let property = VariableReference::new("test".to_string(), Type::Bool(Span::call_site()), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), Some(&contract), None); + assert_eq!(property.name, "test"); + assert_eq!(property.ty, Type::Bool(Span::call_site())); + assert_eq!(property.location, Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0))); + assert_eq!(property.contract, Some(contract)); + assert_eq!(property.file, None); + } + + #[test] + fn new_standalone_variable() { + let file = Rc::new(RefCell::new(FileReference::new("test.sol".to_string()))); + let property = VariableReference::new("test".to_string(), Type::Bool(Span::call_site()), Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0)), None, Some(&file)); assert_eq!(property.name, "test"); assert_eq!(property.ty, Type::Bool(Span::call_site())); assert_eq!(property.location, Location::new("test.sol".to_string(), Bound::new(0, 0), Bound::new(0, 0))); - assert_eq!(property.contract, contract); + assert_eq!(property.contract, None); + assert_eq!(property.file, Some(file)); } } \ No newline at end of file From 960f367c3f4db6f24d857b863031ad3245a65e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Mon, 18 Sep 2023 23:22:45 +0100 Subject: [PATCH 09/27] feat(libs/ast-references): add function to retrieve FileReference from ast --- libs/ast-references/src/file_retriever.rs | 101 ++++++++++++++++++++++ libs/ast-references/src/lib.rs | 1 + 2 files changed, 102 insertions(+) create mode 100644 libs/ast-references/src/file_retriever.rs diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs new file mode 100644 index 00000000..515d12cf --- /dev/null +++ b/libs/ast-references/src/file_retriever.rs @@ -0,0 +1,101 @@ +/** + * file_retriever.rs + * Function to retrieve a file reference from AST + * author: ByFish + */ +use crate::types::contract_reference::ContractReference; +use crate::types::file_reference::FileReference; +use crate::types::location::{Bound, Location}; +use crate::types::struct_reference::StructReference; +use proc_macro2::TokenStream; +use std::cell::RefCell; +use std::fs; +use std::rc::Rc; +use std::str::FromStr; +use syn_solidity::{ItemContract, ItemStruct, Visit}; + +struct FileVisitor { + file_reference: Rc>, + current_contract: Option>>, +} + +impl FileVisitor { + pub fn new(path: String) -> Self { + Self { + file_reference: Rc::new(RefCell::new(FileReference::new(path.to_string()))), + current_contract: None, + } + } +} + +impl<'ast> Visit<'ast> for FileVisitor { + fn visit_item_contract(&mut self, i: &ItemContract) { + let contract_reference = ContractReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + &self.file_reference, + ); + self.file_reference + .borrow_mut() + .add_contract(contract_reference); + self.current_contract = Some( + self.file_reference + .borrow() + .contracts + .last() + .unwrap() + .clone(), + ); + syn_solidity::visit::visit_item_contract(self, i); + self.current_contract = None; + } + fn visit_item_struct(&mut self, i: &'ast ItemStruct) { + let struct_reference = StructReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + None, + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_struct(&Rc::new(RefCell::new(struct_reference))); + } else { + self.file_reference + .borrow_mut() + .add_struct(struct_reference); + } + syn_solidity::visit::visit_item_struct(self, i) + } +} + +pub fn retrieve_file_reference_from_path(path: String) -> Rc> { + let source = fs::read_to_string(path.to_string()).unwrap(); + let tokens = TokenStream::from_str(source.as_str()).unwrap(); + let ast = syn_solidity::parse2(tokens).unwrap(); + let mut visitor = FileVisitor::new(path.to_string()); + visitor.visit_file(&ast); + visitor.file_reference +} diff --git a/libs/ast-references/src/lib.rs b/libs/ast-references/src/lib.rs index cd408564..03782f9a 100644 --- a/libs/ast-references/src/lib.rs +++ b/libs/ast-references/src/lib.rs @@ -1 +1,2 @@ +pub mod file_retriever; pub mod types; From 6a1cc78faf9f58645679818c1657909ead995569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Tue, 19 Sep 2023 10:37:38 +0100 Subject: [PATCH 10/27] feat(libs/ast-references): add current contract into StructReference --- libs/ast-references/src/file_retriever.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 515d12cf..c2a385b0 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -59,6 +59,7 @@ impl<'ast> Visit<'ast> for FileVisitor { syn_solidity::visit::visit_item_contract(self, i); self.current_contract = None; } + fn visit_item_struct(&mut self, i: &'ast ItemStruct) { let struct_reference = StructReference::new( i.name.to_string(), @@ -73,7 +74,7 @@ impl<'ast> Visit<'ast> for FileVisitor { i.brace_token.span.join().end().column as u32, ), ), - None, + self.current_contract.as_ref(), Some(&self.file_reference), ); if self.current_contract.is_some() { @@ -99,3 +100,14 @@ pub fn retrieve_file_reference_from_path(path: String) -> Rc Date: Tue, 19 Sep 2023 10:48:16 +0100 Subject: [PATCH 11/27] feat: add visitor item enum --- libs/ast-references/src/file_retriever.rs | 40 +++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index c2a385b0..1f938d72 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -90,6 +90,35 @@ impl<'ast> Visit<'ast> for FileVisitor { } syn_solidity::visit::visit_item_struct(self, i) } + + fn visit_item_enum(&mut self, i: &'ast ItemStruct) { + let enum_reference = EnumReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_enum(&Rc::new(RefCell::new(enum_reference))); + } else { + self.file_reference.borrow_mut().add_enum(enum_reference); + } + syn_solidity::visit::visit_item_enum(self, i) + } } pub fn retrieve_file_reference_from_path(path: String) -> Rc> { @@ -108,6 +137,13 @@ mod tests { #[test] fn test_retrieve_contract_nodes_empty() { retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); - assert_eq!(1,0) + assert_eq!(1, 0) } -} \ No newline at end of file + + #[test] + fn test_retrieve_enums_nodes() { + retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); + visit_item_enum(); + assert_eq!(1, 0) + } +} From a2b65a6901c9dbc308706a65a31786b69e0f26f0 Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 10:56:54 +0100 Subject: [PATCH 12/27] feat: add visit item event --- libs/ast-references/src/file_retriever.rs | 42 +++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 1f938d72..162e46b7 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -4,6 +4,8 @@ * author: ByFish */ use crate::types::contract_reference::ContractReference; +use crate::types::enum_reference::EnumReference; +use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; use crate::types::location::{Bound, Location}; use crate::types::struct_reference::StructReference; @@ -12,7 +14,7 @@ use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ItemContract, ItemStruct, Visit}; +use syn_solidity::{ItemContract, ItemEnum, ItemEvent, ItemStruct, Visit}; struct FileVisitor { file_reference: Rc>, @@ -91,7 +93,7 @@ impl<'ast> Visit<'ast> for FileVisitor { syn_solidity::visit::visit_item_struct(self, i) } - fn visit_item_enum(&mut self, i: &'ast ItemStruct) { + fn visit_item_enum(&mut self, i: &'ast ItemEnum) { let enum_reference = EnumReference::new( i.name.to_string(), Location::new( @@ -119,6 +121,35 @@ impl<'ast> Visit<'ast> for FileVisitor { } syn_solidity::visit::visit_item_enum(self, i) } + + fn visit_item_event(&mut self, i: &'ast ItemEvent) { + let event_reference = EventReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_event(&Rc::new(RefCell::new(event_reference))); + } else { + self.file_reference.borrow_mut().add_event(event_reference); + } + syn_solidity::visit::visit_item_event(self, i) + } } pub fn retrieve_file_reference_from_path(path: String) -> Rc> { @@ -146,4 +177,11 @@ mod tests { visit_item_enum(); assert_eq!(1, 0) } + + #[test] + fn test_retrieve_event_nodes() { + retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); + visit_item_event(); + assert_eq!(1, 0) + } } From 4b81f07896816ff488fb70525ad0d11d307ef293 Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 11:00:32 +0100 Subject: [PATCH 13/27] feat: add visit item error --- libs/ast-references/tests/enums/one.sol | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 libs/ast-references/tests/enums/one.sol diff --git a/libs/ast-references/tests/enums/one.sol b/libs/ast-references/tests/enums/one.sol new file mode 100644 index 00000000..8784443d --- /dev/null +++ b/libs/ast-references/tests/enums/one.sol @@ -0,0 +1,21 @@ +enum one { + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday +} + +contract One { + enum another_one { + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday + } +} From 8bf54e149463c0adfbbc7377356cd150eada37b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Tue, 19 Sep 2023 11:32:49 +0100 Subject: [PATCH 14/27] feat(libs/ast-reference): fix references location --- libs/ast-references/src/file_retriever.rs | 121 ++++++++++------------ 1 file changed, 53 insertions(+), 68 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 162e46b7..b84058c6 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -4,7 +4,6 @@ * author: ByFish */ use crate::types::contract_reference::ContractReference; -use crate::types::enum_reference::EnumReference; use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; use crate::types::location::{Bound, Location}; @@ -14,7 +13,7 @@ use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ItemContract, ItemEnum, ItemEvent, ItemStruct, Visit}; +use syn_solidity::{ItemContract, ItemEvent, ItemStruct, Spanned, Visit}; struct FileVisitor { file_reference: Rc>, @@ -37,12 +36,12 @@ impl<'ast> Visit<'ast> for FileVisitor { Location::new( self.file_reference.borrow_mut().path.clone(), Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, + i.name.span().start().line as u32, + i.name.span().start().column as u32, ), Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, + i.name.span().end().line as u32, + i.name.span().end().column as u32, ), ), &self.file_reference, @@ -62,49 +61,47 @@ impl<'ast> Visit<'ast> for FileVisitor { self.current_contract = None; } - fn visit_item_struct(&mut self, i: &'ast ItemStruct) { - let struct_reference = StructReference::new( - i.name.to_string(), - Location::new( - self.file_reference.borrow_mut().path.clone(), - Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, - ), - Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, - ), - ), - self.current_contract.as_ref(), - Some(&self.file_reference), - ); - if self.current_contract.is_some() { - self.current_contract - .as_ref() - .unwrap() - .borrow_mut() - .add_struct(&Rc::new(RefCell::new(struct_reference))); - } else { - self.file_reference - .borrow_mut() - .add_struct(struct_reference); - } - syn_solidity::visit::visit_item_struct(self, i) - } + //fn visit_item_enum(&mut self, i: &'ast ItemEnum) { + // let enum_reference = EnumReference::new( + // i.name.to_string(), + // Location::new( + // self.file_reference.borrow_mut().path.clone(), + // Bound::new( + // i.name.span().start().line as u32, + // i.name.span().start().column as u32, + // ), + // Bound::new( + // i.name.span().start().line as u32, + // i.name.span().start().column as u32, + // ), + // ), + // self.current_contract.as_ref(), + // Some(&self.file_reference), + // ); + // if self.current_contract.is_some() { + // self.current_contract + // .as_ref() + // .unwrap() + // .borrow_mut() + // .add_enum(&Rc::new(RefCell::new(enum_reference))); + // } else { + // self.file_reference.borrow_mut().add_enum(enum_reference); + // } + // syn_solidity::visit::visit_item_enum(self, i) + //} - fn visit_item_enum(&mut self, i: &'ast ItemEnum) { - let enum_reference = EnumReference::new( + fn visit_item_event(&mut self, i: &'ast ItemEvent) { + let event_reference = EventReference::new( i.name.to_string(), Location::new( self.file_reference.borrow_mut().path.clone(), Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, + i.name.span().start().line as u32, + i.name.span().start().column as u32, ), Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, + i.name.span().end().line as u32, + i.name.span().end().column as u32, ), ), self.current_contract.as_ref(), @@ -115,25 +112,25 @@ impl<'ast> Visit<'ast> for FileVisitor { .as_ref() .unwrap() .borrow_mut() - .add_enum(&Rc::new(RefCell::new(enum_reference))); + .add_event(&Rc::new(RefCell::new(event_reference))); } else { - self.file_reference.borrow_mut().add_enum(enum_reference); + self.file_reference.borrow_mut().add_event(event_reference); } - syn_solidity::visit::visit_item_enum(self, i) + syn_solidity::visit::visit_item_event(self, i) } - fn visit_item_event(&mut self, i: &'ast ItemEvent) { - let event_reference = EventReference::new( + fn visit_item_struct(&mut self, i: &'ast ItemStruct) { + let struct_reference = StructReference::new( i.name.to_string(), Location::new( self.file_reference.borrow_mut().path.clone(), Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, + i.name.span().start().line as u32, + i.name.span().start().column as u32, ), Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, + i.name.span().end().line as u32, + i.name.span().end().column as u32, ), ), self.current_contract.as_ref(), @@ -144,11 +141,13 @@ impl<'ast> Visit<'ast> for FileVisitor { .as_ref() .unwrap() .borrow_mut() - .add_event(&Rc::new(RefCell::new(event_reference))); + .add_struct(&Rc::new(RefCell::new(struct_reference))); } else { - self.file_reference.borrow_mut().add_event(event_reference); + self.file_reference + .borrow_mut() + .add_struct(struct_reference); } - syn_solidity::visit::visit_item_event(self, i) + syn_solidity::visit::visit_item_struct(self, i) } } @@ -170,18 +169,4 @@ mod tests { retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); assert_eq!(1, 0) } - - #[test] - fn test_retrieve_enums_nodes() { - retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); - visit_item_enum(); - assert_eq!(1, 0) - } - - #[test] - fn test_retrieve_event_nodes() { - retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); - visit_item_event(); - assert_eq!(1, 0) - } } From cf320ff77a75173a38b68ae85b40e47bf458243c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Tue, 19 Sep 2023 12:11:28 +0100 Subject: [PATCH 15/27] feat(libs/ast-references): add visit item function --- libs/ast-references/src/file_retriever.rs | 28 +++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index b84058c6..9e7d7fda 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -6,14 +6,15 @@ use crate::types::contract_reference::ContractReference; use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; -use crate::types::location::{Bound, Location}; use crate::types::struct_reference::StructReference; +use crate::types::function_reference::FunctionReference; +use crate::types::location::{Bound, Location}; use proc_macro2::TokenStream; use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ItemContract, ItemEvent, ItemStruct, Spanned, Visit}; +use syn_solidity::{ItemContract, ItemEvent, ItemFunction, ItemStruct, Spanned, Visit}; struct FileVisitor { file_reference: Rc>, @@ -119,6 +120,29 @@ impl<'ast> Visit<'ast> for FileVisitor { syn_solidity::visit::visit_item_event(self, i) } + fn visit_item_function(&mut self, i: &'ast ItemFunction) { + if self.current_contract.is_some() { + let function_reference = FunctionReference::new( + i.name.as_ref().unwrap().0.to_string().clone(), + i.kind.clone(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.name.span().start().line as u32, + i.name.span().start().column as u32, + ), + Bound::new( + i.name.span().end().line as u32, + i.name.span().end().column as u32, + ), + ), + self.current_contract.as_ref().unwrap(), + ); + self.current_contract.as_ref().unwrap().borrow_mut().add_function(&Rc::new(RefCell::new(function_reference))) + } + syn_solidity::visit::visit_item_function(self, i) + } + fn visit_item_struct(&mut self, i: &'ast ItemStruct) { let struct_reference = StructReference::new( i.name.to_string(), From 71edeeae17cad73348f3e28c09a483e1dc5bb45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Tue, 19 Sep 2023 14:31:20 +0100 Subject: [PATCH 16/27] feat(libs/ast-references): add visit variable definition --- libs/ast-references/src/file_retriever.rs | 67 ++++++++++++++++------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 9e7d7fda..f317844d 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -8,13 +8,14 @@ use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; use crate::types::struct_reference::StructReference; use crate::types::function_reference::FunctionReference; +use crate::types::variable_reference::VariableReference; use crate::types::location::{Bound, Location}; use proc_macro2::TokenStream; use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ItemContract, ItemEvent, ItemFunction, ItemStruct, Spanned, Visit}; +use syn_solidity::{ItemContract, ItemEvent, ItemFunction, ItemStruct, Spanned, VariableDeclaration, Visit}; struct FileVisitor { file_reference: Rc>, @@ -31,9 +32,13 @@ impl FileVisitor { } impl<'ast> Visit<'ast> for FileVisitor { - fn visit_item_contract(&mut self, i: &ItemContract) { - let contract_reference = ContractReference::new( - i.name.to_string(), + fn visit_variable_declaration(&mut self, i: &'ast VariableDeclaration) { + if i.name.is_none() { + return; + } + let variable_reference = VariableReference::new( + i.name.as_ref().unwrap().0.to_string().clone(), + i.ty.clone(), Location::new( self.file_reference.borrow_mut().path.clone(), Bound::new( @@ -45,23 +50,14 @@ impl<'ast> Visit<'ast> for FileVisitor { i.name.span().end().column as u32, ), ), - &self.file_reference, - ); - self.file_reference - .borrow_mut() - .add_contract(contract_reference); - self.current_contract = Some( - self.file_reference - .borrow() - .contracts - .last() - .unwrap() - .clone(), + self.current_contract.as_ref(), + Some(&self.file_reference), ); - syn_solidity::visit::visit_item_contract(self, i); - self.current_contract = None; + self.file_reference.borrow_mut().add_variable(variable_reference); + syn_solidity::visit::visit_variable_declaration(self, i) } + // TODO: Add enum reference in contract references //fn visit_item_enum(&mut self, i: &'ast ItemEnum) { // let enum_reference = EnumReference::new( // i.name.to_string(), @@ -91,6 +87,37 @@ impl<'ast> Visit<'ast> for FileVisitor { // syn_solidity::visit::visit_item_enum(self, i) //} + fn visit_item_contract(&mut self, i: &ItemContract) { + let contract_reference = ContractReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.name.span().start().line as u32, + i.name.span().start().column as u32, + ), + Bound::new( + i.name.span().end().line as u32, + i.name.span().end().column as u32, + ), + ), + &self.file_reference, + ); + self.file_reference + .borrow_mut() + .add_contract(contract_reference); + self.current_contract = Some( + self.file_reference + .borrow() + .contracts + .last() + .unwrap() + .clone(), + ); + syn_solidity::visit::visit_item_contract(self, i); + self.current_contract = None; + } + fn visit_item_event(&mut self, i: &'ast ItemEvent) { let event_reference = EventReference::new( i.name.to_string(), @@ -138,9 +165,9 @@ impl<'ast> Visit<'ast> for FileVisitor { ), self.current_contract.as_ref().unwrap(), ); - self.current_contract.as_ref().unwrap().borrow_mut().add_function(&Rc::new(RefCell::new(function_reference))) + self.current_contract.as_ref().unwrap().borrow_mut().add_function(&Rc::new(RefCell::new(function_reference))); } - syn_solidity::visit::visit_item_function(self, i) + syn_solidity::visit::visit_item_function(self, i); } fn visit_item_struct(&mut self, i: &'ast ItemStruct) { From 5f11acfb37b9e9e9491faab2ca82532bbf2893aa Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 15:42:09 +0100 Subject: [PATCH 17/27] feat: add enum vec in contract reference --- libs/ast-references/src/file_retriever.rs | 129 ++++++++++++++- .../src/types/contract_reference.rs | 156 ++++++++++++++---- 2 files changed, 249 insertions(+), 36 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index f317844d..a8af741b 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -4,18 +4,23 @@ * author: ByFish */ use crate::types::contract_reference::ContractReference; +use crate::types::enum_reference::EnumReference; +use crate::types::error_reference::ErrorReference; use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; -use crate::types::struct_reference::StructReference; use crate::types::function_reference::FunctionReference; -use crate::types::variable_reference::VariableReference; use crate::types::location::{Bound, Location}; +use crate::types::struct_reference::StructReference; +use crate::types::variable_reference::VariableReference; use proc_macro2::TokenStream; use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ItemContract, ItemEvent, ItemFunction, ItemStruct, Spanned, VariableDeclaration, Visit}; +use syn_solidity::{ + ItemContract, ItemEnum, ItemError, ItemEvent, ItemFunction, ItemStruct, Spanned, + VariableDeclaration, Visit, +}; struct FileVisitor { file_reference: Rc>, @@ -53,7 +58,9 @@ impl<'ast> Visit<'ast> for FileVisitor { self.current_contract.as_ref(), Some(&self.file_reference), ); - self.file_reference.borrow_mut().add_variable(variable_reference); + self.file_reference + .borrow_mut() + .add_variable(variable_reference); syn_solidity::visit::visit_variable_declaration(self, i) } @@ -165,7 +172,11 @@ impl<'ast> Visit<'ast> for FileVisitor { ), self.current_contract.as_ref().unwrap(), ); - self.current_contract.as_ref().unwrap().borrow_mut().add_function(&Rc::new(RefCell::new(function_reference))); + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_function(&Rc::new(RefCell::new(function_reference))); } syn_solidity::visit::visit_item_function(self, i); } @@ -200,6 +211,93 @@ impl<'ast> Visit<'ast> for FileVisitor { } syn_solidity::visit::visit_item_struct(self, i) } + + fn visit_item_enum(&mut self, i: &'ast ItemEnum) { + let enum_reference = EnumReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_enum(&Rc::new(RefCell::new(enum_reference))); + } else { + self.file_reference.borrow_mut().add_enum(enum_reference); + } + syn_solidity::visit::visit_item_enum(self, i) + } + + fn visit_item_event(&mut self, i: &'ast ItemEvent) { + let event_reference = EventReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_event(&Rc::new(RefCell::new(event_reference))); + } else { + self.file_reference.borrow_mut().add_event(event_reference); + } + syn_solidity::visit::visit_item_event(self, i) + } + + fn visit_item_error(&mut self, i: &'ast ItemError) { + let error_reference = ErrorReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.brace_token.span.join().start().line as u32, + i.brace_token.span.join().start().column as u32, + ), + Bound::new( + i.brace_token.span.join().end().line as u32, + i.brace_token.span.join().end().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_error(&Rc::new(RefCell::new(error_reference))); + } else { + self.file_reference.borrow_mut().add_error(error_reference); + } + syn_solidity::visit::visit_item_error(self, i) + } } pub fn retrieve_file_reference_from_path(path: String) -> Rc> { @@ -220,4 +318,25 @@ mod tests { retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); assert_eq!(1, 0) } + + #[test] + fn test_retrieve_enums_nodes() { + retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); + visit_item_enum(); + assert_eq!(1, 0) + } + + #[test] + fn test_retrieve_event_nodes() { + retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); + visit_item_event(); + assert_eq!(1, 0) + } + + #[test] + fn test_retrieve_error_nodes() { + retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); + visit_item_error(); + assert_eq!(1, 0) + } } diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index b4fe290a..2ff78795 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -1,19 +1,19 @@ +use crate::types::file_reference::FileReference; +use crate::types::function_reference::FunctionReference; +use crate::types::location::Location; +use crate::types::struct_reference::StructReference; +use crate::types::variable_reference::VariableReference; +use std::cell::RefCell; /** * ContractReference.rs * Definition of ContractReference struct * author: 0xMemoryGrinder */ - use std::fmt; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use std::cell::RefCell; -use crate::types::location::Location; -use crate::types::file_reference::FileReference; -use crate::types::struct_reference::StructReference; -use crate::types::function_reference::FunctionReference; -use crate::types::variable_reference::VariableReference; +use super::enum_reference::EnumReference; use super::error_reference::ErrorReference; use super::event_reference::EventReference; @@ -30,6 +30,7 @@ pub struct ContractReference { pub properties: Vec>>, pub errors: Vec>>, pub events: Vec>>, + pub enums: Vec>>, } /****************************************************************************** @@ -37,7 +38,11 @@ pub struct ContractReference { *****************************************************************************/ impl ContractReference { - pub fn new(name: String, location: Location, file: &Rc>) -> ContractReference { + pub fn new( + name: String, + location: Location, + file: &Rc>, + ) -> ContractReference { ContractReference { name: name, location: location, @@ -47,6 +52,7 @@ impl ContractReference { properties: Vec::new(), errors: Vec::new(), events: Vec::new(), + enums: Vec::new(), } } @@ -69,6 +75,10 @@ impl ContractReference { pub fn add_event(&mut self, event: &Rc>) { self.events.push(event.clone()); } + + pub fn add_enum(&mut self, enums: &Rc>) { + self.enums.push(enums.clone()); + } } impl fmt::Display for ContractReference { @@ -116,7 +126,15 @@ mod tests { #[test] fn new_good_construct() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file); + let result = ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ); assert_eq!(result.file, file); assert_eq!(result.name, "Test"); @@ -130,30 +148,54 @@ mod tests { #[test] fn add_struct() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let strct = Rc::new(RefCell::new(StructReference::new("TestStruct".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), Some(&file)))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let strct = Rc::new(RefCell::new(StructReference::new( + "TestStruct".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + Some(&file), + ))); (*result).borrow_mut().add_struct(&strct); assert_eq!(result.borrow().structs.len(), 1); assert_eq!(result.borrow().structs[0], strct); } - + #[test] fn add_function() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let function = Rc::new( - RefCell::new( - FunctionReference::new( - "TestFunction".to_string(), - syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), - Location::new( - "File.test".to_string(), - Bound {line: 0, column: 0}, - Bound { line: 0, column: 0} - ), - &result))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let function = Rc::new(RefCell::new(FunctionReference::new( + "TestFunction".to_string(), + syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &result, + ))); (*result).borrow_mut().add_function(&function); @@ -164,8 +206,26 @@ mod tests { #[test] fn add_property() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let property = Rc::new(RefCell::new(VariableReference::new("TestProperty".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let property = Rc::new(RefCell::new(VariableReference::new( + "TestProperty".to_string(), + Type::Bool(Span::call_site()), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + None, + ))); (*result).borrow_mut().add_property(&property); @@ -176,8 +236,25 @@ mod tests { #[test] fn add_error() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let error = Rc::new(RefCell::new(ErrorReference::new("TestError".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let error = Rc::new(RefCell::new(ErrorReference::new( + "TestError".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + None, + ))); (*result).borrow_mut().add_error(&error); @@ -188,12 +265,29 @@ mod tests { #[test] fn add_event() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let event = Rc::new(RefCell::new(EventReference::new("TestEvent".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let event = Rc::new(RefCell::new(EventReference::new( + "TestEvent".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + None, + ))); (*result).borrow_mut().add_event(&event); assert_eq!(result.borrow().events.len(), 1); assert_eq!(result.borrow().events[0], event); } -} \ No newline at end of file +} From f4ef223a0db89977250e850c9b526b65e1b2377b Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 16:45:59 +0100 Subject: [PATCH 18/27] Revert "feat: add enum vec in contract reference" This reverts commit 18d9382c5867141ac99791825d4e44c7fd0447db. --- libs/ast-references/src/file_retriever.rs | 129 +-------------- .../src/types/contract_reference.rs | 156 ++++-------------- 2 files changed, 36 insertions(+), 249 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index a8af741b..f317844d 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -4,23 +4,18 @@ * author: ByFish */ use crate::types::contract_reference::ContractReference; -use crate::types::enum_reference::EnumReference; -use crate::types::error_reference::ErrorReference; use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; -use crate::types::function_reference::FunctionReference; -use crate::types::location::{Bound, Location}; use crate::types::struct_reference::StructReference; +use crate::types::function_reference::FunctionReference; use crate::types::variable_reference::VariableReference; +use crate::types::location::{Bound, Location}; use proc_macro2::TokenStream; use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ - ItemContract, ItemEnum, ItemError, ItemEvent, ItemFunction, ItemStruct, Spanned, - VariableDeclaration, Visit, -}; +use syn_solidity::{ItemContract, ItemEvent, ItemFunction, ItemStruct, Spanned, VariableDeclaration, Visit}; struct FileVisitor { file_reference: Rc>, @@ -58,9 +53,7 @@ impl<'ast> Visit<'ast> for FileVisitor { self.current_contract.as_ref(), Some(&self.file_reference), ); - self.file_reference - .borrow_mut() - .add_variable(variable_reference); + self.file_reference.borrow_mut().add_variable(variable_reference); syn_solidity::visit::visit_variable_declaration(self, i) } @@ -172,11 +165,7 @@ impl<'ast> Visit<'ast> for FileVisitor { ), self.current_contract.as_ref().unwrap(), ); - self.current_contract - .as_ref() - .unwrap() - .borrow_mut() - .add_function(&Rc::new(RefCell::new(function_reference))); + self.current_contract.as_ref().unwrap().borrow_mut().add_function(&Rc::new(RefCell::new(function_reference))); } syn_solidity::visit::visit_item_function(self, i); } @@ -211,93 +200,6 @@ impl<'ast> Visit<'ast> for FileVisitor { } syn_solidity::visit::visit_item_struct(self, i) } - - fn visit_item_enum(&mut self, i: &'ast ItemEnum) { - let enum_reference = EnumReference::new( - i.name.to_string(), - Location::new( - self.file_reference.borrow_mut().path.clone(), - Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, - ), - Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, - ), - ), - self.current_contract.as_ref(), - Some(&self.file_reference), - ); - if self.current_contract.is_some() { - self.current_contract - .as_ref() - .unwrap() - .borrow_mut() - .add_enum(&Rc::new(RefCell::new(enum_reference))); - } else { - self.file_reference.borrow_mut().add_enum(enum_reference); - } - syn_solidity::visit::visit_item_enum(self, i) - } - - fn visit_item_event(&mut self, i: &'ast ItemEvent) { - let event_reference = EventReference::new( - i.name.to_string(), - Location::new( - self.file_reference.borrow_mut().path.clone(), - Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, - ), - Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, - ), - ), - self.current_contract.as_ref(), - Some(&self.file_reference), - ); - if self.current_contract.is_some() { - self.current_contract - .as_ref() - .unwrap() - .borrow_mut() - .add_event(&Rc::new(RefCell::new(event_reference))); - } else { - self.file_reference.borrow_mut().add_event(event_reference); - } - syn_solidity::visit::visit_item_event(self, i) - } - - fn visit_item_error(&mut self, i: &'ast ItemError) { - let error_reference = ErrorReference::new( - i.name.to_string(), - Location::new( - self.file_reference.borrow_mut().path.clone(), - Bound::new( - i.brace_token.span.join().start().line as u32, - i.brace_token.span.join().start().column as u32, - ), - Bound::new( - i.brace_token.span.join().end().line as u32, - i.brace_token.span.join().end().column as u32, - ), - ), - self.current_contract.as_ref(), - Some(&self.file_reference), - ); - if self.current_contract.is_some() { - self.current_contract - .as_ref() - .unwrap() - .borrow_mut() - .add_error(&Rc::new(RefCell::new(error_reference))); - } else { - self.file_reference.borrow_mut().add_error(error_reference); - } - syn_solidity::visit::visit_item_error(self, i) - } } pub fn retrieve_file_reference_from_path(path: String) -> Rc> { @@ -318,25 +220,4 @@ mod tests { retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); assert_eq!(1, 0) } - - #[test] - fn test_retrieve_enums_nodes() { - retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); - visit_item_enum(); - assert_eq!(1, 0) - } - - #[test] - fn test_retrieve_event_nodes() { - retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); - visit_item_event(); - assert_eq!(1, 0) - } - - #[test] - fn test_retrieve_error_nodes() { - retrieve_file_reference_from_path("C:\\Users\\byfish\\Desktop\\DEV\\osmium\\libs\\ast-extractor\\tests\\files\\contracts\\two.sol".to_string()); - visit_item_error(); - assert_eq!(1, 0) - } } diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index 2ff78795..b4fe290a 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -1,19 +1,19 @@ -use crate::types::file_reference::FileReference; -use crate::types::function_reference::FunctionReference; -use crate::types::location::Location; -use crate::types::struct_reference::StructReference; -use crate::types::variable_reference::VariableReference; -use std::cell::RefCell; /** * ContractReference.rs * Definition of ContractReference struct * author: 0xMemoryGrinder */ + use std::fmt; use std::hash::{Hash, Hasher}; use std::rc::Rc; +use std::cell::RefCell; +use crate::types::location::Location; +use crate::types::file_reference::FileReference; +use crate::types::struct_reference::StructReference; +use crate::types::function_reference::FunctionReference; +use crate::types::variable_reference::VariableReference; -use super::enum_reference::EnumReference; use super::error_reference::ErrorReference; use super::event_reference::EventReference; @@ -30,7 +30,6 @@ pub struct ContractReference { pub properties: Vec>>, pub errors: Vec>>, pub events: Vec>>, - pub enums: Vec>>, } /****************************************************************************** @@ -38,11 +37,7 @@ pub struct ContractReference { *****************************************************************************/ impl ContractReference { - pub fn new( - name: String, - location: Location, - file: &Rc>, - ) -> ContractReference { + pub fn new(name: String, location: Location, file: &Rc>) -> ContractReference { ContractReference { name: name, location: location, @@ -52,7 +47,6 @@ impl ContractReference { properties: Vec::new(), errors: Vec::new(), events: Vec::new(), - enums: Vec::new(), } } @@ -75,10 +69,6 @@ impl ContractReference { pub fn add_event(&mut self, event: &Rc>) { self.events.push(event.clone()); } - - pub fn add_enum(&mut self, enums: &Rc>) { - self.enums.push(enums.clone()); - } } impl fmt::Display for ContractReference { @@ -126,15 +116,7 @@ mod tests { #[test] fn new_good_construct() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = ContractReference::new( - "Test".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &file, - ); + let result = ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file); assert_eq!(result.file, file); assert_eq!(result.name, "Test"); @@ -148,54 +130,30 @@ mod tests { #[test] fn add_struct() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new( - "Test".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &file, - ))); - let strct = Rc::new(RefCell::new(StructReference::new( - "TestStruct".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - Some(&result), - Some(&file), - ))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let strct = Rc::new(RefCell::new(StructReference::new("TestStruct".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), Some(&file)))); (*result).borrow_mut().add_struct(&strct); assert_eq!(result.borrow().structs.len(), 1); assert_eq!(result.borrow().structs[0], strct); } - + #[test] fn add_function() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new( - "Test".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &file, - ))); - let function = Rc::new(RefCell::new(FunctionReference::new( - "TestFunction".to_string(), - syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &result, - ))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let function = Rc::new( + RefCell::new( + FunctionReference::new( + "TestFunction".to_string(), + syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), + Location::new( + "File.test".to_string(), + Bound {line: 0, column: 0}, + Bound { line: 0, column: 0} + ), + &result))); (*result).borrow_mut().add_function(&function); @@ -206,26 +164,8 @@ mod tests { #[test] fn add_property() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new( - "Test".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &file, - ))); - let property = Rc::new(RefCell::new(VariableReference::new( - "TestProperty".to_string(), - Type::Bool(Span::call_site()), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - Some(&result), - None, - ))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let property = Rc::new(RefCell::new(VariableReference::new("TestProperty".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); (*result).borrow_mut().add_property(&property); @@ -236,25 +176,8 @@ mod tests { #[test] fn add_error() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new( - "Test".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &file, - ))); - let error = Rc::new(RefCell::new(ErrorReference::new( - "TestError".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - Some(&result), - None, - ))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let error = Rc::new(RefCell::new(ErrorReference::new("TestError".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); (*result).borrow_mut().add_error(&error); @@ -265,29 +188,12 @@ mod tests { #[test] fn add_event() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new( - "Test".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - &file, - ))); - let event = Rc::new(RefCell::new(EventReference::new( - "TestEvent".to_string(), - Location::new( - "File.test".to_string(), - Bound { line: 0, column: 0 }, - Bound { line: 0, column: 0 }, - ), - Some(&result), - None, - ))); + let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); + let event = Rc::new(RefCell::new(EventReference::new("TestEvent".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); (*result).borrow_mut().add_event(&event); assert_eq!(result.borrow().events.len(), 1); assert_eq!(result.borrow().events[0], event); } -} +} \ No newline at end of file From 7fe12591fb508d64ef9e6ea7b2e3e6cc6eb0a022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Tue, 19 Sep 2023 16:53:09 +0100 Subject: [PATCH 19/27] feat(libs/ast-references): add properties to contract --- libs/ast-references/src/file_retriever.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index f317844d..463e839a 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -53,7 +53,17 @@ impl<'ast> Visit<'ast> for FileVisitor { self.current_contract.as_ref(), Some(&self.file_reference), ); - self.file_reference.borrow_mut().add_variable(variable_reference); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_property(&Rc::new(RefCell::new(variable_reference))); + } else { + self.file_reference + .borrow_mut() + .add_variable(variable_reference); + } syn_solidity::visit::visit_variable_declaration(self, i) } From d6c02d6ad672a5c067d5384616b9c8345f02754d Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 17:02:19 +0100 Subject: [PATCH 20/27] feat: add visit item error --- libs/ast-references/src/file_retriever.rs | 141 ++++++++++++---- .../src/types/contract_reference.rs | 156 ++++++++++++++---- libs/ast-references/tests/enums/one.sol | 21 --- libs/ast-references/tests/good.sol | 7 + 4 files changed, 239 insertions(+), 86 deletions(-) delete mode 100644 libs/ast-references/tests/enums/one.sol create mode 100644 libs/ast-references/tests/good.sol diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 463e839a..88cead04 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -4,18 +4,23 @@ * author: ByFish */ use crate::types::contract_reference::ContractReference; +use crate::types::enum_reference::EnumReference; +use crate::types::error_reference::ErrorReference; use crate::types::event_reference::EventReference; use crate::types::file_reference::FileReference; -use crate::types::struct_reference::StructReference; use crate::types::function_reference::FunctionReference; -use crate::types::variable_reference::VariableReference; use crate::types::location::{Bound, Location}; +use crate::types::struct_reference::StructReference; +use crate::types::variable_reference::VariableReference; use proc_macro2::TokenStream; use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ItemContract, ItemEvent, ItemFunction, ItemStruct, Spanned, VariableDeclaration, Visit}; +use syn_solidity::{ + ItemContract, ItemEnum, ItemError, ItemEvent, ItemFunction, ItemStruct, Spanned, + VariableDeclaration, Visit, +}; struct FileVisitor { file_reference: Rc>, @@ -67,35 +72,34 @@ impl<'ast> Visit<'ast> for FileVisitor { syn_solidity::visit::visit_variable_declaration(self, i) } - // TODO: Add enum reference in contract references - //fn visit_item_enum(&mut self, i: &'ast ItemEnum) { - // let enum_reference = EnumReference::new( - // i.name.to_string(), - // Location::new( - // self.file_reference.borrow_mut().path.clone(), - // Bound::new( - // i.name.span().start().line as u32, - // i.name.span().start().column as u32, - // ), - // Bound::new( - // i.name.span().start().line as u32, - // i.name.span().start().column as u32, - // ), - // ), - // self.current_contract.as_ref(), - // Some(&self.file_reference), - // ); - // if self.current_contract.is_some() { - // self.current_contract - // .as_ref() - // .unwrap() - // .borrow_mut() - // .add_enum(&Rc::new(RefCell::new(enum_reference))); - // } else { - // self.file_reference.borrow_mut().add_enum(enum_reference); - // } - // syn_solidity::visit::visit_item_enum(self, i) - //} + fn visit_item_enum(&mut self, i: &'ast ItemEnum) { + let enum_reference = EnumReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.name.span().start().line as u32, + i.name.span().start().column as u32, + ), + Bound::new( + i.name.span().start().line as u32, + i.name.span().start().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_enum(&Rc::new(RefCell::new(enum_reference))); + } else { + self.file_reference.borrow_mut().add_enum(enum_reference); + } + syn_solidity::visit::visit_item_enum(self, i) + } fn visit_item_contract(&mut self, i: &ItemContract) { let contract_reference = ContractReference::new( @@ -175,7 +179,11 @@ impl<'ast> Visit<'ast> for FileVisitor { ), self.current_contract.as_ref().unwrap(), ); - self.current_contract.as_ref().unwrap().borrow_mut().add_function(&Rc::new(RefCell::new(function_reference))); + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_function(&Rc::new(RefCell::new(function_reference))); } syn_solidity::visit::visit_item_function(self, i); } @@ -210,6 +218,35 @@ impl<'ast> Visit<'ast> for FileVisitor { } syn_solidity::visit::visit_item_struct(self, i) } + + fn visit_item_error(&mut self, i: &'ast ItemError) { + let error_reference = ErrorReference::new( + i.name.to_string(), + Location::new( + self.file_reference.borrow_mut().path.clone(), + Bound::new( + i.name.span().start().line as u32, + i.name.span().start().column as u32, + ), + Bound::new( + i.name.span().end().line as u32, + i.name.span().end().column as u32, + ), + ), + self.current_contract.as_ref(), + Some(&self.file_reference), + ); + if self.current_contract.is_some() { + self.current_contract + .as_ref() + .unwrap() + .borrow_mut() + .add_error(&Rc::new(RefCell::new(error_reference))); + } else { + self.file_reference.borrow_mut().add_error(error_reference); + } + syn_solidity::visit::visit_item_error(self, i) + } } pub fn retrieve_file_reference_from_path(path: String) -> Rc> { @@ -225,9 +262,45 @@ pub fn retrieve_file_reference_from_path(path: String) -> Rc>>, pub errors: Vec>>, pub events: Vec>>, + pub enums: Vec>>, } /****************************************************************************** @@ -37,7 +38,11 @@ pub struct ContractReference { *****************************************************************************/ impl ContractReference { - pub fn new(name: String, location: Location, file: &Rc>) -> ContractReference { + pub fn new( + name: String, + location: Location, + file: &Rc>, + ) -> ContractReference { ContractReference { name: name, location: location, @@ -47,6 +52,7 @@ impl ContractReference { properties: Vec::new(), errors: Vec::new(), events: Vec::new(), + enums: Vec::new(), } } @@ -69,6 +75,10 @@ impl ContractReference { pub fn add_event(&mut self, event: &Rc>) { self.events.push(event.clone()); } + + pub fn add_enum(&mut self, enums: &Rc>) { + self.enums.push(enums.clone()); + } } impl fmt::Display for ContractReference { @@ -116,7 +126,15 @@ mod tests { #[test] fn new_good_construct() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file); + let result = ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ); assert_eq!(result.file, file); assert_eq!(result.name, "Test"); @@ -130,30 +148,54 @@ mod tests { #[test] fn add_struct() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let strct = Rc::new(RefCell::new(StructReference::new("TestStruct".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), Some(&file)))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let strct = Rc::new(RefCell::new(StructReference::new( + "TestStruct".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + Some(&file), + ))); (*result).borrow_mut().add_struct(&strct); assert_eq!(result.borrow().structs.len(), 1); assert_eq!(result.borrow().structs[0], strct); } - + #[test] fn add_function() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let function = Rc::new( - RefCell::new( - FunctionReference::new( - "TestFunction".to_string(), - syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), - Location::new( - "File.test".to_string(), - Bound {line: 0, column: 0}, - Bound { line: 0, column: 0} - ), - &result))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let function = Rc::new(RefCell::new(FunctionReference::new( + "TestFunction".to_string(), + syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &result, + ))); (*result).borrow_mut().add_function(&function); @@ -164,8 +206,26 @@ mod tests { #[test] fn add_property() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let property = Rc::new(RefCell::new(VariableReference::new("TestProperty".to_string(), Type::Bool(Span::call_site()), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let property = Rc::new(RefCell::new(VariableReference::new( + "TestProperty".to_string(), + Type::Bool(Span::call_site()), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + None, + ))); (*result).borrow_mut().add_property(&property); @@ -176,8 +236,25 @@ mod tests { #[test] fn add_error() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let error = Rc::new(RefCell::new(ErrorReference::new("TestError".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let error = Rc::new(RefCell::new(ErrorReference::new( + "TestError".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + None, + ))); (*result).borrow_mut().add_error(&error); @@ -188,12 +265,29 @@ mod tests { #[test] fn add_event() { let file = Rc::new(RefCell::new(FileReference::new("File.test".to_string()))); - let result = Rc::new(RefCell::new(ContractReference::new("Test".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), &file))); - let event = Rc::new(RefCell::new(EventReference::new("TestEvent".to_string(), Location::new("File.test".to_string(), Bound {line: 0, column: 0}, Bound { line: 0, column: 0}), Some(&result), None))); + let result = Rc::new(RefCell::new(ContractReference::new( + "Test".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + &file, + ))); + let event = Rc::new(RefCell::new(EventReference::new( + "TestEvent".to_string(), + Location::new( + "File.test".to_string(), + Bound { line: 0, column: 0 }, + Bound { line: 0, column: 0 }, + ), + Some(&result), + None, + ))); (*result).borrow_mut().add_event(&event); assert_eq!(result.borrow().events.len(), 1); assert_eq!(result.borrow().events[0], event); } -} \ No newline at end of file +} diff --git a/libs/ast-references/tests/enums/one.sol b/libs/ast-references/tests/enums/one.sol deleted file mode 100644 index 8784443d..00000000 --- a/libs/ast-references/tests/enums/one.sol +++ /dev/null @@ -1,21 +0,0 @@ -enum one { - Monday, - Tuesday, - Wednesday, - Thursday, - Friday, - Saturday, - Sunday -} - -contract One { - enum another_one { - Monday, - Tuesday, - Wednesday, - Thursday, - Friday, - Saturday, - Sunday - } -} diff --git a/libs/ast-references/tests/good.sol b/libs/ast-references/tests/good.sol new file mode 100644 index 00000000..56a8500d --- /dev/null +++ b/libs/ast-references/tests/good.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.8.0; + +contract Good { + function hello() public pure returns (string memory) { + return "Hello World"; + } +} From b194858e1ef537a4dbac0cc7d9f02253c6ab6de5 Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 18:46:11 +0100 Subject: [PATCH 21/27] add test for item variable Co-authored-by: 0xMemoryGrinder <0xMemoryGrinder@users.noreply.github.com> --- libs/ast-references/Cargo.lock | 32 +++++++++ libs/ast-references/Cargo.toml | 3 +- libs/ast-references/src/file_retriever.rs | 79 ++++++++++++++++++++--- libs/ast-references/tests/file.sol | 3 + libs/ast-references/tests/good.sol | 4 +- 5 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 libs/ast-references/tests/file.sol diff --git a/libs/ast-references/Cargo.lock b/libs/ast-references/Cargo.lock index eebcaf3b..94c741dd 100644 --- a/libs/ast-references/Cargo.lock +++ b/libs/ast-references/Cargo.lock @@ -2,10 +2,22 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ast-extractor" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "syn-solidity", + "thiserror", +] + [[package]] name = "ast-references" version = "0.1.0" dependencies = [ + "ast-extractor", "proc-macro2", "syn-solidity", ] @@ -57,6 +69,26 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.11" diff --git a/libs/ast-references/Cargo.toml b/libs/ast-references/Cargo.toml index ef975a21..561f2234 100644 --- a/libs/ast-references/Cargo.toml +++ b/libs/ast-references/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] proc-macro2 = { version = "1.0.66", features = ["span-locations"]} -syn-solidity = { version = "0.3.1", features = ["visit"] } \ No newline at end of file +syn-solidity = { version = "0.3.1", features = ["visit"] } +ast-extractor = { path = "../ast-extractor"} \ No newline at end of file diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 88cead04..a126ba20 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -19,7 +19,7 @@ use std::rc::Rc; use std::str::FromStr; use syn_solidity::{ ItemContract, ItemEnum, ItemError, ItemEvent, ItemFunction, ItemStruct, Spanned, - VariableDeclaration, Visit, + VariableDefinition, Visit, }; struct FileVisitor { @@ -37,12 +37,9 @@ impl FileVisitor { } impl<'ast> Visit<'ast> for FileVisitor { - fn visit_variable_declaration(&mut self, i: &'ast VariableDeclaration) { - if i.name.is_none() { - return; - } + fn visit_variable_definition(&mut self, i: &'ast VariableDefinition) { let variable_reference = VariableReference::new( - i.name.as_ref().unwrap().0.to_string().clone(), + i.name.0.to_string().clone(), i.ty.clone(), Location::new( self.file_reference.borrow_mut().path.clone(), @@ -69,7 +66,7 @@ impl<'ast> Visit<'ast> for FileVisitor { .borrow_mut() .add_variable(variable_reference); } - syn_solidity::visit::visit_variable_declaration(self, i) + syn_solidity::visit::visit_variable_definition(self, i) } fn visit_item_enum(&mut self, i: &'ast ItemEnum) { @@ -263,9 +260,71 @@ mod tests { use super::*; #[test] - fn test_retrieve_variables() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); - assert_eq!(1, 0) + fn test_retrieve_contract_variables() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("good.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let contract_ref = ContractReference::new( + "Good".to_string(), + Location::new(path_str, Bound { line: 1, column: 1 }, Bound::new(1, 10)), + &visitor.file_reference, + ); + visitor + .file_reference + .borrow_mut() + .add_contract(contract_ref); + visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let contract = file.items.iter().find(|item| match item { + syn_solidity::Item::Contract(contract) => true, + _ => false, + }); + let contract = match contract { + Some(syn_solidity::Item::Contract(contract)) => contract, + _ => panic!("No contract found"), + }; + let variables = contract.body.iter().find(|item| match item { + syn_solidity::Item::Variable(_) => true, + _ => false, + }); + let variables = match variables { + Some(syn_solidity::Item::Variable(variables)) => variables, + _ => panic!("No variables found"), + }; + visitor.visit_variable_definition(variables); + assert_eq!( + visitor.file_reference.borrow().contracts[0] + .borrow() + .properties + .len(), + 1 + ); + } + + #[test] + fn test_retrieve_file_variables() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("file.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let variable = file.items.iter().find(|item| match item { + syn_solidity::Item::Variable(contract) => true, + _ => false, + }); + let variable = match variable { + Some(syn_solidity::Item::Variable(var)) => var, + _ => panic!("Expect variable declaration"), + }; + visitor.visit_variable_definition(variable); + assert_eq!(visitor.file_reference.borrow().variables.len(), 1); } #[test] diff --git a/libs/ast-references/tests/file.sol b/libs/ast-references/tests/file.sol new file mode 100644 index 00000000..b065d6d0 --- /dev/null +++ b/libs/ast-references/tests/file.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.8.0; + +uint256 constant a = 1; diff --git a/libs/ast-references/tests/good.sol b/libs/ast-references/tests/good.sol index 56a8500d..f85c3d4b 100644 --- a/libs/ast-references/tests/good.sol +++ b/libs/ast-references/tests/good.sol @@ -1,7 +1,5 @@ pragma solidity ^0.8.0; contract Good { - function hello() public pure returns (string memory) { - return "Hello World"; - } + uint256 public x; } From 27a5312a266a9b2b43a7172637a021d320f96c8f Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 18:57:53 +0100 Subject: [PATCH 22/27] test: add sol files for test --- libs/ast-references/src/file_retriever.rs | 74 ++++++++++++++++++- .../{good.sol => contracts/contract.sol} | 0 .../tests/{ => contracts}/file.sol | 0 libs/ast-references/tests/enums/contract.sol | 5 ++ libs/ast-references/tests/enums/file.sol | 3 + libs/ast-references/tests/errors/contract.sol | 5 ++ libs/ast-references/tests/events/contract.sol | 5 ++ libs/ast-references/tests/events/file.sol | 3 + .../tests/functions/contract.sol | 5 ++ .../ast-references/tests/structs/contract.sol | 5 ++ libs/ast-references/tests/structs/file.sol | 3 + .../tests/variables/contract.sol | 5 ++ libs/ast-references/tests/variables/file.sol | 3 + 13 files changed, 112 insertions(+), 4 deletions(-) rename libs/ast-references/tests/{good.sol => contracts/contract.sol} (100%) rename libs/ast-references/tests/{ => contracts}/file.sol (100%) create mode 100644 libs/ast-references/tests/enums/contract.sol create mode 100644 libs/ast-references/tests/enums/file.sol create mode 100644 libs/ast-references/tests/errors/contract.sol create mode 100644 libs/ast-references/tests/events/contract.sol create mode 100644 libs/ast-references/tests/events/file.sol create mode 100644 libs/ast-references/tests/functions/contract.sol create mode 100644 libs/ast-references/tests/structs/contract.sol create mode 100644 libs/ast-references/tests/structs/file.sol create mode 100644 libs/ast-references/tests/variables/contract.sol create mode 100644 libs/ast-references/tests/variables/file.sol diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index a126ba20..d8e8e8f7 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -263,7 +263,8 @@ mod tests { fn test_retrieve_contract_variables() { let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); path.push("tests"); - path.push("good.sol"); + path.push("variables"); + path.push("contract.sol"); let path_str = path.to_str().unwrap().to_string(); let source = fs::read_to_string(&path).unwrap(); @@ -309,6 +310,7 @@ mod tests { fn test_retrieve_file_variables() { let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); path.push("tests"); + path.push("variables"); path.push("file.sol"); let path_str = path.to_str().unwrap().to_string(); let source = fs::read_to_string(&path).unwrap(); @@ -328,9 +330,73 @@ mod tests { } #[test] - fn test_retrieve_enums() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); - assert_eq!(1, 0) + fn test_retrieve_contract_enums() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("enums"); + path.push("contract.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let contract_ref = ContractReference::new( + "Good".to_string(), + Location::new(path_str, Bound { line: 1, column: 1 }, Bound::new(1, 10)), + &visitor.file_reference, + ); + visitor + .file_reference + .borrow_mut() + .add_contract(contract_ref); + visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let contract = file.items.iter().find(|item| match item { + syn_solidity::Item::Contract(contract) => true, + _ => false, + }); + let contract = match contract { + Some(syn_solidity::Item::Contract(contract)) => contract, + _ => panic!("No contract found"), + }; + let enums = contract.body.iter().find(|item| match item { + syn_solidity::Item::Enum(_) => true, + _ => false, + }); + let enums = match enums { + Some(syn_solidity::Item::Enum(enums)) => enums, + _ => panic!("No enums found"), + }; + visitor.visit_item_enum(enums); + assert_eq!( + visitor.file_reference.borrow().contracts[0] + .borrow() + .properties + .len(), + 1 + ); + } + + #[test] + fn test_retrieve_file_enums() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("enums"); + path.push("file.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let enums = file.items.iter().find(|item| match item { + syn_solidity::Item::Enum(contract) => true, + _ => false, + }); + let enums = match enums { + Some(syn_solidity::Item::Enum(var)) => var, + _ => panic!("Expect enums declaration"), + }; + visitor.visit_item_enum(enums); + assert_eq!(visitor.file_reference.borrow().enums.len(), 1); } #[test] diff --git a/libs/ast-references/tests/good.sol b/libs/ast-references/tests/contracts/contract.sol similarity index 100% rename from libs/ast-references/tests/good.sol rename to libs/ast-references/tests/contracts/contract.sol diff --git a/libs/ast-references/tests/file.sol b/libs/ast-references/tests/contracts/file.sol similarity index 100% rename from libs/ast-references/tests/file.sol rename to libs/ast-references/tests/contracts/file.sol diff --git a/libs/ast-references/tests/enums/contract.sol b/libs/ast-references/tests/enums/contract.sol new file mode 100644 index 00000000..f85c3d4b --- /dev/null +++ b/libs/ast-references/tests/enums/contract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract Good { + uint256 public x; +} diff --git a/libs/ast-references/tests/enums/file.sol b/libs/ast-references/tests/enums/file.sol new file mode 100644 index 00000000..b065d6d0 --- /dev/null +++ b/libs/ast-references/tests/enums/file.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.8.0; + +uint256 constant a = 1; diff --git a/libs/ast-references/tests/errors/contract.sol b/libs/ast-references/tests/errors/contract.sol new file mode 100644 index 00000000..f85c3d4b --- /dev/null +++ b/libs/ast-references/tests/errors/contract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract Good { + uint256 public x; +} diff --git a/libs/ast-references/tests/events/contract.sol b/libs/ast-references/tests/events/contract.sol new file mode 100644 index 00000000..f85c3d4b --- /dev/null +++ b/libs/ast-references/tests/events/contract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract Good { + uint256 public x; +} diff --git a/libs/ast-references/tests/events/file.sol b/libs/ast-references/tests/events/file.sol new file mode 100644 index 00000000..b065d6d0 --- /dev/null +++ b/libs/ast-references/tests/events/file.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.8.0; + +uint256 constant a = 1; diff --git a/libs/ast-references/tests/functions/contract.sol b/libs/ast-references/tests/functions/contract.sol new file mode 100644 index 00000000..f85c3d4b --- /dev/null +++ b/libs/ast-references/tests/functions/contract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract Good { + uint256 public x; +} diff --git a/libs/ast-references/tests/structs/contract.sol b/libs/ast-references/tests/structs/contract.sol new file mode 100644 index 00000000..f85c3d4b --- /dev/null +++ b/libs/ast-references/tests/structs/contract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract Good { + uint256 public x; +} diff --git a/libs/ast-references/tests/structs/file.sol b/libs/ast-references/tests/structs/file.sol new file mode 100644 index 00000000..b065d6d0 --- /dev/null +++ b/libs/ast-references/tests/structs/file.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.8.0; + +uint256 constant a = 1; diff --git a/libs/ast-references/tests/variables/contract.sol b/libs/ast-references/tests/variables/contract.sol new file mode 100644 index 00000000..f85c3d4b --- /dev/null +++ b/libs/ast-references/tests/variables/contract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract Good { + uint256 public x; +} diff --git a/libs/ast-references/tests/variables/file.sol b/libs/ast-references/tests/variables/file.sol new file mode 100644 index 00000000..b065d6d0 --- /dev/null +++ b/libs/ast-references/tests/variables/file.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.8.0; + +uint256 constant a = 1; From 4fcc69a05c34082f0e91e2121633e5934adaa3cd Mon Sep 17 00:00:00 2001 From: leon3108 Date: Tue, 19 Sep 2023 22:31:42 +0100 Subject: [PATCH 23/27] test: add tests --- libs/ast-references/src/file_retriever.rs | 179 ++++++++++++++++-- .../tests/contracts/contract.sol | 5 - libs/ast-references/tests/contracts/file.sol | 3 - libs/ast-references/tests/enums/contract.sol | 6 +- libs/ast-references/tests/enums/file.sol | 6 +- libs/ast-references/tests/errors/contract.sol | 2 +- libs/ast-references/tests/events/contract.sol | 2 +- libs/ast-references/tests/events/file.sol | 3 - .../tests/functions/contract.sol | 4 +- .../ast-references/tests/structs/contract.sol | 7 +- libs/ast-references/tests/structs/file.sol | 7 +- 11 files changed, 195 insertions(+), 29 deletions(-) delete mode 100644 libs/ast-references/tests/contracts/contract.sol delete mode 100644 libs/ast-references/tests/contracts/file.sol delete mode 100644 libs/ast-references/tests/events/file.sol diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index d8e8e8f7..1a37b5a7 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -401,31 +401,188 @@ mod tests { #[test] fn test_retrieve_contract_nodes_empty() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("contracts"); + path.push("file.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let contracts = file.items.iter().find(|item| match item { + syn_solidity::Item::Contract(contract) => true, + _ => false, + }); + let contracts = match contracts { + Some(syn_solidity::Item::Contract(var)) => var, + _ => panic!("Expect contracts declaration"), + }; + visitor.visit_item_contract(contracts); + assert_eq!(visitor.file_reference.borrow().contracts.len(), 1); assert_eq!(1, 0) } #[test] - fn test_retrieve_event() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); - assert_eq!(1, 0) + fn test_retrieve_contract_event() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("events"); + path.push("file.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let events = file.items.iter().find(|item| match item { + syn_solidity::Item::Event(contract) => true, + _ => false, + }); + let events = match events { + Some(syn_solidity::Item::Event(var)) => var, + _ => panic!("Expect events declaration"), + }; + visitor.visit_item_event(events); + assert_eq!(visitor.file_reference.borrow().events.len(), 1); } #[test] fn test_retrieve_functions() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); - assert_eq!(1, 0) + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("functions"); + path.push("contract.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let contract_ref = ContractReference::new( + "Good".to_string(), + Location::new(path_str, Bound { line: 1, column: 1 }, Bound::new(1, 10)), + &visitor.file_reference, + ); + visitor + .file_reference + .borrow_mut() + .add_contract(contract_ref); + visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let contract = file.items.iter().find(|item| match item { + syn_solidity::Item::Contract(contract) => true, + _ => false, + }); + let contract = match contract { + Some(syn_solidity::Item::Contract(contract)) => contract, + _ => panic!("No contract found"), + }; + let function = contract.body.iter().find(|item| match item { + syn_solidity::Item::Function(_) => true, + _ => false, + }); + let function = match function { + Some(syn_solidity::Item::Function(function)) => function, + _ => panic!("No function found"), + }; + visitor.visit_item_function(function); + assert_eq!( + visitor.file_reference.borrow().contracts[0] + .borrow() + .properties + .len(), + 1 + ); } #[test] - fn test_retrieve_structs() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); - assert_eq!(1, 0) + fn test_retrieve_contract_structs() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("structs"); + path.push("contract.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let contract_ref = ContractReference::new( + "Good".to_string(), + Location::new(path_str, Bound { line: 1, column: 1 }, Bound::new(1, 10)), + &visitor.file_reference, + ); + visitor + .file_reference + .borrow_mut() + .add_contract(contract_ref); + visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let contract = file.items.iter().find(|item| match item { + syn_solidity::Item::Contract(contract) => true, + _ => false, + }); + let contract = match contract { + Some(syn_solidity::Item::Contract(contract)) => contract, + _ => panic!("No contract found"), + }; + let structs = contract.body.iter().find(|item| match item { + syn_solidity::Item::Struct(_) => true, + _ => false, + }); + let structs = match structs { + Some(syn_solidity::Item::Struct(structs)) => structs, + _ => panic!("No structs found"), + }; + visitor.visit_item_struct(structs); + assert_eq!( + visitor.file_reference.borrow().contracts[0] + .borrow() + .properties + .len(), + 1 + ); + } + + #[test] + fn test_retrieve_file_structs() { + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("structs"); + path.push("file.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let structs = file.items.iter().find(|item| match item { + syn_solidity::Item::Struct(contract) => true, + _ => false, + }); + let structs = match structs { + Some(syn_solidity::Item::Struct(var)) => var, + _ => panic!("Expect structs declaration"), + }; + visitor.visit_item_struct(structs); + assert_eq!(visitor.file_reference.borrow().structs.len(), 1); } #[test] fn test_retrieve_errors() { - retrieve_file_reference_from_path("./tests/two.sol".to_string()); - assert_eq!(1, 0) + let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests"); + path.push("errors"); + path.push("contract.sol"); + let path_str = path.to_str().unwrap().to_string(); + let source = fs::read_to_string(&path).unwrap(); + + let mut visitor = FileVisitor::new(path_str.clone()); + let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let errors = file.items.iter().find(|item| match item { + syn_solidity::Item::Error(contract) => true, + _ => false, + }); + let errors = match errors { + Some(syn_solidity::Item::Error(var)) => var, + _ => panic!("Expect errors declaration"), + }; + visitor.visit_item_error(errors); + assert_eq!(visitor.file_reference.borrow().errors.len(), 1); } } diff --git a/libs/ast-references/tests/contracts/contract.sol b/libs/ast-references/tests/contracts/contract.sol deleted file mode 100644 index f85c3d4b..00000000 --- a/libs/ast-references/tests/contracts/contract.sol +++ /dev/null @@ -1,5 +0,0 @@ -pragma solidity ^0.8.0; - -contract Good { - uint256 public x; -} diff --git a/libs/ast-references/tests/contracts/file.sol b/libs/ast-references/tests/contracts/file.sol deleted file mode 100644 index b065d6d0..00000000 --- a/libs/ast-references/tests/contracts/file.sol +++ /dev/null @@ -1,3 +0,0 @@ -pragma solidity ^0.8.0; - -uint256 constant a = 1; diff --git a/libs/ast-references/tests/enums/contract.sol b/libs/ast-references/tests/enums/contract.sol index f85c3d4b..49d3b990 100644 --- a/libs/ast-references/tests/enums/contract.sol +++ b/libs/ast-references/tests/enums/contract.sol @@ -1,5 +1,9 @@ pragma solidity ^0.8.0; contract Good { - uint256 public x; + enum State { + Waiting, + Ready, + Active + } } diff --git a/libs/ast-references/tests/enums/file.sol b/libs/ast-references/tests/enums/file.sol index b065d6d0..42714f2d 100644 --- a/libs/ast-references/tests/enums/file.sol +++ b/libs/ast-references/tests/enums/file.sol @@ -1,3 +1,7 @@ pragma solidity ^0.8.0; -uint256 constant a = 1; +enum State { + Waiting, + Ready, + Active +} diff --git a/libs/ast-references/tests/errors/contract.sol b/libs/ast-references/tests/errors/contract.sol index f85c3d4b..ca291940 100644 --- a/libs/ast-references/tests/errors/contract.sol +++ b/libs/ast-references/tests/errors/contract.sol @@ -1,5 +1,5 @@ pragma solidity ^0.8.0; contract Good { - uint256 public x; + error InsufficientBalance(uint256 available, uint256 required); } diff --git a/libs/ast-references/tests/events/contract.sol b/libs/ast-references/tests/events/contract.sol index f85c3d4b..5d9cd154 100644 --- a/libs/ast-references/tests/events/contract.sol +++ b/libs/ast-references/tests/events/contract.sol @@ -1,5 +1,5 @@ pragma solidity ^0.8.0; contract Good { - uint256 public x; + event Deposit(address indexed _from, bytes32 indexed _id, uint256 _value); } diff --git a/libs/ast-references/tests/events/file.sol b/libs/ast-references/tests/events/file.sol deleted file mode 100644 index b065d6d0..00000000 --- a/libs/ast-references/tests/events/file.sol +++ /dev/null @@ -1,3 +0,0 @@ -pragma solidity ^0.8.0; - -uint256 constant a = 1; diff --git a/libs/ast-references/tests/functions/contract.sol b/libs/ast-references/tests/functions/contract.sol index f85c3d4b..d66927ce 100644 --- a/libs/ast-references/tests/functions/contract.sol +++ b/libs/ast-references/tests/functions/contract.sol @@ -1,5 +1,7 @@ pragma solidity ^0.8.0; contract Good { - uint256 public x; + function f() public pure returns (uint) { + return 1; + } } diff --git a/libs/ast-references/tests/structs/contract.sol b/libs/ast-references/tests/structs/contract.sol index f85c3d4b..7cb64f89 100644 --- a/libs/ast-references/tests/structs/contract.sol +++ b/libs/ast-references/tests/structs/contract.sol @@ -1,5 +1,10 @@ pragma solidity ^0.8.0; contract Good { - uint256 public x; + struct User { + uint id; + string name; + uint age; + uint balance; + } } diff --git a/libs/ast-references/tests/structs/file.sol b/libs/ast-references/tests/structs/file.sol index b065d6d0..bcc1d2c1 100644 --- a/libs/ast-references/tests/structs/file.sol +++ b/libs/ast-references/tests/structs/file.sol @@ -1,3 +1,8 @@ pragma solidity ^0.8.0; -uint256 constant a = 1; +struct User { + uint id; + string name; + uint age; + uint balance; +} From fbfd06babde424a2df33de2845160011b348f211 Mon Sep 17 00:00:00 2001 From: leon3108 Date: Wed, 20 Sep 2023 11:48:27 +0100 Subject: [PATCH 24/27] fix: 3 tests --- libs/ast-references/src/file_retriever.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 1a37b5a7..bc755546 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -370,7 +370,7 @@ mod tests { assert_eq!( visitor.file_reference.borrow().contracts[0] .borrow() - .properties + .enums .len(), 1 ); @@ -428,7 +428,7 @@ mod tests { let mut path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); path.push("tests"); path.push("events"); - path.push("file.sol"); + path.push("contract.sol"); let path_str = path.to_str().unwrap().to_string(); let source = fs::read_to_string(&path).unwrap(); @@ -458,7 +458,7 @@ mod tests { let mut visitor = FileVisitor::new(path_str.clone()); let contract_ref = ContractReference::new( "Good".to_string(), - Location::new(path_str, Bound { line: 1, column: 1 }, Bound::new(1, 10)), + Location::new(path_str, Bound { line: 1, column: 1 }, Bound::new(10, 100)), &visitor.file_reference, ); visitor @@ -487,7 +487,7 @@ mod tests { assert_eq!( visitor.file_reference.borrow().contracts[0] .borrow() - .properties + .functions .len(), 1 ); @@ -534,7 +534,7 @@ mod tests { assert_eq!( visitor.file_reference.borrow().contracts[0] .borrow() - .properties + .structs .len(), 1 ); From eaa995456227daba3a199fbddbe03793d5597faa Mon Sep 17 00:00:00 2001 From: leon3108 Date: Wed, 20 Sep 2023 16:04:20 +0100 Subject: [PATCH 25/27] test: add sol file for test --- libs/ast-references/tests/contracts/file.sol | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 libs/ast-references/tests/contracts/file.sol diff --git a/libs/ast-references/tests/contracts/file.sol b/libs/ast-references/tests/contracts/file.sol new file mode 100644 index 00000000..551bb919 --- /dev/null +++ b/libs/ast-references/tests/contracts/file.sol @@ -0,0 +1,3 @@ +pragma solidity ^0.8.0; + +contract Good {} From 7852951ae2cba4cdaa29c5b40fd766960c35abfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Maringer?= Date: Wed, 20 Sep 2023 18:14:33 +0100 Subject: [PATCH 26/27] feat(libs/ast-references): remove wrong assert in test --- libs/ast-references/src/file_retriever.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index bc755546..5d36f854 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -420,7 +420,6 @@ mod tests { }; visitor.visit_item_contract(contracts); assert_eq!(visitor.file_reference.borrow().contracts.len(), 1); - assert_eq!(1, 0) } #[test] From 7532300869f923ff0eae3bd286a04baabd1688b3 Mon Sep 17 00:00:00 2001 From: 0xMemoryGrinder <35138272+0xMemoryGrinder@users.noreply.github.com> Date: Tue, 3 Oct 2023 19:11:21 -0400 Subject: [PATCH 27/27] fix(libs/ast-references): fixed compilztion error and made tests pass --- libs/ast-references/Cargo.lock | 5 +- libs/ast-references/Cargo.toml | 1 - libs/ast-references/src/file_retriever.rs | 104 ++++++++++-------- .../src/types/contract_reference.rs | 4 +- .../src/types/error_reference.rs | 2 +- .../src/types/event_reference.rs | 2 +- .../src/types/file_reference.rs | 2 +- .../src/types/function_reference.rs | 4 +- .../src/types/variable_reference.rs | 2 +- libs/ast-references/tests/errors/contract.sol | 4 +- toolchains/solidity/linter/core/Cargo.lock | 4 +- 11 files changed, 71 insertions(+), 63 deletions(-) diff --git a/libs/ast-references/Cargo.lock b/libs/ast-references/Cargo.lock index 94c741dd..b156f712 100644 --- a/libs/ast-references/Cargo.lock +++ b/libs/ast-references/Cargo.lock @@ -19,7 +19,6 @@ version = "0.1.0" dependencies = [ "ast-extractor", "proc-macro2", - "syn-solidity", ] [[package]] @@ -59,9 +58,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397f229dc34c7b8231b6ef85502f9ca4e3425b8625e6d403bb74779e6b1917b5" +checksum = "1b8a5a633f1172a0c80b1516a988e7e8efa7ce9cededf56590f54e593e4513b3" dependencies = [ "paste", "proc-macro2", diff --git a/libs/ast-references/Cargo.toml b/libs/ast-references/Cargo.toml index 561f2234..cef452db 100644 --- a/libs/ast-references/Cargo.toml +++ b/libs/ast-references/Cargo.toml @@ -7,5 +7,4 @@ edition = "2021" [dependencies] proc-macro2 = { version = "1.0.66", features = ["span-locations"]} -syn-solidity = { version = "0.3.1", features = ["visit"] } ast-extractor = { path = "../ast-extractor"} \ No newline at end of file diff --git a/libs/ast-references/src/file_retriever.rs b/libs/ast-references/src/file_retriever.rs index 5d36f854..7efabdb1 100644 --- a/libs/ast-references/src/file_retriever.rs +++ b/libs/ast-references/src/file_retriever.rs @@ -17,7 +17,7 @@ use std::cell::RefCell; use std::fs; use std::rc::Rc; use std::str::FromStr; -use syn_solidity::{ +use ast_extractor::{ ItemContract, ItemEnum, ItemError, ItemEvent, ItemFunction, ItemStruct, Spanned, VariableDefinition, Visit, }; @@ -66,7 +66,7 @@ impl<'ast> Visit<'ast> for FileVisitor { .borrow_mut() .add_variable(variable_reference); } - syn_solidity::visit::visit_variable_definition(self, i) + ast_extractor::visit::visit_variable_definition(self, i) } fn visit_item_enum(&mut self, i: &'ast ItemEnum) { @@ -95,7 +95,7 @@ impl<'ast> Visit<'ast> for FileVisitor { } else { self.file_reference.borrow_mut().add_enum(enum_reference); } - syn_solidity::visit::visit_item_enum(self, i) + ast_extractor::visit::visit_item_enum(self, i) } fn visit_item_contract(&mut self, i: &ItemContract) { @@ -125,7 +125,7 @@ impl<'ast> Visit<'ast> for FileVisitor { .unwrap() .clone(), ); - syn_solidity::visit::visit_item_contract(self, i); + ast_extractor::visit::visit_item_contract(self, i); self.current_contract = None; } @@ -155,7 +155,7 @@ impl<'ast> Visit<'ast> for FileVisitor { } else { self.file_reference.borrow_mut().add_event(event_reference); } - syn_solidity::visit::visit_item_event(self, i) + ast_extractor::visit::visit_item_event(self, i) } fn visit_item_function(&mut self, i: &'ast ItemFunction) { @@ -182,7 +182,7 @@ impl<'ast> Visit<'ast> for FileVisitor { .borrow_mut() .add_function(&Rc::new(RefCell::new(function_reference))); } - syn_solidity::visit::visit_item_function(self, i); + ast_extractor::visit::visit_item_function(self, i); } fn visit_item_struct(&mut self, i: &'ast ItemStruct) { @@ -213,7 +213,7 @@ impl<'ast> Visit<'ast> for FileVisitor { .borrow_mut() .add_struct(struct_reference); } - syn_solidity::visit::visit_item_struct(self, i) + ast_extractor::visit::visit_item_struct(self, i) } fn visit_item_error(&mut self, i: &'ast ItemError) { @@ -242,14 +242,14 @@ impl<'ast> Visit<'ast> for FileVisitor { } else { self.file_reference.borrow_mut().add_error(error_reference); } - syn_solidity::visit::visit_item_error(self, i) + ast_extractor::visit::visit_item_error(self, i) } } pub fn retrieve_file_reference_from_path(path: String) -> Rc> { let source = fs::read_to_string(path.to_string()).unwrap(); let tokens = TokenStream::from_str(source.as_str()).unwrap(); - let ast = syn_solidity::parse2(tokens).unwrap(); + let ast = ast_extractor::parse2(tokens).unwrap(); let mut visitor = FileVisitor::new(path.to_string()); visitor.visit_file(&ast); visitor.file_reference @@ -279,21 +279,21 @@ mod tests { .borrow_mut() .add_contract(contract_ref); visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let contract = file.items.iter().find(|item| match item { - syn_solidity::Item::Contract(contract) => true, + ast_extractor::Item::Contract(_) => true, _ => false, }); let contract = match contract { - Some(syn_solidity::Item::Contract(contract)) => contract, + Some(ast_extractor::Item::Contract(contract)) => contract, _ => panic!("No contract found"), }; let variables = contract.body.iter().find(|item| match item { - syn_solidity::Item::Variable(_) => true, + ast_extractor::Item::Variable(_) => true, _ => false, }); let variables = match variables { - Some(syn_solidity::Item::Variable(variables)) => variables, + Some(ast_extractor::Item::Variable(variables)) => variables, _ => panic!("No variables found"), }; visitor.visit_variable_definition(variables); @@ -316,13 +316,13 @@ mod tests { let source = fs::read_to_string(&path).unwrap(); let mut visitor = FileVisitor::new(path_str.clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let variable = file.items.iter().find(|item| match item { - syn_solidity::Item::Variable(contract) => true, + ast_extractor::Item::Variable(_) => true, _ => false, }); let variable = match variable { - Some(syn_solidity::Item::Variable(var)) => var, + Some(ast_extractor::Item::Variable(var)) => var, _ => panic!("Expect variable declaration"), }; visitor.visit_variable_definition(variable); @@ -349,21 +349,21 @@ mod tests { .borrow_mut() .add_contract(contract_ref); visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let contract = file.items.iter().find(|item| match item { - syn_solidity::Item::Contract(contract) => true, + ast_extractor::Item::Contract(_) => true, _ => false, }); let contract = match contract { - Some(syn_solidity::Item::Contract(contract)) => contract, + Some(ast_extractor::Item::Contract(contract)) => contract, _ => panic!("No contract found"), }; let enums = contract.body.iter().find(|item| match item { - syn_solidity::Item::Enum(_) => true, + ast_extractor::Item::Enum(_) => true, _ => false, }); let enums = match enums { - Some(syn_solidity::Item::Enum(enums)) => enums, + Some(ast_extractor::Item::Enum(enums)) => enums, _ => panic!("No enums found"), }; visitor.visit_item_enum(enums); @@ -386,13 +386,13 @@ mod tests { let source = fs::read_to_string(&path).unwrap(); let mut visitor = FileVisitor::new(path_str.clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let enums = file.items.iter().find(|item| match item { - syn_solidity::Item::Enum(contract) => true, + ast_extractor::Item::Enum(_) => true, _ => false, }); let enums = match enums { - Some(syn_solidity::Item::Enum(var)) => var, + Some(ast_extractor::Item::Enum(var)) => var, _ => panic!("Expect enums declaration"), }; visitor.visit_item_enum(enums); @@ -409,13 +409,13 @@ mod tests { let source = fs::read_to_string(&path).unwrap(); let mut visitor = FileVisitor::new(path_str.clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let contracts = file.items.iter().find(|item| match item { - syn_solidity::Item::Contract(contract) => true, + ast_extractor::Item::Contract(_) => true, _ => false, }); let contracts = match contracts { - Some(syn_solidity::Item::Contract(var)) => var, + Some(ast_extractor::Item::Contract(var)) => var, _ => panic!("Expect contracts declaration"), }; visitor.visit_item_contract(contracts); @@ -432,13 +432,21 @@ mod tests { let source = fs::read_to_string(&path).unwrap(); let mut visitor = FileVisitor::new(path_str.clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); - let events = file.items.iter().find(|item| match item { - syn_solidity::Item::Event(contract) => true, + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); + let contract = file.items.iter().find(|item| match item { + ast_extractor::Item::Contract(_) => true, + _ => false, + }); + let contract = match contract { + Some(ast_extractor::Item::Contract(contract)) => contract, + _ => panic!("No contract found"), + }; + let events = contract.body.iter().find(|item| match item { + ast_extractor::Item::Event(_) => true, _ => false, }); let events = match events { - Some(syn_solidity::Item::Event(var)) => var, + Some(ast_extractor::Item::Event(var)) => var, _ => panic!("Expect events declaration"), }; visitor.visit_item_event(events); @@ -465,21 +473,21 @@ mod tests { .borrow_mut() .add_contract(contract_ref); visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let contract = file.items.iter().find(|item| match item { - syn_solidity::Item::Contract(contract) => true, + ast_extractor::Item::Contract(_) => true, _ => false, }); let contract = match contract { - Some(syn_solidity::Item::Contract(contract)) => contract, + Some(ast_extractor::Item::Contract(contract)) => contract, _ => panic!("No contract found"), }; let function = contract.body.iter().find(|item| match item { - syn_solidity::Item::Function(_) => true, + ast_extractor::Item::Function(_) => true, _ => false, }); let function = match function { - Some(syn_solidity::Item::Function(function)) => function, + Some(ast_extractor::Item::Function(function)) => function, _ => panic!("No function found"), }; visitor.visit_item_function(function); @@ -512,21 +520,21 @@ mod tests { .borrow_mut() .add_contract(contract_ref); visitor.current_contract = Some(visitor.file_reference.borrow().contracts[0].clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let contract = file.items.iter().find(|item| match item { - syn_solidity::Item::Contract(contract) => true, + ast_extractor::Item::Contract(_) => true, _ => false, }); let contract = match contract { - Some(syn_solidity::Item::Contract(contract)) => contract, + Some(ast_extractor::Item::Contract(contract)) => contract, _ => panic!("No contract found"), }; let structs = contract.body.iter().find(|item| match item { - syn_solidity::Item::Struct(_) => true, + ast_extractor::Item::Struct(_) => true, _ => false, }); let structs = match structs { - Some(syn_solidity::Item::Struct(structs)) => structs, + Some(ast_extractor::Item::Struct(structs)) => structs, _ => panic!("No structs found"), }; visitor.visit_item_struct(structs); @@ -549,13 +557,13 @@ mod tests { let source = fs::read_to_string(&path).unwrap(); let mut visitor = FileVisitor::new(path_str.clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let structs = file.items.iter().find(|item| match item { - syn_solidity::Item::Struct(contract) => true, + ast_extractor::Item::Struct(_) => true, _ => false, }); let structs = match structs { - Some(syn_solidity::Item::Struct(var)) => var, + Some(ast_extractor::Item::Struct(var)) => var, _ => panic!("Expect structs declaration"), }; visitor.visit_item_struct(structs); @@ -572,13 +580,13 @@ mod tests { let source = fs::read_to_string(&path).unwrap(); let mut visitor = FileVisitor::new(path_str.clone()); - let file = ast_extractor::extract::extract_ast_from(source).unwrap(); + let file = ast_extractor::extract::extract_ast_from_content(&source).unwrap(); let errors = file.items.iter().find(|item| match item { - syn_solidity::Item::Error(contract) => true, + ast_extractor::Item::Error(_) => true, _ => false, }); let errors = match errors { - Some(syn_solidity::Item::Error(var)) => var, + Some(ast_extractor::Item::Error(var)) => var, _ => panic!("Expect errors declaration"), }; visitor.visit_item_error(errors); diff --git a/libs/ast-references/src/types/contract_reference.rs b/libs/ast-references/src/types/contract_reference.rs index 2ff78795..819a66a4 100644 --- a/libs/ast-references/src/types/contract_reference.rs +++ b/libs/ast-references/src/types/contract_reference.rs @@ -117,7 +117,7 @@ mod tests { use std::cell::RefCell; use proc_macro2::Span; - use syn_solidity::{kw::function, Type}; + use ast_extractor::{kw::function, Type}; use crate::types::location::Bound; @@ -188,7 +188,7 @@ mod tests { ))); let function = Rc::new(RefCell::new(FunctionReference::new( "TestFunction".to_string(), - syn_solidity::FunctionKind::Function(function(proc_macro2::Span::call_site())), + ast_extractor::FunctionKind::Function(function(proc_macro2::Span::call_site())), Location::new( "File.test".to_string(), Bound { line: 0, column: 0 }, diff --git a/libs/ast-references/src/types/error_reference.rs b/libs/ast-references/src/types/error_reference.rs index d3d84363..8f48a929 100644 --- a/libs/ast-references/src/types/error_reference.rs +++ b/libs/ast-references/src/types/error_reference.rs @@ -7,7 +7,7 @@ use std::fmt; use std::rc::Rc; use std::cell::RefCell; -use syn_solidity::{Type, Storage}; +use ast_extractor::{Type, Storage}; use crate::types::location::Location; use crate::types::file_reference::FileReference; use crate::types::contract_reference::ContractReference; diff --git a/libs/ast-references/src/types/event_reference.rs b/libs/ast-references/src/types/event_reference.rs index da23bcc8..b525c3ad 100644 --- a/libs/ast-references/src/types/event_reference.rs +++ b/libs/ast-references/src/types/event_reference.rs @@ -7,7 +7,7 @@ use std::fmt; use std::rc::Rc; use std::cell::RefCell; -use syn_solidity::{Type, Storage}; +use ast_extractor::{Type, Storage}; use crate::types::location::Location; use crate::types::file_reference::FileReference; use crate::types::contract_reference::ContractReference; diff --git a/libs/ast-references/src/types/file_reference.rs b/libs/ast-references/src/types/file_reference.rs index e0d572e4..83a51642 100644 --- a/libs/ast-references/src/types/file_reference.rs +++ b/libs/ast-references/src/types/file_reference.rs @@ -106,7 +106,7 @@ impl Hash for FileReference { mod tests { use std::cell::RefCell; use proc_macro2::Span; - use syn_solidity::Type; + use ast_extractor::Type; use crate::types::location::{Bound, Location}; diff --git a/libs/ast-references/src/types/function_reference.rs b/libs/ast-references/src/types/function_reference.rs index 24f3d082..bda6123d 100644 --- a/libs/ast-references/src/types/function_reference.rs +++ b/libs/ast-references/src/types/function_reference.rs @@ -7,7 +7,7 @@ use std::cell::RefCell; use std::fmt; use std::rc::Rc; -use syn_solidity::FunctionKind; +use ast_extractor::FunctionKind; use crate::types::location::Location; use crate::types::contract_reference::ContractReference; @@ -64,7 +64,7 @@ impl PartialEq for FunctionReference { mod tests { use std::cell::RefCell; use proc_macro2::Span; - use syn_solidity::kw::function; + use ast_extractor::kw::function; use crate::types::{location::{Bound, Location}, file_reference::FileReference}; diff --git a/libs/ast-references/src/types/variable_reference.rs b/libs/ast-references/src/types/variable_reference.rs index aa54f13a..861a7a7d 100644 --- a/libs/ast-references/src/types/variable_reference.rs +++ b/libs/ast-references/src/types/variable_reference.rs @@ -7,7 +7,7 @@ use std::fmt; use std::rc::Rc; use std::cell::RefCell; -use syn_solidity::Type; +use ast_extractor::Type; use crate::types::location::Location; use crate::types::contract_reference::ContractReference; diff --git a/libs/ast-references/tests/errors/contract.sol b/libs/ast-references/tests/errors/contract.sol index ca291940..194c9853 100644 --- a/libs/ast-references/tests/errors/contract.sol +++ b/libs/ast-references/tests/errors/contract.sol @@ -1,5 +1,7 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +error InsufficientBalance(uint256 available, uint256 required); + contract Good { - error InsufficientBalance(uint256 available, uint256 required); } diff --git a/toolchains/solidity/linter/core/Cargo.lock b/toolchains/solidity/linter/core/Cargo.lock index 715f9323..0d21a114 100644 --- a/toolchains/solidity/linter/core/Cargo.lock +++ b/toolchains/solidity/linter/core/Cargo.lock @@ -631,9 +631,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397f229dc34c7b8231b6ef85502f9ca4e3425b8625e6d403bb74779e6b1917b5" +checksum = "1b8a5a633f1172a0c80b1516a988e7e8efa7ce9cededf56590f54e593e4513b3" dependencies = [ "paste", "proc-macro2",