New flattening impl#52
Conversation
|
This should also fix issues with aliases (like foundry-rs/foundry#2545, foundry-rs/foundry#3265). Current impl handles aliases renaming via regex'es and may often be inaccurate. |
|
I've refactored code and added logic for correct processing of references to types declared in scope of contracts. It requires such workaround because for some reason solc does not give any information about the parent contract for That way, if we want to rename contract |
|
@sakulstra I believe you had some issues with flattening in the past, do you know any projects we should test this against? |
|
@mattsse there were a few issues/things i commented in the past:
For #4034 specifically we also had some issues with that, but can't recall right now in which contracts. Will check if i can find on monday. |
|
Added test and fix for foundry-rs/foundry#2378 If any of files contains any |
|
Pushed solution for foundry-rs/foundry#6539. Lines 586 to 624 in ce8e427 I've also shared it's logic with current flattening implementation and rewritten it a bit as it not longer needs to be recursive. |
|
@mattsse pushed fixes let's merge a bit later, I will now write integration of it into foundry and may decide to change the API of |
mattsse
left a comment
There was a problem hiding this comment.
sgtm!
pending foundry companion pr
Evalir
left a comment
There was a problem hiding this comment.
amazing. some nits on docs only
| let ordered_deps = collect_ordered_deps(&flatten_target, self, &graph)?; | ||
|
|
||
| let mut sources = Vec::new(); | ||
|
|
||
| let mut result = String::new(); | ||
|
|
||
| for path in ordered_deps.iter() { | ||
| let node_id = graph.files().get(path).ok_or_else(|| { | ||
| SolcError::msg(format!("cannot resolve file at {}", path.display())) | ||
| })?; | ||
| let node = graph.node(*node_id); | ||
| let mut content = node.content().to_owned(); | ||
|
|
||
| for alias in node.imports().iter().flat_map(|i| i.data().aliases()) { | ||
| let (alias, target) = match alias { | ||
| SolImportAlias::Contract(alias, target) => (alias.clone(), target.clone()), | ||
| _ => continue, | ||
| }; | ||
| let name_regex = utils::create_contract_or_lib_name_regex(&alias); | ||
| let target_len = target.len() as isize; | ||
| let mut replace_offset = 0; | ||
| for cap in name_regex.captures_iter(&content.clone()) { | ||
| if cap.name("ignore").is_some() { | ||
| continue; | ||
| } | ||
| if let Some(name_match) = | ||
| ["n1", "n2", "n3"].iter().find_map(|name| cap.name(name)) | ||
| { | ||
| let name_match_range = | ||
| utils::range_by_offset(&name_match.range(), replace_offset); | ||
| replace_offset += target_len - (name_match_range.len() as isize); | ||
| content.replace_range(name_match_range, &target); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
could we add a bit of docs over what's happening here?
There was a problem hiding this comment.
will add, however this code was written before me so I might get something wrong haha
| utils, Graph, Project, ProjectCompileOutput, ProjectPathsConfig, Result, | ||
| }; | ||
|
|
||
| #[derive(Debug, PartialEq, Eq, Hash, Clone)] |
Ref foundry-rs/foundry#4034.
Solution
solang-parser AST was not sufficient to rename stuff, because it doesn't collect IDs of declarations and we can't match specific identifier to the declaration. Native solc AST gives such ability, so I've implemented native solc AST visitor.
The implementation of flattening itself consits of several steps:
OracleLikeinterfaces becomeOracleLike_0andOracleLike_1)This flattener implementation can be a full replacer of the current impl for all cases when source being flattened can be compiled via solc.