diff --git a/Cargo.toml b/Cargo.toml index af4caf253..3426b8c12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ semver = { version = "1.0", features = ["serde"] } serde = { version = "1", features = ["derive", "rc"] } serde_json = "1.0" similar-asserts = "1" -solar = { package = "solar-compiler", version = "=0.1.7", default-features = false } +solar = { package = "solar-compiler", version = "=0.1.8", default-features = false } svm = { package = "svm-rs", version = "0.5", default-features = false } tempfile = "3.20" thiserror = "2" diff --git a/crates/compilers/src/compilers/mod.rs b/crates/compilers/src/compilers/mod.rs index 29e1ca75d..ea9db512a 100644 --- a/crates/compilers/src/compilers/mod.rs +++ b/crates/compilers/src/compilers/mod.rs @@ -166,6 +166,14 @@ pub trait SourceParser: Clone + Debug + Send + Sync { }) .collect::>() } + + fn finalize_imports( + &mut self, + _nodes: &mut Vec>, + _include_paths: &BTreeSet, + ) -> Result<()> { + Ok(()) + } } /// Parser of the source files which is used to identify imports and version requirements of the diff --git a/crates/compilers/src/compilers/multi.rs b/crates/compilers/src/compilers/multi.rs index 0953349c5..6543a3ac0 100644 --- a/crates/compilers/src/compilers/multi.rs +++ b/crates/compilers/src/compilers/multi.rs @@ -412,6 +412,43 @@ impl SourceParser for MultiCompilerParser { ) .collect()) } + + fn finalize_imports( + &mut self, + all_nodes: &mut Vec>, + include_paths: &BTreeSet, + ) -> Result<()> { + let mut solc_nodes = Vec::new(); + let mut vyper_nodes = Vec::new(); + for node in std::mem::take(all_nodes) { + match node.data { + MultiCompilerParsedSource::Solc(_) => { + solc_nodes.push(node.map_data(|data| match data { + MultiCompilerParsedSource::Solc(data) => data, + _ => unreachable!(), + })) + } + MultiCompilerParsedSource::Vyper(_) => { + vyper_nodes.push(node.map_data(|data| match data { + MultiCompilerParsedSource::Vyper(data) => data, + _ => unreachable!(), + })) + } + } + } + + self.solc.finalize_imports(&mut solc_nodes, include_paths)?; + self.vyper.finalize_imports(&mut vyper_nodes, include_paths)?; + + all_nodes.extend( + solc_nodes.into_iter().map(|node| node.map_data(MultiCompilerParsedSource::Solc)), + ); + all_nodes.extend( + vyper_nodes.into_iter().map(|node| node.map_data(MultiCompilerParsedSource::Vyper)), + ); + + Ok(()) + } } impl ParsedSource for MultiCompilerParsedSource { diff --git a/crates/compilers/src/compilers/solc/mod.rs b/crates/compilers/src/compilers/solc/mod.rs index bf7792e5e..0f044d314 100644 --- a/crates/compilers/src/compilers/solc/mod.rs +++ b/crates/compilers/src/compilers/solc/mod.rs @@ -399,8 +399,9 @@ impl SourceParser for SolParser { &mut self, sources: &mut Sources, ) -> Result)>> { - self.compiler_mut().enter_mut(|compiler| { + self.compiler.enter_mut(|compiler| { let mut pcx = compiler.parse(); + pcx.set_resolve_imports(false); let files = sources .par_iter() .map(|(path, source)| { @@ -423,29 +424,44 @@ impl SourceParser for SolParser { ); (path.clone(), node) }); - let mut parsed = parsed.collect::>(); + let parsed = parsed.collect::>(); - // Set error on the first successful source, if any. This doesn't really have to be - // exact, as long as at least one source has an error set it should be enough. - if let Some(Err(diag)) = compiler.gcx().sess.emitted_errors() { - if let Some(idx) = parsed - .iter() - .position(|(_, node)| node.data.parse_result.is_ok()) - .or_else(|| parsed.first().map(|_| 0)) - { - let (_, node) = &mut parsed[idx]; - node.data.parse_result = Err(diag.to_string()); - } + Ok(parsed) + }) + } + + fn finalize_imports( + &mut self, + nodes: &mut Vec>, + include_paths: &BTreeSet, + ) -> Result<()> { + let compiler = &mut self.compiler; + compiler.sess_mut().opts.include_paths.extend(include_paths.iter().cloned()); + compiler.enter_mut(|compiler| { + let mut pcx = compiler.parse(); + pcx.set_resolve_imports(true); + pcx.force_resolve_all_imports(); + }); + + // Set error on the first successful source, if any. This doesn't really have to be + // exact, as long as at least one source has an error set it should be enough. + if let Some(Err(diag)) = compiler.sess().emitted_errors() { + if let Some(idx) = nodes + .iter() + .position(|node| node.data.parse_result.is_ok()) + .or_else(|| nodes.first().map(|_| 0)) + { + nodes[idx].data.parse_result = Err(diag.to_string()); } + } - for (path, node) in &parsed { - if let Err(e) = &node.data.parse_result { - debug!("failed parsing {}: {e}", path.display()); - } + for node in nodes.iter() { + if let Err(e) = &node.data.parse_result { + debug!("failed parsing:\n{e}"); } + } - Ok(parsed) - }) + Ok(()) } } diff --git a/crates/compilers/src/resolver/mod.rs b/crates/compilers/src/resolver/mod.rs index 4a9cc85fc..0f16b9870 100644 --- a/crates/compilers/src/resolver/mod.rs +++ b/crates/compilers/src/resolver/mod.rs @@ -484,6 +484,8 @@ impl Graph

{ ); } + parser.finalize_imports(&mut nodes, &resolved_solc_include_paths)?; + let edges = GraphEdges { edges, rev_edges,