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

Commit

Permalink
feat: poc of compiler support
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmemorygrinder committed Nov 15, 2023
1 parent b1e79b5 commit 2b035f3
Show file tree
Hide file tree
Showing 28 changed files with 16,003 additions and 512 deletions.
7,063 changes: 7,063 additions & 0 deletions libs/foundry-wrapper/Cargo.lock

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions libs/foundry-wrapper/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[package]
name = "osmium-libs-foundry-wrapper"
version = "0.1.0"
edition = "2021"
authors = ["Astrodevs-Labs"]
description = "Foundry abstractions for all extensions"
license = "GPL-3.0-or-later"
repository = "https://github.com/astrodevs-labs/osmium"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
glob = "0.3.1"
clap = "4.4.8"
thiserror = "1.0"
foundry-config = { git = "https://github.com/foundry-rs/foundry" }
forge = { git = "https://github.com/foundry-rs/foundry" }
foundry-cli = { git = "https://github.com/foundry-rs/foundry" }
foundry-common = { git = "https://github.com/foundry-rs/foundry" }
# solc & compilation utilities
foundry-compilers = { version = "0.1", default-features = false }

# forge dependencies
eyre = "0.6"
once_cell = "1"
semver = "1"
tracing = "0.1"
regex = { version = "1", default-features = false }
yansi = "0.5"

[patch.crates-io]
ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-addressbook = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-core = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-contract = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-contract-abigen = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-providers = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-signers = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-middleware = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-etherscan = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }
ethers-solc = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" }

foundry-block-explorers = { git = "https://github.com/foundry-rs/block-explorers" }

alloy-dyn-abi = { git = "https://github.com/alloy-rs/core/" }
alloy-primitives = { git = "https://github.com/alloy-rs/core/" }
alloy-json-abi = { git = "https://github.com/alloy-rs/core/" }
alloy-sol-types = { git = "https://github.com/alloy-rs/core/" }
675 changes: 675 additions & 0 deletions libs/foundry-wrapper/LICENSE.txt

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions libs/foundry-wrapper/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@osmium-libs/foundry-wrapper",
"scripts": {
"build": "cargo build --release",
"format": "cargo fmt --check --all",
"test": "cargo test",
"lint": "cargo clippy --all-targets --all-features -- -D warnings",
"publish": "cargo package && cargo publish"
}
}
65 changes: 65 additions & 0 deletions libs/foundry-wrapper/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::{types::{WorkspaceConfig, ProjectCompileOutput}, error::Error, utils::install_missing_dependencies};

#[derive(Debug)]
pub struct CompilerInner {
root_path: String,
workspace_config: WorkspaceConfig,
}

#[derive(Debug)]
pub struct Compiler {
inner: CompilerInner,
}

impl Compiler {
pub fn new() -> Self {
Self {
inner: CompilerInner {
root_path: String::new(),
workspace_config: WorkspaceConfig::new(),
}
}
}

pub fn load_workspace(&mut self, root_folder: String) -> Result<(), Error> {
self.inner.workspace_config.load_projects(&root_folder)?;
self.inner.root_path = root_folder;
Ok(())
}

pub fn reload_project_for_file(&mut self, file_path: &str) -> Result<(), Error> {
self.inner.workspace_config.reload_project_for_file(file_path)
}

pub fn compile(&mut self, file_path: &str) -> Result<(String, ProjectCompileOutput), Error> {
let (_, config) = self.inner.workspace_config.get_config_for_file(file_path)
.ok_or_else(|| Error::InvalidFilePath(file_path.to_string()))?;

if install_missing_dependencies(config, true) {
let path = self.inner.root_path.clone();
self.inner.workspace_config.reload_project_for_file(&path)?;
}
let (project_path, project) = self.inner.workspace_config.get_project_for_file(file_path)
.ok_or_else(|| Error::InvalidFilePath(file_path.to_string()))?;

Ok((project_path, project.compile()?))

/*
if install::install_missing_dependencies(&mut config, self.args.silent) &&
config.auto_detect_remappings
{
// need to re-configure here to also catch additional remappings
config = self.load_config();
project = config.project()?;
}
let filters = self.skip.unwrap_or_default();
if self.args.silent {
compile::suppress_compile_with_filter(&project, filters)
} else {
let compiler = ProjectCompiler::with_filter(self.names, self.sizes, filters);
compiler.compile(&project)
} */
}
}
18 changes: 18 additions & 0 deletions libs/foundry-wrapper/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use foundry_compilers::error::SolcError;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
#[error("Config loading error: {0}")]
ConfigLoading(SolcError),
#[error("Project loading error: {0}")]
ProjectLoading(SolcError),
#[error("Workspace loading error: {0}")]
InvalidRootPath(#[from] glob::PatternError),
#[error("Invalid file path: {0}")]
InvalidFilePath(String),
#[error("Compilation error: {0}")]
CompilationError(SolcError),
#[error("Unkown error: {0}")]
UnkownError(#[from] SolcError),
}
10 changes: 10 additions & 0 deletions libs/foundry-wrapper/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mod utils;

mod types;
pub use types::*;

mod compiler;
pub use compiler::*;

mod error;
pub use error::*;
11 changes: 11 additions & 0 deletions libs/foundry-wrapper/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pub(crate) mod project_compile_output;
pub use project_compile_output::{ProjectCompileOutput, CompilationError, Position, Range, Severity};

pub(crate) mod project_config;
pub use project_config::ProjectConfig;

pub(crate) mod project;
pub use project::Project;

pub(crate) mod workspace_config;
pub use workspace_config::WorkspaceConfig;
25 changes: 25 additions & 0 deletions libs/foundry-wrapper/src/types/project.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::error::Error;

use super::{ProjectConfig, ProjectCompileOutput};

#[derive(Debug)]
pub(crate) struct ProjectInner(foundry_compilers::Project);

#[derive(Debug)]
pub struct Project {
inner: ProjectInner,
}

impl Project {
pub(super) fn new(config: &ProjectConfig) -> Result<Self, Error> {
Ok(Self {
inner: ProjectInner(
config.inner.0.project().map_err(|e| Error::ProjectLoading(e))?
),
})
}

pub(crate) fn compile(&self) -> Result<ProjectCompileOutput, Error> {
Ok(self.inner.0.compile().map_err(|e| Error::UnkownError(e))?.into())
}
}
110 changes: 110 additions & 0 deletions libs/foundry-wrapper/src/types/project_compile_output.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#[derive(Clone, Debug)]
pub struct ProjectCompileOutput(foundry_compilers::ProjectCompileOutput);

impl From<foundry_compilers::ProjectCompileOutput> for ProjectCompileOutput {
fn from(output: foundry_compilers::ProjectCompileOutput) -> Self {
Self(output)
}
}

impl ProjectCompileOutput {
pub fn get_errors(&self) -> Vec<CompilationError> {
self.0.clone().output().errors.into_iter().map(|e| CompilationError::from(e)).collect()
}
}

#[derive(Clone, Debug)]
pub struct CompilationError(foundry_compilers::artifacts::Error);

impl From<foundry_compilers::artifacts::Error> for CompilationError {
fn from(error: foundry_compilers::artifacts::Error) -> Self {
Self(error)
}
}

impl CompilationError {
pub fn get_message(&self) -> String {
self.0.message.clone()
}

pub fn get_file_path(&self) -> Option<String> {
Some(self.0.source_location.clone()?.file.clone())
}

pub fn get_start_idx(&self) -> Option<i32> {
Some(self.0.source_location.clone()?.start)
}

pub fn get_end_idx(&self) -> Option<i32> {
Some(self.0.source_location.clone()?.end)
}

pub fn get_start_position(&self, source_content: &str) -> Option<Position> {
let idx = self.get_start_idx()?;
Position::from_index(idx, source_content)
}

pub fn get_end_position(&self, source_content: &str) -> Option<Position> {
let idx = self.get_end_idx()?;
Position::from_index(idx, source_content)
}

pub fn get_range(&self, source_content: &str) -> Option<Range> {
Some(Range {
start: self.get_start_position(source_content)?,
end: self.get_end_position(source_content)?
})
}

pub fn get_severity(&self) -> Severity {
self.0.severity.into()
}
}

/**
* Position of error, 0 based indexes
*/
#[derive(Clone, Debug)]
pub struct Position {
pub line: u32,
pub column: u32
}

impl Position {
pub fn from_index(idx: i32, source: &str) -> Option<Self> {
let mut idx: usize = idx as usize;
for (i, l) in source.lines().enumerate() {
if idx < l.len() {
return Some(Self {
line: i as u32,
column: idx as u32
})
}
idx -= l.len() + 1;
}
None
}
}

#[derive(Clone, Debug)]
pub struct Range {
pub start: Position,
pub end: Position
}

#[derive(Clone, Debug)]
pub enum Severity {
Error,
Warning,
Info,
}

impl From<foundry_compilers::artifacts::Severity> for Severity {
fn from(severity: foundry_compilers::artifacts::Severity) -> Self {
match severity {
foundry_compilers::artifacts::Severity::Error => Self::Error,
foundry_compilers::artifacts::Severity::Warning => Self::Warning,
foundry_compilers::artifacts::Severity::Info => Self::Info,
}
}
}
34 changes: 34 additions & 0 deletions libs/foundry-wrapper/src/types/project_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use foundry_config::Config;
use crate::error::Error;

use super::Project;

#[derive(Clone, Debug)]
pub(crate) struct ProjectConfigInner(pub Config);

impl ProjectConfigInner {
pub(crate) fn load_with_root(root: &str) -> Self {
Self(Config::load_with_root(root))
}

pub(crate) fn get_mut(&mut self) -> &mut Config {
&mut self.0
}
}

#[derive(Clone, Debug)]
pub struct ProjectConfig {
pub(crate) inner: ProjectConfigInner,
}

impl ProjectConfig {
pub fn load_with_root(root: &str) -> Self {
Self {
inner: ProjectConfigInner::load_with_root(root),
}
}

pub fn project(&self) -> Result<Project, Error> {
Ok(Project::new(self)?)
}
}
Loading

0 comments on commit 2b035f3

Please sign in to comment.