Skip to content

Commit

Permalink
Adding using fors
Browse files Browse the repository at this point in the history
  • Loading branch information
beta-ziliani committed Dec 13, 2024
1 parent 98126a2 commit 873c856
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 8 additions & 5 deletions crates/solidity/testing/sanctuary/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -192,22 +194,23 @@ 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();
let metrics = metrics_guard.as_slice();
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,
Expand Down
125 changes: 88 additions & 37 deletions crates/solidity/testing/sanctuary/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Vec<String>>,
#[derive(Debug)]
struct HeritageGraphNode {
parents: Vec<String>,
using_fors: usize,
}
struct MetricsGraph {
graph: HashMap<String, HeritageGraphNode>,
}

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<String> {
&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)
}
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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<Version> {
if compiler.starts_with("vyper:") {
// Ignore contracts not compiled by "solc":
Expand Down

0 comments on commit 873c856

Please sign in to comment.