diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 435bf2e..384e93b 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,3 +1,4 @@ Blake Gentry Bo Jeans Timothée Peignier +Chris Johnson diff --git a/gen.go b/gen.go index 90f9879..f36d0d3 100644 --- a/gen.go +++ b/gen.go @@ -70,6 +70,10 @@ func (s *Schema) Generate() ([]byte, error) { Definition: schema, } + if !s.CheckForDuplicateTitles() { + return nil, fmt.Errorf("duplicate titles detected for %s", context.Name) + } + templates.ExecuteTemplate(&buf, "struct.tmpl", context) templates.ExecuteTemplate(&buf, "funcs.tmpl", context) } @@ -237,22 +241,24 @@ func (s *Schema) Values(name string, l *Link) []string { return values } -// UniqueLinks returns a list of links, unique by title. +// CheckForDuplicateTitles ensures that all titles are unique for a schema. // -// If more than one link in a given schema has the same title, only the one -// appearing last will appear in this list. This matches the behavior of the -// heroics Ruby gem and avoids generating structs and funcs with duplicate -// names. -func (s *Schema) UniqueLinks() []*Link { +// If more than one link in a given schema has the same title, we cannot +// accurately generate the client from the schema. Although it's not strictly a +// schema violation, it needs to be fixed before the client can be properly +// generated. +func (s *Schema) CheckForDuplicateTitles() bool { titles := map[string]bool{} var uniqueLinks []*Link for _, link := range s.Links { - if _, ok := titles[link.Title]; !ok { + title := strings.ToLower(link.Title) + if _, ok := titles[title]; !ok { uniqueLinks = append(uniqueLinks, link) } - titles[link.Title] = true + titles[title] = true } - return uniqueLinks + + return len(uniqueLinks) != len(s.Links) } // URL returns schema base URL. diff --git a/gen_test.go b/gen_test.go index 74b6f52..d7afb78 100644 --- a/gen_test.go +++ b/gen_test.go @@ -616,3 +616,63 @@ func TestValues(t *testing.T) { } } } + +var linkTitleTests = []struct { + Schema *Schema + Expected bool +}{ + { + Schema: &Schema{ + Title: "Selfreferencing", + Type: "object", + Links: []*Link{ + { + Title: "Create", + }, + { + Title: "Create", + }, + }, + }, + Expected: true, + }, + { + Schema: &Schema{ + Title: "Selfreferencing", + Type: "object", + Links: []*Link{ + { + Title: "update", + }, + { + Title: "Update", + }, + }, + }, + Expected: true, + }, + { + Schema: &Schema{ + Title: "Selfreferencing", + Type: "object", + Links: []*Link{ + { + Title: "Create", + }, + { + Title: "Delete", + }, + }, + }, + Expected: false, + }, +} + +func TestLinkTitles(t *testing.T) { + for i, lt := range linkTitleTests { + resp := lt.Schema.CheckForDuplicateTitles() + if resp != lt.Expected { + t.Errorf("%d: wants %v, got %v", i, lt.Expected, resp) + } + } +} diff --git a/templates/funcs.tmpl b/templates/funcs.tmpl index 91e6e69..5aa25d1 100644 --- a/templates/funcs.tmpl +++ b/templates/funcs.tmpl @@ -1,6 +1,6 @@ {{$Name := .Name}} {{$Def := .Definition}} -{{range .Definition.UniqueLinks}} +{{range .Definition.Links}} {{if .AcceptsCustomType}} type {{paramType $Name .}} {{linkGoType .}} {{end}} @@ -19,4 +19,3 @@ {{end}} } {{end}} - diff --git a/templates/templates.go b/templates/templates.go index 13340da..85e618f 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -6,7 +6,7 @@ var templates = map[string]string{"field.tmpl": `{{initialCap .Name}} {{.Type}} `, "funcs.tmpl": `{{$Name := .Name}} {{$Def := .Definition}} -{{range .Definition.UniqueLinks}} +{{range .Definition.Links}} {{if .AcceptsCustomType}} type {{paramType $Name .}} {{linkGoType .}} {{end}} @@ -263,4 +263,3 @@ func Parse(t *template.Template) (*template.Template, error) { } return t, nil } -