fix(solc): flatten random statement order (#1292)

* fix random statement order

* linter
This commit is contained in:
Roman Krasiuk 2022-05-20 23:00:36 +03:00 committed by GitHub
parent 809ccbc9ad
commit 592144e308
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 32 deletions

View File

@ -311,31 +311,29 @@ impl ProjectPathsConfig {
let mut content = content.as_bytes().to_vec(); let mut content = content.as_bytes().to_vec();
let mut offset = 0_isize; let mut offset = 0_isize;
if strip_license { let mut statements = [
if let Some(license) = target_node.license() { (target_node.license(), strip_license),
let license_range = license.loc_by_offset(offset); (target_node.version(), strip_version_pragma),
offset -= license_range.len() as isize; (target_node.experimental(), strip_experimental_pragma),
content.splice(license_range, std::iter::empty()); ]
} .iter()
} .filter_map(|(data, condition)| if *condition { data.to_owned().as_ref() } else { None })
.collect::<Vec<_>>();
statements.sort_by_key(|x| x.loc().start);
if strip_version_pragma { let (mut imports, mut statements) =
if let Some(version) = target_node.version() { (imports.iter().peekable(), statements.iter().peekable());
let version_range = version.loc_by_offset(offset); while imports.peek().is_some() || statements.peek().is_some() {
offset -= version_range.len() as isize; let (next_import_start, next_statement_start) = (
content.splice(version_range, std::iter::empty()); imports.peek().map_or(usize::max_value(), |x| x.loc().start),
} statements.peek().map_or(usize::max_value(), |x| x.loc().start),
} );
if next_statement_start < next_import_start {
if strip_experimental_pragma { let repl_range = statements.next().unwrap().loc_by_offset(offset);
if let Some(experiment) = target_node.experimental() { offset -= repl_range.len() as isize;
let experimental_pragma_range = experiment.loc_by_offset(offset); content.splice(repl_range, std::iter::empty());
offset -= experimental_pragma_range.len() as isize; } else {
content.splice(experimental_pragma_range, std::iter::empty()); let import = imports.next().unwrap();
}
}
for import in imports.iter() {
let import_path = self.resolve_import(target_dir, import.data().path())?; let import_path = self.resolve_import(target_dir, import.data().path())?;
let s = self.flatten_node(&import_path, graph, imported, true, true, true)?; let s = self.flatten_node(&import_path, graph, imported, true, true, true)?;
@ -345,6 +343,7 @@ impl ProjectPathsConfig {
offset += import_content_len - (import_range.len() as isize); offset += import_content_len - (import_range.len() as isize);
content.splice(import_range, import_content.iter().copied()); content.splice(import_range, import_content.iter().copied());
} }
}
let result = String::from_utf8(content).map_err(|err| { let result = String::from_utf8(content).map_err(|err| {
SolcError::msg(format!("failed to convert extended bytes to string: {}", err)) SolcError::msg(format!("failed to convert extended bytes to string: {}", err))

View File

@ -873,6 +873,71 @@ contract Contract is ParentContract,
); );
} }
#[test]
fn can_flatten_with_version_pragma_after_imports() {
let project = TempProject::dapptools().unwrap();
let f = project
.add_source(
"A",
r#"
pragma solidity ^0.8.10;
import * as B from "./B.sol";
contract A { }
"#,
)
.unwrap();
project
.add_source(
"B",
r#"
import D from "./D.sol";
pragma solidity ^0.8.10;
import * as C from "./C.sol";
contract B { }
"#,
)
.unwrap();
project
.add_source(
"C",
r#"
pragma solidity ^0.8.10;
contract C { }
"#,
)
.unwrap();
project
.add_source(
"D",
r#"
pragma solidity ^0.8.10;
contract D { }
"#,
)
.unwrap();
let result = project.flatten(&f).unwrap();
assert_eq!(
result,
r#"pragma solidity ^0.8.10;
contract D { }
contract C { }
contract B { }
contract A { }
"#
);
}
#[test] #[test]
fn can_detect_type_error() { fn can_detect_type_error() {
let project = TempProject::<ConfigurableArtifacts>::dapptools().unwrap(); let project = TempProject::<ConfigurableArtifacts>::dapptools().unwrap();