@@ -6,7 +6,7 @@ use foundry_compilers::Updates;
6
6
use itertools:: Itertools ;
7
7
use solar_parse:: interface:: Session ;
8
8
use solar_sema:: {
9
- hir:: { ContractId , Expr , ExprKind , Hir , NamedArg , TypeKind , Visit } ,
9
+ hir:: { CallArgs , ContractId , Expr , ExprKind , Hir , NamedArg , Stmt , StmtKind , TypeKind , Visit } ,
10
10
interface:: { data_structures:: Never , source_map:: FileName , SourceMap } ,
11
11
} ;
12
12
use std:: {
@@ -105,6 +105,8 @@ enum BytecodeDependencyKind {
105
105
value : Option < String > ,
106
106
/// `salt` (if any) used when creating contract.
107
107
salt : Option < String > ,
108
+ /// Whether it's a try contract creation statement.
109
+ try_stmt : bool ,
108
110
} ,
109
111
}
110
112
@@ -182,42 +184,17 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
182
184
183
185
fn visit_expr ( & mut self , expr : & ' hir Expr < ' hir > ) -> ControlFlow < Self :: BreakValue > {
184
186
match & expr. kind {
185
- ExprKind :: Call ( ty, call_args, named_args) => {
186
- if let ExprKind :: New ( ty_new) = & ty. kind {
187
- if let TypeKind :: Custom ( item_id) = ty_new. kind {
188
- if let Some ( contract_id) = item_id. as_contract ( ) {
189
- let name_loc = span_to_range ( self . source_map , ty_new. span ) ;
190
- let name = & self . src [ name_loc] ;
191
-
192
- // Calculate offset to remove named args, e.g. for an expression like
193
- // `new Counter {value: 333} ( address(this))`
194
- // the offset will be used to replace `{value: 333} ( ` with `(`
195
- let call_args_offset = if named_args. is_some ( ) && !call_args. is_empty ( )
196
- {
197
- ( call_args. span ( ) . lo ( ) - ty_new. span . hi ( ) ) . to_usize ( )
198
- } else {
199
- 0
200
- } ;
201
-
202
- let args_len = expr. span . hi ( ) - ty_new. span . hi ( ) ;
203
- self . collect_dependency ( BytecodeDependency {
204
- kind : BytecodeDependencyKind :: New {
205
- name : name. to_string ( ) ,
206
- args_length : args_len. to_usize ( ) ,
207
- call_args_offset,
208
- value : named_arg (
209
- self . src ,
210
- named_args,
211
- "value" ,
212
- self . source_map ,
213
- ) ,
214
- salt : named_arg ( self . src , named_args, "salt" , self . source_map ) ,
215
- } ,
216
- loc : span_to_range ( self . source_map , ty. span ) ,
217
- referenced_contract : contract_id,
218
- } ) ;
219
- }
220
- }
187
+ ExprKind :: Call ( call_expr, call_args, named_args) => {
188
+ if let Some ( dependency) = handle_call_expr (
189
+ self . src ,
190
+ self . source_map ,
191
+ expr,
192
+ call_expr,
193
+ call_args,
194
+ named_args,
195
+ false ,
196
+ ) {
197
+ self . collect_dependency ( dependency) ;
221
198
}
222
199
}
223
200
ExprKind :: Member ( member_expr, ident) => {
@@ -239,6 +216,78 @@ impl<'hir> Visit<'hir> for BytecodeDependencyCollector<'hir> {
239
216
}
240
217
self . walk_expr ( expr)
241
218
}
219
+
220
+ fn visit_stmt ( & mut self , stmt : & ' hir Stmt < ' hir > ) -> ControlFlow < Self :: BreakValue > {
221
+ if let StmtKind :: Try ( stmt_try) = stmt. kind {
222
+ if let ExprKind :: Call ( call_expr, call_args, named_args) = stmt_try. expr . kind {
223
+ if let Some ( dependency) = handle_call_expr (
224
+ self . src ,
225
+ self . source_map ,
226
+ & stmt_try. expr ,
227
+ call_expr,
228
+ & call_args,
229
+ & named_args,
230
+ true ,
231
+ ) {
232
+ self . collect_dependency ( dependency) ;
233
+ for clause in stmt_try. clauses {
234
+ for & var in clause. args {
235
+ self . visit_nested_var ( var) ?;
236
+ }
237
+ for stmt in clause. block {
238
+ self . visit_stmt ( stmt) ?;
239
+ }
240
+ }
241
+ return ControlFlow :: Continue ( ( ) ) ;
242
+ }
243
+ }
244
+ }
245
+ self . walk_stmt ( stmt)
246
+ }
247
+ }
248
+
249
+ /// Helper function to analyze and extract bytecode dependency from a given call expression.
250
+ fn handle_call_expr (
251
+ src : & str ,
252
+ source_map : & SourceMap ,
253
+ parent_expr : & Expr < ' _ > ,
254
+ call_expr : & Expr < ' _ > ,
255
+ call_args : & CallArgs < ' _ > ,
256
+ named_args : & Option < & [ NamedArg < ' _ > ] > ,
257
+ try_stmt : bool ,
258
+ ) -> Option < BytecodeDependency > {
259
+ if let ExprKind :: New ( ty_new) = & call_expr. kind {
260
+ if let TypeKind :: Custom ( item_id) = ty_new. kind {
261
+ if let Some ( contract_id) = item_id. as_contract ( ) {
262
+ let name_loc = span_to_range ( source_map, ty_new. span ) ;
263
+ let name = & src[ name_loc] ;
264
+
265
+ // Calculate offset to remove named args, e.g. for an expression like
266
+ // `new Counter {value: 333} ( address(this))`
267
+ // the offset will be used to replace `{value: 333} ( ` with `(`
268
+ let call_args_offset = if named_args. is_some ( ) && !call_args. is_empty ( ) {
269
+ ( call_args. span ( ) . lo ( ) - ty_new. span . hi ( ) ) . to_usize ( )
270
+ } else {
271
+ 0
272
+ } ;
273
+
274
+ let args_len = parent_expr. span . hi ( ) - ty_new. span . hi ( ) ;
275
+ return Some ( BytecodeDependency {
276
+ kind : BytecodeDependencyKind :: New {
277
+ name : name. to_string ( ) ,
278
+ args_length : args_len. to_usize ( ) ,
279
+ call_args_offset,
280
+ value : named_arg ( src, named_args, "value" , source_map) ,
281
+ salt : named_arg ( src, named_args, "salt" , source_map) ,
282
+ try_stmt,
283
+ } ,
284
+ loc : span_to_range ( source_map, call_expr. span ) ,
285
+ referenced_contract : contract_id,
286
+ } )
287
+ }
288
+ }
289
+ }
290
+ None
242
291
}
243
292
244
293
/// Helper function to extract value of a given named arg.
@@ -300,8 +349,14 @@ pub(crate) fn remove_bytecode_dependencies(
300
349
call_args_offset,
301
350
value,
302
351
salt,
352
+ try_stmt,
303
353
} => {
304
- let mut update = format ! ( "{name}(payable({vm}.deployCode({{" ) ;
354
+ let ( mut update, closing_seq) = if * try_stmt {
355
+ ( String :: new ( ) , "})" )
356
+ } else {
357
+ ( format ! ( "{name}(payable(" ) , "})))" )
358
+ } ;
359
+ update. push_str ( & format ! ( "{vm}.deployCode({{" ) ) ;
305
360
update. push_str ( & format ! ( "_artifact: \" {artifact}\" " ) ) ;
306
361
307
362
if let Some ( value) = value {
@@ -327,13 +382,14 @@ pub(crate) fn remove_bytecode_dependencies(
327
382
update. push ( '(' ) ;
328
383
}
329
384
updates. insert ( ( dep. loc . start , dep. loc . end + call_args_offset, update) ) ;
385
+
330
386
updates. insert ( (
331
387
dep. loc . end + args_length,
332
388
dep. loc . end + args_length,
333
- ")})))" . to_string ( ) ,
389
+ format ! ( "){closing_seq}" ) ,
334
390
) ) ;
335
391
} else {
336
- update. push_str ( "})))" ) ;
392
+ update. push_str ( closing_seq ) ;
337
393
updates. insert ( ( dep. loc . start , dep. loc . end + args_length, update) ) ;
338
394
}
339
395
}
0 commit comments