Skip to content

Commit

Permalink
Improve error msg for invalid enum values on convert
Browse files Browse the repository at this point in the history
  • Loading branch information
aq17 committed Dec 1, 2022
1 parent 7afac76 commit 927e9d4
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 6 deletions.
@@ -0,0 +1,4 @@
changes:
- type: fix
scope: programgen
description: Improve error message for invalid enum values on `pulumi convert`.
5 changes: 4 additions & 1 deletion pkg/codegen/dotnet/gen_program_expressions.go
Expand Up @@ -335,9 +335,12 @@ func (g *generator) genIntrensic(w io.Writer, from model.Expression, to model.Ty
if isOutput {
g.Fgenf(w, "%.v.Apply(%s)", from, convertFn)
} else {
pcl.GenEnum(to, from, g.genSafeEnum(w, to), func(from model.Expression) {
diag := pcl.GenEnum(to, from, g.genSafeEnum(w, to), func(from model.Expression) {
g.Fgenf(w, "%s(%v)", convertFn, from)
})
if diag != nil {
g.diagnostics = append(g.diagnostics, diag)
}
}
default:
g.Fgenf(w, "%.v", from) // <- probably wrong w.r.t. precedence
Expand Down
5 changes: 4 additions & 1 deletion pkg/codegen/go/gen_program_expressions.go
Expand Up @@ -205,9 +205,12 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
from, enumTag, underlyingType)
return
}
pcl.GenEnum(to, from, g.genSafeEnum(w, to), func(from model.Expression) {
diag := pcl.GenEnum(to, from, g.genSafeEnum(w, to), func(from model.Expression) {
g.Fgenf(w, "%s(%v)", enumTag, from)
})
if diag != nil {
g.diagnostics = append(g.diagnostics, diag)
}
return
}
switch arg := from.(type) {
Expand Down
5 changes: 4 additions & 1 deletion pkg/codegen/nodejs/gen_program_expressions.go
Expand Up @@ -336,13 +336,16 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
if isOutput {
g.Fgenf(w, "%.v.apply((x) => %s[x])", from, enum)
} else {
pcl.GenEnum(to, from, func(member *schema.Enum) {
diag := pcl.GenEnum(to, from, func(member *schema.Enum) {
memberTag, err := enumMemberName(tokenToName(to.Token), member)
contract.AssertNoErrorf(err, "Failed to get member name on enum '%s'", enum)
g.Fgenf(w, "%s.%s", enum, memberTag)
}, func(from model.Expression) {
g.Fgenf(w, "%s[%.v]", enum, from)
})
if diag != nil {
g.diagnostics = append(g.diagnostics, diag)
}
}
} else {
g.Fgenf(w, "%v", from)
Expand Down
44 changes: 42 additions & 2 deletions pkg/codegen/pcl/binder_schema.go
Expand Up @@ -16,6 +16,7 @@ package pcl

import (
"fmt"
"strings"
"sync"

"github.com/blang/semver"
Expand Down Expand Up @@ -549,7 +550,7 @@ func GenEnum(
from model.Expression,
safeEnum func(member *schema.Enum),
unsafeEnum func(from model.Expression),
) {
) *hcl.Diagnostic {
known := cty.NilVal
if from, ok := from.(*model.TemplateExpression); ok && len(from.Parts) == 1 {
if from, ok := from.Parts[0].(*model.LiteralValueExpression); ok {
Expand All @@ -566,8 +567,47 @@ func GenEnum(
contract.Assertf(ok,
"We have determined %s is a safe enum, which we define as "+
"being able to calculate a member for", t)
safeEnum(member)
if member != nil {
safeEnum(member)
} else {
unsafeEnum(from)
knownVal := strings.Split(strings.Split(known.GoString(), "(")[1], ")")[0]
diag := &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: fmt.Sprintf("%v is not a valid value of the enum \"%v\"", knownVal, t.Token),
}
if members := enumMemberValues(t); len(members) > 0 {
diag.Detail = fmt.Sprintf("Valid members are %v", listToString(members))
}
return diag
}
} else {
unsafeEnum(from)
}
return nil
}

func enumMemberValues(t *model.EnumType) []interface{} {
srcBase, ok := GetSchemaForType(t)
if !ok {
return nil
}
src := srcBase.(*schema.EnumType)
members := make([]interface{}, len(src.Elements))
for i, el := range src.Elements {
members[i] = el.Value
}
return members
}

func listToString(l []interface{}) string {
vals := ""
for i, v := range l {
if i == 0 {
vals = fmt.Sprintf("\"%v\"", v)
} else {
vals = fmt.Sprintf("%s, \"%v\"", vals, v)
}
}
return vals
}
34 changes: 34 additions & 0 deletions pkg/codegen/pcl/binder_schema_test.go
Expand Up @@ -4,9 +4,12 @@ import (
"path/filepath"
"testing"

"github.com/pulumi/pulumi/pkg/v3/codegen/hcl2/model"
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
"github.com/pulumi/pulumi/pkg/v3/codegen/testing/utils"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
"github.com/stretchr/testify/assert"
"github.com/zclconf/go-cty/cty"
)

var testdataPath = filepath.Join("..", "testing", "test", "testdata")
Expand All @@ -19,3 +22,34 @@ func BenchmarkLoadPackage(b *testing.B) {
contract.AssertNoError(err)
}
}

func TestGenEnum(t *testing.T) {
t.Parallel()
enum := &model.EnumType{
Elements: []cty.Value{
cty.StringVal("foo"),
cty.StringVal("bar"),
},
Type: model.StringType,
Token: "my:enum",
Annotations: []interface{}{
enumSchemaType{
Type: &schema.EnumType{Elements: []*schema.Enum{{Value: "foo"}, {Value: "bar"}}},
},
},
}
safeEnumFunc := func(member *schema.Enum) {}
unsafeEnumFunc := func(from model.Expression) {}

d := GenEnum(enum, &model.LiteralValueExpression{
Value: cty.StringVal("foo"),
}, safeEnumFunc, unsafeEnumFunc)
assert.Nil(t, d)

d = GenEnum(enum, &model.LiteralValueExpression{
Value: cty.StringVal("Bar"),
}, safeEnumFunc, unsafeEnumFunc)
assert.Equal(t, d.Summary, `"Bar" is not a valid value of the enum "my:enum"`)
assert.Equal(t, d.Detail, `Valid members are "foo", "bar"`)

}
5 changes: 4 additions & 1 deletion pkg/codegen/python/gen_program_expressions.go
Expand Up @@ -247,7 +247,7 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
if isOutput {
g.Fgenf(w, "%.v.apply(lambda x: %s.%s(x))", from, pkg, enumName)
} else {
pcl.GenEnum(to, from, func(member *schema.Enum) {
diag := pcl.GenEnum(to, from, func(member *schema.Enum) {
tag := member.Name
if tag == "" {
tag = fmt.Sprintf("%v", member.Value)
Expand All @@ -258,6 +258,9 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
}, func(from model.Expression) {
g.Fgenf(w, "%s.%s(%.v)", pkg, enumName, from)
})
if diag != nil {
g.diagnostics = append(g.diagnostics, diag)
}
}
default:
switch arg := from.(type) {
Expand Down

0 comments on commit 927e9d4

Please sign in to comment.