Skip to content

Commit

Permalink
fix(expr): deprecate RawExpression (#275)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
martinohmann committed Jul 28, 2023
1 parent baaa35a commit 1c0c368
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 47 deletions.
5 changes: 5 additions & 0 deletions crates/hcl-rs/src/eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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"),
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/hcl-rs/src/eval/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())),
}
Expand Down
12 changes: 11 additions & 1 deletion crates/hcl-rs/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -71,6 +73,10 @@ pub enum Expression {
ForExpr(Box<ForExpr>),
/// 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),
}

Expand All @@ -96,7 +102,7 @@ impl From<Expression> 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()),
}
}
}
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 0 additions & 5 deletions crates/hcl-rs/src/expr/ser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
7 changes: 6 additions & 1 deletion crates/hcl-rs/src/format/impls.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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<W>(&self, fmt: &mut Formatter<W>) -> Result<()>
where
Expand Down
8 changes: 6 additions & 2 deletions crates/hcl-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
10 changes: 3 additions & 7 deletions crates/hcl-rs/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down
9 changes: 7 additions & 2 deletions crates/hcl-rs/src/structure/tests.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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"))
Expand Down
33 changes: 7 additions & 26 deletions crates/hcl-rs/src/tests.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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
);
Expand Down Expand Up @@ -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")))
);
}
13 changes: 10 additions & 3 deletions crates/hcl-rs/tests/ser.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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"
Expand All @@ -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"
}
}
});
Expand Down

0 comments on commit 1c0c368

Please sign in to comment.