git.delta.rocks / jrsonnet / refs/commits / 3ee61c42d34d

difftreelog

source

crates/jrsonnet-evaluator/src/trace/location.rs2.5 KiBsourcehistory
1#[allow(clippy::module_name_repetitions)]2#[derive(Clone, PartialEq, Eq, Debug)]3pub struct CodeLocation {4	pub offset: usize,56	pub line: usize,7	pub column: usize,89	pub line_start_offset: usize,10	pub line_end_offset: usize,11}1213#[allow(clippy::module_name_repetitions)]14pub fn location_to_offset(mut file: &str, mut line: usize, column: usize) -> Option<usize> {15	let mut offset = 0;16	while line > 1 {17		let pos = file.find('\n')?;18		offset += pos + 1;19		file = &file[pos + 1..];20		line -= 1;21	}22	offset += column - 1;23	Some(offset)24}2526#[allow(clippy::module_name_repetitions)]27pub fn offset_to_location(file: &str, offsets: &[u32]) -> Vec<CodeLocation> {28	if offsets.is_empty() {29		return vec![];30	}31	let mut line = 1;32	let mut column = 1;33	let max_offset = *offsets.iter().max().expect("offsets is not empty");3435	let mut offset_map = offsets36		.iter()37		.enumerate()38		.map(|(pos, offset)| (*offset, pos))39		.collect::<Vec<_>>();40	offset_map.sort_by_key(|v| v.0);41	offset_map.reverse();4243	let mut out = vec![44		CodeLocation {45			offset: 0,46			column: 0,47			line: 0,48			line_start_offset: 0,49			line_end_offset: 050		};51		offsets.len()52	];53	let mut with_no_known_line_ending = vec![];54	let mut this_line_offset = 0;55	for (pos, ch) in file56		.chars()57		.enumerate()58		.chain(std::iter::once((file.len(), ' ')))59	{60		column += 1;61		match offset_map.last() {62			Some(x) if x.0 == pos as u32 => {63				let out_idx = x.1;64				with_no_known_line_ending.push(out_idx);65				out[out_idx].offset = pos;66				out[out_idx].line = line;67				out[out_idx].column = column;68				out[out_idx].line_start_offset = this_line_offset;69				offset_map.pop();70			}71			_ => {}72		}73		if ch == '\n' {74			line += 1;75			column = 1;7677			for idx in with_no_known_line_ending.drain(..) {78				out[idx].line_end_offset = pos;79			}80			this_line_offset = pos + 1;8182			if pos == max_offset as usize + 1 {83				break;84			}85		}86	}87	let file_end = file.chars().count();88	for idx in with_no_known_line_ending {89		out[idx].line_end_offset = file_end;90	}9192	out93}9495#[cfg(test)]96pub mod tests {97	use super::{offset_to_location, CodeLocation};9899	#[test]100	fn test() {101		assert_eq!(102			offset_to_location(103				"hello world\n_______________________________________________________",104				&[0, 14]105			),106			vec![107				CodeLocation {108					offset: 0,109					line: 1,110					column: 2,111					line_start_offset: 0,112					line_end_offset: 11,113				},114				CodeLocation {115					offset: 14,116					line: 2,117					column: 4,118					line_start_offset: 12,119					line_end_offset: 67120				}121			]122		)123	}124}