Skip to content

Commit

Permalink
Approval testing for the Analyzer.
Browse files Browse the repository at this point in the history
  • Loading branch information
g-r-a-n-t committed May 4, 2021
1 parent 38b2264 commit 525aa09
Show file tree
Hide file tree
Showing 219 changed files with 117,696 additions and 552 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions analyzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ strum = { version = "0.20.0", features = ["derive"] }
lexical-core = "0.7.6"

[dev-dependencies]
insta = "1.7.1"
rstest = "0.6.4"
2 changes: 1 addition & 1 deletion analyzer/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub enum ValueMethod {
AbiEncodePacked,
}

#[derive(Clone, Debug, PartialEq, EnumString, IntoStaticStr)]
#[derive(Clone, Debug, PartialEq, EnumString, IntoStaticStr, Hash)]
#[strum(serialize_all = "snake_case")]
pub enum GlobalMethod {
Keccak256,
Expand Down
191 changes: 144 additions & 47 deletions analyzer/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ use crate::errors::SemanticError;
use crate::namespace::events::EventDef;
use crate::namespace::scopes::{ContractFunctionDef, ContractScope, ModuleScope, Shared};
use crate::namespace::types::{Contract, FixedSize, Struct, Tuple, Type};
use fe_parser::node::NodeId;
use fe_common::Span;
use fe_parser::ast as fe;
use fe_parser::node::{Node, NodeId};
use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;

/// Indicates where an expression is stored.
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Hash)]
pub enum Location {
/// A storage value may not have a nonce known at compile time, so it is
/// optional.
Expand Down Expand Up @@ -37,7 +41,7 @@ impl Location {
}

/// Contains contextual information relating to a contract AST node.
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Hash)]
pub struct ContractAttributes {
/// Public functions that have been defined by the user.
pub public_functions: Vec<FunctionAttributes>,
Expand All @@ -46,13 +50,13 @@ pub struct ContractAttributes {
/// Events that have been defined by the user.
pub events: Vec<EventDef>,
/// Static strings that the contract defines
pub string_literals: HashSet<String>,
pub string_literals: BTreeSet<String>,
/// Structs that have been defined by the user
pub structs: Vec<Struct>,
/// External contracts that may be called from within this contract.
pub external_contracts: Vec<Contract>,
/// Names of contracts that have been created inside of this contract.
pub created_contracts: HashSet<String>,
pub created_contracts: BTreeSet<String>,
}

impl From<Shared<ContractScope>> for ContractAttributes {
Expand Down Expand Up @@ -121,7 +125,7 @@ impl From<Shared<ContractScope>> for ContractAttributes {
}

/// Contains contextual information relating to an expression AST node.
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Hash)]
pub struct ExpressionAttributes {
pub typ: Type,
pub location: Location,
Expand Down Expand Up @@ -215,7 +219,7 @@ impl ExpressionAttributes {
}

/// The type of a function call.
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Hash)]
pub enum CallType {
BuiltinFunction { func: GlobalMethod },
TypeConstructor { typ: Type },
Expand All @@ -225,7 +229,7 @@ pub enum CallType {
}

/// Contains contextual information relating to a function definition AST node.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct FunctionAttributes {
pub is_public: bool,
pub name: String,
Expand Down Expand Up @@ -260,7 +264,7 @@ impl From<ContractFunctionDef> for FunctionAttributes {
#[derive(Clone, Debug, PartialEq)]
pub struct ModuleAttributes {
/// Type definitions in a module.
pub type_defs: HashMap<String, Type>,
pub type_defs: BTreeMap<String, Type>,
/// Tuples that were used inside of a module.
///
/// BTreeSet is used for ordering, this way items are retrieved in the same order every time.
Expand All @@ -280,14 +284,18 @@ impl From<Shared<ModuleScope>> for ModuleAttributes {
/// `Spanned` AST nodes.
#[derive(Clone, Debug, Default)]
pub struct Context {
pub expressions: HashMap<NodeId, ExpressionAttributes>,
pub emits: HashMap<NodeId, EventDef>,
pub functions: HashMap<NodeId, FunctionAttributes>,
pub declarations: HashMap<NodeId, FixedSize>,
pub contracts: HashMap<NodeId, ContractAttributes>,
pub calls: HashMap<NodeId, CallType>,
pub events: HashMap<NodeId, EventDef>,
pub type_descs: HashMap<NodeId, Type>,
/// Node ids in the order they were visited.
pub node_ids: Vec<NodeId>,
/// The span of a given node id.
pub spans: BTreeMap<NodeId, Span>,
pub expressions: BTreeMap<NodeId, ExpressionAttributes>,
pub emits: BTreeMap<NodeId, EventDef>,
pub functions: BTreeMap<NodeId, FunctionAttributes>,
pub declarations: BTreeMap<NodeId, FixedSize>,
pub contracts: BTreeMap<NodeId, ContractAttributes>,
pub calls: BTreeMap<NodeId, CallType>,
pub events: BTreeMap<NodeId, EventDef>,
pub type_descs: BTreeMap<NodeId, Type>,
pub module: Option<ModuleAttributes>,
}

Expand All @@ -298,25 +306,19 @@ impl Context {

pub fn new() -> Self {
Context {
expressions: HashMap::new(),
emits: HashMap::new(),
functions: HashMap::new(),
declarations: HashMap::new(),
contracts: HashMap::new(),
calls: HashMap::new(),
events: HashMap::new(),
type_descs: HashMap::new(),
module: None,
..Default::default()
}
}

fn add_node<T>(&mut self, node: &Node<T>) {
self.node_ids.push(node.id);
self.spans.insert(node.id, node.span);
}

/// Attribute contextual information to an expression node.
pub fn add_expression<T: Into<NodeId>>(
&mut self,
node_id: T,
attributes: ExpressionAttributes,
) {
self.expressions.insert(node_id.into(), attributes);
pub fn add_expression(&mut self, node: &Node<fe::Expr>, attributes: ExpressionAttributes) {
self.add_node(node);
self.expressions.insert(node.id, attributes);
}

/// Get information that has been attributed to an expression node.
Expand All @@ -325,8 +327,9 @@ impl Context {
}

/// Attribute contextual information to an emit statement node.
pub fn add_emit<T: Into<NodeId>>(&mut self, node_id: T, event: EventDef) {
self.emits.insert(node_id.into(), event);
pub fn add_emit(&mut self, node: &Node<fe::FuncStmt>, event: EventDef) {
self.add_node(node);
self.emits.insert(node.id, event);
}

/// Get information that has been attributed to an emit statement node.
Expand All @@ -335,8 +338,9 @@ impl Context {
}

/// Attribute contextual information to a function definition node.
pub fn add_function<T: Into<NodeId>>(&mut self, node_id: T, attributes: FunctionAttributes) {
self.functions.insert(node_id.into(), attributes);
pub fn add_function(&mut self, node: &Node<fe::ContractStmt>, attributes: FunctionAttributes) {
self.add_node(node);
self.functions.insert(node.id, attributes);
}

/// Get information that has been attributed to a function definition node.
Expand All @@ -345,8 +349,9 @@ impl Context {
}

/// Attribute contextual information to a declaration node.
pub fn add_declaration<T: Into<NodeId>>(&mut self, node_id: T, typ: FixedSize) {
self.declarations.insert(node_id.into(), typ);
pub fn add_declaration(&mut self, node: &Node<fe::FuncStmt>, typ: FixedSize) {
self.add_node(node);
self.declarations.insert(node.id, typ);
}

/// Get information that has been attributed to a declaration node.
Expand All @@ -355,8 +360,9 @@ impl Context {
}

/// Attribute contextual information to a contract definition node.
pub fn add_contract<T: Into<NodeId>>(&mut self, node_id: T, attributes: ContractAttributes) {
self.contracts.insert(node_id.into(), attributes);
pub fn add_contract(&mut self, node: &Node<fe::ModuleStmt>, attributes: ContractAttributes) {
self.add_node(node);
self.contracts.insert(node.id, attributes);
}

/// Get information that has been attributed to a contract definition node.
Expand All @@ -365,8 +371,9 @@ impl Context {
}

/// Attribute contextual information to a call expression node.
pub fn add_call<T: Into<NodeId>>(&mut self, node_id: T, call_type: CallType) {
self.calls.insert(node_id.into(), call_type);
pub fn add_call(&mut self, node: &Node<fe::Expr>, call_type: CallType) {
self.add_node(node);
self.calls.insert(node.id, call_type);
}

/// Get information that has been attributed to a call expression node.
Expand All @@ -375,8 +382,9 @@ impl Context {
}

/// Attribute contextual information to an event definition node.
pub fn add_event<T: Into<NodeId>>(&mut self, node_id: T, event: EventDef) {
self.events.insert(node_id.into(), event);
pub fn add_event(&mut self, node: &Node<fe::ContractStmt>, event: EventDef) {
self.add_node(node);
self.events.insert(node.id, event);
}

/// Get information that has been attributed to an event definition node.
Expand All @@ -385,8 +393,9 @@ impl Context {
}

/// Attribute contextual information to a type description node.
pub fn add_type_desc<T: Into<NodeId>>(&mut self, node_id: T, typ: Type) {
self.type_descs.insert(node_id.into(), typ);
pub fn add_type_desc(&mut self, node: &Node<fe::TypeDesc>, typ: Type) {
self.add_node(node);
self.type_descs.insert(node.id, typ);
}

/// Get information that has been attributed to a type description node.
Expand All @@ -403,4 +412,92 @@ impl Context {
pub fn get_module(&self) -> Option<&ModuleAttributes> {
self.module.as_ref()
}

/// Get the span and attributes of all expressions.
pub fn get_spanned_expressions(&self) -> Vec<(Span, ExpressionAttributes)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_expression(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all emits.
pub fn get_spanned_emits(&self) -> Vec<(Span, EventDef)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_emit(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all functions.
pub fn get_spanned_functions(&self) -> Vec<(Span, FunctionAttributes)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_function(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all declarations.
pub fn get_spanned_declarations(&self) -> Vec<(Span, FixedSize)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_declaration(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all contracts.
pub fn get_spanned_contracts(&self) -> Vec<(Span, ContractAttributes)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_contract(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all calls.
pub fn get_spanned_calls(&self) -> Vec<(Span, CallType)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_call(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all events.
pub fn get_spanned_events(&self) -> Vec<(Span, EventDef)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_event(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}

/// Get the span and attributes of all type descs.
pub fn get_spanned_type_descs(&self) -> Vec<(Span, Type)> {
self.node_ids
.iter()
.filter_map(|node_id| {
self.get_type_desc(*node_id)
.map(|attributes| (self.spans[node_id], attributes.to_owned()))
})
.collect::<Vec<_>>()
}
}
2 changes: 1 addition & 1 deletion analyzer/src/namespace/events.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::namespace::types::{AbiEncoding, FixedSize};
use fe_common::utils::keccak;

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Hash)]
pub struct EventDef {
pub name: String,
pub topic: String,
Expand Down
Loading

0 comments on commit 525aa09

Please sign in to comment.