@@ -1348,66 +1348,65 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> {
13481348
13491349 let is_parent_call_expr = self . is_callee_of_call_expr ;
13501350
1351- match analyze_property_chain ( & it. object , self . semantic ) {
1352- Ok ( source) => {
1353- if let Some ( source) = source {
1354- if is_parent_call_expr {
1355- self . found_dependencies . insert ( source) ;
1356- } else {
1357- let new_chain = Vec :: from ( [ it. property . name ] ) ;
1358-
1359- let mut destructured_props: Vec < Atom < ' a > > = vec ! [ ] ;
1360- let mut did_see_ref = false ;
1361- let needs_full_chain = self
1362- . iter_destructure_bindings ( |id| {
1363- if let Cow :: Borrowed ( id) = id {
1364- if id == "current" {
1365- did_see_ref = true ;
1366- } else {
1367- destructured_props. push ( id. into ( ) ) ;
1368- }
1351+ if let Ok ( source) = analyze_property_chain ( & it. object , self . semantic ) {
1352+ if let Some ( source) = source {
1353+ if is_parent_call_expr {
1354+ self . found_dependencies . insert ( source) ;
1355+ } else {
1356+ let new_chain = Vec :: from ( [ it. property . name ] ) ;
1357+
1358+ let mut destructured_props: Vec < Atom < ' a > > = vec ! [ ] ;
1359+ let mut did_see_ref = false ;
1360+ let needs_full_chain = self
1361+ . iter_destructure_bindings ( |id| {
1362+ if let Cow :: Borrowed ( id) = id {
1363+ if id == "current" {
1364+ did_see_ref = true ;
13691365 } else {
1370- // todo
1366+ destructured_props . push ( id . into ( ) ) ;
13711367 }
1372- } )
1373- . unwrap_or ( true ) ;
1374-
1375- let symbol_id =
1376- self . semantic . scoping ( ) . get_reference ( source. reference_id ) . symbol_id ( ) ;
1377- if needs_full_chain || ( destructured_props. is_empty ( ) && !did_see_ref) {
1368+ } else {
1369+ // todo
1370+ }
1371+ } )
1372+ . unwrap_or ( true ) ;
1373+
1374+ let symbol_id =
1375+ self . semantic . scoping ( ) . get_reference ( source. reference_id ) . symbol_id ( ) ;
1376+ if needs_full_chain || ( destructured_props. is_empty ( ) && !did_see_ref) {
1377+ self . found_dependencies . insert ( Dependency {
1378+ name : source. name ,
1379+ reference_id : source. reference_id ,
1380+ span : source. span ,
1381+ chain : [ source. chain . clone ( ) , new_chain] . concat ( ) ,
1382+ symbol_id,
1383+ } ) ;
1384+ } else {
1385+ for prop in destructured_props {
13781386 self . found_dependencies . insert ( Dependency {
13791387 name : source. name ,
13801388 reference_id : source. reference_id ,
13811389 span : source. span ,
1382- chain : [ source. chain . clone ( ) , new_chain] . concat ( ) ,
1390+ chain : [ source. chain . clone ( ) , new_chain. clone ( ) , vec ! [ prop] ]
1391+ . concat ( ) ,
13831392 symbol_id,
13841393 } ) ;
1385- } else {
1386- for prop in destructured_props {
1387- self . found_dependencies . insert ( Dependency {
1388- name : source. name ,
1389- reference_id : source. reference_id ,
1390- span : source. span ,
1391- chain : [ source. chain . clone ( ) , new_chain. clone ( ) , vec ! [ prop] ]
1392- . concat ( ) ,
1393- symbol_id,
1394- } ) ;
1395- }
13961394 }
13971395 }
13981396 }
1399-
1400- let cur_skip_reporting_dependency = self . skip_reporting_dependency ;
1401- self . skip_reporting_dependency = true ;
1402- self . visit_expression ( & it. object ) ;
1403- self . skip_reporting_dependency = cur_skip_reporting_dependency;
14041397 }
1398+
1399+ let cur_skip_reporting_dependency = self . skip_reporting_dependency ;
1400+ self . skip_reporting_dependency = true ;
1401+ self . is_callee_of_call_expr = false ;
1402+ self . visit_expression ( & it. object ) ;
1403+ self . skip_reporting_dependency = cur_skip_reporting_dependency;
1404+ } else {
14051405 // this means that some part of the chain could not be analyzed
14061406 // for example `foo.bar.baz().abc`. `baz()` cannot be statically analyzed
14071407 // instead, continue to go down, looking at the object to gather dependencies
1408- Err ( ( ) ) => {
1409- self . visit_expression ( & it. object ) ;
1410- }
1408+ self . is_callee_of_call_expr = false ;
1409+ self . visit_expression ( & it. object ) ;
14111410 }
14121411 }
14131412
@@ -2656,6 +2655,25 @@ fn test() {
26562655 onStuff();
26572656 }, []);
26582657 }" ,
2658+ // Issue #15796 - object property access should work correctly
2659+ r"export const FileSize = ({ file, showSize = true }) => {
2660+ const fileSizeInMB = useMemo(
2661+ () => (showSize ? (file.size / (1024 * 1024)).toFixed(2) : undefined),
2662+ [showSize, file.size],
2663+ );
2664+ return fileSizeInMB;
2665+ }" ,
2666+ // Additional tests for nested property access within expressions
2667+ r"function MyComponent({ obj }) {
2668+ useMemo(() => {
2669+ return (obj.value * 2).toFixed(2);
2670+ }, [obj.value]);
2671+ }" ,
2672+ r"function MyComponent({ data }) {
2673+ useCallback(() => {
2674+ console.log((data.count + 1).toString());
2675+ }, [data.count]);
2676+ }" ,
26592677 ] ;
26602678
26612679 let fail = vec ! [
0 commit comments