@@ -351,6 +351,17 @@ impl Visit<'_> for RubyIndexer<'_> {
351351 self . local_graph . add_definition ( fully_qualified_name, definition) ;
352352 self . local_graph . add_member ( & previous_nesting_id, declaration_id, & name) ;
353353
354+ if let ruby_prism:: Node :: ConstantPathNode { .. } = node. constant_path ( ) {
355+ let constant_path = node. constant_path ( ) . as_constant_path_node ( ) . unwrap ( ) ;
356+ if let Some ( parent) = constant_path. parent ( ) {
357+ self . visit ( & parent) ;
358+ }
359+ }
360+
361+ if let Some ( superclass) = node. superclass ( ) {
362+ self . visit ( & superclass) ;
363+ }
364+
354365 if let Some ( body) = node. body ( ) {
355366 self . visit ( & body) ;
356367 }
@@ -376,13 +387,35 @@ impl Visit<'_> for RubyIndexer<'_> {
376387 self . local_graph . add_definition ( fully_qualified_name, definition) ;
377388 self . local_graph . add_member ( & previous_nesting_id, declaration_id, & name) ;
378389
390+ if let ruby_prism:: Node :: ConstantPathNode { .. } = node. constant_path ( ) {
391+ let constant_path = node. constant_path ( ) . as_constant_path_node ( ) . unwrap ( ) ;
392+ if let Some ( parent) = constant_path. parent ( ) {
393+ self . visit ( & parent) ;
394+ }
395+ }
396+
379397 if let Some ( body) = node. body ( ) {
380398 self . visit ( & body) ;
381399 }
382400
383401 self . scope . leave ( ) ;
384402 }
385403
404+ fn visit_constant_and_write_node ( & mut self , node : & ruby_prism:: ConstantAndWriteNode ) {
405+ self . index_constant_reference ( & node. name_loc ( ) ) ;
406+ self . visit ( & node. value ( ) ) ;
407+ }
408+
409+ fn visit_constant_operator_write_node ( & mut self , node : & ruby_prism:: ConstantOperatorWriteNode ) {
410+ self . index_constant_reference ( & node. name_loc ( ) ) ;
411+ self . visit ( & node. value ( ) ) ;
412+ }
413+
414+ fn visit_constant_or_write_node ( & mut self , node : & ruby_prism:: ConstantOrWriteNode ) {
415+ self . index_constant_reference ( & node. name_loc ( ) ) ;
416+ self . visit ( & node. value ( ) ) ;
417+ }
418+
386419 fn visit_constant_write_node ( & mut self , node : & ruby_prism:: ConstantWriteNode ) {
387420 let previous_nesting_id = self . scope . current_nesting_id ( ) . unwrap_or ( * OBJECT_ID ) ;
388421 let name_loc = node. name_loc ( ) ;
@@ -406,6 +439,18 @@ impl Visit<'_> for RubyIndexer<'_> {
406439 self . visit ( & node. value ( ) ) ;
407440 }
408441
442+ fn visit_constant_path_and_write_node ( & mut self , node : & ruby_prism:: ConstantPathAndWriteNode ) {
443+ self . visit_constant_path_node ( & node. target ( ) ) ;
444+ }
445+
446+ fn visit_constant_path_operator_write_node ( & mut self , node : & ruby_prism:: ConstantPathOperatorWriteNode ) {
447+ self . visit_constant_path_node ( & node. target ( ) ) ;
448+ }
449+
450+ fn visit_constant_path_or_write_node ( & mut self , node : & ruby_prism:: ConstantPathOrWriteNode ) {
451+ self . visit_constant_path_node ( & node. target ( ) ) ;
452+ }
453+
409454 fn visit_constant_path_write_node ( & mut self , node : & ruby_prism:: ConstantPathWriteNode ) {
410455 let previous_nesting_id = self . scope . current_nesting_id ( ) . unwrap_or ( * OBJECT_ID ) ;
411456 let location = node. target ( ) . location ( ) ;
@@ -426,6 +471,10 @@ impl Visit<'_> for RubyIndexer<'_> {
426471
427472 self . local_graph . add_definition ( fully_qualified_name, definition) ;
428473 self . local_graph . add_member ( & previous_nesting_id, declaration_id, & name) ;
474+
475+ if let Some ( parent) = node. target ( ) . parent ( ) {
476+ self . visit ( & parent) ;
477+ }
429478 self . visit ( & node. value ( ) ) ;
430479 }
431480
@@ -434,6 +483,10 @@ impl Visit<'_> for RubyIndexer<'_> {
434483 }
435484
436485 fn visit_constant_path_node ( & mut self , node : & ruby_prism:: ConstantPathNode < ' _ > ) {
486+ if let Some ( parent) = node. parent ( ) {
487+ self . visit ( & parent) ;
488+ }
489+
437490 self . index_constant_reference ( & node. location ( ) ) ;
438491 }
439492
@@ -822,6 +875,16 @@ mod tests {
822875 } ;
823876 }
824877
878+ fn collect_constant_reference_names ( graph : & Graph ) -> Vec < & String > {
879+ graph
880+ . unresolved_references ( )
881+ . iter ( )
882+ . map ( |r| match r {
883+ UnresolvedReference :: Constant ( constant) => graph. names ( ) . get ( constant. name_id ( ) ) . unwrap ( ) ,
884+ } )
885+ . collect :: < Vec < _ > > ( )
886+ }
887+
825888 #[ test]
826889 fn index_class_node ( ) {
827890 let mut context = GraphTest :: new ( ) ;
@@ -1827,10 +1890,24 @@ mod tests {
18271890 } ) ;
18281891
18291892 let refs = context. graph . unresolved_references ( ) ;
1830- assert_eq ! ( refs. len( ) , 1 ) ;
1893+ assert_eq ! ( refs. len( ) , 2 ) ;
18311894
18321895 let reference = & refs[ 0 ] ;
18331896
1897+ match reference {
1898+ UnresolvedReference :: Constant ( unresolved) => {
1899+ assert_eq ! ( unresolved. name_id( ) , & NameId :: from( "Bar" ) ) ;
1900+ assert_eq ! (
1901+ unresolved. nesting( ) . as_ref( ) . unwrap( ) . ids_as_vec( ) ,
1902+ vec![ DeclarationId :: from( "Foo" ) , DeclarationId :: from( "Foo::Bar::Baz" ) ]
1903+ ) ;
1904+ assert_eq ! ( unresolved. uri_id( ) , UriId :: from( "file:///foo.rb" ) ) ;
1905+ assert_eq ! ( unresolved. offset( ) , & Offset :: new( 19 , 22 ) ) ;
1906+ }
1907+ }
1908+
1909+ let reference = & refs[ 1 ] ;
1910+
18341911 match reference {
18351912 UnresolvedReference :: Constant ( unresolved) => {
18361913 assert_eq ! ( unresolved. name_id( ) , & NameId :: from( "String" ) ) ;
@@ -1845,7 +1922,7 @@ mod tests {
18451922 }
18461923
18471924 #[ test]
1848- fn index_unresolved_constant_references ( ) {
1925+ fn index_unresolved_constant_reference_context ( ) {
18491926 let mut context = GraphTest :: new ( ) ;
18501927
18511928 context. index_uri ( "file:///foo.rb" , {
@@ -1891,10 +1968,24 @@ mod tests {
18911968 } ) ;
18921969
18931970 let refs = context. graph . unresolved_references ( ) ;
1894- assert_eq ! ( refs. len( ) , 1 ) ;
1971+ assert_eq ! ( refs. len( ) , 2 ) ;
18951972
18961973 let reference = & refs[ 0 ] ;
18971974
1975+ match reference {
1976+ UnresolvedReference :: Constant ( unresolved) => {
1977+ assert_eq ! ( unresolved. name_id( ) , & NameId :: from( "Object" ) ) ;
1978+ assert_eq ! (
1979+ unresolved. nesting( ) . as_ref( ) . unwrap( ) . ids_as_vec( ) ,
1980+ vec![ DeclarationId :: from( "Foo" ) , DeclarationId :: from( "Foo::Bar" ) ]
1981+ ) ;
1982+ assert_eq ! ( unresolved. uri_id( ) , UriId :: from( "file:///foo.rb" ) ) ;
1983+ assert_eq ! ( unresolved. offset( ) , & Offset :: new( 27 , 33 ) ) ;
1984+ }
1985+ }
1986+
1987+ let reference = & refs[ 1 ] ;
1988+
18981989 match reference {
18991990 UnresolvedReference :: Constant ( unresolved) => {
19001991 assert_eq ! ( unresolved. name_id( ) , & NameId :: from( "Object::String" ) ) ;
@@ -1907,4 +1998,148 @@ mod tests {
19071998 }
19081999 }
19092000 }
2001+
2002+ #[ test]
2003+ fn index_unresolved_constant_references ( ) {
2004+ let mut context = GraphTest :: new ( ) ;
2005+
2006+ context. index_uri ( "file:///foo.rb" , {
2007+ "
2008+ puts C1
2009+ puts C2::C3::C4
2010+ puts foo::C5
2011+ puts C6.foo
2012+ foo = C7
2013+ C8 << 42
2014+ C9 += 42
2015+ C10 ||= 42
2016+ C11 &&= 42
2017+ C12[C13]
2018+ C14::IGNORED1 = 42 # IGNORED1 is an assignment
2019+ C15::C16 << 42
2020+ C17::C18 += 42
2021+ C19::C20 ||= 42
2022+ C21::C22 &&= 42
2023+ puts \" #{C23}\"
2024+
2025+ ::IGNORED2 = 42 # IGNORED2 is an assignment
2026+ puts \" IGNORED3\"
2027+ puts :IGNORED4
2028+ "
2029+ } ) ;
2030+
2031+ assert_eq ! (
2032+ collect_constant_reference_names( & context. graph) ,
2033+ vec![
2034+ "C1" ,
2035+ "C2" ,
2036+ "C2::C3" ,
2037+ "C2::C3::C4" ,
2038+ "foo::C5" ,
2039+ "C6" ,
2040+ "C7" ,
2041+ "C8" ,
2042+ "C9" ,
2043+ "C10" ,
2044+ "C11" ,
2045+ "C12" ,
2046+ "C13" ,
2047+ "C14" ,
2048+ "C15" ,
2049+ "C15::C16" ,
2050+ "C17" ,
2051+ "C17::C18" ,
2052+ "C19" ,
2053+ "C19::C20" ,
2054+ "C21" ,
2055+ "C21::C22" ,
2056+ "C23"
2057+ ]
2058+ ) ;
2059+ }
2060+
2061+ #[ test]
2062+ fn index_unresolved_constant_references_from_values ( ) {
2063+ let mut context = GraphTest :: new ( ) ;
2064+
2065+ context. index_uri ( "file:///foo.rb" , {
2066+ "
2067+ IGNORED1 = C1
2068+ IGNORED2 = [C2::C3]
2069+ C4 << C5
2070+ C6 += C7
2071+ C8 ||= C9
2072+ C10 &&= C11
2073+ C12[C13] = C14
2074+ "
2075+ } ) ;
2076+
2077+ assert_eq ! (
2078+ collect_constant_reference_names( & context. graph) ,
2079+ vec![
2080+ "C1" , "C2" , "C2::C3" , "C4" , "C5" , "C6" , "C7" , "C8" , "C9" , "C10" , "C11" , "C12" , "C13" , "C14" ,
2081+ ]
2082+ ) ;
2083+ }
2084+
2085+ #[ test]
2086+ fn index_unresolved_constant_references_for_classes ( ) {
2087+ let mut context = GraphTest :: new ( ) ;
2088+
2089+ context. index_uri ( "file:///foo.rb" , {
2090+ "
2091+ C1.new
2092+
2093+ class IGNORED < ::C2; end
2094+ class IGNORED < C3; end
2095+ class IGNORED < C4::C5; end
2096+ class IGNORED < ::C6::C7; end
2097+
2098+ class C8::IGNORED; end
2099+ class ::C9::IGNORED; end
2100+ class C10::C11::IGNORED; end
2101+ "
2102+ } ) ;
2103+
2104+ assert_eq ! (
2105+ collect_constant_reference_names( & context. graph) ,
2106+ vec![
2107+ "C1" , "C2" , "C3" , "C4" , "C4::C5" , "C6" , "C6::C7" , "C8" , "C9" , "C10" , "C10::C11" ,
2108+ ]
2109+ ) ;
2110+ }
2111+
2112+ #[ test]
2113+ fn index_unresolved_constant_references_for_modules ( ) {
2114+ let mut context = GraphTest :: new ( ) ;
2115+
2116+ context. index_uri ( "file:///foo.rb" , {
2117+ "
2118+ module X
2119+ include M1
2120+ include M2::M3
2121+ extend M4
2122+ extend M5::M6
2123+ prepend M7
2124+ prepend M8::M9
2125+ end
2126+
2127+ M10.include M11
2128+ M12.extend M13
2129+ M14.prepend M15
2130+
2131+ module M16::IGNORED; end
2132+ module ::M17::IGNORED; end
2133+ module M18::M19::IGNORED; end
2134+ "
2135+ } ) ;
2136+
2137+ assert_eq ! (
2138+ collect_constant_reference_names( & context. graph) ,
2139+ vec![
2140+ "M1" , "M2" , "M2::M3" , "M4" , "M5" , "M5::M6" , "M7" , "M8" , "M8::M9" , "M10" , "M11" , "M12" , "M13" , "M14" ,
2141+ "M15" , "M16" , "M17" , "M18" , "M18::M19" ,
2142+ ]
2143+ ) ;
2144+ }
19102145}
0 commit comments