Skip to content

chore: simplify pragma parsing #260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 1, 2025
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
4 changes: 1 addition & 3 deletions crates/compilers/src/compilers/solc/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,7 @@ impl Solc {
/// Parses the given source looking for the `pragma` definition and
/// returns the corresponding SemVer version requirement.
pub fn source_version_req(source: &Source) -> Result<VersionReq> {
let version =
utils::find_version_pragma(&source.content).ok_or(SolcError::PragmaNotFound)?;
Ok(SolData::parse_version_req(version.as_str())?)
Ok(SolData::parse_version_pragma(&source.content).ok_or(SolcError::PragmaNotFound)??)
}

/// Given a Solidity source, it detects the latest compiler version which can be used
Expand Down
2 changes: 1 addition & 1 deletion crates/compilers/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ impl ProjectPathsConfig<SolcLanguage> {
sources.push(content);
}

if let Some(version) = combine_version_pragmas(version_pragmas) {
if let Some(version) = combine_version_pragmas(&version_pragmas) {
result.push_str(&version);
result.push('\n');
}
Expand Down
33 changes: 12 additions & 21 deletions crates/compilers/src/flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use foundry_compilers_core::{
};
use itertools::Itertools;
use std::{
collections::{HashMap, HashSet},
collections::{BTreeSet, HashMap, HashSet},
hash::Hash,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -724,7 +724,7 @@ impl Flattener {

let mut pragmas = Vec::new();

if let Some(version_pragma) = combine_version_pragmas(version_pragmas) {
if let Some(version_pragma) = combine_version_pragmas(&version_pragmas) {
pragmas.push(version_pragma);
}

Expand Down Expand Up @@ -881,26 +881,17 @@ pub fn collect_ordered_deps<D: ParsedSource + MaybeSolData>(
Ok(ordered_deps)
}

pub fn combine_version_pragmas(pragmas: Vec<&str>) -> Option<String> {
let mut versions = pragmas
.into_iter()
.filter_map(|p| {
SolData::parse_version_req(
p.replace("pragma", "").replace("solidity", "").replace(';', "").trim(),
)
.ok()
})
pub fn combine_version_pragmas(pragmas: &[impl AsRef<str>]) -> Option<String> {
let versions = pragmas
.iter()
.map(AsRef::as_ref)
.filter_map(SolData::parse_version_pragma)
.filter_map(Result::ok)
.flat_map(|req| req.comparators)
.collect::<HashSet<_>>()
.into_iter()
.map(|comp| comp.to_string())
.collect::<Vec<_>>();

versions.sort();

if !versions.is_empty() {
return Some(format!("pragma solidity {};", versions.iter().format(" ")));
.collect::<BTreeSet<_>>();
if versions.is_empty() {
return None;
}

None
Some(format!("pragma solidity {};", versions.iter().format(" ")))
}
8 changes: 8 additions & 0 deletions crates/compilers/src/resolver/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ impl SolData {
}
}

/// Parses the version pragma and returns the corresponding SemVer version requirement.
///
/// See [`parse_version_req`](Self::parse_version_req).
pub fn parse_version_pragma(pragma: &str) -> Option<Result<VersionReq, semver::Error>> {
let version = utils::find_version_pragma(pragma)?.as_str();
Some(Self::parse_version_req(version))
}

/// Returns the corresponding SemVer version requirement for the solidity version.
///
/// Note: This is a workaround for the fact that `VersionReq::parse` does not support whitespace
Expand Down
Loading