refactor(tvix/eval): use internal SourceCode field in error printers
Makes use of the SourceCode field now being stored directly in errors (see parent CL). With this change, the default `Display` implementation can now format errors correctly, and there is no need to keep a `SourceCode` around just for error formatting. Updates dependent crates (CLI, serde, tvixbolt) to use this correctly. Change-Id: Iddc5d7a6b4bab391f30a999e4c68aca34304c059 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10987 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
parent
3c87687798
commit
94f582341e
5 changed files with 22 additions and 33 deletions
|
@ -323,12 +323,7 @@ fn eval(model: &Model) -> Output {
|
||||||
|
|
||||||
if !result.errors.is_empty() {
|
if !result.errors.is_empty() {
|
||||||
for error in &result.errors {
|
for error in &result.errors {
|
||||||
writeln!(
|
writeln!(&mut out.errors, "{}\n", error.fancy_format_str().trim(),).unwrap();
|
||||||
&mut out.errors,
|
|
||||||
"{}\n",
|
|
||||||
error.fancy_format_str(&source).trim(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -159,7 +159,7 @@ fn interpret(code: &str, path: Option<PathBuf>, args: &Args, explain: bool) -> b
|
||||||
}
|
}
|
||||||
|
|
||||||
for error in &result.errors {
|
for error in &result.errors {
|
||||||
error.fancy_format_stderr(&source_map);
|
error.fancy_format_stderr();
|
||||||
}
|
}
|
||||||
|
|
||||||
if !args.no_warnings {
|
if !args.no_warnings {
|
||||||
|
@ -207,7 +207,7 @@ fn lint(code: &str, path: Option<PathBuf>, args: &Args) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
for error in &result.errors {
|
for error in &result.errors {
|
||||||
error.fancy_format_stderr(&source_map);
|
error.fancy_format_stderr();
|
||||||
}
|
}
|
||||||
|
|
||||||
for warning in &result.warnings {
|
for warning in &result.warnings {
|
||||||
|
|
|
@ -514,7 +514,7 @@ to a missing value in the attribute set(s) included via `with`."#,
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.kind)
|
write!(f, "{}", self.fancy_format_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,17 +739,16 @@ fn spans_for_parse_errors(file: &File, errors: &[rnix::parser::ParseError]) -> V
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn fancy_format_str(&self, source: &SourceCode) -> String {
|
pub fn fancy_format_str(&self) -> String {
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
Emitter::vec(&mut out, Some(&*source.codemap())).emit(&self.diagnostics(source));
|
Emitter::vec(&mut out, Some(&*self.source.codemap())).emit(&self.diagnostics());
|
||||||
String::from_utf8_lossy(&out).to_string()
|
String::from_utf8_lossy(&out).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render a fancy, human-readable output of this error and print
|
/// Render a fancy, human-readable output of this error and print
|
||||||
/// it to stderr.
|
/// it to stderr.
|
||||||
pub fn fancy_format_stderr(&self, source: &SourceCode) {
|
pub fn fancy_format_stderr(&self) {
|
||||||
Emitter::stderr(ColorConfig::Auto, Some(&*source.codemap()))
|
Emitter::stderr(ColorConfig::Auto, Some(&*self.source.codemap())).emit(&self.diagnostics());
|
||||||
.emit(&self.diagnostics(source));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the optional span label displayed as an annotation on
|
/// Create the optional span label displayed as an annotation on
|
||||||
|
@ -863,14 +862,14 @@ impl Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spans(&self, source: &SourceCode) -> Vec<SpanLabel> {
|
fn spans(&self) -> Vec<SpanLabel> {
|
||||||
let mut spans = match &self.kind {
|
let mut spans = match &self.kind {
|
||||||
ErrorKind::ImportParseError { errors, file, .. } => {
|
ErrorKind::ImportParseError { errors, file, .. } => {
|
||||||
spans_for_parse_errors(file, errors)
|
spans_for_parse_errors(file, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorKind::ParseErrors(errors) => {
|
ErrorKind::ParseErrors(errors) => {
|
||||||
let file = source.get_file(self.span);
|
let file = self.source.get_file(self.span);
|
||||||
spans_for_parse_errors(&file, errors)
|
spans_for_parse_errors(&file, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,22 +948,22 @@ impl Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the primary diagnostic for a given error.
|
/// Create the primary diagnostic for a given error.
|
||||||
fn diagnostic(&self, source: &SourceCode) -> Diagnostic {
|
fn diagnostic(&self) -> Diagnostic {
|
||||||
Diagnostic {
|
Diagnostic {
|
||||||
level: Level::Error,
|
level: Level::Error,
|
||||||
message: self.to_string(),
|
message: self.to_string(),
|
||||||
spans: self.spans(source),
|
spans: self.spans(),
|
||||||
code: Some(self.code().into()),
|
code: Some(self.code().into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the primary diagnostic and all further associated diagnostics (if
|
/// Return the primary diagnostic and all further associated diagnostics (if
|
||||||
/// any) of an error.
|
/// any) of an error.
|
||||||
fn diagnostics(&self, source: &SourceCode) -> Vec<Diagnostic> {
|
fn diagnostics(&self) -> Vec<Diagnostic> {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
ErrorKind::ImportCompilerError { errors, .. } => {
|
ErrorKind::ImportCompilerError { errors, .. } => {
|
||||||
let mut out = vec![self.diagnostic(source)];
|
let mut out = vec![self.diagnostic()];
|
||||||
out.extend(errors.iter().map(|e| e.diagnostic(source)));
|
out.extend(errors.iter().map(|e| e.diagnostic()));
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,7 +990,7 @@ impl Error {
|
||||||
let mut this_span = self.span;
|
let mut this_span = self.span;
|
||||||
|
|
||||||
// Diagnostic spans for *this* error.
|
// Diagnostic spans for *this* error.
|
||||||
let mut this_spans = self.spans(source);
|
let mut this_spans = self.spans();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if is_new_span(
|
if is_new_span(
|
||||||
|
@ -1008,7 +1007,7 @@ impl Error {
|
||||||
|
|
||||||
this_message = next.to_string();
|
this_message = next.to_string();
|
||||||
this_span = next.span;
|
this_span = next.span;
|
||||||
this_spans = next.spans(source);
|
this_spans = next.spans();
|
||||||
|
|
||||||
match next.kind {
|
match next.kind {
|
||||||
ErrorKind::NativeError { err: inner, .. }
|
ErrorKind::NativeError { err: inner, .. }
|
||||||
|
@ -1017,7 +1016,7 @@ impl Error {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
diagnostics.extend(next.diagnostics(source));
|
diagnostics.extend(next.diagnostics());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1026,7 +1025,7 @@ impl Error {
|
||||||
diagnostics
|
diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => vec![self.diagnostic(source)],
|
_ => vec![self.diagnostic()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,11 @@ where
|
||||||
config(&mut eval);
|
config(&mut eval);
|
||||||
|
|
||||||
eval.strict = true;
|
eval.strict = true;
|
||||||
let source = eval.source_map();
|
|
||||||
let result = eval.evaluate(src, None);
|
let result = eval.evaluate(src, None);
|
||||||
|
|
||||||
if !result.errors.is_empty() {
|
if !result.errors.is_empty() {
|
||||||
return Err(Error::NixErrors {
|
return Err(Error::NixErrors {
|
||||||
errors: result.errors,
|
errors: result.errors,
|
||||||
source,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,7 @@ pub enum Error {
|
||||||
|
|
||||||
/// Evaluation of the supplied Nix code failed while computing the
|
/// Evaluation of the supplied Nix code failed while computing the
|
||||||
/// value for deserialisation.
|
/// value for deserialisation.
|
||||||
NixErrors {
|
NixErrors { errors: Vec<tvix_eval::Error> },
|
||||||
errors: Vec<tvix_eval::Error>,
|
|
||||||
source: tvix_eval::SourceCode,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Could not determine an externally tagged enum representation.
|
/// Could not determine an externally tagged enum representation.
|
||||||
AmbiguousEnum,
|
AmbiguousEnum,
|
||||||
|
@ -56,7 +53,7 @@ impl Display for Error {
|
||||||
write!(f, "expected type {}, but got Nix type {}", expected, got)
|
write!(f, "expected type {}, but got Nix type {}", expected, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
Error::NixErrors { errors, source } => {
|
Error::NixErrors { errors } => {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"{} occured during Nix evaluation: ",
|
"{} occured during Nix evaluation: ",
|
||||||
|
@ -64,7 +61,7 @@ impl Display for Error {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for err in errors {
|
for err in errors {
|
||||||
writeln!(f, "{}", err.fancy_format_str(source))?;
|
writeln!(f, "{}", err.fancy_format_str())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue