Skip to main content

SpannedExpr

Struct SpannedExpr 

Source
pub struct SpannedExpr<'src> {
    pub origin: Origin<'src>,
    pub inner: Expr<'src>,
}
Expand description

An expression along with its source origin (span and unparsed form).

An expression’s span covers exactly the bytes the expression was parsed from, with no surrounding whitespace. A parenthesized expression includes its parentheses, so every span is a balanced, self-contained slice of the source.

NOTE: SpannedExpr has a manual PartialEq implementation that only considers the underlying expression, not the span. In opther words, two SpannedExpr instances are equal if their ASTs are equal, even if their source spans are not.

Fields§

§origin: Origin<'src>

The expression’s source origin.

§inner: Expr<'src>

The expression itself.

Implementations§

Source§

impl<'a> SpannedExpr<'a>

Source

pub fn contexts(&self) -> Vec<(&Context<'a>, &Origin<'a>)>

Returns the contexts in this expression, along with their origins.

This includes all contexts in the expression, even those that don’t directly flow into the evaluation. For example, ${{ foo.bar == 'abc' }} returns foo.bar since it’s a context in the expression, even though it flows into a boolean evaluation rather than directly into the output.

For dataflow contexts, see SpannedExpr::dataflow_contexts.

Source

pub fn dataflow_contexts(&self) -> Vec<(&Context<'a>, &Origin<'a>)>

Returns the contexts in this expression that directly flow into the expression’s evaluation.

For example ${{ foo.bar }} returns foo.bar since the value of foo.bar flows into the evaluation. On the other hand, ${{ foo.bar == 'abc' }} returns no expanded contexts, since the value of foo.bar flows into a boolean evaluation that gets expanded.

Source

pub fn leaf_expressions(&self) -> Vec<&SpannedExpr<'a>>

Returns all possible leaf expressions that could be the result of evaluating this expression.

Uses GitHub Actions’ short-circuit semantics:

  • A && B: only B can flow into the result (A is a condition)
  • A || B: either A or B can be the result

Leaf expressions are any non-BinOp expressions: literals, contexts, function calls, etc.

For example, ${{ foo.bar == 'true' && 'hello' || '' }} returns ['hello', ''] since those are the two possible evaluated values. ${{ foo.abc || foo.def }} returns [foo.abc, foo.def].

Source

pub fn computed_indices(&self) -> Vec<&SpannedExpr<'a>>

Returns any computed indices in this expression.

A computed index is any index operation with a non-literal evaluation, e.g. foo[a.b.c].

Source

pub fn constant_reducible_subexprs(&self) -> Vec<&SpannedExpr<'a>>

Like Expr::constant_reducible, but for all subexpressions rather than the top-level expression.

This has slightly different semantics than constant_reducible: it doesn’t include “trivially” reducible expressions like literals, since flagging these as reducible within a larger expression would be misleading.

Methods from Deref<Target = Expr<'a>>§

Source

pub fn is_literal(&self) -> bool

Returns whether the expression is a literal.

Source

pub fn constant_reducible(&self) -> bool

Returns whether the expression is constant reducible.

“Constant reducible” is similar to “constant foldable” but with meta-evaluation semantics: the expression 5 would not be constant foldable in a normal program (because it’s already an atom), but is “constant reducible” in a GitHub Actions expression because an expression containing it (e.g. ${{ 5 }}) can be elided entirely and replaced with 5.

There are three kinds of reducible expressions:

  1. Literals, which reduce to their literal value;
  2. Binops/unops with reducible subexpressions, which reduce to their evaluation;
  3. Select function calls where the semantics of the function mean that reducible arguments make the call itself reducible.

NOTE: This implementation is sound but not complete.

Source

pub fn commutative_matches(&self, other: &Expr<'src>) -> bool

Returns whether this expression ‘commutatively matches’ the given expression.

For most expressions, this is the same as equivalence (i.e. ==). For binary expressions that are also commutative, this takes commutivity into account. For example, a == b is considered to match b == a, but a > b is not considered to match b > a. This check is recusive, i.e. two nested binary expressions will be fully checked for commutative equivalence.

Source

pub fn consteval(&self) -> Option<Evaluation>

Evaluates a constant-reducible expression to its literal value.

Returns Some(Evaluation) if the expression can be constant-evaluated, or None if the expression contains non-constant elements (like contexts or non-reducible function calls).

This implementation follows GitHub Actions’ evaluation semantics as documented at: https://docs.github.com/en/actions/reference/workflows-and-actions/expressions

§Examples
use github_actions_expressions::{Expr, Evaluation};

let expr = Expr::parse("'hello'").unwrap();
let result = expr.consteval().unwrap();
assert_eq!(result.sema().to_string(), "hello");

let expr = Expr::parse("true && false").unwrap();
let result = expr.consteval().unwrap();
assert_eq!(result, Evaluation::Boolean(false));

Trait Implementations§

Source§

impl<'src> Debug for SpannedExpr<'src>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Deref for SpannedExpr<'a>

Source§

type Target = Expr<'a>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<'doc> From<&SpannedExpr<'doc>> for Fragment<'doc>

Source§

fn from(expr: &SpannedExpr<'doc>) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for SpannedExpr<'_>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more

Auto Trait Implementations§

§

impl<'src> Freeze for SpannedExpr<'src>

§

impl<'src> RefUnwindSafe for SpannedExpr<'src>

§

impl<'src> Send for SpannedExpr<'src>

§

impl<'src> Sync for SpannedExpr<'src>

§

impl<'src> Unpin for SpannedExpr<'src>

§

impl<'src> UnsafeUnpin for SpannedExpr<'src>

§

impl<'src> UnwindSafe for SpannedExpr<'src>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.