Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ each rename.
|---|---|---|
| `client_address`, `client-address`, `client.address` | `ClientAddress` | Any character that is not a letter or a digit splits words, apart from the symbols below. |
| `fooBar`, `HTTPServer` | `FooBar`, `HTTPServer` | A capital starts a word. An upper-case run ends before its last capital when a lower-case letter follows. |
| `v2api`, `404NotFound` | `V2API`, `N404NotFound` | Digits stay with the word before them. A letter after them starts a new word. |
| `v2api`, `404NotFound` | `V2API`, `N404NotFound` | Digits stay with the word before them. A letter after them starts a new word, unless the word starts with the digits: `1st` stays one word. |
| `CLIENT_ADDRESS`, `SSN` | `ClientAddress`, `Ssn` | Every word is written with one capital, unless it is an initialism. |
| `userId`, `urls`, `userIDs`, `id2` | `UserID`, `URLs`, `UserIDs`, `ID2` | Initialisms stay upper case, also with a plural `s` or trailing digits. |
| `userId`, `urls`, `userIDs`, `id2`, `short_2url` | `UserID`, `URLs`, `UserIDs`, `ID2`, `Short2URL` | Initialisms stay upper case, also with a plural `s` or digits before or after them. |
| `1st`, `200` | `N1st`, `N200` | A name that would start with a digit gets `N` in front. |
| `+1`, `-1`, `-created_at`, `@type` | `Plus1`, `Minus1`, `MinusCreatedAt`, `AtType` | `+` and `@` become words anywhere, `-` only at the start. |
| `1.5`, `v1.2` | `N1Dot5`, `V1Dot2` | A dot between two digits becomes `Dot`. |
Expand All @@ -39,7 +39,8 @@ naming:
```

An initialism matches a whole word in any case: `Id`, `id` and `ID` all give `ID`. It does not
match inside a word, so `userid` stays `Userid`.
match inside a word, so `userid` stays `Userid`. Digits in front do not stop it: with `DS` listed,
`force_3ds_flow` gives `Force3DSFlow`.

## Names for types without a name

Expand Down
23 changes: 18 additions & 5 deletions internal/naming/namer.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,22 +241,35 @@ func (n *Namer) camel(part string) string {
return b.String()
}

// caseWord keeps initialisms canonical, also with a plural "s" or trailing digits: IDs, HTTP2.
// caseWord keeps initialisms canonical, also after leading digits: IDs, HTTP2, 3DS.
func (n *Namer) caseWord(w string) string {
lw := strings.ToLower(w)
if c, ok := n.initialisms[lw]; ok {
if c, ok := n.initialism(lw); ok {
return c
}

rest := strings.TrimLeft(lw, "0123456789")
if c, ok := n.initialism(rest); ok {
return lw[:len(lw)-len(rest)] + c
}
return strings.ToUpper(lw[:1]) + lw[1:]
}

// initialism writes lw canonical when it is one, also with a plural "s" or trailing digits.
func (n *Namer) initialism(lw string) (string, bool) {
if c, ok := n.initialisms[lw]; ok {
return c, true
}

letters := strings.TrimRight(lw, "0123456789")
digits := lw[len(letters):]
if c, ok := n.initialisms[letters]; ok {
return c + digits
return c + digits, true
}
if base, ok := strings.CutSuffix(letters, "s"); ok {
if c, found := n.initialisms[base]; found {
return c + "s" + digits
return c + "s" + digits, true
}
}
return strings.ToUpper(lw[:1]) + lw[1:]
return "", false
}
4 changes: 4 additions & 0 deletions internal/naming/namer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ func TestExported(t *testing.T) {
{name: "Leading digits before capitals", parts: []string{"2FA"}, want: "N2Fa"},
{name: "Leading digits before camel case", parts: []string{"404NotFound"}, want: "N404NotFound"},
{name: "Leading digit after a separator", parts: []string{"_3d"}, want: "N3d"},
{name: "Initialism after leading digits", parts: []string{"short_2url"}, want: "Short2URL"},
{name: "Plural initialism after leading digits", parts: []string{"3ids"}, want: "N3IDs"},
{name: "Decimal point between digits", parts: []string{"1.5"}, want: "N1Dot5"},
{name: "Version number", parts: []string{"v1.2.3"}, want: "V1Dot2Dot3"},
{name: "Dot after a letter is a separator", parts: []string{"a.1"}, want: "A1"},
Expand Down Expand Up @@ -134,6 +136,8 @@ func TestExportedWithExtraInitialisms(t *testing.T) {
{name: "Extra initialism", extra: []string{"PSP"}, in: "pspId", want: "PSPID"},
{name: "Extra initialism given in lower case is written upper case", extra: []string{"ssn"}, in: "SSN", want: "SSN"},
{name: "Extra initialism plural", extra: []string{"PSP"}, in: "PSPs", want: "PSPs"},
{name: "Extra initialism after leading digits", extra: []string{"DS"}, in: "force_3ds_flow", want: "Force3DSFlow"},
{name: "Extra initialism that starts with a digit", extra: []string{"3DS"}, in: "3ds", want: "N3DS"},
{name: "Empty extra is ignored", extra: []string{""}, in: "s", want: "S"},
{name: "Defaults stay with extras", extra: []string{"PSP"}, in: "url", want: "URL"},
}
Expand Down
Loading