diff --git a/references/cuegen/convert.go b/references/cuegen/convert.go index 6ae51d196..98bd23774 100644 --- a/references/cuegen/convert.go +++ b/references/cuegen/convert.go @@ -93,11 +93,16 @@ func (g *Generator) convert(typ gotypes.Type) (cueast.Expr, error) { if err != nil { return nil, err } - return &cueast.BinaryExpr{ - X: cueast.NewNull(), - Op: cuetoken.OR, - Y: expr, - }, nil + + // generate null enum for pointer type + if g.opts.nullable { + return &cueast.BinaryExpr{ + X: cueast.NewNull(), + Op: cuetoken.OR, + Y: expr, + }, nil + } + return expr, nil case *gotypes.Slice: if t.Elem().String() == "byte" { return ident("bytes", false), nil diff --git a/references/cuegen/convert_test.go b/references/cuegen/convert_test.go index a22c0d2c2..cafba24fa 100644 --- a/references/cuegen/convert_test.go +++ b/references/cuegen/convert_test.go @@ -63,3 +63,16 @@ func TestConvertInvalid(t *testing.T) { t.Error(err) } } + +func TestConvertNullable(t *testing.T) { + g, err := NewGenerator("testdata/nullable.go") + assert.NoError(t, err) + + got := &bytes.Buffer{} + assert.NoError(t, g.Generate(got, WithNullable())) + + want, err := os.ReadFile("testdata/nullable.cue") + assert.NoError(t, err) + + assert.Equal(t, got.String(), string(want)) +} diff --git a/references/cuegen/option.go b/references/cuegen/option.go index f50da0db3..08e680b10 100644 --- a/references/cuegen/option.go +++ b/references/cuegen/option.go @@ -18,6 +18,7 @@ package cuegen type options struct { anyTypes map[string]struct{} + nullable bool } var defaultOptions = &options{ @@ -25,6 +26,7 @@ var defaultOptions = &options{ "map[string]interface{}": {}, "map[string]any": {}, "interface{}": {}, "any": {}, }, + nullable: false, } // Option is a function that configures generation options @@ -42,3 +44,10 @@ func WithAnyTypes(types ...string) Option { } } } + +// WithNullable will generate null enum for pointer type +func WithNullable() Option { + return func(opts *options) { + opts.nullable = true + } +} diff --git a/references/cuegen/option_test.go b/references/cuegen/option_test.go index 0a16f7d2a..9ac042cce 100644 --- a/references/cuegen/option_test.go +++ b/references/cuegen/option_test.go @@ -47,10 +47,29 @@ func TestWithAnyTypes(t *testing.T) { } for _, tt := range tests { - opts := options{map[string]struct{}{}} + opts := options{anyTypes: map[string]struct{}{}} for _, opt := range tt.opts { opt(&opts) } assert.Equal(t, opts.anyTypes, tt.extra, tt.name) } } + +func TestWithNullable(t *testing.T) { + tests := []struct { + name string + opts []Option + want bool + }{ + {name: "default", opts: nil, want: false}, + {name: "true", opts: []Option{WithNullable()}, want: true}, + } + + for _, tt := range tests { + opts := options{nullable: false} + for _, opt := range tt.opts { + opt(&opts) + } + assert.Equal(t, opts.nullable, tt.want, tt.name) + } +} diff --git a/references/cuegen/testdata/nullable.cue b/references/cuegen/testdata/nullable.cue new file mode 100644 index 000000000..162fa7c5b --- /dev/null +++ b/references/cuegen/testdata/nullable.cue @@ -0,0 +1,14 @@ +package testdata + +Nullable: { + field1?: null | string + field2?: null | int + field3?: null | bool + Field4: null | { + field1: null | string + field2: null | int + field3: null | bool + } + field5?: null | [...string] + field6?: null | [...int] +} diff --git a/references/cuegen/testdata/nullable.go b/references/cuegen/testdata/nullable.go new file mode 100644 index 000000000..93f129ef5 --- /dev/null +++ b/references/cuegen/testdata/nullable.go @@ -0,0 +1,30 @@ +/* +Copyright 2023 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testdata + +type Nullable struct { + Field1 *string `json:"field1,omitempty"` + Field2 *int `json:"field2,omitempty"` + Field3 *bool `json:"field3,omitempty"` + Field4 *struct { + Field1 *string `json:"field1"` + Field2 *int `json:"field2"` + Field3 *bool `json:"field3"` + } + Field5 *[]string `json:"field5,omitempty"` + Field6 *[]int `json:"field6,omitempty"` +} diff --git a/references/cuegen/testdata/valid.cue b/references/cuegen/testdata/valid.cue index a41601b88..bd04c4250 100644 --- a/references/cuegen/testdata/valid.cue +++ b/references/cuegen/testdata/valid.cue @@ -52,7 +52,7 @@ AnonymousField: SmallStruct: { field1: string field2: string } -ReferenceField: field1: null | { +ReferenceField: field1: { field1: string field2: string } @@ -61,7 +61,7 @@ StructField: { field1: string field2: string } - field2: null | { + field2: { field1: string field2: string }