This repository has been archived by the owner on Jul 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip(solidity/core/solc-references): in the name
- Loading branch information
1 parent
6ab8aff
commit d4d7ac1
Showing
16 changed files
with
702 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} | ||
} |
Oops, something went wrong.