Skip to content

Commit ca91e15

Browse files
authored
Merge pull request #16 from github/aibaars/locations
Fix locations in the
2 parents 743eca7 + 4c04b8b commit ca91e15

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

extractor/src/extractor.rs

+47-7
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl Visitor<'_> {
103103
}
104104
if node.is_missing() {
105105
error!(
106-
"{}:{}: parse expecting '{}'",
106+
"{}:{}: parse error: expecting '{}'",
107107
&self.path,
108108
node.start_position().row,
109109
node.kind()
@@ -134,7 +134,8 @@ impl Visitor<'_> {
134134
let loc = Label::Location(self.counter);
135135
self.trap_output.push(TrapEntry::New(id));
136136
self.trap_output.push(TrapEntry::New(loc));
137-
self.trap_output.push(location_for(&self.path, loc, node));
137+
self.trap_output
138+
.push(location_for(&self.source, &self.path, loc, node));
138139
let table_name = node_type_name(node.kind(), node.is_named());
139140
let args: Option<Vec<Arg>>;
140141
if fields.is_empty() {
@@ -272,11 +273,50 @@ fn sliced_source_arg(source: &Vec<u8>, n: Node) -> Arg {
272273
}
273274

274275
// Emit a 'Located' TrapEntry for the provided node, appropriately calibrated.
275-
fn location_for<'a>(fp: &String, label: Label, n: Node) -> TrapEntry {
276-
let start_line = n.start_position().row;
277-
let start_col = n.start_position().column;
278-
let end_line = n.end_position().row;
279-
let end_col = n.end_position().column;
276+
fn location_for<'a>(source: &Vec<u8>, fp: &String, label: Label, n: Node) -> TrapEntry {
277+
// Tree-sitter row, column values are 0-based while CodeQL starts
278+
// counting at 1. In addition Tree-sitter's row and column for the
279+
// end position are exclusive while CodeQL's end positions are inclusive.
280+
// This means that all values should be incremented by 1 and in addition the
281+
// end position needs to be shift 1 to the left. In most cases this means
282+
// simply incrementing all values except the end column except in cases where
283+
// the end column is 0 (start of a line). In such cases the end position must be
284+
// set to the end of the previous line.
285+
let start_line = n.start_position().row + 1;
286+
let start_col = n.start_position().column + 1;
287+
let mut end_line = n.end_position().row + 1;
288+
let mut end_col = n.end_position().column;
289+
if end_col == 0 {
290+
if start_line >= end_line {
291+
// the range is empty, clip it to sensible values
292+
end_line = start_line;
293+
end_col = start_col - 1;
294+
} else {
295+
let mut index = n.end_byte();
296+
// end_col = 0 means that we are the start of a line
297+
// unfortunately 0 is invalid as column number, therefore
298+
// we should update the end location to be the end of the
299+
// previous line
300+
if index > 0 && index <= source.len() {
301+
index -= 1;
302+
if source[index] != b'\n' {
303+
error!("expecting a line break symbol, but none found while correcting end column value");
304+
}
305+
end_line -= 1;
306+
end_col = 1;
307+
while index > 0 && source[index - 1] != b'\n' {
308+
index -= 1;
309+
end_col += 1;
310+
}
311+
} else {
312+
error!(
313+
"cannot correct end column value: end_byte index {} is not in range [0,{}]",
314+
index,
315+
source.len()
316+
);
317+
}
318+
}
319+
}
280320
TrapEntry::Located(vec![
281321
Arg::Label(label),
282322
Arg::String(fp.to_owned()),

0 commit comments

Comments
 (0)