diff --git a/CHANGELOG.md b/CHANGELOG.md index 7accdb7447..13d16a762e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - 'from_unix_timestamp' now accepts a new unit: Microseconds. - `parse_nginx_log` no longer fails if `upstream_response_length`, `upstream_response_time`, `upstream_status` are missing (https://github.com/vectordotdev/vrl/pull/498) - added `parse_float` function (https://github.com/vectordotdev/vrl/pull/484) - +- improved fallibility diagnostics (https://github.com/vectordotdev/vrl/pull/523) ## `0.7.0` (2023-09-25) #### Bug Fixes diff --git a/lib/tests/tests/diagnostics/unhandled_parse_regex_all_type.vrl b/lib/tests/tests/diagnostics/unhandled_parse_regex_all_type.vrl index 195102c969..d30ea0aca1 100644 --- a/lib/tests/tests/diagnostics/unhandled_parse_regex_all_type.vrl +++ b/lib/tests/tests/diagnostics/unhandled_parse_regex_all_type.vrl @@ -9,10 +9,12 @@ # │ │ │ # │ │ this expression is fallible # │ │ update the expression to be infallible +# │ │ note if an argument type is invalid it can render a function fallible # │ or change this to an infallible assignment: # │ .a, err = sha3(.result[0].an) # │ # = see documentation about error handling at https://errors.vrl.dev/#handling +# = see functions characteristics documentation at https://vrl.dev/expressions/#function-call-characteristics # = learn more about error code 103 at https://errors.vrl.dev/103 # = see language documentation at https://vrl.dev # = try your code in the VRL REPL, learn more at https://vrl.dev/examples diff --git a/lib/tests/tests/examples/blog_vector_remap_language_error_diagnostic.vrl b/lib/tests/tests/examples/blog_vector_remap_language_error_diagnostic.vrl index 5114c7600b..26643f046f 100644 --- a/lib/tests/tests/examples/blog_vector_remap_language_error_diagnostic.vrl +++ b/lib/tests/tests/examples/blog_vector_remap_language_error_diagnostic.vrl @@ -15,10 +15,12 @@ # │ │ │ # │ │ this expression is fallible # │ │ update the expression to be infallible +# │ │ note if an argument type is invalid it can render a function fallible # │ or change this to an infallible assignment: # │ ., err = parse_common_log(.log) # │ # = see documentation about error handling at https://errors.vrl.dev/#handling +# = see functions characteristics documentation at https://vrl.dev/expressions/#function-call-characteristics # = learn more about error code 103 at https://errors.vrl.dev/103 # = see language documentation at https://vrl.dev # = try your code in the VRL REPL, learn more at https://vrl.dev/examples diff --git a/src/compiler/expression/assignment.rs b/src/compiler/expression/assignment.rs index fe5831a362..51aea1e76a 100644 --- a/src/compiler/expression/assignment.rs +++ b/src/compiler/expression/assignment.rs @@ -1,10 +1,5 @@ use std::{convert::TryFrom, fmt}; -use crate::diagnostic::{DiagnosticMessage, Label, Note}; -use crate::path::{OwnedSegment, OwnedTargetPath}; -use crate::path::{OwnedValuePath, PathPrefix}; -use crate::value::{Kind, Value}; - use crate::compiler::{ expression::{assignment::ErrorVariant::InvalidParentPathSegment, Expr, Resolved}, parser::{ @@ -16,6 +11,10 @@ use crate::compiler::{ value::kind::DefaultValue, CompileConfig, Context, Expression, Span, TypeDef, }; +use crate::diagnostic::{DiagnosticMessage, Label, Note}; +use crate::path::{OwnedSegment, OwnedTargetPath}; +use crate::path::{OwnedValuePath, PathPrefix}; +use crate::value::{Kind, Value}; #[derive(Clone, PartialEq)] pub struct Assignment { @@ -671,6 +670,10 @@ impl DiagnosticMessage for Error { ], FallibleAssignment(target, expr) => vec![ Label::primary("this expression is fallible", self.expr_span), + Label::context( + "note if an argument type is invalid it can render a function fallible", + self.expr_span, + ), Label::context("update the expression to be infallible", self.expr_span), Label::context( "or change this to an infallible assignment:", @@ -718,7 +721,12 @@ impl DiagnosticMessage for Error { use ErrorVariant::{FallibleAssignment, InfallibleAssignment}; match &self.variant { - FallibleAssignment(..) | InfallibleAssignment(..) => vec![Note::SeeErrorDocs], + FallibleAssignment(..) => { + vec![Note::SeeErrorDocs, Note::SeeFunctionCharacteristicsDocs] + } + InfallibleAssignment(..) => { + vec![Note::SeeErrorDocs] + } InvalidParentPathSegment { variant, parent_str, diff --git a/src/diagnostic/mod.rs b/src/diagnostic/mod.rs index b1a4ec8cf5..7a8ebc2720 100644 --- a/src/diagnostic/mod.rs +++ b/src/diagnostic/mod.rs @@ -16,6 +16,13 @@ clippy::needless_pass_by_value, // allowed in initial deny commit )] +pub use diagnostic::{Diagnostic, DiagnosticList}; +pub use formatter::Formatter; +pub use label::Label; +pub use note::Note; +pub use severity::Severity; +pub use span::{span, Span}; + #[allow(clippy::module_inception)] mod diagnostic; mod formatter; @@ -24,13 +31,6 @@ mod note; mod severity; mod span; -pub use diagnostic::{Diagnostic, DiagnosticList}; -pub use formatter::Formatter; -pub use label::Label; -pub use note::Note; -pub use severity::Severity; -pub use span::{span, Span}; - const VRL_DOCS_ROOT_URL: &str = "https://vrl.dev"; const VRL_ERROR_DOCS_ROOT_URL: &str = "https://errors.vrl.dev"; const VRL_FUNCS_ROOT_URL: &str = "https://functions.vrl.dev"; @@ -97,4 +97,9 @@ impl Urls { fn example_docs() -> String { format!("{VRL_DOCS_ROOT_URL}/examples") } + + #[must_use] + pub fn func_characteristics() -> String { + format!("{VRL_DOCS_ROOT_URL}/expressions/#function-call-characteristics") + } } diff --git a/src/diagnostic/note.rs b/src/diagnostic/note.rs index 5bbf76ae69..00d2938a9e 100644 --- a/src/diagnostic/note.rs +++ b/src/diagnostic/note.rs @@ -11,6 +11,7 @@ pub enum Note { SeeErrorDocs, SeeCodeDocs(usize), SeeLangDocs, + SeeFunctionCharacteristicsDocs, SeeRepl, #[doc(hidden)] @@ -37,8 +38,9 @@ impl Note { impl fmt::Display for Note { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use Note::{ - Basic, CoerceValue, Example, Hint, SeeCodeDocs, SeeDocs, SeeErrorDocs, SeeFunctionDocs, - SeeLangDocs, SeeRepl, UserErrorMessage, + Basic, CoerceValue, Example, Hint, SeeCodeDocs, SeeDocs, SeeErrorDocs, + SeeFunctionCharacteristicsDocs, SeeFunctionDocs, SeeLangDocs, SeeRepl, + UserErrorMessage, }; match self { @@ -65,6 +67,10 @@ impl fmt::Display for Note { write!(f, "see language documentation at {url}") } + SeeFunctionCharacteristicsDocs => { + let url = Urls::func_characteristics(); + write!(f, "see functions characteristics documentation at {url}") + } SeeRepl => { let url = Urls::example_docs();