diff --git a/pkg/codegen/model.go b/pkg/codegen/model.go index ae56bffb..5164a828 100644 --- a/pkg/codegen/model.go +++ b/pkg/codegen/model.go @@ -277,7 +277,7 @@ type AliasType struct { } func (p AliasType) Generate(out *Emitter) error { - out.Printf("type %s = %s", p.Alias, p.Name) + out.Printlnf("type %s = %s", p.Alias, p.Name) return nil } diff --git a/pkg/generator/generate.go b/pkg/generator/generate.go index 0ea248e4..554063a8 100644 --- a/pkg/generator/generate.go +++ b/pkg/generator/generate.go @@ -147,6 +147,14 @@ func (g *Generator) AddFile(fileName string, schema *schemas.Schema) error { return err } + if schema.ID != "" { + if _, processed := o.processedSchemas[schema.ID]; processed { + return nil + } + + o.processedSchemas[schema.ID] = true + } + return newSchemaGenerator(g, schema, fileName, o).generateRootType() } @@ -213,6 +221,7 @@ func (g *Generator) beginOutput( declsBySchema: map[*schemas.Type]*codegen.TypeDecl{}, declsByName: map[string]*codegen.TypeDecl{}, unmarshallersByTypeDecl: map[*codegen.TypeDecl]bool{}, + processedSchemas: map[string]bool{}, } g.outputs[id] = output diff --git a/pkg/generator/output.go b/pkg/generator/output.go index 9fd42cf6..8fe756cb 100644 --- a/pkg/generator/output.go +++ b/pkg/generator/output.go @@ -16,6 +16,7 @@ type output struct { declsByName map[string]*codegen.TypeDecl declsBySchema map[*schemas.Type]*codegen.TypeDecl unmarshallersByTypeDecl map[*codegen.TypeDecl]bool + processedSchemas map[string]bool warner func(string) } diff --git a/pkg/schemas/model.go b/pkg/schemas/model.go index 2bb7860c..9852589d 100644 --- a/pkg/schemas/model.go +++ b/pkg/schemas/model.go @@ -304,6 +304,7 @@ func AnyOf(types []*Type, baseType *Type) (*Type, error) { return nil, err } + typ.Required = mergeRequiredUnion(types, baseType) typ.subSchemaType = SubSchemaTypeAnyOf typ.subSchemasCount = len(types) @@ -339,6 +340,29 @@ func MergeTypes(types []*Type, baseType *Type) (*Type, error) { return result, nil } +func mergeRequiredUnion(types []*Type, baseType *Type) []string { + required := make([]string, len(baseType.Required)) + copy(required, baseType.Required) + + for _, r := range types[0].Required { + valid := true + + for _, t := range types { + if !slices.Contains(t.Required, r) { + valid = false + + break + } + } + + if valid && !slices.Contains(required, r) { + required = append(required, r) //nolint:makezero + } + } + + return required +} + func updateAllRefsValues(structValue *reflect.Value, refPath string) error { switch structValue.Kind() { //nolint:exhaustive case reflect.Struct: diff --git a/tests/data/core/anyOf/anyOf.1.go b/tests/data/core/anyOf/anyOf.1.go index 5584cf2e..58e05d0e 100644 --- a/tests/data/core/anyOf/anyOf.1.go +++ b/tests/data/core/anyOf/anyOf.1.go @@ -18,13 +18,13 @@ type AnyOf1 struct { type AnyOf1ConfigurationsElem struct { // Bar corresponds to the JSON schema field "bar". - Bar float64 `json:"bar" yaml:"bar" mapstructure:"bar"` + Bar *float64 `json:"bar,omitempty" yaml:"bar,omitempty" mapstructure:"bar,omitempty"` // Baz corresponds to the JSON schema field "baz". Baz *bool `json:"baz,omitempty" yaml:"baz,omitempty" mapstructure:"baz,omitempty"` // Foo corresponds to the JSON schema field "foo". - Foo string `json:"foo" yaml:"foo" mapstructure:"foo"` + Foo *string `json:"foo,omitempty" yaml:"foo,omitempty" mapstructure:"foo,omitempty"` } type AnyOf1ConfigurationsElem_0 struct { diff --git a/tests/data/core/anyOf/anyOf.2.go b/tests/data/core/anyOf/anyOf.2.go index 8a68d370..1d21546b 100644 --- a/tests/data/core/anyOf/anyOf.2.go +++ b/tests/data/core/anyOf/anyOf.2.go @@ -15,13 +15,13 @@ type AnyOf2 struct { type AnyOf2ConfigurationsElem struct { // Bar corresponds to the JSON schema field "bar". - Bar float64 `json:"bar" yaml:"bar" mapstructure:"bar"` + Bar *float64 `json:"bar,omitempty" yaml:"bar,omitempty" mapstructure:"bar,omitempty"` // Baz corresponds to the JSON schema field "baz". Baz *bool `json:"baz,omitempty" yaml:"baz,omitempty" mapstructure:"baz,omitempty"` // Foo corresponds to the JSON schema field "foo". - Foo string `json:"foo" yaml:"foo" mapstructure:"foo"` + Foo *string `json:"foo,omitempty" yaml:"foo,omitempty" mapstructure:"foo,omitempty"` } type AnyOf2ConfigurationsElem_1 struct { diff --git a/tests/data/core/anyOf/anyOf.3.go b/tests/data/core/anyOf/anyOf.3.go index 0d38f304..e9ac8b7c 100644 --- a/tests/data/core/anyOf/anyOf.3.go +++ b/tests/data/core/anyOf/anyOf.3.go @@ -10,13 +10,13 @@ import yaml "gopkg.in/yaml.v3" // object with anyOf properties as root type AnyOf3 struct { // Bar corresponds to the JSON schema field "bar". - Bar float64 `json:"bar" yaml:"bar" mapstructure:"bar"` + Bar *float64 `json:"bar,omitempty" yaml:"bar,omitempty" mapstructure:"bar,omitempty"` // Configurations corresponds to the JSON schema field "configurations". Configurations []interface{} `json:"configurations,omitempty" yaml:"configurations,omitempty" mapstructure:"configurations,omitempty"` // Foo corresponds to the JSON schema field "foo". - Foo string `json:"foo" yaml:"foo" mapstructure:"foo"` + Foo *string `json:"foo,omitempty" yaml:"foo,omitempty" mapstructure:"foo,omitempty"` } type AnyOf3_0 struct { diff --git a/tests/data/core/anyOf/anyOf.4.go b/tests/data/core/anyOf/anyOf.4.go index 5fea31b6..4cad4a15 100644 --- a/tests/data/core/anyOf/anyOf.4.go +++ b/tests/data/core/anyOf/anyOf.4.go @@ -13,10 +13,10 @@ type AnyOf4 []AnyOf4Elem type AnyOf4Elem struct { // When consuming a CDEvent, you are consuming a parent event. So, when looking at // the 'from' key, this is the parent's parent. - From EmbeddedlinkendFrom `json:"from" yaml:"from" mapstructure:"from"` + From *EmbeddedlinkendFrom `json:"from,omitempty" yaml:"from,omitempty" mapstructure:"from,omitempty"` // LinkKind corresponds to the JSON schema field "linkKind". - LinkKind string `json:"linkKind" yaml:"linkKind" mapstructure:"linkKind"` + LinkKind *string `json:"linkKind,omitempty" yaml:"linkKind,omitempty" mapstructure:"linkKind,omitempty"` // LinkType corresponds to the JSON schema field "linkType". LinkType EmbeddedlinkendLinkType `json:"linkType" yaml:"linkType" mapstructure:"linkType"` @@ -25,7 +25,7 @@ type AnyOf4Elem struct { Tags EmbeddedlinkendTags `json:"tags,omitempty" yaml:"tags,omitempty" mapstructure:"tags,omitempty"` // Target corresponds to the JSON schema field "target". - Target EmbeddedlinkrelationTarget `json:"target" yaml:"target" mapstructure:"target"` + Target *EmbeddedlinkrelationTarget `json:"target,omitempty" yaml:"target,omitempty" mapstructure:"target,omitempty"` } // UnmarshalYAML implements yaml.Unmarshaler. @@ -515,7 +515,9 @@ func (j *Embeddedlinkrelation) UnmarshalJSON(value []byte) error { } type AnyOf4Elem_2 = Embeddedlinkrelation + type AnyOf4Elem_1 = Embeddedlinkpath + type AnyOf4Elem_0 = Embeddedlinkend // UnmarshalYAML implements yaml.Unmarshaler. diff --git a/tests/data/core/anyOf/anyOf.6.go b/tests/data/core/anyOf/anyOf.6.go index f79b40ae..43c3a81c 100644 --- a/tests/data/core/anyOf/anyOf.6.go +++ b/tests/data/core/anyOf/anyOf.6.go @@ -152,16 +152,27 @@ func (j *Bar2ContentElem) UnmarshalYAML(value *yaml.Node) error { } type Baz2ContentElem_2 = Baz2 + type Baz2ContentElem_0 = Foo2 + type AnyOf6Qux2Elem_2 = Baz2 + type AnyOf6Qux2Elem_1 = Bar2 + type AnyOf6Qux2Elem_0 = Foo2 + type Foo2ContentElem_0 = Foo2 + type Foo2ContentElem_1 = Bar2 + type Foo2ContentElem_2 = Baz2 + type Baz2ContentElem_1 = Bar2 + type Bar2ContentElem_2 = Baz2 + type Bar2ContentElem_1 = Bar2 + type Bar2ContentElem_0 = Foo2 // UnmarshalJSON implements json.Unmarshaler. diff --git a/tests/data/core/anyOf/anyOf.7.go b/tests/data/core/anyOf/anyOf.7.go index 839864a4..21c6ad0e 100644 --- a/tests/data/core/anyOf/anyOf.7.go +++ b/tests/data/core/anyOf/anyOf.7.go @@ -88,6 +88,7 @@ func (j *Item) UnmarshalYAML(value *yaml.Node) error { } type AnyOf7BazElem_0 = Item + type Item struct { // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` @@ -140,6 +141,7 @@ func (j *AnyOf7BazElem) UnmarshalYAML(value *yaml.Node) error { } type AnyOf7BarElem_0 = Item + type AnyOf7Foo struct { // Name corresponds to the JSON schema field "name". Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` diff --git a/tests/data/core/anyOf/anyOfMultipleRequired.go b/tests/data/core/anyOf/anyOfMultipleRequired.go index a44531d6..32a1f712 100644 --- a/tests/data/core/anyOf/anyOfMultipleRequired.go +++ b/tests/data/core/anyOf/anyOfMultipleRequired.go @@ -93,16 +93,18 @@ func (j *MultipleRequiredMiddle) UnmarshalYAML(value *yaml.Node) error { } type ComposedWithMultipleRequired_0 = MultipleRequiredBase + type ComposedWithMultipleRequired_1 = MultipleRequiredMiddle + type ComposedWithMultipleRequired struct { // BaseField corresponds to the JSON schema field "baseField". - BaseField string `json:"baseField" yaml:"baseField" mapstructure:"baseField"` + BaseField *string `json:"baseField,omitempty" yaml:"baseField,omitempty" mapstructure:"baseField,omitempty"` // DirectField corresponds to the JSON schema field "directField". DirectField bool `json:"directField" yaml:"directField" mapstructure:"directField"` // MiddleField corresponds to the JSON schema field "middleField". - MiddleField float64 `json:"middleField" yaml:"middleField" mapstructure:"middleField"` + MiddleField *float64 `json:"middleField,omitempty" yaml:"middleField,omitempty" mapstructure:"middleField,omitempty"` AdditionalProperties interface{} `mapstructure:",remain"` } diff --git a/tests/data/core/anyOf/anyOfWithDirectProperties.go b/tests/data/core/anyOf/anyOfWithDirectProperties.go index ddcb65e4..d5248703 100644 --- a/tests/data/core/anyOf/anyOfWithDirectProperties.go +++ b/tests/data/core/anyOf/anyOfWithDirectProperties.go @@ -52,6 +52,7 @@ func (j *BaseObject) UnmarshalYAML(value *yaml.Node) error { } type ComposedWithAllOfAndProperties_0 = BaseObject + type ComposedWithAllOfAndProperties struct { // BaseField corresponds to the JSON schema field "BaseField". BaseField string `json:"BaseField" yaml:"BaseField" mapstructure:"BaseField"` diff --git a/tests/unmarshal_json_test.go b/tests/unmarshal_json_test.go index e569151a..b576fd08 100644 --- a/tests/unmarshal_json_test.go +++ b/tests/unmarshal_json_test.go @@ -85,8 +85,8 @@ func TestJsonUmarshalAnyOf(t *testing.T) { t, &testAnyOf.AnyOf1{ Configurations: []testAnyOf.AnyOf1ConfigurationsElem{ - {Foo: "hello"}, - {Bar: 2.2}, + {Foo: ptr("hello")}, + {Bar: ptr(2.2)}, {Baz: ptr(true)}, }, Flags: "hello", @@ -115,8 +115,8 @@ func TestJsonUmarshalAnyOf(t *testing.T) { t, &testAnyOf.AnyOf1{ Configurations: []testAnyOf.AnyOf1ConfigurationsElem{ - {Foo: "ciao"}, - {Bar: 200.0}, + {Foo: ptr("ciao")}, + {Bar: ptr(200.0)}, }, Flags: true, }, @@ -145,8 +145,8 @@ func TestJsonUmarshalAnyOf(t *testing.T) { t, &testAnyOf.AnyOf2{ Configurations: []testAnyOf.AnyOf2ConfigurationsElem{ - {Foo: "ciao"}, - {Bar: 2.0}, + {Foo: ptr("ciao")}, + {Bar: ptr(2.0)}, {Baz: ptr(false)}, }, }, @@ -162,7 +162,7 @@ func TestJsonUmarshalAnyOf(t *testing.T) { assert.Equal( t, &testAnyOf.AnyOf3{ - Foo: "ciao", + Foo: ptr("ciao"), }, target, ) @@ -176,7 +176,7 @@ func TestJsonUmarshalAnyOf(t *testing.T) { assert.Equal( t, &testAnyOf.AnyOf3{ - Bar: 2.0, + Bar: ptr(2.0), }, target, )