From 873c856398ba486c1e1b69ecca2f232fe405d4f6 Mon Sep 17 00:00:00 2001 From: Beta Ziliani Date: Fri, 13 Dec 2024 15:24:12 -0300 Subject: [PATCH] Adding using fors --- .../sanctuary/src/counting_allocator.rs | 1 + .../solidity/testing/sanctuary/src/events.rs | 13 +- .../solidity/testing/sanctuary/src/tests.rs | 125 ++++++++++++------ 3 files changed, 97 insertions(+), 42 deletions(-) diff --git a/crates/solidity/testing/sanctuary/src/counting_allocator.rs b/crates/solidity/testing/sanctuary/src/counting_allocator.rs index bf2804ff28..4f99b8f0b5 100644 --- a/crates/solidity/testing/sanctuary/src/counting_allocator.rs +++ b/crates/solidity/testing/sanctuary/src/counting_allocator.rs @@ -4,6 +4,7 @@ use std::sync::atomic::Ordering::Relaxed; pub struct CountingAlloc; #[cfg_attr(feature = "mem_profiler", global_allocator)] +#[allow(dead_code)] static COUNTING_ALLOCATOR: CountingAlloc = CountingAlloc; static ALLOCATED: AtomicUsize = AtomicUsize::new(0); diff --git a/crates/solidity/testing/sanctuary/src/events.rs b/crates/solidity/testing/sanctuary/src/events.rs index f879dab384..b75fc4f166 100644 --- a/crates/solidity/testing/sanctuary/src/events.rs +++ b/crates/solidity/testing/sanctuary/src/events.rs @@ -26,8 +26,9 @@ pub(crate) struct Metric { pub locs: usize, pub number_of_contracts: usize, pub total_inheritance_count: usize, - pub max_inheritance_count: usize, + pub inheritance_tree_height: usize, pub cst_height: usize, + pub number_of_using_fors: usize, pub number_of_nodes: usize, pub without_trivia: usize, pub number_of_refs: usize, @@ -44,8 +45,9 @@ impl Metric { locs: 0, number_of_contracts: 0, total_inheritance_count: 0, - max_inheritance_count: 0, + inheritance_tree_height: 0, cst_height: 0, + number_of_using_fors: 0, number_of_nodes: 0, without_trivia: 0, number_of_refs: 0, @@ -192,7 +194,7 @@ impl Events { }; writeln!( writer, - "file,bytes,locs,number_of_contracts,total_inheritance_count,max_inheritance_count,cst_height,number_of_nodes,without_trivia,number_of_refs,parsing_time,bindings_time,memory_usage" + "file,bytes,locs,number_of_contracts,total_inheritance_count,inheritance_tree_height,cst_height,using_fors,number_of_nodes,without_trivia,number_of_refs,parsing_time,bindings_time,memory_usage" )?; let metrics_guard = self.metrics.lock().unwrap(); @@ -200,14 +202,15 @@ impl Events { for metric in metrics { writeln!( writer, - "{},{},{},{},{},{},{},{},{},{},{},{},{}", + "{},{},{},{},{},{},{},{},{},{},{},{},{},{}", metric.file, metric.bytes, metric.locs, metric.number_of_contracts, metric.total_inheritance_count, - metric.max_inheritance_count, + metric.inheritance_tree_height, metric.cst_height, + metric.number_of_using_fors, metric.number_of_nodes, metric.without_trivia, metric.number_of_refs, diff --git a/crates/solidity/testing/sanctuary/src/tests.rs b/crates/solidity/testing/sanctuary/src/tests.rs index ded6de0d08..683c79a5a8 100644 --- a/crates/solidity/testing/sanctuary/src/tests.rs +++ b/crates/solidity/testing/sanctuary/src/tests.rs @@ -88,45 +88,81 @@ fn nodes(edges: &[Edge]) -> (usize, usize) { (nodes_count, without_trivia) } -fn hierarchy_height() -> usize { - 0 -} - fn locs(source: &str) -> usize { source.split('\n').count() } -struct HeritageGraph { - graph: HashMap>, +#[derive(Debug)] +struct HeritageGraphNode { + parents: Vec, + using_fors: usize, +} +struct MetricsGraph { + graph: HashMap, } -impl HeritageGraph { - pub(crate) fn new() -> HeritageGraph { - HeritageGraph { +impl HeritageGraphNode { + pub fn new() -> Self { + HeritageGraphNode { + parents: vec![], + using_fors: 0, + } + } + + pub fn push_parent(&mut self, parent: String) { + self.parents.push(parent); + } + + pub fn parents(&self) -> &Vec { + &self.parents + } +} +impl MetricsGraph { + pub(crate) fn new() -> MetricsGraph { + MetricsGraph { graph: HashMap::new(), } } pub(crate) fn add_contract(&mut self, name: String) { - self.graph.entry(name).or_insert(vec![]); + self.graph.entry(name).or_insert(HeritageGraphNode::new()); } pub(crate) fn add_link(&mut self, name: String, parent: String) { - self.graph.entry(name).and_modify(|v| v.push(parent)); + self.add_contract(parent.clone()); + self.graph.entry(name).and_modify(|v| v.push_parent(parent)); + } + + pub(crate) fn add_using_for(&mut self, name: String) { + self.graph.entry(name).and_modify(|v| v.using_fors += 1); } pub(crate) fn number_of_contracts(&self) -> usize { self.graph.keys().count() } - pub(crate) fn heritage_count(&self) -> usize { - self.graph.values().map(|v| v.len()).sum() + pub(crate) fn inheritance_count(&self) -> usize { + self.graph.values().map(|v| v.parents().len()).sum() } - pub(crate) fn heritage_avg(&self) -> usize { + pub(crate) fn number_of_using_fors(&self) -> usize { + self.graph.values().map(|v| v.using_fors).sum() + } + + fn node_height(&self, name: &String) -> usize { + let node = self.graph.get(name).unwrap(); + let mut height = 0; + for parent in node.parents() { + let parent_height = self.node_height(parent); + height = height.max(parent_height + 1); + } + height + } + + pub(crate) fn inheritance_height(&self) -> usize { self.graph .keys() - .map(|k| self.graph.get(k).unwrap().len()) + .map(|contract| self.node_height(contract)) .max() .unwrap_or(0) } @@ -208,30 +244,12 @@ pub fn run_test( metric.bytes = source.len(); metric.locs = locs(&source); - let mut graph = HeritageGraph::new(); - let query1 = Query::parse("[ContractDefinition @contract_name name:[Identifier]]").unwrap(); - let query2 = - Query::parse("[InterfaceDefinition @contract_name name:[Identifier]]").unwrap(); - let query3 = Query::parse("[ContractDefinition @contract_name name:[Identifier] inheritance:[InheritanceSpecifier types:[InheritanceTypes @types (item:[InheritanceType])+]]]").unwrap(); - let query4 = Query::parse("[InterfaceDefinition @contract_name name:[Identifier] inheritance:[InheritanceSpecifier types:[InheritanceTypes @types (item:[InheritanceType])+]]]").unwrap(); - let query_match = output - .create_tree_cursor() - .query(vec![query1, query2, query3, query4]); - - for q in query_match { - let (_, mut it) = q.capture("contract_name").unwrap(); - let contract_name = it.next().unwrap().node().unparse(); - if let Some((_, mut it)) = q.capture("types") { - let is_type = it.next().unwrap().node().unparse(); - graph.add_link(contract_name, is_type); - } else { - graph.add_contract(contract_name); - } - } + let graph = build_graph(&output); metric.number_of_contracts = graph.number_of_contracts(); - metric.total_inheritance_count = graph.heritage_count(); - metric.max_inheritance_count = graph.heritage_avg(); + metric.total_inheritance_count = graph.inheritance_count(); + metric.inheritance_tree_height = graph.inheritance_height(); + metric.number_of_using_fors = graph.number_of_using_fors(); metric.cst_height = height(output.tree().children()); let (nodes, without_trivia) = nodes(output.tree().children()); @@ -266,6 +284,39 @@ pub fn run_test( Ok(()) } +fn build_graph(output: &ParseOutput) -> MetricsGraph { + let mut graph = MetricsGraph::new(); + let query1 = Query::parse("[ContractDefinition @contract_name name:[Identifier]]").unwrap(); + let query2 = Query::parse("[InterfaceDefinition @contract_name name:[Identifier]]").unwrap(); + let query3 = Query::parse("[ContractDefinition @contract_name name:[Identifier] inheritance:[InheritanceSpecifier types:[InheritanceTypes @types (item:[InheritanceType])+]]]").unwrap(); + let query4 = Query::parse("[InterfaceDefinition @contract_name name:[Identifier] inheritance:[InheritanceSpecifier types:[InheritanceTypes @types (item:[InheritanceType])+]]]").unwrap(); + let query5 = Query::parse("[ContractDefinition @contract_name name:[Identifier] [ContractMembers item:[ContractMember @using (variant:[UsingDirective])+]]]").unwrap(); + let query_match = output + .create_tree_cursor() + .query(vec![query1, query2, query3, query4, query5]); + + for q in query_match { + let (_, mut it) = q.capture("contract_name").unwrap(); + let contract_name = it.next().unwrap().node().unparse(); + graph.add_contract(contract_name.clone()); + if let Some((_, mut it)) = q.capture("types") { + let is_type = it.next().unwrap().node(); + let mut is_type = is_type.children().iter().filter(|p| !p.is_trivia()); + let next = is_type.next().unwrap(); + let remaining = next + .children() + .iter() + .filter(|n| !n.is_trivia()) + .collect_vec(); + assert_eq!(remaining.len(), 1); + graph.add_link(contract_name, remaining.first().unwrap().unparse()); + } else if q.capture("using").is_some() { + graph.add_using_for(contract_name); + } + } + graph +} + fn extract_compiler_version(compiler: &str) -> Option { if compiler.starts_with("vyper:") { // Ignore contracts not compiled by "solc":