Add support for null safe indexing e.g. for arrays (#631)

* Add support for null safe indexing e.g. for arrays

This follows the JavaScript syntax:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#syntax

* add docs

* Add test for safe access index to non indexable

Co-authored-by: Josiah Hilden <jhilden13@gmail.com>

Co-authored-by: Josiah Hilden <jhilden13@gmail.com>
Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>
This commit is contained in:
Roland Fredenhagen 2023-01-05 20:21:29 +01:00 committed by GitHub
parent 29bfe4129f
commit 6a64a28629
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 9 additions and 1 deletions

View file

@ -8,6 +8,7 @@ All notable changes to eww will be listed here, starting at changes since versio
### Features ### Features
- Add support for safe access (`?.`) in simplexpr (By: oldwomanjosiah) - Add support for safe access (`?.`) in simplexpr (By: oldwomanjosiah)
- Allow floating-point numbers in percentages for window-geometry - Allow floating-point numbers in percentages for window-geometry
- Add support for safe access with index (`?.[n]`) (By: ModProg)
- Made `and`, `or` and `?:` lazily evaluated in simplexpr (By: ModProg) - Made `and`, `or` and `?:` lazily evaluated in simplexpr (By: ModProg)
## [0.4.0] (04.09.2022) ## [0.4.0] (04.09.2022)

View file

@ -401,6 +401,9 @@ mod tests {
string_to_string(r#""Hello""#) => Ok(DynVal::from("Hello".to_string())), string_to_string(r#""Hello""#) => Ok(DynVal::from("Hello".to_string())),
safe_access_to_existing(r#"{ "a": { "b": 2 } }.a?.b"#) => Ok(DynVal::from(2)), safe_access_to_existing(r#"{ "a": { "b": 2 } }.a?.b"#) => Ok(DynVal::from(2)),
safe_access_to_missing(r#"{ "a": { "b": 2 } }.b?.b"#) => Ok(DynVal::from(&serde_json::Value::Null)), safe_access_to_missing(r#"{ "a": { "b": 2 } }.b?.b"#) => Ok(DynVal::from(&serde_json::Value::Null)),
safe_access_index_to_existing(r#"[1, 2]?.[1]"#) => Ok(DynVal::from(2)),
safe_access_index_to_missing(r#""null"?.[1]"#) => Ok(DynVal::from(&serde_json::Value::Null)),
safe_access_index_to_non_indexable(r#"32?.[1]"#) => Err(super::EvalError::CannotIndex("32".to_string())),
normal_access_to_existing(r#"{ "a": { "b": 2 } }.a.b"#) => Ok(DynVal::from(2)), normal_access_to_existing(r#"{ "a": { "b": 2 } }.a.b"#) => Ok(DynVal::from(2)),
normal_access_to_missing(r#"{ "a": { "b": 2 } }.b.b"#) => Err(super::EvalError::CannotIndex("null".to_string())), normal_access_to_missing(r#"{ "a": { "b": 2 } }.b.b"#) => Err(super::EvalError::CannotIndex("null".to_string())),
lazy_evaluation_and(r#"false && "null".test"#) => Ok(DynVal::from(false)), lazy_evaluation_and(r#"false && "null".test"#) => Ok(DynVal::from(false)),

View file

@ -76,9 +76,13 @@ pub Expr: SimplExpr = {
#[precedence(level="1")] #[assoc(side="right")] #[precedence(level="1")] #[assoc(side="right")]
<l:@L> <ident:"identifier"> "(" <args: Comma<ExprReset>> ")" <r:@R> => FunctionCall(Span(l, r, fid), ident, args), <l:@L> <ident:"identifier"> "(" <args: Comma<ExprReset>> ")" <r:@R> => FunctionCall(Span(l, r, fid), ident, args),
<l:@L> <value:Expr> "[" <index: ExprReset> "]" <r:@R> => { <l:@L> <value:Expr> "[" <index: ExprReset> "]" <r:@R> => {
JsonAccess(Span(l, r, fid), AccessType::Normal, b(value), b(index)) JsonAccess(Span(l, r, fid), AccessType::Normal, b(value), b(index))
}, },
<l:@L> <value:Expr> "?." "[" <index: ExprReset> "]" <r:@R> => {
JsonAccess(Span(l, r, fid), AccessType::Safe, b(value), b(index))
},
<l:@L> <value:Expr> "." <lit_l:@L> <index:"identifier"> <r:@R> => { <l:@L> <value:Expr> "." <lit_l:@L> <index:"identifier"> <r:@R> => {
JsonAccess(Span(l, r, fid), AccessType::Normal, b(value), b(Literal(index.into()))) JsonAccess(Span(l, r, fid), AccessType::Normal, b(value), b(Literal(index.into())))

View file

@ -26,7 +26,7 @@ Supported currently are the following features:
- elvis operator (`?:`) - elvis operator (`?:`)
- if the left side is `""` or a JSON `null`, then returns the right side, - if the left side is `""` or a JSON `null`, then returns the right side,
otherwise evaluates to the left side. otherwise evaluates to the left side.
- Safe Access operator (`?.`) - Safe Access operator (`?.`) or (`?.[index]`)
- if the left side is `""` or a JSON `null`, then return `null`. Otherwise, - if the left side is `""` or a JSON `null`, then return `null`. Otherwise,
attempt to index. attempt to index.
- This can still cause an error to occur if the left hand side exists but is - This can still cause an error to occur if the left hand side exists but is