Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions crates/compilers/src/compilers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ pub trait SourceParser: Clone + Debug + Send + Sync {
})
.collect::<Result<_>>()
}

fn finalize_imports(
&mut self,
_nodes: &mut Vec<Node<Self::ParsedSource>>,
_include_paths: &BTreeSet<PathBuf>,
) -> Result<()> {
Ok(())
}
}

/// Parser of the source files which is used to identify imports and version requirements of the
Expand Down
37 changes: 37 additions & 0 deletions crates/compilers/src/compilers/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,43 @@ impl SourceParser for MultiCompilerParser {
)
.collect())
}

fn finalize_imports(
&mut self,
all_nodes: &mut Vec<crate::resolver::Node<Self::ParsedSource>>,
include_paths: &BTreeSet<PathBuf>,
) -> 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 {
Expand Down
54 changes: 35 additions & 19 deletions crates/compilers/src/compilers/solc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,9 @@ impl SourceParser for SolParser {
&mut self,
sources: &mut Sources,
) -> Result<Vec<(PathBuf, Node<Self::ParsedSource>)>> {
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)| {
Expand All @@ -423,29 +424,44 @@ impl SourceParser for SolParser {
);
(path.clone(), node)
});
let mut parsed = parsed.collect::<Vec<_>>();
let parsed = parsed.collect::<Vec<_>>();

// 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<Node<Self::ParsedSource>>,
include_paths: &BTreeSet<PathBuf>,
) -> 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(())
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/compilers/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ impl<P: SourceParser> Graph<P> {
);
}

parser.finalize_imports(&mut nodes, &resolved_solc_include_paths)?;

let edges = GraphEdges {
edges,
rev_edges,
Expand Down