diff --git a/docs/extensions.md b/docs/extensions.md index b8a2b23..2577961 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -96,7 +96,10 @@ Two extensions set a name: - Both take part in clash resolution with the highest rank ([naming](naming.md#clashes)). - A name that still has to change gets a warning. -- The name is exported unless `x-go-name-exact: true` is set. +- The name is used as written, with its first letter upper case: `ThreeDSACSURL` stays + `ThreeDSACSURL`. `x-go-name-exact: true` keeps the first letter too, so the name can be + unexported. A name that is still not exported, such as `_note`, goes through the + [naming rules](naming.md). ## x-sensitive-data diff --git a/internal/gomodel/extensions.go b/internal/gomodel/extensions.go index e600102..83a9398 100644 --- a/internal/gomodel/extensions.go +++ b/internal/gomodel/extensions.go @@ -9,9 +9,12 @@ package gomodel import ( "fmt" + "go/token" "slices" "strconv" "strings" + "unicode" + "unicode/utf8" "github.com/mockzilla/mockzilla-codegen/internal/diag" "github.com/mockzilla/mockzilla-codegen/internal/extension" @@ -100,11 +103,16 @@ func (r *extReader) clash(p *spec.Parameter, name, outer, inner string) { }) } -// goName is the Go name x-go-name asks for: as written with x-go-name-exact, else exported. +// goName is the Go name x-go-name asks for, as written with its first letter upper unless exact. func (r *extReader) goName(set extension.Set, name string) string { if name == "" || set.IsExactName { return name } + + first, size := utf8.DecodeRuneInString(name) + if upper := string(unicode.ToUpper(first)) + name[size:]; token.IsExported(upper) { + return upper + } return r.namer.Exported(name) } diff --git a/internal/gomodel/testdata/extensions.golden b/internal/gomodel/testdata/extensions.golden index bd075b8..96f346f 100644 --- a/internal/gomodel/testdata/extensions.golden +++ b/internal/gomodel/testdata/extensions.golden @@ -1,6 +1,8 @@ Customer struct models.types Identifier string json=id required yaml=id accountSecret *string json=secret omitempty jsonIgnored yaml=secret,omitempty + ThreeDSACSURL *string json=acs_url omitempty yaml=acs_url,omitempty + Note *string json=_note omitempty yaml=_note,omitempty Nickname string json=nickname omitempty yaml=nickname,omitempty Count *int json=count yaml=count Code *string json=code omitempty yaml=code,omitempty @@ -40,6 +42,6 @@ op GetAccount GET /accounts/{id} warning extension-value 11:11 /paths/~1accounts~1{id}/get/parameters/3: x-go-extra-tags db of query parameter "sort" is "sort", and "order" in its schema; the parameter's is used warning extension-value 11:11 /paths/~1accounts~1{id}/get/parameters/3: x-go-name of query parameter "sort" is "SortBy", and "Order" in its schema; the parameter's is used warning extension-value 21:13 /components/parameters/Cursor: x-go-name of query parameter "cursor" is "After", and "Before" in its schema; the parameter's is used -warning extension-unknown 69:11 /components/schemas/Account/properties/typo/x-go-nam: unknown extension x-go-nam; it is left out -warning enum-name-unexported 76:7 /components/schemas/Shade/x-enum-names/0: x-enum-names "light" is unexported; it is used as written -warning name-clash 93:16 /components/schemas/Renamed/properties/clash: "Validate" is reserved, renamed to "Validate2" +warning extension-unknown 75:11 /components/schemas/Account/properties/typo/x-go-nam: unknown extension x-go-nam; it is left out +warning enum-name-unexported 82:7 /components/schemas/Shade/x-enum-names/0: x-enum-names "light" is unexported; it is used as written +warning name-clash 99:16 /components/schemas/Renamed/properties/clash: "Validate" is reserved, renamed to "Validate2" diff --git a/internal/gomodel/testdata/extensions.yaml b/internal/gomodel/testdata/extensions.yaml index bd59653..57f3f94 100644 --- a/internal/gomodel/testdata/extensions.yaml +++ b/internal/gomodel/testdata/extensions.yaml @@ -33,6 +33,12 @@ components: x-go-name: accountSecret x-go-name-exact: true x-go-json-ignore: true + acs_url: + type: string + x-go-name: ThreeDSACSURL + _note: + type: string + x-go-name: _note nickname: type: string x-go-type-skip-optional-pointer: true