@@ -122,7 +122,15 @@ struct Section {
122
122
children : Vec < DocumentSymbol > ,
123
123
}
124
124
125
- struct CollectContext ;
125
+ struct CollectContext {
126
+ top_level : bool ,
127
+ }
128
+
129
+ impl CollectContext {
130
+ fn new ( ) -> Self {
131
+ Self { top_level : true }
132
+ }
133
+ }
126
134
127
135
pub ( crate ) fn document_symbols (
128
136
state : & WorldState ,
@@ -138,8 +146,13 @@ pub(crate) fn document_symbols(
138
146
let mut result = Vec :: new ( ) ;
139
147
140
148
// Extract and process all symbols from the AST
141
- let mut ctx = CollectContext ;
142
- if let Err ( err) = collect_symbols ( & mut ctx, & root_node, contents, 0 , & mut result) {
149
+ if let Err ( err) = collect_symbols (
150
+ & mut CollectContext :: new ( ) ,
151
+ & root_node,
152
+ contents,
153
+ 0 ,
154
+ & mut result,
155
+ ) {
143
156
log:: error!( "Failed to collect symbols: {err:?}" ) ;
144
157
return Ok ( Vec :: new ( ) ) ;
145
158
}
@@ -156,7 +169,12 @@ fn collect_symbols(
156
169
symbols : & mut Vec < DocumentSymbol > ,
157
170
) -> anyhow:: Result < ( ) > {
158
171
match node. node_type ( ) {
159
- NodeType :: Program | NodeType :: BracedExpression => {
172
+ NodeType :: Program => {
173
+ collect_sections ( ctx, node, contents, current_level, symbols) ?;
174
+ } ,
175
+
176
+ NodeType :: BracedExpression => {
177
+ ctx. top_level = false ;
160
178
collect_sections ( ctx, node, contents, current_level, symbols) ?;
161
179
} ,
162
180
@@ -425,18 +443,25 @@ fn collect_assignment(
425
443
return collect_assignment_with_function ( ctx, node, contents, symbols) ;
426
444
}
427
445
428
- // Otherwise, collect as generic object
429
- let name = contents. node_slice ( & lhs) ?. to_string ( ) ;
446
+ if ctx. top_level {
447
+ // Collect as generic object, but only if we're at top-level. Assigned
448
+ // objects in nested functions and blocks cause the outline to become
449
+ // too busy.
450
+ let name = contents. node_slice ( & lhs) ?. to_string ( ) ;
430
451
431
- let start = convert_point_to_position ( contents, lhs. start_position ( ) ) ;
432
- let end = convert_point_to_position ( contents, lhs. end_position ( ) ) ;
452
+ let start = convert_point_to_position ( contents, lhs. start_position ( ) ) ;
453
+ let end = convert_point_to_position ( contents, lhs. end_position ( ) ) ;
433
454
434
- // Now recurse into RHS
435
- let mut children = Vec :: new ( ) ;
436
- collect_symbols ( ctx, & rhs, contents, 0 , & mut children) ?;
455
+ // Now recurse into RHS
456
+ let mut children = Vec :: new ( ) ;
457
+ collect_symbols ( ctx, & rhs, contents, 0 , & mut children) ?;
437
458
438
- let symbol = new_symbol_node ( name, SymbolKind :: VARIABLE , Range { start, end } , children) ;
439
- symbols. push ( symbol) ;
459
+ let symbol = new_symbol_node ( name, SymbolKind :: VARIABLE , Range { start, end } , children) ;
460
+ symbols. push ( symbol) ;
461
+ } else {
462
+ // Recurse into RHS
463
+ collect_symbols ( ctx, & rhs, contents, 0 , symbols) ?;
464
+ }
440
465
441
466
Ok ( ( ) )
442
467
}
@@ -541,8 +566,14 @@ mod tests {
541
566
let node = doc. ast . root_node ( ) ;
542
567
543
568
let mut symbols = Vec :: new ( ) ;
544
- let mut ctx = CollectContext ;
545
- collect_symbols ( & mut ctx, & node, & doc. contents , 0 , & mut symbols) . unwrap ( ) ;
569
+ collect_symbols (
570
+ & mut CollectContext :: new ( ) ,
571
+ & node,
572
+ & doc. contents ,
573
+ 0 ,
574
+ & mut symbols,
575
+ )
576
+ . unwrap ( ) ;
546
577
symbols
547
578
}
548
579
@@ -620,33 +651,7 @@ mod tests {
620
651
621
652
#[ test]
622
653
fn test_symbol_assignment_function_nested ( ) {
623
- let range = Range {
624
- start : Position {
625
- line : 0 ,
626
- character : 20 ,
627
- } ,
628
- end : Position {
629
- line : 0 ,
630
- character : 23 ,
631
- } ,
632
- } ;
633
- let bar = new_symbol ( String :: from ( "bar" ) , SymbolKind :: VARIABLE , range) ;
634
-
635
- let range = Range {
636
- start : Position {
637
- line : 0 ,
638
- character : 0 ,
639
- } ,
640
- end : Position {
641
- line : 0 ,
642
- character : 30 ,
643
- } ,
644
- } ;
645
- let mut foo = new_symbol ( String :: from ( "foo" ) , SymbolKind :: FUNCTION , range) ;
646
- foo. children = Some ( vec ! [ bar] ) ;
647
- foo. detail = Some ( String :: from ( "function()" ) ) ;
648
-
649
- assert_eq ! ( test_symbol( "foo <- function() { bar <- 1 }" ) , vec![ foo] ) ;
654
+ insta:: assert_debug_snapshot!( test_symbol( "foo <- function() { bar <- function() 1 }" ) ) ;
650
655
}
651
656
652
657
#[ test]
@@ -664,23 +669,6 @@ foo <- function() {
664
669
) ) ;
665
670
}
666
671
667
- #[ test]
668
- fn test_symbol_braced_list ( ) {
669
- let range = Range {
670
- start : Position {
671
- line : 0 ,
672
- character : 2 ,
673
- } ,
674
- end : Position {
675
- line : 0 ,
676
- character : 5 ,
677
- } ,
678
- } ;
679
- let foo = new_symbol ( String :: from ( "foo" ) , SymbolKind :: VARIABLE , range) ;
680
-
681
- assert_eq ! ( test_symbol( "{ foo <- 1 }" ) , vec![ foo] ) ;
682
- }
683
-
684
672
#[ test]
685
673
fn test_symbol_section_ranges_extend ( ) {
686
674
let symbols = test_symbol (
@@ -840,4 +828,21 @@ class <- r6::r6class(
840
828
"
841
829
) ) ;
842
830
}
831
+
832
+ #[ test]
833
+ // Assigned variables in nested contexts are not emitted as symbols
834
+ fn test_symbol_nested_assignments ( ) {
835
+ insta:: assert_debug_snapshot!( test_symbol(
836
+ "
837
+ local({
838
+ inner1 <- 1 # Not a symbol
839
+ })
840
+ a <- function() {
841
+ inner2 <- 2 # Not a symbol
842
+ inner3 <- function() 3 # Symbol
843
+ }
844
+ "
845
+ ) ) ;
846
+ assert_eq ! ( test_symbol( "{ foo <- 1 }" ) , vec![ ] ) ;
847
+ }
843
848
}
0 commit comments