Skip to content

Commit c86c4aa

Browse files
committed
Cleanup, filter collected dependencies to be source contracts
1 parent 4241d2b commit c86c4aa

File tree

3 files changed

+52
-30
lines changed

3 files changed

+52
-30
lines changed

crates/compilers/src/preprocessor/data.rs

-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub type PreprocessorData = BTreeMap<u32, ContractData>;
1919
pub fn collect_preprocessor_data(
2020
sess: &Session,
2121
hir: &Hir<'_>,
22-
libs: &[PathBuf],
2322
referenced_contracts: HashSet<u32>,
2423
) -> PreprocessorData {
2524
let mut data = PreprocessorData::default();
@@ -31,13 +30,6 @@ pub fn collect_preprocessor_data(
3130
continue;
3231
};
3332

34-
// Do not include external dependencies / libs.
35-
// TODO: better to include only files from project src in order to avoid processing mocks
36-
// within test dir.
37-
if libs.iter().any(|lib_paths| path.starts_with(lib_paths)) {
38-
continue;
39-
}
40-
4133
let contract_data =
4234
ContractData::new(hir, contract_id, contract, path, source, sess.source_map());
4335
data.insert(contract_id, contract_data);

crates/compilers/src/preprocessor/deps.rs

+47-17
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ use std::{
2020

2121
/// Holds data about referenced source contracts and bytecode dependencies.
2222
pub struct PreprocessorDependencies {
23-
// Mapping test contract id -> test contract bytecode dependencies.
24-
pub bytecode_deps: BTreeMap<u32, Vec<BytecodeDependency>>,
23+
// Mapping contract id to preprocess -> contract bytecode dependencies.
24+
pub preprocessed_contracts: BTreeMap<u32, Vec<BytecodeDependency>>,
2525
// Referenced contract ids.
2626
pub referenced_contracts: HashSet<u32>,
2727
}
2828

2929
impl PreprocessorDependencies {
30-
pub fn new(sess: &Session, hir: &Hir<'_>, paths: &[PathBuf]) -> Self {
31-
let mut inner = BTreeMap::new();
32-
let mut references = HashSet::default();
30+
pub fn new(sess: &Session, hir: &Hir<'_>, paths: &[PathBuf], src_dir: &PathBuf) -> Self {
31+
let mut preprocessed_contracts = BTreeMap::new();
32+
let mut referenced_contracts = HashSet::new();
3333
for contract_id in Hir::contract_ids(hir) {
3434
let contract = Hir::contract(hir, contract_id);
3535
let source = Hir::source(hir, contract.source);
@@ -43,18 +43,22 @@ impl PreprocessorDependencies {
4343
continue;
4444
}
4545

46-
let mut deps_collector =
47-
BytecodeDependencyCollector::new(sess.source_map(), hir, source.file.src.as_str());
46+
let mut deps_collector = BytecodeDependencyCollector::new(
47+
sess.source_map(),
48+
hir,
49+
source.file.src.as_str(),
50+
src_dir,
51+
);
4852
// Analyze current contract.
4953
deps_collector.walk_contract(contract);
5054
// Ignore empty test contracts declared in source files with other contracts.
5155
if !deps_collector.dependencies.is_empty() {
52-
inner.insert(contract_id.get(), deps_collector.dependencies);
56+
preprocessed_contracts.insert(contract_id.get(), deps_collector.dependencies);
5357
}
5458
// Record collected referenced contract ids.
55-
references.extend(deps_collector.referenced_contracts);
59+
referenced_contracts.extend(deps_collector.referenced_contracts);
5660
}
57-
Self { bytecode_deps: inner, referenced_contracts: references }
61+
Self { preprocessed_contracts, referenced_contracts }
5862
}
5963
}
6064

@@ -86,22 +90,50 @@ struct BytecodeDependencyCollector<'hir> {
8690
hir: &'hir Hir<'hir>,
8791
/// Source content of current contract.
8892
src: &'hir str,
93+
/// Project source dir, used to determine if referenced contract is a source contract.
94+
src_dir: &'hir PathBuf,
8995
/// Dependencies collected for current contract.
9096
dependencies: Vec<BytecodeDependency>,
91-
/// HIR ids of contracts referenced from current contract.
97+
/// Unique HIR ids of contracts referenced from current contract.
9298
referenced_contracts: HashSet<u32>,
9399
}
94100

95101
impl<'hir> BytecodeDependencyCollector<'hir> {
96-
fn new(source_map: &'hir SourceMap, hir: &'hir Hir<'hir>, src: &'hir str) -> Self {
102+
fn new(
103+
source_map: &'hir SourceMap,
104+
hir: &'hir Hir<'hir>,
105+
src: &'hir str,
106+
src_dir: &'hir PathBuf,
107+
) -> Self {
97108
Self {
98109
source_map,
99110
hir,
100111
src,
112+
src_dir,
101113
dependencies: vec![],
102114
referenced_contracts: HashSet::default(),
103115
}
104116
}
117+
118+
/// Collects reference identified as bytecode dependency of analyzed contract.
119+
/// Discards any reference that is not in project src directory (e.g. external
120+
/// libraries or mock contracts that extend source contracts).
121+
fn collect_dependency(&mut self, dependency: BytecodeDependency) {
122+
let contract = Hir::contract(self.hir, ContractId::new(dependency.referenced_contract));
123+
let source = Hir::source(self.hir, contract.source);
124+
let FileName::Real(path) = &source.file.name else {
125+
return;
126+
};
127+
128+
if !path.starts_with(self.src_dir) {
129+
let path = path.display();
130+
trace!("ignore dependency {path}");
131+
return;
132+
}
133+
134+
self.referenced_contracts.insert(dependency.referenced_contract);
135+
self.dependencies.push(dependency);
136+
}
105137
}
106138

107139
impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
@@ -121,15 +153,14 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
121153
// TODO: check if there's a better way to determine where constructor call
122154
// ends.
123155
let args_len = self.src[name_loc.end..].split_once(';').unwrap().0.len();
124-
self.dependencies.push(BytecodeDependency {
156+
self.collect_dependency(BytecodeDependency {
125157
kind: BytecodeDependencyKind::New(name.to_string(), args_len),
126158
loc: SourceMapLocation::from_span(
127159
self.source_map,
128160
Span::new(expr.span.lo(), expr.span.hi()),
129161
),
130162
referenced_contract: contract_id.get(),
131163
});
132-
self.referenced_contracts.insert(contract_id.get());
133164
}
134165
}
135166
}
@@ -138,12 +169,11 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
138169
if let ExprKind::TypeCall(ty) = &member_expr.kind {
139170
if let TypeKind::Custom(contract_id) = &ty.kind {
140171
if let Some(contract_id) = contract_id.as_contract() {
141-
self.dependencies.push(BytecodeDependency {
172+
self.collect_dependency(BytecodeDependency {
142173
kind: BytecodeDependencyKind::CreationCode,
143174
loc: SourceMapLocation::from_span(self.source_map, expr.span),
144175
referenced_contract: contract_id.get(),
145176
});
146-
self.referenced_contracts.insert(contract_id.get());
147177
}
148178
}
149179
}
@@ -163,7 +193,7 @@ pub fn remove_bytecode_dependencies(
163193
data: &PreprocessorData,
164194
) -> Updates {
165195
let mut updates = Updates::default();
166-
for (contract_id, deps) in &deps.bytecode_deps {
196+
for (contract_id, deps) in &deps.preprocessed_contracts {
167197
let contract = Hir::contract(hir, ContractId::new(*contract_id));
168198
let source = Hir::source(hir, contract.source);
169199
let FileName::Real(path) = &source.file.name else {

crates/compilers/src/preprocessor/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ impl Preprocessor<SolcCompiler> for TestOptimizerPreprocessor {
9191

9292
let hir = &parsing_context.parse_and_lower_to_hir(&hir_arena)?;
9393
// Collect tests and scripts dependencies.
94-
let deps = PreprocessorDependencies::new(&sess, hir, &preprocessed_paths);
95-
// Collect data of source contracts referenced in tests and scripts.
96-
let data = collect_preprocessor_data(
94+
let deps = PreprocessorDependencies::new(
9795
&sess,
9896
hir,
99-
&paths.libraries,
100-
deps.referenced_contracts.clone(),
97+
&preprocessed_paths,
98+
&paths.paths_relative().sources,
10199
);
100+
// Collect data of source contracts referenced in tests and scripts.
101+
let data = collect_preprocessor_data(&sess, hir, deps.referenced_contracts.clone());
102102

103103
// Extend existing sources with preprocessor deploy helper sources.
104104
sources.extend(create_deploy_helpers(&data));

0 commit comments

Comments
 (0)