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

difftreelog

perf move error and stacktrace to heap

Lach2020-08-23parent: #d09f1c2.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -76,7 +76,7 @@
 }
 impl From<Error> for LocError {
 	fn from(e: Error) -> Self {
-		Self(e, StackTrace(vec![]))
+		Self::new(e)
 	}
 }
 
@@ -89,10 +89,20 @@
 pub struct StackTrace(pub Vec<StackTraceElement>);
 
 #[derive(Debug, Clone)]
-pub struct LocError(pub Error, pub StackTrace);
+pub struct LocError(Box<(Error, StackTrace)>);
 impl LocError {
 	pub fn new(e: Error) -> Self {
-		Self(e, StackTrace(vec![]))
+		Self(Box::new((e, StackTrace(vec![]))))
+	}
+
+	pub fn error(&self) -> &Error {
+		&(self.0).0
+	}
+	pub fn trace(&self) -> &StackTrace {
+		&(self.0).1
+	}
+	pub fn trace_mut(&mut self) -> &mut StackTrace {
+		&mut (self.0).1
 	}
 }
 
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -285,7 +285,7 @@
 		let result = f();
 		self.data_mut().stack_depth -= 1;
 		if let Err(mut err) = result {
-			(err.1).0.push(StackTraceElement {
+			err.trace_mut().0.push(StackTraceElement {
 				location: e.clone(),
 				desc: frame_desc(),
 			});
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
after · crates/jrsonnet-evaluator/src/trace/mod.rs
1mod location;23use crate::{EvaluationState, LocError};4pub use location::*;5use std::path::PathBuf;67/// How paths should be displayed8pub enum PathResolver {9	/// Only filename will be shown10	FileName,11	/// Absolute path of file12	Absolute,13	/// Relative path from base directory14	Relative(PathBuf),15}1617impl PathResolver {18	pub fn resolve(&self, from: &PathBuf) -> String {19		match self {20			PathResolver::FileName => from.file_name().unwrap().to_string_lossy().into_owned(),21			PathResolver::Absolute => from.to_string_lossy().into_owned(),22			PathResolver::Relative(base) => {23				if from.is_relative() {24					return from.to_string_lossy().into_owned();25				}26				pathdiff::diff_paths(from, base)27					.unwrap()28					.to_string_lossy()29					.into_owned()30			}31		}32	}33}3435/// Implements trace to string pretty-printing36pub trait TraceFormat {37	fn write_trace(38		&self,39		out: &mut dyn std::fmt::Write,40		evaluation_state: &EvaluationState,41		error: &LocError,42	) -> Result<(), std::fmt::Error>;43	// fn print_trace(44	// 	&self,45	// 	evaluation_state: &EvaluationState,46	// 	error: &LocError,47	// ) -> Result<(), std::fmt::Error> {48	// 	self.write_trace(&mut std::fmt::stdout(), evaluation_state, error)49	// }50}5152fn print_code_location(53	out: &mut impl std::fmt::Write,54	start: &CodeLocation,55	end: &CodeLocation,56) -> Result<(), std::fmt::Error> {57	if start.line == end.line {58		if start.column == end.column {59			write!(out, "{}:{}", start.line, end.column - 1)?;60		} else {61			write!(out, "{}:{}-{}", start.line, start.column - 1, end.column)?;62		}63	} else {64		write!(65			out,66			"{}:{}-{}:{}",67			start.line,68			end.column - 1,69			start.line,70			end.column71		)?;72	}73	Ok(())74}7576/// vanilla jsonnet like formatting77pub struct CompactFormat {78	pub resolver: PathResolver,79	pub padding: usize,80}8182impl TraceFormat for CompactFormat {83	fn write_trace(84		&self,85		out: &mut dyn std::fmt::Write,86		evaluation_state: &EvaluationState,87		error: &LocError,88	) -> Result<(), std::fmt::Error> {89		writeln!(out, "{:?}", error.error())?;90		let file_names = error91			.trace()92			.093			.iter()94			.map(|el| {95				let resolved_path = self.resolver.resolve(&el.location.0);96				// TODO: Process all trace elements first97				let location = evaluation_state98					.map_source_locations(&el.location.0, &[el.location.1, el.location.2]);99				(resolved_path, location)100			})101			.map(|(mut n, location)| {102				use std::fmt::Write;103				write!(n, ":").unwrap();104				print_code_location(&mut n, &location[0], &location[1]).unwrap();105				n106			})107			.collect::<Vec<_>>();108		let align = file_names.iter().map(|e| e.len()).max().unwrap_or(0);109		for (i, (el, file)) in error.trace().0.iter().zip(file_names).enumerate() {110			if i != 0 {111				writeln!(out)?;112			}113			write!(114				out,115				"{:<p$}{:<w$}: {}",116				"",117				file,118				el.desc,119				p = self.padding,120				w = align121			)?;122		}123		Ok(())124	}125}126127pub struct JSFormat;128impl TraceFormat for JSFormat {129	fn write_trace(130		&self,131		out: &mut dyn std::fmt::Write,132		evaluation_state: &EvaluationState,133		error: &LocError,134	) -> Result<(), std::fmt::Error> {135		writeln!(out, "{:?}", error.error())?;136		for (i, item) in error.trace().0.iter().enumerate() {137			if i != 0 {138				writeln!(out)?;139			}140			let desc = &item.desc;141			let source = item.location.clone();142			let start_end = evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);143144			write!(145				out,146				"    at {} ({}:{}:{})",147				desc,148				source.0.to_str().unwrap(),149				start_end[0].line,150				start_end[0].column,151			)?;152		}153		Ok(())154	}155}156157/// rustc-like trace displaying158#[cfg(feature = "explaining-traces")]159pub struct ExplainingFormat {160	pub resolver: PathResolver,161}162#[cfg(feature = "explaining-traces")]163impl TraceFormat for ExplainingFormat {164	fn write_trace(165		&self,166		out: &mut dyn std::fmt::Write,167		evaluation_state: &EvaluationState,168		error: &LocError,169	) -> Result<(), std::fmt::Error> {170		use annotate_snippets::{171			display_list::{DisplayList, FormatOptions},172			snippet::{AnnotationType, Slice, Snippet, SourceAnnotation},173		};174		writeln!(out, "{:?}", error.error())?;175		let trace = &error.trace();176		for item in trace.0.iter() {177			let desc = &item.desc;178			let source = item.location.clone();179			let start_end = evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);180181			let source_fragment: String = evaluation_state182				.get_source(&source.0)183				.unwrap()184				.chars()185				.skip(start_end[0].line_start_offset)186				.take(start_end[1].line_end_offset - start_end[0].line_start_offset)187				.collect();188189			let origin = self.resolver.resolve(&source.0);190			let snippet = Snippet {191				opt: FormatOptions {192					color: true,193					..Default::default()194				},195				title: None,196				footer: vec![],197				slices: vec![Slice {198					source: &source_fragment,199					line_start: start_end[0].line,200					origin: Some(&origin),201					fold: false,202					annotations: vec![SourceAnnotation {203						label: desc,204						annotation_type: AnnotationType::Error,205						range: (206							source.1 - start_end[0].line_start_offset,207							source.2 - start_end[0].line_start_offset,208						),209					}],210				}],211			};212213			let dl = DisplayList::from(snippet);214			writeln!(out, "{}", dl)?;215		}216		Ok(())217	}218}