@@ -13,6 +13,7 @@ use tower_lsp::lsp_types::FoldingRange;
13
13
use tower_lsp:: lsp_types:: FoldingRangeKind ;
14
14
15
15
use super :: symbols:: parse_comment_as_section;
16
+ use crate :: lsp;
16
17
use crate :: lsp:: documents:: Document ;
17
18
18
19
pub fn folding_range ( document : & Document ) -> anyhow:: Result < Vec < FoldingRange > > {
@@ -89,13 +90,15 @@ fn parse_ts_node(
89
90
// Nested comment section handling
90
91
let comment_line = get_line_text ( document, start. row , None , None ) ;
91
92
92
- nested_processor (
93
+ if let Err ( err ) = nested_processor (
93
94
document,
94
95
comment_stack,
95
96
folding_ranges,
96
97
start. row ,
97
98
& comment_line,
98
- ) ;
99
+ ) {
100
+ lsp:: log_error!( "Can't process comment: {err:?}" ) ;
101
+ } ;
99
102
region_processor ( folding_ranges, region_marker, start. row , & comment_line) ;
100
103
cell_processor ( folding_ranges, cell_marker, start. row , & comment_line) ;
101
104
} ,
@@ -242,51 +245,75 @@ fn nested_processor(
242
245
folding_ranges : & mut Vec < FoldingRange > ,
243
246
line_num : usize ,
244
247
comment_line : & str ,
245
- ) {
248
+ ) -> anyhow :: Result < ( ) > {
246
249
let Some ( ( level, _title) ) = parse_comment_as_section ( comment_line) else {
247
- return ; // return if the line is not a comment section
250
+ return Ok ( ( ) ) ; // return if the line is not a comment section
248
251
} ;
252
+
249
253
if comment_stack. is_empty ( ) {
250
- tracing:: error!(
251
- "Folding Range: comment_stack should always contain at least one element here"
252
- ) ;
253
- return ;
254
+ return Err ( anyhow:: anyhow!(
255
+ "Folding Range: comment_stack should always contain at least one element"
256
+ ) ) ;
254
257
}
258
+
255
259
loop {
256
- if comment_stack. last ( ) . unwrap ( ) . is_empty ( ) {
257
- comment_stack. last_mut ( ) . unwrap ( ) . push ( ( level, line_num) ) ;
258
- return ; // return if the stack is empty
260
+ if comment_stack. last_or_error ( ) ? . is_empty ( ) {
261
+ comment_stack. last_mut_or_error ( ) ? . push ( ( level, line_num) ) ;
262
+ return Ok ( ( ) ) ; // return if the stack is empty
259
263
}
260
264
261
- let Some ( ( last_level, _) ) = comment_stack. last ( ) . unwrap ( ) . last ( ) else {
265
+ let Some ( ( last_level, _) ) = comment_stack. last_or_error ( ) ? . last ( ) else {
262
266
tracing:: error!( "Folding Range: comment_stacks should not be empty here" ) ;
263
- return ;
267
+ return Err ( anyhow :: anyhow! ( "Empty comment stack" ) ) ;
264
268
} ;
269
+
265
270
match last_level. cmp ( & level) {
266
271
Ordering :: Less => {
267
- comment_stack. last_mut ( ) . unwrap ( ) . push ( ( level, line_num) ) ;
272
+ comment_stack. last_mut_or_error ( ) ? . push ( ( level, line_num) ) ;
268
273
break ;
269
274
} ,
270
275
Ordering :: Equal => {
271
- let start_line = comment_stack. last ( ) . unwrap ( ) . last ( ) . unwrap ( ) . 1 ;
276
+ let start_line = comment_stack. last_or_error ( ) ? . last_or_error ( ) ? . 1 ;
272
277
folding_ranges. push ( comment_range (
273
278
start_line,
274
279
find_last_non_empty_line ( document, start_line, line_num - 1 ) ,
275
280
) ) ;
276
- comment_stack. last_mut ( ) . unwrap ( ) . pop ( ) ;
277
- comment_stack. last_mut ( ) . unwrap ( ) . push ( ( level, line_num) ) ;
281
+ comment_stack. last_mut_or_error ( ) ? . pop ( ) ;
282
+ comment_stack. last_mut_or_error ( ) ? . push ( ( level, line_num) ) ;
278
283
break ;
279
284
} ,
280
285
Ordering :: Greater => {
281
- let start_line = comment_stack. last ( ) . unwrap ( ) . last ( ) . unwrap ( ) . 1 ;
286
+ let start_line = comment_stack. last_or_error ( ) ? . last_or_error ( ) ? . 1 ;
282
287
folding_ranges. push ( comment_range (
283
288
start_line,
284
289
find_last_non_empty_line ( document, start_line, line_num - 1 ) ,
285
290
) ) ;
286
- comment_stack. last_mut ( ) . unwrap ( ) . pop ( ) ; // Safe: the loop exits early if the stack becomes empty
291
+ comment_stack
292
+ . last_mut ( )
293
+ . ok_or_else ( || anyhow:: anyhow!( "Empty comment stack" ) ) ?
294
+ . pop ( ) ; // Safe: the loop exits early if the stack becomes empty
287
295
} ,
288
296
}
289
297
}
298
+ Ok ( ( ) )
299
+ }
300
+
301
+ // Mostly a hack until we switch to a stackless an iterative approach
302
+ trait VecResultExt < T > {
303
+ fn last_or_error ( & self ) -> anyhow:: Result < & T > ;
304
+ fn last_mut_or_error ( & mut self ) -> anyhow:: Result < & mut T > ;
305
+ }
306
+
307
+ impl < T > VecResultExt < T > for Vec < T > {
308
+ fn last_or_error ( & self ) -> anyhow:: Result < & T > {
309
+ self . last ( )
310
+ . ok_or_else ( || anyhow:: anyhow!( "Empty comment stack" ) )
311
+ }
312
+
313
+ fn last_mut_or_error ( & mut self ) -> anyhow:: Result < & mut T > {
314
+ self . last_mut ( )
315
+ . ok_or_else ( || anyhow:: anyhow!( "Empty comment stack" ) )
316
+ }
290
317
}
291
318
292
319
/// Enum representing the type of region marker
0 commit comments