difftreelog
feat show only source code slice on error
in: master
2 files changed
cmds/jsonnet/src/location.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/jsonnet/src/location.rs
@@ -0,0 +1,99 @@
+#[derive(Clone, PartialEq, Debug)]
+pub struct CodeLocation {
+ pub line: usize,
+ pub column: usize,
+
+ pub line_start_offset: usize,
+ pub line_end_offset: usize,
+}
+
+pub fn offset_to_location(file: &str, offsets: &[usize]) -> Vec<CodeLocation> {
+ if offsets.is_empty() {
+ return vec![];
+ }
+ let mut line = 1;
+ let mut column = 0;
+ let max_offset = *offsets.iter().max().unwrap();
+
+ let mut offset_map = offsets
+ .iter()
+ .enumerate()
+ .map(|(pos, offset)| (*offset, pos))
+ .collect::<Vec<_>>();
+ offset_map.sort_by_key(|v| v.0);
+ offset_map.reverse();
+
+ let mut out = vec![
+ CodeLocation {
+ column: 0,
+ line: 0,
+ line_start_offset: 0,
+ line_end_offset: 0
+ };
+ offsets.len()
+ ];
+ let mut with_no_known_line_ending = vec![];
+ let mut this_line_offset = 0;
+ for (pos, ch) in file.chars().enumerate() {
+ column += 1;
+ match offset_map.last() {
+ Some(x) if x.0 == pos => {
+ let out_idx = x.1;
+ with_no_known_line_ending.push(out_idx);
+ out[out_idx].line = line;
+ out[out_idx].column = column;
+ out[out_idx].line_start_offset = this_line_offset + 1;
+ offset_map.pop();
+ }
+ _ => {}
+ }
+ if ch == '\n' {
+ line += 1;
+ column = 0;
+
+ for idx in with_no_known_line_ending.drain(..) {
+ out[idx].line_end_offset = pos;
+ }
+ this_line_offset = pos;
+
+ if pos == max_offset + 1 {
+ break;
+ }
+ }
+ }
+ let file_end = file.chars().count();
+ for idx in with_no_known_line_ending {
+ out[idx].line_end_offset = file_end;
+ }
+
+ out
+}
+
+#[cfg(test)]
+pub mod tests {
+ use super::{offset_to_location, CodeLocation};
+
+ #[test]
+ fn test() {
+ assert_eq!(
+ offset_to_location(
+ "hello world\n_______________________________________________________",
+ &[0, 14]
+ ),
+ vec![
+ CodeLocation {
+ line: 1,
+ column: 1,
+ line_start_offset: 0,
+ line_end_offset: 11
+ },
+ CodeLocation {
+ line: 2,
+ column: 3,
+ line_start_offset: 11,
+ line_end_offset: 67
+ }
+ ]
+ )
+ }
+}
cmds/jsonnet/src/main.rsdiffbeforeafterboth1pub mod location;21use clap::Clap;3use clap::Clap;2use jsonnet_evaluator::{EvaluationState, LocError, StackTrace, Val};4use jsonnet_evaluator::{EvaluationState, LocError, StackTrace, Val};5use location::{offset_to_location, CodeLocation};3use std::env::current_dir;6use std::env::current_dir;4use std::str::FromStr;7use std::str::FromStr;58145 print_trace(&(err.1), evaluator, &opts);148 print_trace(&(err.1), evaluator, &opts);146}149}147150148fn line_columns(file: &str, offsets: &[usize]) -> Vec<(usize, usize)> {151fn print_trace(trace: &StackTrace, evaluator: EvaluationState, opts: &Opts) {152 use annotate_snippets::{153 display_list::{DisplayList, FormatOptions},154 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},155 };156 for item in trace.0.iter() {157 let desc = &item.1;149 if offsets.is_empty() {158 if (item.0).1.is_none() {150 return vec![];159 continue;151 }160 }152 let mut line = 0;153 let mut column = 0;154 let max_offset = *offsets.iter().max().unwrap();161 let source = (item.0).1.clone().unwrap();155156 let mut offset_map = offsets162 let code = evaluator.get_source(&source.0);157 .iter()158 .enumerate()159 .map(|(pos, offset)| (*offset, pos))160 .collect::<Vec<_>>();161 offset_map.sort_by_key(|v| v.0);163 if code.is_none() {164 continue;165 }162 offset_map.reverse();166 let code = code.unwrap();163164 let mut out = vec![(0usize, 0usize); offsets.len()];167 let start_end = offset_to_location(&code, &[source.1, source.2]);168 if opts.trace_format == TraceFormat::Custom {169 let source_fragment: String = code170 .chars()165 for (pos, ch) in (0..max_offset + 1).zip(file.chars()) {171 .skip(start_end[0].line_start_offset)166 column += 1;172 .take(start_end[1].line_end_offset - start_end[0].line_start_offset)173 .collect();174 let snippet = Snippet {175 opt: FormatOptions {176 color: true,167 if offset_map.last().unwrap().0 == pos {177 ..Default::default()178 },179 title: Some(Annotation {180 label: Some(&item.1),181 id: None,182 annotation_type: AnnotationType::Error,183 }),184 footer: vec![],185 slices: vec![Slice {186 source: &source_fragment,187 line_start: start_end[0].line,188 origin: Some(&source.0.to_str().unwrap()),189 fold: false,190 annotations: vec![SourceAnnotation {191 label: desc,192 annotation_type: AnnotationType::Error,193 range: (194 source.1 - start_end[0].line_start_offset,195 source.2 - start_end[0].line_start_offset,196 ),197 }],198 }],199 };200168 out[offset_map.last().unwrap().1] = (line, column);201 let dl = DisplayList::from(snippet);169 offset_map.pop();202 println!("{}", dl);170 }171 if ch == '\n' {203 } else {172 line += 1;204 print_jsonnet_pair(205 source.0.to_str().unwrap(),173 column = 0;206 &start_end[0],207 &start_end[1],208 opts.trace_format == TraceFormat::GoJsonnet,209 );174 }210 }175 }176177 out178}211 }212}179213180fn print_trace(trace: &StackTrace, evaluator: EvaluationState, opts: &Opts) {214fn print_jsonnet_pair(file: &str, start: &CodeLocation, end: &CodeLocation, is_go: bool) {181 use annotate_snippets::{182 display_list::{DisplayList, FormatOptions},183 snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},221222 let dl = DisplayList::from(snippet);223 println!("{}", dl);224 } else {225 if opts.trace_format == TraceFormat::CppJsonnet {215 if is_go {226 print!(" ");216 print!(" ");227 } else {217 } else {228 print!(" ");218 print!(" ");229 }219 }230 print!("{}:", source.0.to_str().unwrap());220 print!("{}:", file);231 if start_end[0].0 == start_end[1].0 {221 if start.line == end.line {232 // IDK why, but this is the behavior original jsonnet shows222 // IDK why, but this is the behavior original jsonnet cpp impl shows233 if start_end[0].1 == start_end[1].1223 if start.column == end.column || !is_go && start.column + 1 == end.column {234 || opts.trace_format == TraceFormat::CppJsonnet235 && start_end[0].1 + 1 == start_end[1].1236 {237 println!("{}:{}", start_end[0].0 + 1, start_end[0].1)224 println!("{}:{}", start.line, end.column)238 } else {225 } else {239 println!(226 println!("{}:{}-{}", start.line, start.column, end.column);240 "{}:{}-{}",241 start_end[0].0 + 1,242 start_end[0].1,243 start_end[1].1244 );245 }227 }246 } else {228 } else {247 println!(229 println!(248 "({}:{})-({}:{})",230 "({}:{})-({}:{})",249 start_end[0].0 + 1,231 start.line, end.column, start.line, end.column250 start_end[0].1,251 start_end[1].0 + 1,252 start_end[1].1253 );232 );254 }233 }255 }234}256 }257}258235