Skip to content
This repository has been archived by the owner on Jul 3, 2024. It is now read-only.

Commit

Permalink
wip(solidity/core/solc-references): in the name
Browse files Browse the repository at this point in the history
  • Loading branch information
0xSwapFeeder committed Feb 9, 2024
1 parent 6ab8aff commit d4d7ac1
Show file tree
Hide file tree
Showing 16 changed files with 702 additions and 6 deletions.
11 changes: 11 additions & 0 deletions libs/solc-references/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "solc-references"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
solc-ast-rs-types = { version = "0.1.1", features = ["visit"]}
solc-wrapper = { path="../solc-wrapper" }
thiserror = "1.0.56"
78 changes: 78 additions & 0 deletions libs/solc-references/src/definitions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

use solc_ast_rs_types::types::*;
use solc_ast_rs_types::visit;
use solc_ast_rs_types::visit::*;
use crate::types::InteractableNode;

struct DefinitionFinder {
id: i64,
token: String,
node: Option<InteractableNode>,
to_find: Option<InteractableNode>,
}

impl <'ast> Visit<'ast> for DefinitionFinder {
fn visit_contract_definition(&mut self, contract: &'ast ContractDefinition) {
if contract.id == self.id {
self.node = Some(InteractableNode::ContractDefinition(contract.clone()));
}
visit::visit_contract_definition(self, contract);
}
fn visit_function_definition(&mut self, function: &'ast FunctionDefinition) {
if function.id == self.id {
self.node = Some(InteractableNode::FunctionDefinition(function.clone()));
}
visit::visit_function_definition(self, function);
}
fn visit_modifier_definition(&mut self, modifier: &'ast ModifierDefinition) {
if modifier.id == self.id {
self.node = Some(InteractableNode::ModifierDefinition(modifier.clone()));
}
visit::visit_modifier_definition(self, modifier);
}
fn visit_struct_definition(&mut self, struct_def: &'ast StructDefinition) {
if struct_def.id == self.id {
self.node = Some(InteractableNode::StructDefinition(struct_def.clone()));
}
visit::visit_struct_definition(self, struct_def);
}
fn visit_enum_definition(&mut self, enum_def: &'ast EnumDefinition) {
if enum_def.id == self.id {
self.node = Some(InteractableNode::EnumDefinition(enum_def.clone()));
}
visit::visit_enum_definition(self, enum_def);
}
fn visit_variable_declaration(&mut self, variable: &'ast VariableDeclaration) {
if variable.id == self.id {
self.node = Some(InteractableNode::VariableDeclaration(variable.clone()));
}
visit::visit_variable_declaration(self, variable);
}
fn visit_event_definition(&mut self, event: &'ast EventDefinition) {
if event.id == self.id {
self.node = Some(InteractableNode::EventDefinition(event.clone()));
}
visit::visit_event_definition(self, event);
}
fn visit_enum_value(&mut self, enum_value: &'ast EnumValue) {
if enum_value.id == self.id {
self.node = Some(InteractableNode::EnumValue(enum_value.clone()));
}
visit::visit_enum_value(self, enum_value);
}
}

impl DefinitionFinder {
pub fn new(id: i64, token: String) -> Self {
DefinitionFinder {
id,
token,
node: None,
to_find: None,
}
}
pub fn find(&mut self, src: SourceUnit) -> Option<InteractableNode> {
self.visit_source_unit(&src);
self.node.clone()
}
}
8 changes: 8 additions & 0 deletions libs/solc-references/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use thiserror::Error;
use solc_wrapper::SolcWrapperError;

#[derive(Error, Debug)]
pub enum ReferencesError {
#[error("Solc error: {0}")]
Solc(#[from] SolcWrapperError)
}
67 changes: 67 additions & 0 deletions libs/solc-references/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#[macro_use]
mod types;
mod error;
mod definitions;
mod usages;
mod node_finder;
mod utils;

use error::ReferencesError;
use node_finder::NodeVisitor;
use solc_wrapper::{command::SolcCommand, get_ast_from_solc_output, SolcAstFile};
pub use solc_ast_rs_types::types::*;
use types::{InteractableNode, Position};
use usages::UsagesFinder;


pub struct ReferencesProvider {
files: Vec<SolcAstFile>
}

impl ReferencesProvider {
pub fn update_file_content(&mut self, filepath: String, content: String) -> Result<(), ReferencesError> {
let solc = SolcCommand::new(filepath);
let out = solc.execute_with_input(&content)?;
let out = String::from_utf8_lossy(&out.stdout);
let ast_files = get_ast_from_solc_output(&out)?;
for res_file in &ast_files {
let mut found = false;
for file in &mut self.files {
if file.file == res_file.file {
found = true;
file.ast = res_file.ast.clone();
break;
}
}
if found == false {
self.files.push(res_file.clone());
}
}
Ok(())
}

pub fn get_references(&self, position: Position) -> Vec<(Position, Position)> {
let mut references: Vec<(Position, Position)> = Vec::new();
let mut node: InteractableNode;
let mut node_finder = NodeVisitor::new(position);
for file in &self.files {
node_finder.find(file.ast);
if let Some(node) = node_finder.node {
node = node.clone();
break;
}
}
let mut usages_finder = UsagesFinder {
id: get_id!(node),
token: get_name!(node),
to_find: references,
};
for file in &self.files {
let nodes = usages_finder.find(&file.ast);
for node in nodes {
references.push(node);
}
}
references
}
}
173 changes: 173 additions & 0 deletions libs/solc-references/src/node_finder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use solc_ast_rs_types::types::*;
use solc_ast_rs_types::visit;
use solc_ast_rs_types::visit::*;
use crate::types::{InteractableNode, Position};
use crate::utils::*;

pub struct NodeVisitor {
position: Position,
pub node: Option<InteractableNode>,
above_node: Option<InteractableNode>
}

impl <'ast> Visit<'ast> for NodeVisitor {

fn visit_contract_definition(&mut self,contract: &'ast ContractDefinition) {
if is_node_in_range(&contract.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::ContractDefinition(contract.clone()));
}
visit::visit_contract_definition(self, contract);
}

fn visit_function_definition(&mut self, function: &'ast FunctionDefinition) {
if is_node_in_range(&function.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::FunctionDefinition(function.clone()));
}
visit::visit_function_definition(self, function);
}

fn visit_modifier_definition(&mut self, modifier: &'ast ModifierDefinition) {
if is_node_in_range(&modifier.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::ModifierDefinition(modifier.clone()));
}
visit::visit_modifier_definition(self, modifier);
}

fn visit_struct_definition(&mut self, struct_def: &'ast StructDefinition) {
if is_node_in_range(&struct_def.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::StructDefinition(struct_def.clone()));
}
visit::visit_struct_definition(self, struct_def);
}

fn visit_enum_definition(&mut self, enum_def: &'ast EnumDefinition) {
if is_node_in_range(&enum_def.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::EnumDefinition(enum_def.clone()));
}
visit::visit_enum_definition(self, enum_def);
}

fn visit_variable_declaration(&mut self, variable: &'ast VariableDeclaration) {
if is_node_in_range(&variable.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::VariableDeclaration(variable.clone()));
}
visit::visit_variable_declaration(self, variable);
}

fn visit_event_definition(&mut self, event: &'ast EventDefinition) {
if is_node_in_range(&event.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::EventDefinition(event.clone()));
}
visit::visit_event_definition(self, event);
}

fn visit_enum_value(&mut self, enum_value: &'ast EnumValue) {
if is_node_in_range(&enum_value.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::EnumValue(enum_value.clone()));
}
visit::visit_enum_value(self, enum_value);
}

fn visit_using_for_directive(&mut self, using_for: &'ast UsingForDirective) {
if is_node_in_range(&using_for.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::UsingForDirective(using_for.clone()));
}
visit::visit_using_for_directive(self, using_for);
}

fn visit_import_directive(&mut self, import: &'ast ImportDirective) {
if is_node_in_range(&import.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::ImportDirective(import.clone()));
}
visit::visit_import_directive(self, import);
}

fn visit_error_definition(&mut self, error: &'ast ErrorDefinition) {
if is_node_in_range(&error.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::ErrorDefinition(error.clone()));
}
visit::visit_error_definition(self, error);
}

fn visit_function_call(&mut self, function_call: &'ast FunctionCall) {
if is_node_in_range(&function_call.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::FunctionCall(function_call.clone()));
}
visit::visit_function_call(self, function_call);
}

fn visit_modifier_invocation(&mut self, modifier_invocation: &'ast ModifierInvocation) {
if is_node_in_range(&modifier_invocation.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::ModifierInvocation(modifier_invocation.clone()));
}
visit::visit_modifier_invocation(self, modifier_invocation);
}

fn visit_inheritance_specifier(&mut self, inheritance_specifier: &'ast InheritanceSpecifier) {
if is_node_in_range(&inheritance_specifier.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::InheritanceSpecifier(inheritance_specifier.clone()));
}
visit::visit_inheritance_specifier(self, inheritance_specifier);
}

fn visit_variable_declaration_statement(&mut self, variable_declaration_statement: &'ast VariableDeclarationStatement) {
if is_node_in_range(&variable_declaration_statement.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::VariableDeclarationStatement(variable_declaration_statement.clone()));
}
visit::visit_variable_declaration_statement(self, variable_declaration_statement);
}

fn visit_identifier(&mut self, identifier: &'ast Identifier) {
if is_node_in_range(&identifier.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::Identifier(identifier.clone(), Box::new(self.above_node.clone().unwrap())));
}
visit::visit_identifier(self, identifier);
}

fn visit_member_access(&mut self, member_access: &'ast MemberAccess) {
if is_node_in_range(&member_access.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::MemberAccess(member_access.clone()));
}
visit::visit_member_access(self, member_access);
}

fn visit_new(&mut self, new_expression: &'ast NewExpression) {
if is_node_in_range(&new_expression.src, &self.position) {
self.above_node = self.node.clone();
self.node = Some(InteractableNode::NewExpression(new_expression.clone(), Box::new(self.above_node.clone().unwrap())));
}
visit::visit_new(self, new_expression);
}
}


impl NodeVisitor {
pub fn new(position: Position) -> Self {
NodeVisitor {
position,
node: None,
above_node: None
}
}
pub fn find(&mut self, src: SourceUnit) -> Option<InteractableNode> {
self.visit_source_unit(&src);
self.node.clone()
}
}
Loading

0 comments on commit d4d7ac1

Please sign in to comment.