@@ -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
@@ -428,18 +446,25 @@ fn collect_assignment(
428
446
return collect_assignment_with_function ( ctx, node, contents, symbols) ;
429
447
}
430
448
431
- // Otherwise, collect as generic object
432
- let name = contents. node_slice ( & lhs) ?. to_string ( ) ;
449
+ if ctx. top_level {
450
+ // Collect as generic object, but only if we're at top-level. Assigned
451
+ // objects in nested functions and blocks cause the outline to become
452
+ // too busy.
453
+ let name = contents. node_slice ( & lhs) ?. to_string ( ) ;
433
454
434
- let start = convert_point_to_position ( contents, lhs. start_position ( ) ) ;
435
- let end = convert_point_to_position ( contents, lhs. end_position ( ) ) ;
455
+ let start = convert_point_to_position ( contents, lhs. start_position ( ) ) ;
456
+ let end = convert_point_to_position ( contents, lhs. end_position ( ) ) ;
436
457
437
- // Now recurse into RHS
438
- let mut children = Vec :: new ( ) ;
439
- collect_symbols ( ctx, & rhs, contents, 0 , & mut children) ?;
458
+ // Now recurse into RHS
459
+ let mut children = Vec :: new ( ) ;
460
+ collect_symbols ( ctx, & rhs, contents, 0 , & mut children) ?;
440
461
441
- let symbol = new_symbol_node ( name, SymbolKind :: VARIABLE , Range { start, end } , children) ;
442
- symbols. push ( symbol) ;
462
+ let symbol = new_symbol_node ( name, SymbolKind :: VARIABLE , Range { start, end } , children) ;
463
+ symbols. push ( symbol) ;
464
+ } else {
465
+ // Recurse into RHS
466
+ collect_symbols ( ctx, & rhs, contents, 0 , symbols) ?;
467
+ }
443
468
444
469
Ok ( ( ) )
445
470
}
@@ -544,8 +569,14 @@ mod tests {
544
569
let node = doc. ast . root_node ( ) ;
545
570
546
571
let mut symbols = Vec :: new ( ) ;
547
- let mut ctx = CollectContext ;
548
- collect_symbols ( & mut ctx, & node, & doc. contents , 0 , & mut symbols) . unwrap ( ) ;
572
+ collect_symbols (
573
+ & mut CollectContext :: new ( ) ,
574
+ & node,
575
+ & doc. contents ,
576
+ 0 ,
577
+ & mut symbols,
578
+ )
579
+ . unwrap ( ) ;
549
580
symbols
550
581
}
551
582
@@ -623,33 +654,7 @@ mod tests {
623
654
624
655
#[ test]
625
656
fn test_symbol_assignment_function_nested ( ) {
626
- let range = Range {
627
- start : Position {
628
- line : 0 ,
629
- character : 20 ,
630
- } ,
631
- end : Position {
632
- line : 0 ,
633
- character : 23 ,
634
- } ,
635
- } ;
636
- let bar = new_symbol ( String :: from ( "bar" ) , SymbolKind :: VARIABLE , range) ;
637
-
638
- let range = Range {
639
- start : Position {
640
- line : 0 ,
641
- character : 0 ,
642
- } ,
643
- end : Position {
644
- line : 0 ,
645
- character : 30 ,
646
- } ,
647
- } ;
648
- let mut foo = new_symbol ( String :: from ( "foo" ) , SymbolKind :: FUNCTION , range) ;
649
- foo. children = Some ( vec ! [ bar] ) ;
650
- foo. detail = Some ( String :: from ( "function()" ) ) ;
651
-
652
- assert_eq ! ( test_symbol( "foo <- function() { bar <- 1 }" ) , vec![ foo] ) ;
657
+ insta:: assert_debug_snapshot!( test_symbol( "foo <- function() { bar <- function() 1 }" ) ) ;
653
658
}
654
659
655
660
#[ test]
@@ -667,23 +672,6 @@ foo <- function() {
667
672
) ) ;
668
673
}
669
674
670
- #[ test]
671
- fn test_symbol_braced_list ( ) {
672
- let range = Range {
673
- start : Position {
674
- line : 0 ,
675
- character : 2 ,
676
- } ,
677
- end : Position {
678
- line : 0 ,
679
- character : 5 ,
680
- } ,
681
- } ;
682
- let foo = new_symbol ( String :: from ( "foo" ) , SymbolKind :: VARIABLE , range) ;
683
-
684
- assert_eq ! ( test_symbol( "{ foo <- 1 }" ) , vec![ foo] ) ;
685
- }
686
-
687
675
#[ test]
688
676
fn test_symbol_section_ranges_extend ( ) {
689
677
let symbols = test_symbol (
@@ -843,4 +831,21 @@ class <- r6::r6class(
843
831
"
844
832
) ) ;
845
833
}
834
+
835
+ #[ test]
836
+ // Assigned variables in nested contexts are not emitted as symbols
837
+ fn test_symbol_nested_assignments ( ) {
838
+ insta:: assert_debug_snapshot!( test_symbol(
839
+ "
840
+ local({
841
+ inner1 <- 1 # Not a symbol
842
+ })
843
+ a <- function() {
844
+ inner2 <- 2 # Not a symbol
845
+ inner3 <- function() 3 # Symbol
846
+ }
847
+ "
848
+ ) ) ;
849
+ assert_eq ! ( test_symbol( "{ foo <- 1 }" ) , vec![ ] ) ;
850
+ }
846
851
}
0 commit comments