git.delta.rocks / jrsonnet / refs/commits / e53349155ac3

difftreelog

source

crates/jrsonnet-evaluator/src/trace/location.rs2.3 KiBsourcehistory
1#[derive(Clone, PartialEq, Debug)]2pub struct CodeLocation {3	pub offset: usize,45	pub line: usize,6	pub column: usize,78	pub line_start_offset: usize,9	pub line_end_offset: usize,10}1112pub fn location_to_offset(mut file: &str, mut line: usize, column: usize) -> Option<usize> {13	let mut offset = 0;14	while line > 1 {15		let pos = file.find('\n')?;16		offset += pos + 1;17		file = &file[pos + 1..];18		line -= 1;19	}20	offset += column - 1;21	Some(offset)22}2324pub fn offset_to_location(file: &str, offsets: &[usize]) -> Vec<CodeLocation> {25	if offsets.is_empty() {26		return vec![];27	}28	let mut line = 1;29	let mut column = 1;30	let max_offset = *offsets.iter().max().unwrap();3132	let mut offset_map = offsets33		.iter()34		.enumerate()35		.map(|(pos, offset)| (*offset, pos))36		.collect::<Vec<_>>();37	offset_map.sort_by_key(|v| v.0);38	offset_map.reverse();3940	let mut out = vec![41		CodeLocation {42			offset: 0,43			column: 0,44			line: 0,45			line_start_offset: 0,46			line_end_offset: 047		};48		offsets.len()49	];50	let mut with_no_known_line_ending = vec![];51	let mut this_line_offset = 0;52	for (pos, ch) in file53		.chars()54		.enumerate()55		.chain(std::iter::once((file.len(), ' ')))56	{57		column += 1;58		match offset_map.last() {59			Some(x) if x.0 == pos => {60				let out_idx = x.1;61				with_no_known_line_ending.push(out_idx);62				out[out_idx].offset = pos;63				out[out_idx].line = line;64				out[out_idx].column = column;65				out[out_idx].line_start_offset = this_line_offset;66				offset_map.pop();67			}68			_ => {}69		}70		if ch == '\n' {71			line += 1;72			column = 1;7374			for idx in with_no_known_line_ending.drain(..) {75				out[idx].line_end_offset = pos;76			}77			this_line_offset = pos + 1;7879			if pos == max_offset + 1 {80				break;81			}82		}83	}84	let file_end = file.chars().count();85	for idx in with_no_known_line_ending {86		out[idx].line_end_offset = file_end;87	}8889	out90}9192#[cfg(test)]93pub mod tests {94	use super::{offset_to_location, CodeLocation};9596	#[test]97	fn test() {98		assert_eq!(99			offset_to_location(100				"hello world\n_______________________________________________________",101				&[0, 14]102			),103			vec![104				CodeLocation {105					offset: 0,106					line: 1,107					column: 2,108					line_start_offset: 0,109					line_end_offset: 11,110				},111				CodeLocation {112					offset: 14,113					line: 2,114					column: 4,115					line_start_offset: 12,116					line_end_offset: 67117				}118			]119		)120	}121}