Skip to content

Commit 556f738

Browse files
committed
Remove unsafe unwraps
1 parent 126fda0 commit 556f738

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

crates/ark/src/lsp/folding_range.rs

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use tower_lsp::lsp_types::FoldingRange;
1313
use tower_lsp::lsp_types::FoldingRangeKind;
1414

1515
use super::symbols::parse_comment_as_section;
16+
use crate::lsp;
1617
use crate::lsp::documents::Document;
1718

1819
pub fn folding_range(document: &Document) -> anyhow::Result<Vec<FoldingRange>> {
@@ -89,13 +90,15 @@ fn parse_ts_node(
8990
// Nested comment section handling
9091
let comment_line = get_line_text(document, start.row, None, None);
9192

92-
nested_processor(
93+
if let Err(err) = nested_processor(
9394
document,
9495
comment_stack,
9596
folding_ranges,
9697
start.row,
9798
&comment_line,
98-
);
99+
) {
100+
lsp::log_error!("Can't process comment: {err:?}");
101+
};
99102
region_processor(folding_ranges, region_marker, start.row, &comment_line);
100103
cell_processor(folding_ranges, cell_marker, start.row, &comment_line);
101104
},
@@ -242,51 +245,75 @@ fn nested_processor(
242245
folding_ranges: &mut Vec<FoldingRange>,
243246
line_num: usize,
244247
comment_line: &str,
245-
) {
248+
) -> anyhow::Result<()> {
246249
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
248251
};
252+
249253
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+
));
254257
}
258+
255259
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
259263
}
260264

261-
let Some((last_level, _)) = comment_stack.last().unwrap().last() else {
265+
let Some((last_level, _)) = comment_stack.last_or_error()?.last() else {
262266
tracing::error!("Folding Range: comment_stacks should not be empty here");
263-
return;
267+
return Err(anyhow::anyhow!("Empty comment stack"));
264268
};
269+
265270
match last_level.cmp(&level) {
266271
Ordering::Less => {
267-
comment_stack.last_mut().unwrap().push((level, line_num));
272+
comment_stack.last_mut_or_error()?.push((level, line_num));
268273
break;
269274
},
270275
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;
272277
folding_ranges.push(comment_range(
273278
start_line,
274279
find_last_non_empty_line(document, start_line, line_num - 1),
275280
));
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));
278283
break;
279284
},
280285
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;
282287
folding_ranges.push(comment_range(
283288
start_line,
284289
find_last_non_empty_line(document, start_line, line_num - 1),
285290
));
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
287295
},
288296
}
289297
}
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+
}
290317
}
291318

292319
/// Enum representing the type of region marker

0 commit comments

Comments
 (0)