feat(solc): Strip experimental pragma from all imported contracts (#1116)
* Parse experimental pragma * add integration test for experimental pragma * Fix formatting
This commit is contained in:
parent
509db06080
commit
77931d4c63
|
@ -250,7 +250,7 @@ impl ProjectPathsConfig {
|
||||||
pub fn flatten(&self, target: &Path) -> Result<String> {
|
pub fn flatten(&self, target: &Path) -> Result<String> {
|
||||||
tracing::trace!("flattening file");
|
tracing::trace!("flattening file");
|
||||||
let graph = Graph::resolve(self)?;
|
let graph = Graph::resolve(self)?;
|
||||||
self.flatten_node(target, &graph, &mut Default::default(), false, false)
|
self.flatten_node(target, &graph, &mut Default::default(), false, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flattens a single node from the dependency graph
|
/// Flattens a single node from the dependency graph
|
||||||
|
@ -260,6 +260,7 @@ impl ProjectPathsConfig {
|
||||||
graph: &Graph,
|
graph: &Graph,
|
||||||
imported: &mut HashSet<usize>,
|
imported: &mut HashSet<usize>,
|
||||||
strip_version_pragma: bool,
|
strip_version_pragma: bool,
|
||||||
|
strip_experimental_pragma: bool,
|
||||||
strip_license: bool,
|
strip_license: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let target_dir = target.parent().ok_or_else(|| {
|
let target_dir = target.parent().ok_or_else(|| {
|
||||||
|
@ -299,9 +300,17 @@ impl ProjectPathsConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strip_experimental_pragma {
|
||||||
|
if let Some(experiment) = target_node.experimental() {
|
||||||
|
let (start, end) = experiment.loc_by_offset(offset);
|
||||||
|
content.splice(start..end, std::iter::empty());
|
||||||
|
offset -= (end - start) as isize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for import in imports.iter() {
|
for import in imports.iter() {
|
||||||
let import_path = self.resolve_import(target_dir, import.data())?;
|
let import_path = self.resolve_import(target_dir, import.data())?;
|
||||||
let s = self.flatten_node(&import_path, graph, imported, true, true)?;
|
let s = self.flatten_node(&import_path, graph, imported, true, true, true)?;
|
||||||
let import_content = s.trim().as_bytes();
|
let import_content = s.trim().as_bytes();
|
||||||
let import_content_len = import_content.len() as isize;
|
let import_content_len = import_content.len() as isize;
|
||||||
let (start, end) = import.loc_by_offset(offset);
|
let (start, end) = import.loc_by_offset(offset);
|
||||||
|
|
|
@ -763,6 +763,10 @@ impl Node {
|
||||||
&self.data.version
|
&self.data.version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn experimental(&self) -> &Option<SolDataUnit<String>> {
|
||||||
|
&self.data.experimental
|
||||||
|
}
|
||||||
|
|
||||||
pub fn license(&self) -> &Option<SolDataUnit<String>> {
|
pub fn license(&self) -> &Option<SolDataUnit<String>> {
|
||||||
&self.data.license
|
&self.data.license
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
|
||||||
pub struct SolData {
|
pub struct SolData {
|
||||||
pub license: Option<SolDataUnit<String>>,
|
pub license: Option<SolDataUnit<String>>,
|
||||||
pub version: Option<SolDataUnit<String>>,
|
pub version: Option<SolDataUnit<String>>,
|
||||||
|
pub experimental: Option<SolDataUnit<String>>,
|
||||||
pub imports: Vec<SolDataUnit<PathBuf>>,
|
pub imports: Vec<SolDataUnit<PathBuf>>,
|
||||||
pub version_req: Option<VersionReq>,
|
pub version_req: Option<VersionReq>,
|
||||||
pub libraries: Vec<SolLibrary>,
|
pub libraries: Vec<SolLibrary>,
|
||||||
|
@ -37,6 +38,7 @@ impl SolData {
|
||||||
/// parsing fails, we'll fall back to extract that info via regex
|
/// parsing fails, we'll fall back to extract that info via regex
|
||||||
pub fn parse(content: &str, file: &Path) -> Self {
|
pub fn parse(content: &str, file: &Path) -> Self {
|
||||||
let mut version = None;
|
let mut version = None;
|
||||||
|
let mut experimental = None;
|
||||||
let mut imports = Vec::<SolDataUnit<PathBuf>>::new();
|
let mut imports = Vec::<SolDataUnit<PathBuf>>::new();
|
||||||
let mut libraries = Vec::new();
|
let mut libraries = Vec::new();
|
||||||
let mut contracts = Vec::new();
|
let mut contracts = Vec::new();
|
||||||
|
@ -48,7 +50,12 @@ impl SolData {
|
||||||
SourceUnitPart::PragmaDirective(loc, _, pragma, value) => {
|
SourceUnitPart::PragmaDirective(loc, _, pragma, value) => {
|
||||||
if pragma.name == "solidity" {
|
if pragma.name == "solidity" {
|
||||||
// we're only interested in the solidity version pragma
|
// we're only interested in the solidity version pragma
|
||||||
version = Some(SolDataUnit::new(value.string, loc.into()));
|
version = Some(SolDataUnit::new(value.string.clone(), loc.into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if pragma.name == "experimental" {
|
||||||
|
experimental =
|
||||||
|
Some(SolDataUnit::new(value.string.clone(), loc.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SourceUnitPart::ImportDirective(_, import) => {
|
SourceUnitPart::ImportDirective(_, import) => {
|
||||||
|
@ -106,7 +113,7 @@ impl SolData {
|
||||||
});
|
});
|
||||||
let version_req = version.as_ref().and_then(|v| Solc::version_req(v.data()).ok());
|
let version_req = version.as_ref().and_then(|v| Solc::version_req(v.data()).ok());
|
||||||
|
|
||||||
Self { version_req, version, imports, license, libraries, contracts }
|
Self { version_req, version, experimental, imports, license, libraries, contracts }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the solidity file associated with this type contains a solidity library
|
/// Returns `true` if the solidity file associated with this type contains a solidity library
|
||||||
|
|
|
@ -499,6 +499,61 @@ contract A { }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_flatten_experimental_pragma() {
|
||||||
|
let project = TempProject::dapptools().unwrap();
|
||||||
|
|
||||||
|
let f = project
|
||||||
|
.add_source(
|
||||||
|
"A",
|
||||||
|
r#"
|
||||||
|
pragma solidity ^0.8.10;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
import "./C.sol";
|
||||||
|
import "./B.sol";
|
||||||
|
contract A { }
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
project
|
||||||
|
.add_source(
|
||||||
|
"B",
|
||||||
|
r#"
|
||||||
|
pragma solidity ^0.8.10;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
import "./C.sol";
|
||||||
|
contract B { }
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
project
|
||||||
|
.add_source(
|
||||||
|
"C",
|
||||||
|
r#"
|
||||||
|
pragma solidity ^0.8.10;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
import "./A.sol";
|
||||||
|
contract C { }
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result = project.flatten(&f).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
r#"
|
||||||
|
pragma solidity ^0.8.10;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C { }
|
||||||
|
contract B { }
|
||||||
|
contract A { }
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_flatten_file_with_duplicates() {
|
fn can_flatten_file_with_duplicates() {
|
||||||
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/test-flatten-duplicates");
|
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test-data/test-flatten-duplicates");
|
||||||
|
|
Loading…
Reference in New Issue