From 53319649eafb02fee0b8c1c7ac179a9657db61fa Mon Sep 17 00:00:00 2001 From: Sean Yeh <109418+seanyeh@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:00:05 -0600 Subject: [PATCH 1/3] tmp --- analysis/common_test.go | 4 ++-- analysis/traversal.go | 2 +- ast/environment.go | 6 +++--- cmd/esc/cli/env_get.go | 2 +- environment.go | 4 ++-- eval/eval.go | 11 ++++++----- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/analysis/common_test.go b/analysis/common_test.go index 3e6dfd27..940f15f8 100644 --- a/analysis/common_test.go +++ b/analysis/common_test.go @@ -144,7 +144,7 @@ func visitExprs(env *esc.Environment, visitor func(path string, x esc.Expr)) { } } - for _, key := range sortedKeys(env.Exprs) { - visit(env.Exprs[key], key) + for _, key := range sortedKeys(env.Exprs.Object) { + visit(env.Exprs.Object[key], key) } } diff --git a/analysis/traversal.go b/analysis/traversal.go index bad2b507..1a2299a5 100644 --- a/analysis/traversal.go +++ b/analysis/traversal.go @@ -46,7 +46,7 @@ func (a *Analysis) ExpressionAtPos(pos esc.Pos) (*esc.Expr, bool) { // (nil, nil, false). The returned expression is the "smallest" expression that contains pos. The path to the given // expression is also returned. func (a *Analysis) expressionAtPos(pos esc.Pos) (*esc.Expr, []traverser, bool) { - for key, x := range a.env.Exprs { + for key, x := range a.env.Exprs.Object { if x, where, ok := expressionAtPos(x, []traverser{newRootTraverser(key)}, pos); ok { return x, where, true } diff --git a/ast/environment.go b/ast/environment.go index 73f7bda6..37e2e0c6 100644 --- a/ast/environment.go +++ b/ast/environment.go @@ -196,7 +196,7 @@ type EnvironmentDecl struct { Description *StringExpr Imports ImportListDecl - Values PropertyMapDecl + Values *ObjectExpr } func (d *EnvironmentDecl) Syntax() syntax.Node { @@ -222,7 +222,7 @@ func (d *EnvironmentDecl) NewDiagnosticWriter(w io.Writer, width uint, color boo return newDiagnosticWriter(w, fileMap, width, color) } -func EnvironmentSyntax(node *syntax.ObjectNode, description *StringExpr, imports ImportListDecl, values PropertyMapDecl) *EnvironmentDecl { +func EnvironmentSyntax(node *syntax.ObjectNode, description *StringExpr, imports ImportListDecl, values *ObjectExpr) *EnvironmentDecl { return &EnvironmentDecl{ syntax: node, Description: description, @@ -231,7 +231,7 @@ func EnvironmentSyntax(node *syntax.ObjectNode, description *StringExpr, imports } } -func Environment(description *StringExpr, imports ImportListDecl, values PropertyMapDecl) *EnvironmentDecl { +func Environment(description *StringExpr, imports ImportListDecl, values *ObjectExpr) *EnvironmentDecl { return EnvironmentSyntax(nil, description, imports, values) } diff --git a/cmd/esc/cli/env_get.go b/cmd/esc/cli/env_get.go index 125d4e91..54c1559e 100644 --- a/cmd/esc/cli/env_get.go +++ b/cmd/esc/cli/env_get.go @@ -329,7 +329,7 @@ func (get *envGetCommand) getEnvironmentMember( definitionYAML := "" if valuesNode, ok := (encoding.YAMLSyntax{Node: &docNode}.Get(resource.PropertyPath{"values"})); ok { if node, _ := (encoding.YAMLSyntax{Node: valuesNode}.Get(path)); node != nil { - expr, ok := getEnvExpr(esc.Expr{Object: env.Exprs}, path) + expr, ok := getEnvExpr(*env.Exprs, path) if !ok { return nil, fmt.Errorf("internal error: no expr for path %v", path) } diff --git a/environment.go b/environment.go index 551314ab..1b0f7d5c 100644 --- a/environment.go +++ b/environment.go @@ -164,8 +164,8 @@ type EvaluatedExecutionContext struct { // An Environment contains the result of evaluating an environment definition. type Environment struct { - // Exprs contains the AST for each expression in the environment definition. - Exprs map[string]Expr `json:"exprs,omitempty"` + // Exprs contains the AST for the root object expression. + Exprs *Expr `json:"exprs,omitempty"` // Properties contains the detailed values produced by the environment. Properties map[string]Value `json:"properties,omitempty"` diff --git a/eval/eval.go b/eval/eval.go index e6372ebf..ad1ddcad 100644 --- a/eval/eval.go +++ b/eval/eval.go @@ -136,7 +136,7 @@ func evalEnvironment( showSecrets bool, rotatePaths map[string]bool, ) (*esc.Environment, RotationResult, syntax.Diagnostics) { - if env == nil || (len(env.Values.GetEntries()) == 0 && len(env.Imports.GetElements()) == 0) { + if env == nil || (len(env.Values.Entries) == 0 && len(env.Imports.GetElements()) == 0) { return nil, nil, nil } @@ -163,8 +163,9 @@ func evalEnvironment( envProperties, exportDiags := v.export(name) diags.Extend(exportDiags...) + rootExpr := ec.root.export(name) return &esc.Environment{ - Exprs: ec.root.export(name).Object, + Exprs: &rootExpr, Properties: envProperties.Value.(map[string]esc.Value), Schema: s, ExecutionContext: executionContext, @@ -433,18 +434,18 @@ func (e *evalContext) evaluate() (*value, syntax.Diagnostics) { // Build the root value. We do this manually b/c the AST uses a declaration rather than an expression for the // root. - properties := make(map[string]*expr, len(e.env.Values.GetEntries())) + properties := make(map[string]*expr, len(e.env.Values.Entries)) e.root = &expr{ path: "<" + e.name + ">", repr: &objectExpr{ - node: ast.Object(), + node: e.env.Values, properties: properties, }, base: e.base, } // Declare the root value's properties. - for _, entry := range e.env.Values.GetEntries() { + for _, entry := range e.env.Values.Entries { key := entry.Key.GetValue() if e.isReserveTopLevelKey(key) { From 87a1d9a7d4ffb1de12ebc0236e7d3093cd2b7036 Mon Sep 17 00:00:00 2001 From: Sean Yeh <109418+seanyeh@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:49:48 -0600 Subject: [PATCH 2/3] Add GetEntries() --- ast/expr.go | 7 +++++++ eval/eval.go | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ast/expr.go b/ast/expr.go index ef5155e3..7e0950b0 100644 --- a/ast/expr.go +++ b/ast/expr.go @@ -266,6 +266,13 @@ type ObjectExpr struct { Entries []ObjectProperty } +func (o *ObjectExpr) GetEntries() []ObjectProperty { + if o == nil { + return nil + } + return o.Entries +} + // An ObjectProperty represents an object property. Key must be a string. type ObjectProperty struct { syntax syntax.ObjectPropertyDef diff --git a/eval/eval.go b/eval/eval.go index ad1ddcad..6a864546 100644 --- a/eval/eval.go +++ b/eval/eval.go @@ -136,7 +136,7 @@ func evalEnvironment( showSecrets bool, rotatePaths map[string]bool, ) (*esc.Environment, RotationResult, syntax.Diagnostics) { - if env == nil || (len(env.Values.Entries) == 0 && len(env.Imports.GetElements()) == 0) { + if env == nil || (len(env.Values.GetEntries()) == 0 && len(env.Imports.GetElements()) == 0) { return nil, nil, nil } @@ -434,7 +434,7 @@ func (e *evalContext) evaluate() (*value, syntax.Diagnostics) { // Build the root value. We do this manually b/c the AST uses a declaration rather than an expression for the // root. - properties := make(map[string]*expr, len(e.env.Values.Entries)) + properties := make(map[string]*expr, len(e.env.Values.GetEntries())) e.root = &expr{ path: "<" + e.name + ">", repr: &objectExpr{ @@ -445,7 +445,7 @@ func (e *evalContext) evaluate() (*value, syntax.Diagnostics) { } // Declare the root value's properties. - for _, entry := range e.env.Values.Entries { + for _, entry := range e.env.Values.GetEntries() { key := entry.Key.GetValue() if e.isReserveTopLevelKey(key) { From ec8fa2c9ddbdae24cd604c1d88d6530811c20e41 Mon Sep 17 00:00:00 2001 From: Sean Yeh <109418+seanyeh@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:34:23 -0600 Subject: [PATCH 3/3] update tests --- cmd/esc/cli/client/client_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/esc/cli/client/client_test.go b/cmd/esc/cli/client/client_test.go index 368adfba..bda10a99 100644 --- a/cmd/esc/cli/client/client_test.go +++ b/cmd/esc/cli/client/client_test.go @@ -758,7 +758,9 @@ func TestCheckYAMLEnvironment(t *testing.T) { yaml := []byte(`{"values":{"foo":"bar"}}`) expected := &esc.Environment{ - Exprs: map[string]esc.Expr{"foo": {Literal: "bar"}}, + Exprs: &esc.Expr{ + Object: map[string]esc.Expr{"foo": {Literal: "bar"}}, + }, Properties: map[string]esc.Value{"foo": esc.NewValue("bar")}, Schema: schema.Record(schema.BuilderMap{"foo": schema.String().Const("bar")}).Schema(), } @@ -884,7 +886,9 @@ func TestOpenYAMLEnvironment(t *testing.T) { func TestGetOpenEnvironment(t *testing.T) { t.Run("OK", func(t *testing.T) { expected := &esc.Environment{ - Exprs: map[string]esc.Expr{"foo": {Literal: "bar"}}, + Exprs: &esc.Expr{ + Object: map[string]esc.Expr{"foo": {Literal: "bar"}}, + }, Properties: map[string]esc.Value{"foo": esc.NewValue("bar")}, Schema: schema.Record(schema.BuilderMap{"foo": schema.String().Const("bar")}).Schema(), } @@ -918,7 +922,9 @@ func TestGetOpenEnvironment(t *testing.T) { func TestGetAnonymousOpenEnvironment(t *testing.T) { t.Run("OK", func(t *testing.T) { expected := &esc.Environment{ - Exprs: map[string]esc.Expr{"foo": {Literal: "bar"}}, + Exprs: &esc.Expr{ + Object: map[string]esc.Expr{"foo": {Literal: "bar"}}, + }, Properties: map[string]esc.Value{"foo": esc.NewValue("bar")}, Schema: schema.Record(schema.BuilderMap{"foo": schema.String().Const("bar")}).Schema(), }