Skip to content

Commit 234d63b

Browse files
author
Paolo Tranquilli
committed
Rust: avoid panic from line_index crate
We found out we can stumble upon a `line_index.line_col` panic, specifically when reporting a macro parse error. This replaces `line_col` with safer `try_line_col`, and deals more gracefully with the error.
1 parent aa43d50 commit 234d63b

File tree

1 file changed

+17
-11
lines changed
  • rust/extractor/src/translate

1 file changed

+17
-11
lines changed

rust/extractor/src/translate/base.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ pub struct Translator<'a> {
8181
pub semantics: Option<&'a Semantics<'a, RootDatabase>>,
8282
}
8383

84+
const UNKNOWN_LOCATION: (LineCol, LineCol) =
85+
(LineCol { line: 0, col: 0 }, LineCol { line: 0, col: 0 });
86+
8487
impl<'a> Translator<'a> {
8588
pub fn new(
8689
trap: TrapFile,
@@ -98,8 +101,8 @@ impl<'a> Translator<'a> {
98101
semantics: semantic_info.map(|i| i.semantics),
99102
}
100103
}
101-
fn location(&self, range: TextRange) -> (LineCol, LineCol) {
102-
let start = self.line_index.line_col(range.start());
104+
fn location(&self, range: TextRange) -> Option<(LineCol, LineCol)> {
105+
let start = self.line_index.try_line_col(range.start())?;
103106
let range_end = range.end();
104107
// QL end positions are inclusive, while TextRange offsets are exclusive and point at the position
105108
// right after the last character of the range. We need to shift the end offset one character to the left to
@@ -111,11 +114,11 @@ impl<'a> Translator<'a> {
111114
.checked_sub(i.into())
112115
.and_then(|x| self.line_index.try_line_col(x))
113116
{
114-
return (start, end);
117+
return Some((start, end));
115118
}
116119
}
117-
let end = self.line_index.line_col(range_end);
118-
(start, end)
120+
let end = self.line_index.try_line_col(range_end)?;
121+
Some((start, end))
119122
}
120123

121124
pub fn text_range_for_node(&mut self, node: &impl ast::AstNode) -> Option<TextRange> {
@@ -132,16 +135,18 @@ impl<'a> Translator<'a> {
132135
}
133136
}
134137
pub fn emit_location<T: TrapClass>(&mut self, label: Label<T>, node: &impl ast::AstNode) {
135-
if let Some(range) = self.text_range_for_node(node) {
136-
let (start, end) = self.location(range);
138+
if let Some((start, end)) = self
139+
.text_range_for_node(node)
140+
.and_then(|r| self.location(r))
141+
{
137142
self.trap.emit_location(self.label, label, start, end)
138143
} else {
139144
self.emit_diagnostic(
140145
DiagnosticSeverity::Debug,
141146
"locations".to_owned(),
142147
"missing location for AstNode".to_owned(),
143148
"missing location for AstNode".to_owned(),
144-
(LineCol { line: 0, col: 0 }, LineCol { line: 0, col: 0 }),
149+
UNKNOWN_LOCATION,
145150
);
146151
}
147152
}
@@ -156,8 +161,9 @@ impl<'a> Translator<'a> {
156161
if let Some(clipped_range) = token_range.intersect(parent_range) {
157162
if let Some(parent_range2) = self.text_range_for_node(parent) {
158163
let token_range = clipped_range + parent_range2.start() - parent_range.start();
159-
let (start, end) = self.location(token_range);
160-
self.trap.emit_location(self.label, label, start, end)
164+
if let Some((start, end)) = self.location(token_range) {
165+
self.trap.emit_location(self.label, label, start, end)
166+
}
161167
}
162168
}
163169
}
@@ -206,7 +212,7 @@ impl<'a> Translator<'a> {
206212
"parse_error".to_owned(),
207213
message.clone(),
208214
message,
209-
location,
215+
location.unwrap_or(UNKNOWN_LOCATION),
210216
);
211217
}
212218
}

0 commit comments

Comments
 (0)