Skip to content
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

fix: re-add version regex parsing #223

Merged
merged 1 commit into from
Nov 19, 2024
Merged
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
121 changes: 121 additions & 0 deletions crates/compilers/src/resolver/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ impl SolData {
let e = e.to_string();
trace!("failed parsing {file:?}: {e}");
parse_result = Err(e);

if version.is_none() {
version = utils::capture_outer_and_inner(
content,
&utils::RE_SOL_PRAGMA_VERSION,
&["version"],
)
.first()
.map(|(cap, name)| Spanned::new(name.as_str().to_owned(), cap.range()));
}
if !imports.is_empty() {
imports = capture_imports(content);
}
}
let license = content.lines().next().and_then(|line| {
utils::capture_outer_and_inner(
Expand Down Expand Up @@ -264,3 +277,111 @@ fn library_is_inlined(contract: &ast::ItemContract<'_>) -> bool {
)
})
}

/// Capture the import statement information together with aliases
pub fn capture_imports(content: &str) -> Vec<Spanned<SolImport>> {
let mut imports = vec![];
for cap in utils::RE_SOL_IMPORT.captures_iter(content) {
if let Some(name_match) = ["p1", "p2", "p3", "p4"].iter().find_map(|name| cap.name(name)) {
let statement_match = cap.get(0).unwrap();
let mut aliases = vec![];
for alias_cap in utils::RE_SOL_IMPORT_ALIAS.captures_iter(statement_match.as_str()) {
if let Some(alias) = alias_cap.name("alias") {
let alias = alias.as_str().to_owned();
let import_alias = match alias_cap.name("target") {
Some(target) => SolImportAlias::Contract(alias, target.as_str().to_owned()),
None => SolImportAlias::File(alias),
};
aliases.push(import_alias);
}
}
let sol_import =
SolImport::new(PathBuf::from(name_match.as_str())).set_aliases(aliases);
imports.push(Spanned::new(sol_import, statement_match.range()));
}
}
imports
}

#[cfg(test)]
mod tests {
use super::*;

#[track_caller]
fn assert_version(version_req: Option<&str>, src: &str) {
let data = SolData::parse(src, "test.sol".as_ref());
assert_eq!(data.version_req, version_req.map(|v| v.parse().unwrap()), "src:\n{src}");
}

#[test]
fn soldata_parsing() {
assert_version(None, "");
assert_version(None, "contract C { }");

// https://github.com/foundry-rs/foundry/issues/9349
assert_version(
Some(">=0.4.22, <0.6"),
r#"
pragma solidity >=0.4.22 <0.6;

contract BugReport {
function() external payable {
deposit();
}
function deposit() public payable {}
}
"#,
);
}

#[test]
fn can_capture_curly_imports() {
let content = r#"
import { T } from "../Test.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {DsTest} from "ds-test/test.sol";
"#;

let captured_imports =
capture_imports(content).into_iter().map(|s| s.data.path).collect::<Vec<_>>();

let expected =
utils::find_import_paths(content).map(|m| m.as_str().into()).collect::<Vec<PathBuf>>();

assert_eq!(captured_imports, expected);

assert_eq!(
captured_imports,
vec![
PathBuf::from("../Test.sol"),
"@openzeppelin/contracts/utils/ReentrancyGuard.sol".into(),
"ds-test/test.sol".into(),
],
);
}

#[test]
fn cap_capture_aliases() {
let content = r#"
import * as T from "./Test.sol";
import { DsTest as Test } from "ds-test/test.sol";
import "ds-test/test.sol" as Test;
import { FloatMath as Math, Math as FloatMath } from "./Math.sol";
"#;

let caputred_imports =
capture_imports(content).into_iter().map(|s| s.data.aliases).collect::<Vec<_>>();
assert_eq!(
caputred_imports,
vec![
vec![SolImportAlias::File("T".into())],
vec![SolImportAlias::Contract("Test".into(), "DsTest".into())],
vec![SolImportAlias::File("Test".into())],
vec![
SolImportAlias::Contract("Math".into(), "FloatMath".into()),
SolImportAlias::Contract("FloatMath".into(), "Math".into()),
],
]
);
}
}