From 1c0c3685e4062e71690be39ef221cbfa9cab9016 Mon Sep 17 00:00:00 2001 From: martinohmann Date: Fri, 28 Jul 2023 23:23:17 +0200 Subject: [PATCH] fix(expr): deprecate `RawExpression` (#275) The construct was a mistake from the start and makes it possible to produce invalid HCL. It's also not needed anymore since all types from the HCL expression language are implemented. --- crates/hcl-rs/src/eval/error.rs | 5 +++++ crates/hcl-rs/src/eval/impls.rs | 1 + crates/hcl-rs/src/expr/mod.rs | 12 +++++++++- crates/hcl-rs/src/expr/ser/tests.rs | 5 ----- crates/hcl-rs/src/format/impls.rs | 7 +++++- crates/hcl-rs/src/lib.rs | 8 +++++-- crates/hcl-rs/src/macros.rs | 10 +++------ crates/hcl-rs/src/structure/tests.rs | 9 ++++++-- crates/hcl-rs/src/tests.rs | 33 ++++++---------------------- crates/hcl-rs/tests/ser.rs | 13 ++++++++--- 10 files changed, 56 insertions(+), 47 deletions(-) diff --git a/crates/hcl-rs/src/eval/error.rs b/crates/hcl-rs/src/eval/error.rs index 208f13c8..6078281d 100644 --- a/crates/hcl-rs/src/eval/error.rs +++ b/crates/hcl-rs/src/eval/error.rs @@ -123,6 +123,10 @@ pub enum ErrorKind { /// A function call in an expression returned an error. FuncCall(Identifier, String), /// It was attempted to evaluate a raw expression. + #[deprecated( + since = "0.16.3", + note = "Support for raw expressions will be removed in an upcoming release" + )] RawExpression, } @@ -171,6 +175,7 @@ impl fmt::Display for ErrorKind { ErrorKind::FuncCall(name, msg) => { write!(f, "error calling function `{name}`: {msg}") } + #[allow(deprecated)] ErrorKind::RawExpression => f.write_str("raw expressions cannot be evaluated"), } } diff --git a/crates/hcl-rs/src/eval/impls.rs b/crates/hcl-rs/src/eval/impls.rs index 40298f05..51d61004 100644 --- a/crates/hcl-rs/src/eval/impls.rs +++ b/crates/hcl-rs/src/eval/impls.rs @@ -72,6 +72,7 @@ impl Evaluate for Expression { Expression::Conditional(cond) => cond.evaluate(ctx), Expression::Operation(op) => op.evaluate(ctx), Expression::ForExpr(expr) => expr.evaluate(ctx), + #[allow(deprecated)] Expression::Raw(_) => Err(ctx.error(ErrorKind::RawExpression)), other => Ok(Value::from(other.clone())), } diff --git a/crates/hcl-rs/src/expr/mod.rs b/crates/hcl-rs/src/expr/mod.rs index 723684c1..52f3f3b9 100644 --- a/crates/hcl-rs/src/expr/mod.rs +++ b/crates/hcl-rs/src/expr/mod.rs @@ -3,6 +3,8 @@ //! The module contains the [`Expression`] enum which can represent any valid HCL expression in //! HCL attribute values and templates. +#![allow(deprecated)] + mod conditional; pub(crate) mod de; mod edit; @@ -71,6 +73,10 @@ pub enum Expression { ForExpr(Box), /// Represents a raw HCL expression. This variant will never be emitted by the parser. See /// [`RawExpression`] for more details. + #[deprecated( + since = "0.16.3", + note = "Support for raw expressions will be removed in an upcoming release" + )] Raw(RawExpression), } @@ -96,7 +102,7 @@ impl From for Value { Expression::TemplateExpr(expr) => Value::String(expr.to_string()), Expression::Parenthesis(expr) => Value::from(*expr), Expression::Raw(raw) => Value::String(raw.into()), - other => Value::String(RawExpression(other.to_string()).into()), + other => Value::String(format::to_interpolated_string(&other).unwrap()), } } } @@ -343,6 +349,10 @@ impl Display for ObjectKey { /// /// *Please note*: raw expressions are not validated during serialization, so it is your /// responsiblity to ensure that they are valid HCL. +#[deprecated( + since = "0.16.3", + note = "Support for raw expressions will be removed in an upcoming release" +)] #[derive(Deserialize, Debug, Clone, PartialEq, Eq, Hash)] #[serde(transparent)] pub struct RawExpression(String); diff --git a/crates/hcl-rs/src/expr/ser/tests.rs b/crates/hcl-rs/src/expr/ser/tests.rs index 7a7a912a..1d7ff8e1 100644 --- a/crates/hcl-rs/src/expr/ser/tests.rs +++ b/crates/hcl-rs/src/expr/ser/tests.rs @@ -129,11 +129,6 @@ fn builtin() { Variable::unchecked("var"), Expression::from(Variable::unchecked("var")), ); - - assert_expr( - RawExpression::new("raw"), - Expression::from(RawExpression::new("raw")), - ); } #[test] diff --git a/crates/hcl-rs/src/format/impls.rs b/crates/hcl-rs/src/format/impls.rs index 9421b2de..552e902e 100644 --- a/crates/hcl-rs/src/format/impls.rs +++ b/crates/hcl-rs/src/format/impls.rs @@ -1,7 +1,9 @@ use super::{private, Format, Formatter}; +#[allow(deprecated)] +use crate::expr::RawExpression; use crate::expr::{ BinaryOp, Conditional, Expression, ForExpr, FuncCall, Heredoc, HeredocStripMode, ObjectKey, - Operation, RawExpression, TemplateExpr, Traversal, TraversalOperator, UnaryOp, Variable, + Operation, TemplateExpr, Traversal, TraversalOperator, UnaryOp, Variable, }; use crate::structure::{Attribute, Block, BlockLabel, Body, Structure}; use crate::template::{ @@ -120,6 +122,7 @@ impl Format for Expression { Expression::String(string) => string.format(fmt), Expression::Array(array) => format_array(fmt, array.iter()), Expression::Object(object) => format_object(fmt, object.iter()), + #[allow(deprecated)] Expression::Raw(raw) => raw.format(fmt), Expression::TemplateExpr(expr) => expr.format(fmt), Expression::Variable(var) => var.format(fmt), @@ -204,8 +207,10 @@ impl<'a> Format for StrKey<'a> { } } +#[allow(deprecated)] impl private::Sealed for RawExpression {} +#[allow(deprecated)] impl Format for RawExpression { fn format(&self, fmt: &mut Formatter) -> Result<()> where diff --git a/crates/hcl-rs/src/lib.rs b/crates/hcl-rs/src/lib.rs index 8a4565d3..16c05b0f 100644 --- a/crates/hcl-rs/src/lib.rs +++ b/crates/hcl-rs/src/lib.rs @@ -60,10 +60,14 @@ pub use expr::{to_expression, Expression, Object, ObjectKey}; #[doc(hidden)] pub use expr::{ BinaryOp, BinaryOperator, Conditional, ForExpr, FuncCall, FuncCallBuilder, Heredoc, - HeredocStripMode, Operation, RawExpression, TemplateExpr, Traversal, TraversalOperator, - UnaryOp, UnaryOperator, Variable, + HeredocStripMode, Operation, TemplateExpr, Traversal, TraversalOperator, UnaryOp, + UnaryOperator, Variable, }; +#[allow(deprecated)] +#[doc(hidden)] +pub use expr::RawExpression; + pub use ident::Identifier; pub use parser::parse; diff --git a/crates/hcl-rs/src/macros.rs b/crates/hcl-rs/src/macros.rs index d6b8a766..45431c49 100644 --- a/crates/hcl-rs/src/macros.rs +++ b/crates/hcl-rs/src/macros.rs @@ -9,13 +9,9 @@ /// expressions (`(expr)`). /// - Block labels can be string literals (`"label"`), identifiers (`label`) or parenthesized /// expressions (`(label_expr)`). -/// - Object keys can be string literals (`"key"`), identifiers (`key`), parenthesized -/// expressions (`(key_expr)`) or raw HCL expressions (`#{raw_expr}`). -/// - Attribute expression values can be any valid primitive, collection, expression or raw HCL -/// expression (`#{raw_expr}`). -/// -/// Please note that HCL actually uses `${}` for interpolating expression, but since rust macros do -/// not support matching on `$` it was chosen to use `#{}` instead to support raw expressions. +/// - Object keys can be string literals (`"key"`), identifiers (`key`) or parenthesized +/// expressions (`(key_expr)`). +/// - Attribute expression values can be any valid primitive, collection or expression. /// /// # Unsupported syntax /// diff --git a/crates/hcl-rs/src/structure/tests.rs b/crates/hcl-rs/src/structure/tests.rs index 81607ef9..af770a61 100644 --- a/crates/hcl-rs/src/structure/tests.rs +++ b/crates/hcl-rs/src/structure/tests.rs @@ -1,5 +1,5 @@ use super::{Block, Body}; -use crate::expr::{Heredoc, HeredocStripMode, RawExpression, TemplateExpr}; +use crate::expr::{Heredoc, HeredocStripMode, TemplateExpr, Traversal, Variable}; use crate::{value, Identifier, Value}; use pretty_assertions::assert_eq; @@ -24,7 +24,12 @@ fn body_into_value() { Block::builder("bar") .add_label("baz") .add_attribute(("bar", "baz")) - .add_attribute(("baz", RawExpression::new("var.foo"))) + .add_attribute(( + "baz", + Traversal::builder(Variable::unchecked("var")) + .attr("foo") + .build(), + )) .build(), ) .add_attribute(("foo", "baz")) diff --git a/crates/hcl-rs/src/tests.rs b/crates/hcl-rs/src/tests.rs index d4d56457..639cbf5f 100644 --- a/crates/hcl-rs/src/tests.rs +++ b/crates/hcl-rs/src/tests.rs @@ -1,4 +1,4 @@ -use crate::expr::{Expression, Object, ObjectKey, RawExpression}; +use crate::expr::{Expression, Object, ObjectKey}; use crate::structure::{Attribute, Block, Body, Structure}; use crate::{Identifier, Number}; use pretty_assertions::assert_eq; @@ -28,37 +28,22 @@ fn expression_macro_arrays() { fn expression_macro_objects() { let expected = Expression::Object(Object::from([ (ObjectKey::from("foo"), "bar".into()), - (ObjectKey::from("baz"), true.into()), - (ObjectKey::from("qux"), vec![1, 2, 3].into()), - (ObjectKey::from(1), 2.into()), - ])); - - assert_eq!( - expression!({ - "foo" = "bar", - "baz" = true, - "qux" = [1, 2, 3], - 1 = 2 - }), - expected - ); - - let expected = Expression::Object(Object::from([ - (ObjectKey::from(Identifier::unchecked("foo")), "bar".into()), (ObjectKey::from("bar"), true.into()), ( - ObjectKey::Expression(RawExpression::from("qux").into()), + ObjectKey::from(Identifier::unchecked("qux")), vec![1, 2, 3].into(), ), + (ObjectKey::from(1), 2.into()), ])); let baz = "bar"; assert_eq!( expression!({ - foo = (baz) - (baz) = true - #{"qux"} = [1, 2, 3] + "foo" = (baz), + (baz) = true, + qux = [1, 2, 3], + 1 = 2 }), expected ); @@ -155,8 +140,4 @@ fn structure_macro() { structure!((foo) = "bar"), Structure::Attribute(Attribute::new("bar", "bar")) ); - assert_eq!( - structure!((foo) = #{"raw"}), - Structure::Attribute(Attribute::new("bar", RawExpression::new("raw"))) - ); } diff --git a/crates/hcl-rs/tests/ser.rs b/crates/hcl-rs/tests/ser.rs index 7faa3494..a500e191 100644 --- a/crates/hcl-rs/tests/ser.rs +++ b/crates/hcl-rs/tests/ser.rs @@ -1,7 +1,7 @@ mod common; use common::assert_serialize; -use hcl::expr::{Expression, RawExpression}; +use hcl::expr::{Expression, Traversal, Variable}; use hcl::structure::Attribute; use indoc::indoc; @@ -88,6 +88,13 @@ fn custom_enum() { #[test] fn body() { + let enabled_var = Traversal::builder(Variable::unchecked("var")) + .attr("enabled") + .build(); + let name_var = Traversal::builder(Variable::unchecked("var")) + .attr("name") + .build(); + let value = hcl::body!({ foo = 1 bar = "baz" @@ -105,8 +112,8 @@ fn body() { an_object = { foo = "bar" - "enabled" = (RawExpression::new("var.enabled")) - (RawExpression::from("var.name")) = "the value" + "enabled" = (enabled_var) + (name_var) = "the value" } } });