--- 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" --- 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), } --- 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, } --- 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 { { --- 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, Rc), + #[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), - VariableIsNotDefined(String), + #[error("variable is not defined: {0}")] + VariableIsNotDefined(Rc), + #[error("type mismatch: expected {2}, got {1:?} {0}")] TypeMismatch(&'static str, Vec, ValType), + #[error("no such field: {0}")] NoSuchField(Rc), - UnknownVariable(Rc), - + #[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), + #[error("too many args, function has {0}")] TooManyArgsFunctionHas(usize), + #[error("founction argument is not passed: {0}")] FunctionParameterNotBoundInCall(Rc), + #[error("external variable is not defined: {0}")] UndefinedExternalVariable(Rc), + #[error("native is not defined: {0}")] UndefinedExternalFunction(Rc), + #[error("field name should be string, got {0}")] FieldMustBeStringGot(ValType), + #[error("attempted to index array with string {0}")] AttemptedIndexAnArrayWithString(Rc), + #[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, source_code: Rc, error: Box, }, + #[error("runtime error: {0}")] RuntimeError(Rc), + #[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 for LocError { fn from(e: Error) -> Self { --- a/crates/jrsonnet-evaluator/src/trace/mod.rs +++ b/crates/jrsonnet-evaluator/src/trace/mod.rs @@ -86,7 +86,7 @@ evaluation_state: &EvaluationState, error: &LocError, ) -> Result<(), std::fmt::Error> { - writeln!(out, "{:?}", error.error())?; + writeln!(out, "{}", error.error())?; let file_names = error .trace() .0 @@ -132,7 +132,7 @@ evaluation_state: &EvaluationState, error: &LocError, ) -> Result<(), std::fmt::Error> { - writeln!(out, "{:?}", error.error())?; + writeln!(out, "{}", error.error())?; for (i, item) in error.trace().0.iter().enumerate() { if i != 0 { writeln!(out)?; @@ -171,7 +171,7 @@ display_list::{DisplayList, FormatOptions}, snippet::{AnnotationType, Slice, Snippet, SourceAnnotation}, }; - writeln!(out, "{:?}", error.error())?; + writeln!(out, "{}", error.error())?; let trace = &error.trace(); for item in trace.0.iter() { let desc = &item.desc;