diff --git a/datamodel/high/node_builder.go b/datamodel/high/node_builder.go index 3b064a86..f2de0773 100644 --- a/datamodel/high/node_builder.go +++ b/datamodel/high/node_builder.go @@ -193,7 +193,9 @@ func (n *NodeBuilder) add(key string, i int) { sort.Slice(lines, func(i, j int) bool { return lines[i] < lines[j] }) - nodeEntry.Line = lines[0] + if len(lines) > 0 { + nodeEntry.Line = lines[0] + } case reflect.Struct: y := value.Interface() nodeEntry.Line = 9999 + i @@ -394,7 +396,9 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, entry *nodes.NodeEntry) *ya vn := vnut.GetValueNode() if vn.Kind == yaml.SequenceNode { for i := range vn.Content { - rawNode.Content[i].Style = vn.Content[i].Style + if len(rawNode.Content) > i { + rawNode.Content[i].Style = vn.Content[i].Style + } } } } diff --git a/datamodel/high/node_builder_test.go b/datamodel/high/node_builder_test.go index 81526426..74f93e93 100644 --- a/datamodel/high/node_builder_test.go +++ b/datamodel/high/node_builder_test.go @@ -49,6 +49,12 @@ func (r valueReferenceStruct) GoLowUntyped() any { return &r } +func (r valueReferenceStruct) GetValueNode() *yaml.Node { + n := utils.CreateEmptySequenceNode() + n.Content = append(n.Content, utils.CreateEmptySequenceNode()) + return n +} + type plug struct { Name []string `yaml:"name,omitempty"` } @@ -117,11 +123,103 @@ func (te *test1) GetKeyNode() *yaml.Node { return kn } +func (te *test1) GetValueNode() *yaml.Node { + kn := utils.CreateStringNode("meddy") + kn.Line = 20 + return kn +} + func (te *test1) GoesLowUntyped() any { panic("GoesLowUntyped") return te } +type test2 struct { + Thrat *valueReferenceStruct `yaml:"throg,omitempty"` + Thrig *orderedmap.Map[string, *plug] `yaml:"thrig,omitempty"` + Thing string `yaml:"thing,omitempty"` + Thong int `yaml:"thong,omitempty"` + Thrum int64 `yaml:"thrum,omitempty"` + Thang float32 `yaml:"thang,omitempty"` + Thung float64 `yaml:"thung,omitempty"` + Thyme bool `yaml:"thyme,omitempty"` + Thurm any `yaml:"thurm,omitempty"` + Thugg *bool `yaml:"thugg,renderZero"` + Thurr *int64 `yaml:"thurr,omitempty"` + Thral *float64 `yaml:"thral,omitempty"` + Throo *float64 `yaml:"throo,renderZero,omitempty"` + Tharg []string `yaml:"tharg,omitempty"` + Type []string `yaml:"type,omitempty"` + Throg []*valueReferenceStruct `yaml:"throg,omitempty"` + Throj *valueReferenceStruct `yaml:"throg,omitempty"` + Thrag []*orderedmap.Map[string, []string] `yaml:"thrag,omitempty"` + Thrug *orderedmap.Map[string, string] `yaml:"thrug,omitempty"` + Thoom []*orderedmap.Map[string, string] `yaml:"thoom,omitempty"` + Thomp *orderedmap.Map[low.KeyReference[string], string] `yaml:"thomp,omitempty"` + Thump valueReferenceStruct `yaml:"thump,omitempty"` + Thane valueReferenceStruct `yaml:"thane,omitempty"` + Thunk valueReferenceStruct `yaml:"thunk,omitempty"` + Thrim *valueReferenceStruct `yaml:"thrim,omitempty"` + Thril *orderedmap.Map[string, *valueReferenceStruct] `yaml:"thril,omitempty"` + Extensions *orderedmap.Map[string, *yaml.Node] `yaml:"-"` + ignoreMe string `yaml:"-"` + IgnoreMe string `yaml:"-"` +} + +func (t test2) IsReference() bool { + return true +} + +func (t test2) GetReference() string { + return "aggghhh" +} + +func (t test2) SetReference(ref string, _ *yaml.Node) { + +} + +func (t test2) GetReferenceNode() *yaml.Node { + return nil +} + +func (t test2) MarshalYAML() (interface{}, error) { + return utils.CreateStringNode("pizza"), nil +} + +func (t test2) MarshalYAMLInline() (interface{}, error) { + return utils.CreateStringNode("pizza-inline!"), nil +} + +func (t test2) GoLowUntyped() any { + return &t +} + +func (t test2) GetValue() *yaml.Node { + return nil +} + +func TestNewNodeBuilder_SliceRef_Inline_HasValue(t *testing.T) { + ty := []interface{}{utils.CreateEmptySequenceNode()} + t1 := test1{ + Thrat: ty, + } + + t2 := test2{ + Thrat: &valueReferenceStruct{Value: renderZero}, + } + + nb := NewNodeBuilder(&t1, &t2) + nb.Resolve = true + node := nb.Render() + + data, _ := yaml.Marshal(node) + + desired := `thrat: + - []` + + assert.Equal(t, desired, strings.TrimSpace(string(data))) +} + func TestNewNodeBuilder(t *testing.T) { b := true c := int64(12345) @@ -606,6 +704,27 @@ func TestNewNodeBuilder_SliceRef_Inline(t *testing.T) { assert.Equal(t, desired, strings.TrimSpace(string(data))) } +func TestNewNodeBuilder_SliceRef_InlineNull(t *testing.T) { + c := valueReferenceStruct{Value: "milky"} + ty := []*valueReferenceStruct{&c} + t1 := test1{ + Throg: ty, + } + + t2 := test1{ + Throg: []*valueReferenceStruct{}, + } + + nb := NewNodeBuilder(&t1, &t2) + node := nb.Render() + + data, _ := yaml.Marshal(node) + + desired := "throg:\n - pizza" + + assert.Equal(t, desired, strings.TrimSpace(string(data))) +} + type testRender struct{} func (t testRender) MarshalYAML() (interface{}, error) { diff --git a/datamodel/spec_info.go b/datamodel/spec_info.go index a4dd60b6..904cbd5a 100644 --- a/datamodel/spec_info.go +++ b/datamodel/spec_info.go @@ -114,6 +114,7 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro case "3.1.0", "3.1": specInfo.VersionNumeric = 3.1 specInfo.APISchema = OpenAPI31SchemaData + specInfo.SpecFormat = OAS31 default: specInfo.VersionNumeric = 3.0 specInfo.APISchema = OpenAPI3SchemaData diff --git a/document.go b/document.go index 98aa9f42..5164247b 100644 --- a/document.go +++ b/document.go @@ -296,7 +296,7 @@ func (d *document) BuildV3Model() (*DocumentModel[v3high.Document], []error) { errs = append(errs, fmt.Errorf("unable to build document, no specification has been loaded")) return nil, errs } - if d.info.SpecFormat != datamodel.OAS3 { + if d.info.SpecFormat != datamodel.OAS3 && d.info.SpecFormat != datamodel.OAS31 { errs = append(errs, fmt.Errorf("unable to build openapi document, "+ "supplied spec is a different version (%v). Try 'BuildV2Model()'", d.info.SpecFormat)) return nil, errs diff --git a/index/spec_index_test.go b/index/spec_index_test.go index d63ea04b..3ed625a6 100644 --- a/index/spec_index_test.go +++ b/index/spec_index_test.go @@ -190,7 +190,7 @@ func TestSpecIndex_DigitalOcean(t *testing.T) { // get all the files! files := remoteFS.GetFiles() fileLen := len(files) - assert.Equal(t, 1654, fileLen) + assert.Equal(t, 1658, fileLen) assert.Len(t, remoteFS.GetErrors(), 0) // check circular references