difftreelog
feat(evaluator) readable error messages
in: master
6 files changed
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-evaluator/Cargo.toml
+++ b/crates/jrsonnet-evaluator/Cargo.toml
@@ -37,6 +37,8 @@
base64 = "0.12.3"
rustc-hash = "1.1.0"
+thiserror = "1.0.20"
+
# Serialized stdlib
[dependencies.serde]
version = "1.0.115"
crates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/format.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/format.rs
@@ -2,16 +2,23 @@
#![allow(clippy::too_many_arguments)]
use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val, ValType};
+use thiserror::Error;
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Error)]
pub enum FormatError {
+ #[error("truncated format code")]
TruncatedFormatCode,
+ #[error("unrecognized conversion type: {0}")]
UnrecognizedConversionType(char),
+ #[error("not enough values")]
NotEnoughValues,
+ #[error("cannot use * width with object")]
CannotUseStarWidthWithObject,
+ #[error("mapping keys required")]
MappingKeysRequired,
+ #[error("no such format field: {0}")]
NoSuchFormatField(Rc<str>),
}
crates/jrsonnet-evaluator/src/builtin/sort.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/sort.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/sort.rs
@@ -4,9 +4,11 @@
};
use std::rc::Rc;
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, thiserror::Error)]
pub enum SortError {
+ #[error("sort key should be string or number")]
SortKeyShouldBeStringOrNumber,
+ #[error("sort elements should have equal types")]
SortElementsShouldHaveEqualType,
}
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -63,7 +63,7 @@
.bindings
.get(&name)
.cloned()
- .ok_or_else(|| UnknownVariable(name))?)
+ .ok_or_else(|| VariableIsNotDefined(name))?)
}
pub fn into_future(self, ctx: FutureContext) -> Self {
{
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -4,75 +4,117 @@
};
use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};
use std::{path::PathBuf, rc::Rc};
+use thiserror::Error;
-#[derive(Debug, Clone)]
+#[derive(Error, Debug, Clone)]
pub enum Error {
+ #[error("intrinsic not found: {0}.{1}")]
IntrinsicNotFound(Rc<str>, Rc<str>),
+ #[error("argument reordering in intrisics not supported yet")]
IntrinsicArgumentReorderingIsNotSupportedYet,
+ #[error("operator {0} does not operate on type {1}")]
UnaryOperatorDoesNotOperateOnType(UnaryOpType, ValType),
+ #[error("binary operation {1} {0} {2} is not implemented")]
BinaryOperatorDoesNotOperateOnValues(BinaryOpType, ValType, ValType),
+ #[error("no top level object in this context")]
NoTopLevelObjectFound,
+ #[error("self is only usable inside objects")]
CantUseSelfOutsideOfObject,
+ #[error("super is only usable inside objects")]
CantUseSuperOutsideOfObject,
+ #[error("for loop can only iterate over arrays")]
InComprehensionCanOnlyIterateOverArray,
+ #[error("array out of bounds: {0} is not within [0,{1})")]
ArrayBoundsError(usize, usize),
+ #[error("assert failed: {0}")]
AssertionFailed(Rc<str>),
- VariableIsNotDefined(String),
+ #[error("variable is not defined: {0}")]
+ VariableIsNotDefined(Rc<str>),
+ #[error("type mismatch: expected {2}, got {1:?} {0}")]
TypeMismatch(&'static str, Vec<ValType>, ValType),
+ #[error("no such field: {0}")]
NoSuchField(Rc<str>),
- UnknownVariable(Rc<str>),
-
+ #[error("only functions can be called, got {0}")]
OnlyFunctionsCanBeCalledGot(ValType),
+ #[error("parameter {0} is not defined")]
UnknownFunctionParameter(String),
+ #[error("argument {0} is already bound")]
BindingParameterASecondTime(Rc<str>),
+ #[error("too many args, function has {0}")]
TooManyArgsFunctionHas(usize),
+ #[error("founction argument is not passed: {0}")]
FunctionParameterNotBoundInCall(Rc<str>),
+ #[error("external variable is not defined: {0}")]
UndefinedExternalVariable(Rc<str>),
+ #[error("native is not defined: {0}")]
UndefinedExternalFunction(Rc<str>),
+ #[error("field name should be string, got {0}")]
FieldMustBeStringGot(ValType),
+ #[error("attempted to index array with string {0}")]
AttemptedIndexAnArrayWithString(Rc<str>),
+ #[error("{0} index type should be {1}, got {2}")]
ValueIndexMustBeTypeGot(ValType, ValType, ValType),
+ #[error("cant index into {0}")]
CantIndexInto(ValType),
+ #[error("super can't be used standalone")]
StandaloneSuper,
+ #[error("can't resolve {1} from {0}")]
ImportFileNotFound(PathBuf, PathBuf),
+ #[error("resolved file not found: {0}")]
ResolvedFileNotFound(PathBuf),
+ #[error("imported file is not valid utf-8: {0:?}")]
ImportBadFileUtf8(PathBuf),
+ #[error("tried to import {1} from {0}, but imports is not supported")]
ImportNotSupported(PathBuf, PathBuf),
+ #[error("syntax error")]
ImportSyntaxError {
path: Rc<PathBuf>,
source_code: Rc<str>,
error: Box<jrsonnet_parser::ParseError>,
},
+ #[error("runtime error: {0}")]
RuntimeError(Rc<str>),
+ #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]
StackOverflow,
+ #[error("tried to index by fractional value")]
FractionalIndex,
+ #[error("attempted to divide by zero")]
DivisionByZero,
+ #[error("string manifest output is not an string")]
StringManifestOutputIsNotAString,
+ #[error("stream manifest output is not an array")]
StreamManifestOutputIsNotAArray,
+ #[error("multi manifest output is not an object")]
MultiManifestOutputIsNotAObject,
+ #[error("cant recurse stream manifest")]
StreamManifestOutputCannotBeRecursed,
+ #[error("stream manifest output cannot consist of raw strings")]
StreamManifestCannotNestString,
+ #[error("{0}")]
ImportCallbackError(String),
+ #[error("invalid unicode codepoint: {0}")]
InvalidUnicodeCodepointGot(u32),
- Format(FormatError),
- Sort(SortError),
+ #[error("format error: {0}")]
+ Format(#[from] FormatError),
+ #[error("sort error: {0}")]
+ Sort(#[from] SortError),
}
impl From<Error> for LocError {
fn from(e: Error) -> Self {
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth86 evaluation_state: &EvaluationState,86 evaluation_state: &EvaluationState,87 error: &LocError,87 error: &LocError,88 ) -> Result<(), std::fmt::Error> {88 ) -> Result<(), std::fmt::Error> {89 writeln!(out, "{:?}", error.error())?;89 writeln!(out, "{}", error.error())?;90 let file_names = error90 let file_names = error91 .trace()91 .trace()92 .092 .0132 evaluation_state: &EvaluationState,132 evaluation_state: &EvaluationState,133 error: &LocError,133 error: &LocError,134 ) -> Result<(), std::fmt::Error> {134 ) -> Result<(), std::fmt::Error> {135 writeln!(out, "{:?}", error.error())?;135 writeln!(out, "{}", error.error())?;136 for (i, item) in error.trace().0.iter().enumerate() {136 for (i, item) in error.trace().0.iter().enumerate() {137 if i != 0 {137 if i != 0 {138 writeln!(out)?;138 writeln!(out)?;171 display_list::{DisplayList, FormatOptions},171 display_list::{DisplayList, FormatOptions},172 snippet::{AnnotationType, Slice, Snippet, SourceAnnotation},172 snippet::{AnnotationType, Slice, Snippet, SourceAnnotation},173 };173 };174 writeln!(out, "{:?}", error.error())?;174 writeln!(out, "{}", error.error())?;175 let trace = &error.trace();175 let trace = &error.trace();176 for item in trace.0.iter() {176 for item in trace.0.iter() {177 let desc = &item.desc;177 let desc = &item.desc;