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

Commit

Permalink
feat: add compile exact
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse committed Feb 5, 2022
1 parent 3a73221 commit f2fb044
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 64 deletions.
18 changes: 17 additions & 1 deletion ethers-solc/src/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use colored::Colorize;
use md5::Digest;
use semver::Version;
use std::{
collections::BTreeMap,
collections::{BTreeMap, HashSet},
convert::TryFrom,
fmt, fs,
path::{Path, PathBuf},
Expand Down Expand Up @@ -595,6 +595,22 @@ impl CompilerOutput {
pub fn split(self) -> (SourceFiles, OutputContracts) {
(SourceFiles(self.sources), OutputContracts(self.contracts))
}

/// Retains only those files the given iterator yields
///
/// In other words, removes all contracts for files not included in the iterator
pub fn retain_files<'a, I>(&mut self, files: I)
where
I: IntoIterator<Item = &'a str>,
{
let files: HashSet<_> = files.into_iter().collect();

self.contracts.retain(|f, _| files.contains(f.as_str()));
self.sources.retain(|f, _| files.contains(f.as_str()));
self.errors.retain(|err| {
err.source_location.as_ref().map(|s| files.contains(s.file.as_str())).unwrap_or(true)
});
}
}

/// A wrapper helper type for the `Contracts` type alias
Expand Down
1 change: 0 additions & 1 deletion ethers-solc/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,6 @@ impl<'a, T: ArtifactOutput> ArtifactsCache<'a, T> {
for (file, artifacts) in written_artifacts.as_ref() {
let file_path = Path::new(&file);
if let Some((entry, versions)) = dirty_source_files.get_mut(file_path) {
// TODO
entry.insert_artifacts(artifacts.iter().map(|(name, artifacts)| {
let artifacts = artifacts
.iter()
Expand Down
23 changes: 23 additions & 0 deletions ethers-solc/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,29 @@ impl Solc {
self.compile(&CompilerInput::new(path)?)
}

/// Same as [`Self::compile()`], but only returns those files which are included in the
/// `CompilerInput`.
///
/// In other words, this removes those files from the `CompilerOutput` that are __not__ included
/// in the provided `CompilerInput`.
///
/// # Example
///
/// ```no_run
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use ethers_solc::{CompilerInput, Solc};
/// let solc = Solc::default();
/// let input = CompilerInput::new("./contracts")?;
/// let output = solc.compile_exact(&input)?;
/// # Ok(())
/// # }
/// ```
pub fn compile_exact(&self, input: &CompilerInput) -> Result<CompilerOutput> {
let mut out = self.compile(input)?;
out.retain_files(input.sources.keys().filter_map(|p| p.to_str()));
Ok(out)
}

/// Run `solc --stand-json` and return the `solc`'s output as
/// `CompilerOutput`
///
Expand Down
62 changes: 5 additions & 57 deletions ethers-solc/src/compile/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,8 @@ fn compile_parallel(
#[cfg(feature = "project-util")]
mod tests {
use super::*;
use crate::{
artifacts::FileToContractsMap, project_util::TempProject, MinimalCombinedArtifacts,
};
use semver::Version;
use crate::{project_util::TempProject, MinimalCombinedArtifacts};

use std::path::PathBuf;

#[allow(unused)]
Expand Down Expand Up @@ -457,6 +455,7 @@ mod tests {
}

#[test]
#[ignore]
fn can_compile_real_project() {
init_tracing();
let paths = ProjectPathsConfig::builder()
Expand All @@ -465,58 +464,7 @@ mod tests {
.unwrap();
let project = Project::builder().paths(paths).build().unwrap();
let compiler = ProjectCompiler::new(&project).unwrap();
let sources: BTreeMap<_, _> =
compiler.sources.sources().into_iter().map(|(s, v)| (s.to_string(), v)).collect();
std::fs::write("sources.json", serde_json::to_string_pretty(&sources).unwrap()).unwrap();

let state = compiler.preprocess().unwrap();
// let cache = state.cache.as_cached().unwrap();
// // dbg!(cache.cached_artifacts.as_ref().keys());
// // dbg!(cache.cache.len());
//
// std::fs::write("dirty.json",
// serde_json::to_string_pretty(&cache.dirty_source_files).unwrap()).unwrap();
// dbg!(&cache.dirty_entries);

let state = state.compile().unwrap();
let contracts: FileToContractsMap<Vec<Version>> = state
.output
.contracts
.as_ref()
.clone()
.into_iter()
.map(|(file, contracts)| {
let contracts = contracts
.into_iter()
.map(|(name, versioned)| {
let versions = versioned.into_iter().map(|v| v.version).collect::<Vec<_>>();
(name, versions)
})
.collect();
(file, contracts)
})
.collect();

std::fs::write("contracts.json", serde_json::to_string_pretty(&contracts).unwrap())
.unwrap();

state.output.contracts.contracts_with_files_and_version().for_each(|(file, name, _, v)| {
println!("{} {} {}", file, name, v);
});

// let state = state.write_artifacts().unwrap();
// // state.output.contracts.contracts_with_files_and_version().for_each(|(file, name,_, v)|
// { // println!("{} {} {}", file, name, v);
// // });
// assert_eq!(state.output.contracts, contracts);
// state.compiled_artifacts.artifact_files().for_each(|f| {
// dbg!(f.file.clone());
// });
// dbg!(state.compiled_artifacts.artifact_files().count());
//
// let state = state.write_cache().unwrap();
// dbg!(state.compiled_artifacts.artifact_files().count());

// dbg!(cache.cache.len());
let out = compiler.compile().unwrap();
println!("{}", out);
}
}
12 changes: 7 additions & 5 deletions ethers-solc/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use regex::Match;
use semver::VersionReq;
use solang_parser::pt::{Import, Loc, SourceUnitPart};

use crate::{error::Result, utils, ProjectPathsConfig, Solc, SolcVersion, Source, Sources};
use crate::{error::Result, utils, ProjectPathsConfig, Solc, Source, Sources};

/// The underlying edges of the graph which only contains the raw relationship data.
///
Expand Down Expand Up @@ -446,7 +446,7 @@ impl Graph {
if versioned_nodes.len() == 1 {
tracing::trace!(
"found exact solc version for all sources \"{}\"",
&versioned_nodes[0]
versioned_nodes.keys().next().unwrap()
);
}

Expand All @@ -469,10 +469,12 @@ impl Graph {
/// This is a bit inefficient but is fine, the max. number of versions is ~80 and there's
/// a high chance that the number of source files is <50, even for larger projects.
fn resolve_multiple_versions(
all_candidates: Vec<(usize, HashSet<&SolcVersion>)>,
all_candidates: Vec<(usize, HashSet<&crate::SolcVersion>)>,
) -> HashMap<crate::SolcVersion, Vec<usize>> {
// returns the intersection as sorted set of nodes
fn intersection<'a>(mut sets: Vec<&HashSet<&'a SolcVersion>>) -> Vec<&'a SolcVersion> {
fn intersection<'a>(
mut sets: Vec<&HashSet<&'a crate::SolcVersion>>,
) -> Vec<&'a crate::SolcVersion> {
if sets.is_empty() {
return Vec::new()
}
Expand All @@ -490,7 +492,7 @@ impl Graph {
/// returns the highest version that is installed
/// if the candidates set only contains uninstalled versions then this returns the highest
/// uninstalled version
fn remove_candidate(candidates: &mut Vec<&SolcVersion>) -> SolcVersion {
fn remove_candidate(candidates: &mut Vec<&crate::SolcVersion>) -> crate::SolcVersion {
debug_assert!(!candidates.is_empty());

if let Some(pos) = candidates.iter().rposition(|v| v.is_installed()) {
Expand Down

0 comments on commit f2fb044

Please sign in to comment.