Compare commits

...

113 Commits

Author SHA1 Message Date
re e3c2a6fbb2 fix 2023-01-24 19:48:57 +03:00
Dan Markham ff555f73ed
Merge pull request #71 from moritamori/fix-readme
Readme update for alternative string values flag
2022-11-19 23:05:53 -08:00
moritamori ed2895e2a7 Readme update for alternative string values flag 2022-11-13 23:41:23 +09:00
Dan Markham 71d3edd22d
Merge pull request #69 from eleduardo/publishapplesilicon
publish the apple silicon binary
2022-10-02 13:41:22 -07:00
Eduardo Solis 49441931ac
Merge branch 'master' into publishapplesilicon 2022-09-29 08:38:53 -05:00
Eduardo Solis f8c85a7a99
publish the apple silicon binary 2022-09-29 08:37:54 -05:00
Dan Markham 6e1910cc4f
Merge pull request #68 from eleduardo/go182fix
Fixing go18.2 generation due to tools breaking
2022-09-28 16:08:07 -07:00
Eduardo Solis e79db5ce74
Fixing go18.2 generation due to tools breaking 2022-09-14 15:08:55 -05:00
Dan Markham 0f231a24f5
Merge pull request #60 from urso/bump-tools-v0.1.11
Upgrade golang.org/x/tools to v0.1.11
2022-08-16 09:02:22 -07:00
urso 98641f4fd2 Upgrade golang.org/x/tools to v0.1.11 2022-06-20 13:21:50 +02:00
Dan Markham aa45c0d477
Merge pull request #59 from smlx/bump-tools
fix: upgrade golang.org/x/tools for go 1.18 compatibility
2022-04-12 07:05:12 -07:00
Scott Leggett df780b2a0e
fix: upgrade golang.org/x/tools for go 1.18 compatibility 2022-03-28 19:27:25 +08:00
Dan Markham caff60ea13
Merge pull request #58 from dmarkham/dan/go-bump
Move to go 1.17
2022-03-23 08:59:54 -07:00
Dan Markham 881cbb24bf
MOve to go 1.17 2022-03-23 08:54:45 -07:00
Dan Markham b43356ef4a
Merge pull request #54 from mieubrisse/patch-1
Add usage for module-aware generation
2022-03-23 08:54:11 -07:00
Dan Markham 3bf002e2f3
Merge branch 'master' into patch-1 2022-03-23 08:45:49 -07:00
Dan Markham 28a1efd624
Merge pull request #56 from piiano/nhaas/support_1.18
Upgrade x/tools
2022-03-23 08:45:07 -07:00
Nir Haas af60bb2988 Upgrade x/tools 2022-02-20 15:32:40 +02:00
mieubrisse a1605fba51
Add usage for module-aware generation 2022-02-04 13:25:17 -03:00
Dan Markham 585d6b237e
Merge pull request #51 from mvrahden/feature/values
Feature/values add support for ent EnumValues interface
2021-10-26 13:00:42 -07:00
Menno 67b1febc1d fix comment 2021-10-17 14:32:26 +02:00
Menno 074b95bab8 add documentation for alternative string values flag 2021-10-17 14:32:13 +02:00
Menno f80c486834 add alternative string values method 2021-10-17 14:31:43 +02:00
Dan Markham 328a338ddb
Merge pull request #48 from dmarkham/dan/apple-m1
Adding support for Apple arm64
2021-07-26 08:00:24 -07:00
Dan Markham 367f14bcb1
Adding support for Apple arm64 2021-07-21 23:41:59 -07:00
Dan Markham 9d0b7d4c67
Merge pull request #44 from dmarkham/dan/issue-43
Return the same string passed for error
2021-07-21 23:20:05 -07:00
Dan Markham b85f109b7f
Return the same string passed for error
Fixes Issue #43
2021-07-21 23:11:39 -07:00
Dan Markham 677b61cc2c
Merge pull request #41 from dmarkham/readme-update
Readme update
2021-01-31 09:45:39 -08:00
Dan Markham be4c11f837
Move to go1.15.x 2021-01-30 23:39:52 -08:00
Dan Markham 2479605aa2
Readme update 2021-01-30 23:37:57 -08:00
Dan Markham b96c3ca7db
Merge pull request #39 from vladimiroff/gqlgen
Add flag for generating gqlgen marshaling methods
2021-01-30 23:24:15 -08:00
Kiril Vladimiroff 67e4e9619f Add flag for generating gqlgen marshaling methods 2020-09-18 16:35:44 +03:00
Dan Markham 67fb6efca7
Merge pull request #38 from dmarkham/dan-fix-case-insensitive
case insensitive bug fix
2020-08-08 21:35:08 -07:00
Dan Markham eb484e6440
case insensitive bug fix 2020-08-08 21:23:56 -07:00
Dan Markham 0a1f0e6d70
Merge pull request #36 from dmarkham/golang-bump
golang 1.14
2020-06-09 14:40:58 -07:00
Dan Markham be960ad5f1
golang 1.14 2020-06-09 13:45:55 -07:00
Dan Markham 5c8e883cf6
Merge pull request #35 from xescugc/fg-34
Fixed: Error when transformer emptied the values
2020-06-09 13:11:03 -07:00
xescugc cb6196db58 stringer: Add logic to fail if transformer empties value
If the output of the transformer is '' means that something went wrong (if it had a value before) and so
it needs to fail to not conntinue with silence errors
2020-06-08 21:31:25 +02:00
xescugc 20d9792920 golden_test: Add test for 'linecomment'
It'll fix https://github.com/dmarkham/enumer/issues/27 as it includes the golden
test for it
2020-06-08 20:16:02 +02:00
Dan Markham 9741c5ae47
Merge pull request #33 from dmarkham/sql-typeo
typeo in the template var
2020-03-16 12:27:02 -07:00
Dan Markham 017d714532
typeo in the template var 2020-03-16 10:52:02 -07:00
Dan Markham 3100ad138c
Merge pull request #32 from vladimiroff/scan-type
Implement Scan with a type switch
2020-03-15 23:18:03 -07:00
Kiril Vladimiroff 78ada3fc29
Implement Scan with a type switch
This is just a minor (and a bit opinionated) tweak in Scan. While using
the generated Scan method, realized that what's being returned from any
driver I've stumbled upon is actually []byte instead of string, thus
always causing a one failed type assertion on Scan.
2020-03-05 16:18:52 +02:00
Dan Markham d46c853929
Merge pull request #30 from dmarkham/use-constant-names
Use constant names, Help the compiler detect value changes
2020-02-23 23:11:09 -08:00
Dan Markham 8d7221cc8a
enum value change detector 2020-02-23 22:47:17 -08:00
Dan Markham 9793e421ce
use constant names 2020-02-23 15:24:20 -08:00
Dan Markham 56342fda5f
Merge pull request #29 from dmarkham/multi-prefix
Allow multiple trim prefixes
2020-02-23 13:55:50 -08:00
Dan Markham df8df69062
Update Deps 2020-02-23 13:45:14 -08:00
Dan Markham f6864bbebc
Move to go 1.13.x for default build 2020-02-23 13:30:45 -08:00
Dan Markham 49fa643993
Allow multiple trim prefixes
based on changes from @sgtsquiggs
2020-02-23 13:24:02 -08:00
Dan Markham f93c6b0e0b
Merge pull request #24 from dmarkham/port-runs-threshold-bug
Port runs threshold bug
2019-07-18 08:19:26 -07:00
Dan Markham cdbbf12521
Port fix from @ltpquang 2019-07-18 08:06:39 -07:00
Quang Le 1467a49eb3
Add test cases that make the endtoend test failed 2019-07-18 08:05:55 -07:00
Quang Le 0bc4e9e23e
Fix typos 2019-07-18 08:05:50 -07:00
Dan Markham 2440b832e4
Merge pull request #23 from dmarkham/doc
Doc updates around <Type>String(s string) Case Insensitive
2019-05-05 15:24:55 -07:00
Dan Markham 14261a8f07
Doc updates around <Type>String(s string) Case Insensitive 2019-05-05 15:07:38 -07:00
Dan Markham e080e58c1e
Merge pull request #22 from dmarkham/case-insensitive-name
Make PillString case insensitive
2019-05-05 14:51:03 -07:00
Dan Markham 2a31c850ad
Make PillString case insensitive
fixes #21
2019-05-04 15:33:34 -07:00
Dan Markham f993037eaa
Merge pull request #20 from dmarkham/docs-update
Adding in the Usage
2019-04-24 22:51:19 -07:00
Dan Markham ae561ba734
Adding in the Usage 2019-04-23 21:21:16 -07:00
Dan Markham c504b164b0
Merge pull request #19 from dmarkham/linecomment
Line comment support #18
2019-04-23 15:22:57 -07:00
Dan Markham ccf4a55cf2
Line comment support #18 2019-04-23 15:13:34 -07:00
Dan Markham 325a6e167c
Merge pull request #17 from mvrhov/patch-1
Create temporary file in same directory as the final fiel resides
2019-04-19 00:02:44 -07:00
Miha Vrhovnik ceea85e531
Create temporary file in same directory as the final fiel resides
If temp file is created on different parition, then move command will fail
2019-04-19 08:38:40 +02:00
Dan Markham 1cbec6c016
Merge pull request #15 from dmarkham/readme-updates
Add a example for go mods use
2019-04-08 00:20:15 -07:00
Dan Markham 24de023e5c
Add a example for go mods use 2019-04-07 23:56:38 -07:00
Dan Markham a6b59c2799
Merge pull request #13 from dmarkham/dmarkham-readme
Update README.md
2019-04-07 23:12:50 -07:00
Dan Markham cc772a950e
Merge branch 'master' into dmarkham-readme 2019-04-07 22:55:14 -07:00
Dan Markham 46e7802ac4
Merge pull request #14 from dmarkham/travis-dist-change
use xenial in travis
2019-04-07 22:55:03 -07:00
Dan Markham 66589be05d
use xenial in travis 2019-04-07 22:40:50 -07:00
Dan Markham 49d05009d0
Update README.md 2019-04-07 20:02:31 -07:00
Dan Markham 579c571630
Merge pull request #12 from dmarkham/readme-updates
Readme updates
2019-04-05 06:52:10 -07:00
Dan Markham 76fd2e5795
update 2019-04-05 01:57:06 -07:00
Dan Markham 04ed547ca1
Merge pull request #11 from dmarkham/coverage
Getting coverage setup
2019-04-05 01:41:58 -07:00
Dan Markham 5dff465061
Getting coverage setup 2019-04-05 01:30:06 -07:00
Dan Markham cff78b5241
Merge pull request #10 from dmarkham/travis-setup
testing and deploy with travis
2019-04-05 01:10:09 -07:00
Dan Markham a34ce5a636
testing and deploy with travis 2019-04-05 00:59:36 -07:00
Dan Markham 2d3b4cc0c7
Merge pull request #9 from dmarkham/travis-setup
testing a deploy with travis
2019-04-05 00:04:06 -07:00
Dan Markham f524145d2a
testing a deploy with travis 2019-04-04 23:54:40 -07:00
Dan Markham 988c3334e5
Merge pull request #8 from dmarkham/readme
Updates to the readme
2019-04-04 23:02:50 -07:00
Dan Markham 07dc9c9dbe
Updates to the readme 2019-04-04 22:53:44 -07:00
Dan Markham 296228769d
Merge pull request #7 from dmarkham/new-comment
Only add the comment line when there is a comment
2019-04-04 18:52:02 -07:00
Dan Markham 58249b251f
Only add the comment line when there is a comment 2019-04-04 18:48:04 -07:00
Dan Markham 610f60356d
Merge pull request #6 from dmarkham/whitespace-docs
Whitespace + docs
2019-04-04 18:03:35 -07:00
Dan Markham 107292ddbc
resolve some conflicts 2019-04-04 17:57:54 -07:00
Dan Markham 72a8443d38
Merge pull request #5 from dmarkham/serjlee
Serjlee
2019-04-04 17:15:40 -07:00
Dan Markham f8e96284fe
Merging in serjlee 2019-04-04 17:11:33 -07:00
Dan Markham 586f4733ff
adding in sum 2019-04-04 17:09:21 -07:00
Dan Markham d82b2b06c1
Merge pull request #4 from dmarkham/comments-tmpfile
Comments tmpfile
2019-04-04 16:36:31 -07:00
Dan Markham 1c1330394d
fix merge conflicts 2019-04-04 16:33:59 -07:00
Dan Markham ad406c3e36
Merge pull request #3 from dmarkham/go-modules
Go modules
2019-04-04 16:24:30 -07:00
Dan Markham ecea0f4d48
Remove vendor directory 2019-04-04 16:21:39 -07:00
amanbolat b0dd5b45a5
update to work with go modules 2019-04-04 15:57:51 -07:00
amanbolat bbb4825a38
added usage 2019-04-04 15:57:38 -07:00
amanbolat c7302601d6
remove importers 2019-04-04 15:57:37 -07:00
Dan Markham 2c68820d0e
Merge pull request #2 from dmarkham/fix-non-windows
Fix non windows
2019-04-04 15:47:42 -07:00
Dan Markham fd4c1a3913
Merge remote-tracking branch 'origin/master' into fix-non-windows 2019-04-04 15:44:34 -07:00
Dan Markham da2df55c39
Merge pull request #1 from dmarkham/travis
Adding in travis
2019-04-04 15:42:06 -07:00
Dan Markham 8d88862e90
Addwing in travis 2019-04-04 15:38:58 -07:00
Luca Osti 63cd80f057 Add method for getting a slice of strings 2019-03-22 12:56:38 +01:00
Luca Osti 188f5ebedc Add title-lower transform 2019-03-22 11:37:02 +01:00
Luca Osti d806ebd41f Add test 2019-03-22 11:36:20 +01:00
Luca Osti 5511caae23 Add prefix after transform 2019-03-22 11:36:16 +01:00
Luca Osti ea11b04142 Add withprefix flag 2019-03-22 10:54:07 +01:00
Chris Raborg fdd0a4e9d9
Merge pull request #3 from mgaffney/fix-generated-docs
Fix generated comments
2019-03-02 10:36:55 -05:00
Michael Gaffney f84898d4c3
Fix generated comments
- Add missing punctuation marks.
- Make comments more consistent with comments for similar functions
  in the standard library.
2019-03-01 15:36:43 -05:00
Chris Raborg da4a0ea77c
Merge pull request #1 from zerofox-oss/whitespace-sep
Whitespace sep
2019-02-12 12:46:45 -05:00
Xopherus 6ec30747dc Add whitespace-separated transformation 2019-02-12 12:35:47 -05:00
Chris Raborg d6fc475549
Merge pull request #2 from zerofox-oss/add-transformations
Add Transformers
2019-02-12 12:33:58 -05:00
G.J.R. Timmer 42bd8ecbf7 Merge branch 'add-transformations' into 'master'
Add Transformers

See merge request go/enumer!2
2019-01-17 13:13:07 +01:00
G.J.R. Timmer 06f7d9e03c Merge branch 'fix-non-windows' into 'master'
Fix End2End test for non-windows platforms

See merge request go/enumer!1
2019-01-17 13:12:47 +01:00
Gert-Jan Timmer 78452a952a Add Transformers
- snake-upper
- kebab-upper
- lower (Lowercase)
- upper (Uppercase)
- title (TitleCase)
- first (Use first character of string)
- first-lower (same as first only lower case)
- first-upper (same as first only upper case)
2019-01-17 13:07:52 +01:00
Gert-Jan Timmer 16ae335f48 Fix End2End test for non-windows platforms
Binary name for string was hardcoded to `.exe`
2019-01-16 18:06:03 +01:00
57 changed files with 3227 additions and 1292 deletions

7
.gitignore vendored
View File

@ -4,7 +4,7 @@
*.o
*.a
*.so
cli
# Folders
_obj
_test
@ -20,9 +20,12 @@ _cgo_gotypes.go
_cgo_export.*
_testmain.go
coverage.txt
*.exe
*.test
*.prof
.idea
.vscode
enumer

29
.travis.yml Normal file
View File

@ -0,0 +1,29 @@
language: go
dist: xenial
matrix:
allow_failures:
- go: master
include:
- go: 1.17.x
- go: 1.18.x
env:
global:
- GO111MODULE=on
after_success:
- make build-cli
- bash <(curl -s https://codecov.io/bash)
deploy:
provider: releases
api_key:
secure: VnwZNdY9ryTKIStuy8vJUq3QwyDQe9RVstjLB6kdSj+LE9bg6MDOSYtoN/ricdL0xqYctvYTWpWrt4TNzGOgrzRPV6EriMs0dy4JL1Q+teKWM1Q7/AwTZqINZ4SbczibX+Y66BqB39Ca5+b8Qg6ijP2wu1Yiss9ro9XIdVvNib4/tg1bas1JtDueGTJPm3wYIMexNHP+nGqo6LCSoAO1ul6aEnGb0JlHQkdUKNT05XAQXcNwzuylQ+ckfttMTeBJkeag5xl20hh0g7EYUh+JtQkfkfazyug5PqjO+nxHfdHn1EHq5CTX679UTOM/0EIXqC8LyKIux0p2+4cufAwuArsw9X0e0ui3qL0389Ac+6D3F0fC6we4/BDT79C1DBpdw+eK+wO2roWqSGRymlhbjG5sVmYERDF831OdAy8/7w+pI3NKlGL+BiYEjhRKR33ldRuwf8X82MtWJCVht67guxLHSq09HE9i774yP0aw3h4LmeI2lGdVD2tsb/awhjVnNL3jMylimU7am2qW6Kb6hGXMv8WENX5QmpgXkm0VUT2TCopKjL6fOefJYW0FpPJjb9wFrSdT7csXwu/XhoQTnNBMEKc1FDqX9pb2m/BNvHAnZdwawBS9ysLnMcORGL11Wql+p1D1xfvIGFB1rQs/xdPRJ0/pao+cS6+hLxi1fyI=
skip_cleanup: true
file:
- cli/build/enumer.linux-amd64.tar.gz
- cli/build/enumer.darwin-amd64.tar.gz
- cli/build/enumer.darwin-arm64.tar.gz
- cli/build/enumer.windows-amd64.exe.tar.gz
- cli/build/sha256sum.txt
on:
go: 1.17.x
repo: dmarkham/enumer
tags: true

26
Makefile Normal file
View File

@ -0,0 +1,26 @@
test:
go test -race -coverprofile=coverage.txt -covermode=atomic
build-cli: clean
-mkdir -p ./cli/build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o ./cli/build/enumer.linux-amd64 .
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -a -o ./cli/build/enumer.darwin-amd64 .
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -a -o ./cli/build/enumer.darwin-arm64 .
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -a -o ./cli/build/enumer.windows-amd64.exe .
cd ./cli/build && find . -name 'enumer*' | xargs -I{} tar czf {}.tar.gz {}
cd ./cli/build && shasum -a 256 * > sha256sum.txt
cat ./cli/build/sha256sum.txt
# example: make release V=0.0.0
release:
git tag v$(V)
@read -p "Press enter to confirm and push to origin ..." && git push origin v$(V)
clean:
-rm -r ./cli/build
SHELL = /bin/bash

123
README.md
View File

@ -1,32 +1,80 @@
# Enumer [![GoDoc](https://godoc.org/github.com/alvaroloes/enumer?status.svg)](https://godoc.org/github.com/alvaroloes/enumer) [![Go Report Card](https://goreportcard.com/badge/github.com/alvaroloes/enumer)](https://goreportcard.com/report/github.com/alvaroloes/enumer) [![cover.run go](https://cover.run/go/github.com/alvaroloes/enumer.svg?tag=golang-1.10)](https://cover.run/go/github.com/alvaroloes/enumer?tag=golang-1.10)
# Enumer [![GoDoc](https://godoc.org/git.internal/re/enumer?status.svg)](https://godoc.org/git.internal/re/enumer) [![Go Report Card](https://goreportcard.com/badge/git.internal/re/enumer)](https://goreportcard.com/report/git.internal/re/enumer) [![GitHub Release](https://img.shields.io/github/release/dmarkham/enumer.svg)](https://git.internal/re/enumer/releases)[![Build Status](https://travis-ci.com/dmarkham/enumer.svg?branch=master)](https://travis-ci.com/dmarkham/enumer)
Enumer is a tool to generate Go code that adds useful methods to Go enums (constants with a specific type).
It started as a fork of [Rob Pikes Stringer tool](https://godoc.org/golang.org/x/tools/cmd/stringer).
It started as a fork of [Rob Pikes Stringer tool](https://godoc.org/golang.org/x/tools/cmd/stringer)
maintained by [Álvaro López Espinosa](https://github.com/alvaroloes/enumer).
This was again forked here as (https://git.internal/re/enumer) picking up where Álvaro left off.
```
$ ./enumer --help
Enumer is a tool to generate Go code that adds useful methods to Go enums (constants with a specific type).
Usage of ./enumer:
Enumer [flags] -type T [directory]
Enumer [flags] -type T files... # Must be a single package
For more information, see:
http://godoc.org/git.internal/re/enumer
Flags:
-addprefix string
transform each item name by adding a prefix. Default: ""
-comment value
comments to include in generated code, can repeat. Default: ""
-gqlgen
if true, GraphQL marshaling methods for gqlgen will be generated. Default: false
-json
if true, json marshaling methods will be generated. Default: false
-linecomment
use line comment text as printed text when present
-output string
output file name; default srcdir/<type>_string.go
-sql
if true, the Scanner and Valuer interface will be implemented.
-text
if true, text marshaling methods will be generated. Default: false
-transform string
enum item name transformation method. Default: noop (default "noop")
-trimprefix string
transform each item name by removing a prefix. Default: ""
-type string
comma-separated list of type names; must be set
-values
if true, alternative string values method will be generated. Default: false
-yaml
if true, yaml marshaling methods will be generated. Default: false
```
## Generated functions and methods
When Enumer is applied to a type, it will generate:
* The following basic methods/functions:
- The following basic methods/functions:
* Method `String()`: returns the string representation of the enum value. This makes the enum conform
- Method `String()`: returns the string representation of the enum value. This makes the enum conform
the `Stringer` interface, so whenever you print an enum value, you'll get the string name instead of a number.
* Function `<Type>String(s string)`: returns the enum value from its string representation. This is useful
- Function `<Type>String(s string)`: returns the enum value from its string representation. This is useful
when you need to read enum values from command line arguments, from a configuration file, or
from a REST API request... In short, from those places where using the real enum value (an integer) would
be almost meaningless or hard to trace or use by a human.
* Function `<Type>Values()`: returns a slice with all the values of the enum
* Method `IsA<Type>()`: returns true only if the current value is among the values of the enum. Useful for validations.
* When the flag `json` is provided, two additional methods will be generated, `MarshalJSON()` and `UnmarshalJSON()`. These make
be almost meaningless or hard to trace or use by a human. `s` string is Case Insensitive.
- Function `<Type>Values()`: returns a slice with all the values of the enum
- Function `<Type>Strings()`: returns a slice with all the Strings of the enum
- Method `IsA<Type>()`: returns true only if the current value is among the values of the enum. Useful for validations.
- When the flag `json` is provided, two additional methods will be generated, `MarshalJSON()` and `UnmarshalJSON()`. These make
the enum conform to the `json.Marshaler` and `json.Unmarshaler` interfaces. Very useful to use it in JSON APIs.
* When the flag `text` is provided, two additional methods will be generated, `MarshalText()` and `UnmarshalText()`. These make
- When the flag `text` is provided, two additional methods will be generated, `MarshalText()` and `UnmarshalText()`. These make
the enum conform to the `encoding.TextMarshaler` and `encoding.TextUnmarshaler` interfaces.
**Note:** If you use your enum values as keys in a map and you encode the map as _JSON_, you need this flag set to true to properly
convert the map keys to json (strings). If not, the numeric values will be used instead
* When the flag `yaml` is provided, two additional methods will be generated, `MarshalYAML()` and `UnmarshalYAML()`. These make
- When the flag `yaml` is provided, two additional methods will be generated, `MarshalYAML()` and `UnmarshalYAML()`. These make
the enum conform to the `gopkg.in/yaml.v2.Marshaler` and `gopkg.in/yaml.v2.Unmarshaler` interfaces.
* When the flag `sql` is provided, the methods for implementing the Scanner and Valuer interfaces will be also generated.
- When the flag `sql` is provided, the methods for implementing the `Scanner` and `Valuer` interfaces.
Useful when storing the enum in a database.
For example, if we have an enum type called `Pill`,
```go
type Pill int
@ -38,7 +86,9 @@ const (
Acetaminophen = Paracetamol
)
```
executing `enumer -type=Pill -json` will generate a new file with four basic methods and two extra for JSON:
```go
func (i Pill) String() string {
//...
@ -52,6 +102,10 @@ func PillValues() []Pill {
//...
}
func PillStrings() []string {
//...
}
func (i Pill) IsAPill() bool {
//...
}
@ -64,7 +118,9 @@ func (i *Pill) UnmarshalJSON(data []byte) error {
//...
}
```
From now on, we can:
```go
// Convert any Pill value to string
var aspirinString string = Aspirin.String()
@ -72,7 +128,7 @@ var aspirinString string = Aspirin.String()
fmt.Println("I need ", Paracetamol) // Will print "I need Paracetamol"
// Convert a string with the enum name to the corresponding enum value
pill, err := PillString("Ibuprofen")
pill, err := PillString("Ibuprofen") // "ibuprofen" will also work.
if err != nil {
fmt.Println("Unrecognized pill: ", err)
return
@ -112,30 +168,55 @@ name := MyTypeValue.String() // name => "MyTypeValue"
Sometimes you need to use some other string representation format than CamelCase (i.e. in JSON).
To transform it from CamelCase to snake_case or kebab-case, you can use the `transform` flag.
To transform it from CamelCase to another format, you can use the `transform` flag.
For example, the command `enumer -type=MyType -json -transform=snake` would generate the following string representation:
```go
name := MyTypeValue.String() // name => "my_type_value"
```
**Note**: The transformation only works form CamelCase to snake_case or kebab-case, not the other way around.
**Note**: The transformation only works from CamelCase to snake_case or kebab-case, not the other way around.
### Transformers
- snake
- snake-upper
- kebab
- kebab-upper
- lower (lowercase)
- upper (UPPERCASE)
- title (TitleCase)
- title-lower (titleCase)
- first (Use first character of string)
- first-lower (same as first only lower case)
- first-upper (same as first only upper case)
- whitespace
## How to use
The usage of Enumer is the same as Stringer, so you can refer to the [Stringer docs](https://godoc.org/golang.org/x/tools/cmd/stringer)
for more information.
For a module-aware repo with `enumer` in the `go.mod` file, generation can be called by adding the following to a `.go` source file:
```golang
//go:generate go run git.internal/re/enumer -type=YOURTYPE
```
There are four boolean flags: `json`, `text`, `yaml` and `sql`. You can use any combination of them (i.e. `enumer -type=Pill -json -text`),
For enum string representation transformation the `transform` and `trimprefix` flags
were added (i.e. `enumer -type=MyType -json -transform=snake`).
Possible transform values are `snake` and `kebab` for transformation to snake_case and kebab-case accordingly.
Possible transform values are listed above in the [transformers](#transformers) section.
The default value for `transform` flag is `noop` which means no transformation will be performed.
If a prefix is provided via the `trimprefix` flag, it will be trimmed from the start of each name (before
it is transformed). If a name doesn't have the prefix it will be passed unchanged.
If a prefix is provided via the `addprefix` flag, it will be added to the start of each name (after trimming and after transforming).
The boolean flag `values` will additionally create an alternative string values method `Values() []string` to fullfill the `EnumValues` interface of [ent](https://entgo.io/docs/schema-fields/#enum-fields).
## Inspiring projects
* [Stringer](https://godoc.org/golang.org/x/tools/cmd/stringer)
* [jsonenums](https://github.com/campoy/jsonenums)
- [Álvaro López Espinosa](https://github.com/alvaroloes/enumer)
- [Stringer](https://godoc.org/golang.org/x/tools/cmd/stringer)
- [jsonenums](https://github.com/campoy/jsonenums)

View File

@ -16,10 +16,24 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)
var (
// GOEXE defines the executable file name suffix (".exe" on Windows, "" on other systems).
// Must be defined here, cannot be read from ENVIRONMENT variables
GOEXE = ""
)
func init() {
// Set GOEXE for Windows platform
if runtime.GOOS == "windows" {
GOEXE = ".exe"
}
}
// This file contains a test that compiles and runs each program in testdata
// after generating the string method for its type. The rule is that for testdata/x.go
// we run stringer -type X and then compile and run the program. The resulting
@ -31,8 +45,9 @@ func TestEndToEnd(t *testing.T) {
t.Fatal(err)
}
defer os.RemoveAll(dir)
// Create stringer in temporary directory.
stringer := filepath.Join(dir, "stringer.exe")
stringer := filepath.Join(dir, fmt.Sprintf("stringer%s", GOEXE))
err = run("go", "build", "-o", stringer)
if err != nil {
t.Fatalf("building stringer: %s", err)
@ -50,20 +65,54 @@ func TestEndToEnd(t *testing.T) {
// Generate, compile, and run the test programs.
for _, name := range names {
if !strings.HasSuffix(name, ".go") {
t.Errorf("%s is not a Go file", name)
continue
}
if name == "cgo.go" && !build.Default.CgoEnabled {
t.Logf("cgo is no enabled for %s", name)
continue
}
// Names are known to be ASCII and long enough.
typeName := fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
transformNameMethod := "noop"
if name == "transform.go" {
typeName = "CamelCaseValue"
// Names are known to be ASCII and long enough.
var typeName string
var transformNameMethod string
switch name {
case "transform_snake.go":
typeName = "SnakeCaseValue"
transformNameMethod = "snake"
case "transform_snake_upper.go":
typeName = "SnakeUpperCaseValue"
transformNameMethod = "snake-upper"
case "transform_kebab.go":
typeName = "KebabCaseValue"
transformNameMethod = "kebab"
case "transform_kebab_upper.go":
typeName = "KebabUpperCaseValue"
transformNameMethod = "kebab-upper"
case "transform_upper.go":
typeName = "UpperCaseValue"
transformNameMethod = "upper"
case "transform_lower.go":
typeName = "LowerCaseValue"
transformNameMethod = "lower"
case "transform_title.go":
typeName = "TitleCaseValue"
transformNameMethod = "title"
case "transform_first.go":
typeName = "FirstCaseValue"
transformNameMethod = "first"
case "transform_first_upper.go":
typeName = "FirstUpperCaseValue"
transformNameMethod = "first-upper"
case "transform_first_lower.go":
typeName = "FirstLowerCaseValue"
transformNameMethod = "first-lower"
case "transform_whitespace.go":
typeName = "WhitespaceSeparatedValue"
transformNameMethod = "whitespace"
default:
typeName = fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
transformNameMethod = "noop"
}
stringerCompileAndRun(t, dir, stringer, typeName, name, transformNameMethod)
@ -111,7 +160,14 @@ func copy(to, from string) error {
// run runs a single command and returns an error if it does not succeed.
// os/exec should have this function, to be honest.
func run(name string, arg ...string) error {
return runInDir(".", name, arg...)
}
// runInDir runs a single command in directory dir and returns an error if
// it does not succeed.
func runInDir(dir, name string, arg ...string) error {
cmd := exec.Command(name, arg...)
cmd.Dir = dir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()

View File

@ -10,6 +10,10 @@ func %[1]sString(s string) (%[1]s, error) {
if val, ok := _%[1]sNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _%[1]sNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%%s does not belong to %[1]s values", s)
}
`
@ -22,6 +26,16 @@ func %[1]sValues() []%[1]s {
}
`
// Arguments to format are:
// [1]: type name
const stringsMethod = `// %[1]sStrings returns a slice of all String values of the enum
func %[1]sStrings() []string {
strs := make([]string, len(_%[1]sNames))
copy(strs, _%[1]sNames)
return strs
}
`
// Arguments to format are:
// [1]: type name
const stringBelongsMethodLoop = `// IsA%[1]s returns "true" if the value is listed in the enum definition. "false" otherwise
@ -44,6 +58,18 @@ func (i %[1]s) IsA%[1]s() bool {
}
`
// Arguments to format are:
// [1]: type name
const altStringValuesMethod = `func (%[1]s) Values() []string {
return %[1]sStrings()
}
`
func (g *Generator) buildAltStringValuesMethod(typeName string) {
g.Printf("\n")
g.Printf(altStringValuesMethod, typeName)
}
func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThreshold int) {
// At this moment, either "g.declareIndexAndNameVars()" or "g.declareNameVars()" has been called
@ -51,14 +77,32 @@ func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThresh
g.Printf("\nvar _%sValues = []%s{", typeName, typeName)
for _, values := range runs {
for _, value := range values {
g.Printf("\t%s, ", value.str)
g.Printf("\t%s, ", value.originalName)
}
}
g.Printf("}\n\n")
// Print the map between name and value
g.Printf("\nvar _%sNameToValueMap = map[string]%s{\n", typeName, typeName)
g.printValueMap(runs, typeName, runsThreshold)
// Print the slice of names
g.printNamesSlice(runs, typeName, runsThreshold)
// Print the basic extra methods
g.Printf(stringNameToValueMethod, typeName)
g.Printf(stringValuesMethod, typeName)
g.Printf(stringsMethod, typeName)
if len(runs) <= runsThreshold {
g.Printf(stringBelongsMethodLoop, typeName)
} else { // There is a map of values, the code is simpler then
g.Printf(stringBelongsMethodSet, typeName)
}
}
func (g *Generator) printValueMap(runs [][]Value, typeName string, runsThreshold int) {
thereAreRuns := len(runs) > 1 && len(runs) <= runsThreshold
g.Printf("\nvar _%sNameToValueMap = map[string]%s{\n", typeName, typeName)
var n int
var runID string
for i, values := range runs {
@ -70,20 +114,33 @@ func (g *Generator) buildBasicExtras(runs [][]Value, typeName string, runsThresh
}
for _, value := range values {
g.Printf("\t_%sName%s[%d:%d]: %s,\n", typeName, runID, n, n+len(value.name), &value)
g.Printf("\t_%sName%s[%d:%d]: %s,\n", typeName, runID, n, n+len(value.name), value.originalName)
g.Printf("\t_%sLowerName%s[%d:%d]: %s,\n", typeName, runID, n, n+len(value.name), value.originalName)
n += len(value.name)
}
}
g.Printf("}\n\n")
// Print the basic extra methods
g.Printf(stringNameToValueMethod, typeName)
g.Printf(stringValuesMethod, typeName)
if len(runs) < runsThreshold {
g.Printf(stringBelongsMethodLoop, typeName)
} else { // There is a map of values, the code is simpler then
g.Printf(stringBelongsMethodSet, typeName)
}
func (g *Generator) printNamesSlice(runs [][]Value, typeName string, runsThreshold int) {
thereAreRuns := len(runs) > 1 && len(runs) <= runsThreshold
g.Printf("\nvar _%sNames = []string{\n", typeName)
var n int
var runID string
for i, values := range runs {
if thereAreRuns {
runID = "_" + fmt.Sprintf("%d", i)
n = 0
} else {
runID = ""
}
for _, value := range values {
g.Printf("\t_%sName%s[%d:%d],\n", typeName, runID, n, n+len(value.name))
n += len(value.name)
}
}
g.Printf("}\n\n")
}
// Arguments to format are:

View File

@ -0,0 +1,8 @@
# Go Modules Sample
## Steps
1. Go get enumer `go get -u git.internal/re/enumer`
2. `go generate` This should create `pill_enumer.go`
3. `go run *.go` to see it in action
4. `go mod tidy` to remove the deps for `enumer` once your happy.

3
examples/gomods/go.mod Normal file
View File

@ -0,0 +1,3 @@
module github.com/dmarkham/gomods
go 1.12

0
examples/gomods/go.sum Normal file
View File

20
examples/gomods/main.go Normal file
View File

@ -0,0 +1,20 @@
package main
import "fmt"
//go:generate go run git.internal/re/enumer -type=Pill -json
type Pill int
const (
Placebo Pill = iota
Aspirin
Ibuprofen
Paracetamol
Acetaminophen = Paracetamol
)
func main() {
fmt.Println(PillStrings())
fmt.Println(Placebo.IsAPill())
fmt.Println(Placebo)
}

13
go.mod Normal file
View File

@ -0,0 +1,13 @@
module git.internal/re/enumer
require (
github.com/pascaldekloe/name v1.0.0
golang.org/x/tools v0.1.12
)
require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
)
go 1.17

28
go.sum Normal file
View File

@ -0,0 +1,28 @@
github.com/pascaldekloe/name v1.0.0 h1:n7LKFgHixETzxpRv2R77YgPUFo85QHGZKrdaYm7eY5U=
github.com/pascaldekloe/name v1.0.0/go.mod h1:Z//MfYJnH4jVpQ9wkclwu2I2MkHmXTlT9wR5UZScttM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

File diff suppressed because it is too large Load Diff

26
gqlgen.go Normal file
View File

@ -0,0 +1,26 @@
package main
// Arguments to format are:
// [1]: type name
const gqlgenMethods = `
// MarshalGQL implements the graphql.Marshaler interface for %[1]s
func (i %[1]s) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(i.String()))
}
// UnmarshalGQL implements the graphql.Unmarshaler interface for %[1]s
func (i *%[1]s) UnmarshalGQL(value interface{}) error {
str, ok := value.(string)
if !ok {
return fmt.Errorf("%[1]s should be a string, got %%T", value)
}
var err error
*i, err = %[1]sString(str)
return err
}
`
func (g *Generator) buildGQLGenMethods(runs [][]Value, typeName string) {
g.Printf(gqlgenMethods, typeName)
}

View File

@ -1,16 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.9
package main
import (
"go/importer"
"go/types"
)
func defaultImporter() types.Importer {
return importer.Default()
}

View File

@ -1,16 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
package main
import (
"go/importer"
"go/types"
)
func defaultImporter() types.Importer {
return importer.For("source", nil)
}

18
sql.go
View File

@ -12,14 +12,16 @@ const scanMethod = `func (i *%[1]s) Scan(value interface{}) error {
return nil
}
str, ok := value.(string)
if !ok {
bytes, ok := value.([]byte)
if !ok {
return fmt.Errorf("value is not a byte slice")
}
str = string(bytes[:])
var str string
switch v := value.(type) {
case []byte:
str = string(v)
case string:
str = v
case fmt.Stringer:
str = v.String()
default:
return fmt.Errorf("invalid value of %[1]s: %%[1]T(%%[1]v)", value)
}
val, err := %[1]sString(str)

View File

@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.5
// Enumer is a tool to generate Go code that adds useful methods to Go enums (constants with a specific type).
// It started as a fork of Rob Pikes Stringer tool
//
//Please visit http://github.com/alvaroloes/enumer for a comprehensive documentation
// Please visit http://git.internal/re/enumer for a comprehensive documentation
package main
import (
@ -15,10 +13,9 @@ import (
"flag"
"fmt"
"go/ast"
"go/build"
exact "go/constant"
"go/format"
"go/parser"
"go/importer"
"go/token"
"go/types"
"io/ioutil"
@ -27,6 +24,10 @@ import (
"path/filepath"
"sort"
"strings"
"unicode"
"unicode/utf8"
"golang.org/x/tools/go/packages"
"github.com/pascaldekloe/name"
)
@ -48,9 +49,13 @@ var (
json = flag.Bool("json", false, "if true, json marshaling methods will be generated. Default: false")
yaml = flag.Bool("yaml", false, "if true, yaml marshaling methods will be generated. Default: false")
text = flag.Bool("text", false, "if true, text marshaling methods will be generated. Default: false")
gqlgen = flag.Bool("gqlgen", false, "if true, GraphQL marshaling methods for gqlgen will be generated. Default: false")
altValuesFunc = flag.Bool("values", false, "if true, alternative string values method will be generated. Default: false")
output = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
transformMethod = flag.String("transform", "noop", "enum item name transformation method. Default: noop")
trimPrefix = flag.String("trimprefix", "", "transform each item name by removing a prefix. Default: \"\"")
addPrefix = flag.String("addprefix", "", "transform each item name by adding a prefix. Default: \"\"")
linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
)
var comments arrayFlags
@ -61,12 +66,13 @@ func init() {
// Usage is a replacement usage function for the flags package.
func Usage() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
fmt.Fprintf(os.Stderr, "\tenumer [flags] -type T [directory]\n")
fmt.Fprintf(os.Stderr, "\tenumer [flags] -type T files... # Must be a single package\n")
fmt.Fprintf(os.Stderr, "For more information, see:\n")
fmt.Fprintf(os.Stderr, "\thttps://github.com/alvaroloes/enumer\n")
fmt.Fprintf(os.Stderr, "Flags:\n")
_, _ = fmt.Fprintf(os.Stderr, "Enumer is a tool to generate Go code that adds useful methods to Go enums (constants with a specific type).\n")
_, _ = fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
_, _ = fmt.Fprintf(os.Stderr, "\tEnumer [flags] -type T [directory]\n")
_, _ = fmt.Fprintf(os.Stderr, "\tEnumer [flags] -type T files... # Must be a single package\n")
_, _ = fmt.Fprintf(os.Stderr, "For more information, see:\n")
_, _ = fmt.Fprintf(os.Stderr, "\thttp://godoc.org/git.internal/re/enumer\n")
_, _ = fmt.Fprintf(os.Stderr, "Flags:\n")
flag.PrintDefaults()
}
@ -79,7 +85,7 @@ func main() {
flag.Usage()
os.Exit(2)
}
types := strings.Split(*typeNames, ",")
typs := strings.Split(*typeNames, ",")
// We accept either one directory or a list of files. Which do we have?
args := flag.Args()
@ -96,31 +102,40 @@ func main() {
if len(args) == 1 && isDirectory(args[0]) {
dir = args[0]
g.parsePackageDir(args[0])
// g.parsePackageDir(args[0])
} else {
dir = filepath.Dir(args[0])
g.parsePackageFiles(args)
// g.parsePackageFiles(args)
}
g.parsePackage(args, []string{})
// Print the header and package clause.
g.Printf("// Code generated by \"enumer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
g.Printf("\n")
if comments.String() != "" {
g.Printf("// %s\n", comments.String())
}
g.Printf("package %s", g.pkg.name)
g.Printf("\n")
g.Printf("import (\n")
g.Printf("\t\"fmt\"\n")
g.Printf("\t\"strings\"\n")
if *sql {
g.Printf("\t\"database/sql/driver\"\n")
}
if *json {
g.Printf("\t\"encoding/json\"\n")
}
if *gqlgen {
g.Printf("\t\"io\"\n")
g.Printf("\t\"strconv\"\n")
}
g.Printf(")\n")
// Run generate for each type.
for _, typeName := range types {
g.generate(typeName, *json, *yaml, *sql, *text, *transformMethod, *trimPrefix)
for _, typeName := range typs {
g.generate(typeName, *json, *yaml, *sql, *text, *gqlgen, *transformMethod, *trimPrefix, *addPrefix, *linecomment, *altValuesFunc)
}
// Format the output.
@ -129,12 +144,12 @@ func main() {
// Figure out filename to write to
outputName := *output
if outputName == "" {
baseName := fmt.Sprintf("%s_enumer.go", types[0])
baseName := fmt.Sprintf("%s_enumer.go", typs[0])
outputName = filepath.Join(dir, strings.ToLower(baseName))
}
// Write to tmpfile first
tmpFile, err := ioutil.TempFile("", fmt.Sprintf("%s_enumer_", types[0]))
tmpFile, err := ioutil.TempFile(dir, fmt.Sprintf("%s_enumer_", typs[0]))
if err != nil {
log.Fatalf("creating temporary file for output: %s", err)
}
@ -171,7 +186,7 @@ type Generator struct {
// Printf prints the string to the output
func (g *Generator) Printf(format string, args ...interface{}) {
fmt.Fprintf(&g.buf, format, args...)
_, _ = fmt.Fprintf(&g.buf, format, args...)
}
// File holds a single parsed file and associated data.
@ -181,6 +196,8 @@ type File struct {
// These fields are reset for each type being generated.
typeName string // Name of the constant type.
values []Value // Accumulator for constant values of that type.
trimPrefix string
lineComment bool
}
// Package holds information about a Go package
@ -192,76 +209,111 @@ type Package struct {
typesPkg *types.Package
}
// parsePackageDir parses the package residing in the directory.
func (g *Generator) parsePackageDir(directory string) {
pkg, err := build.Default.ImportDir(directory, 0)
if err != nil {
log.Fatalf("cannot process directory %s: %s", directory, err)
}
var names []string
names = append(names, pkg.GoFiles...)
names = append(names, pkg.CgoFiles...)
// // parsePackageDir parses the package residing in the directory.
// func (g *Generator) parsePackageDir(directory string) {
// pkg, err := build.Default.ImportDir(directory, 0)
// if err != nil {
// log.Fatalf("cannot process directory %s: %s", directory, err)
// }
// var names []string
// names = append(names, pkg.GoFiles...)
// names = append(names, pkg.CgoFiles...)
// // TODO: Need to think about constants in test files. Maybe write type_string_test.go
// // in a separate pass? For later.
// // names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
// names = append(names, pkg.SFiles...)
// names = prefixDirectory(directory, names)
// g.parsePackage(directory, names, nil)
// }
//
// // parsePackageFiles parses the package occupying the named files.
// func (g *Generator) parsePackageFiles(names []string) {
// g.parsePackage(".", names, nil)
// }
// // prefixDirectory places the directory name on the beginning of each name in the list.
// func prefixDirectory(directory string, names []string) []string {
// if directory == "." {
// return names
// }
// ret := make([]string, len(names))
// for i, n := range names {
// ret[i] = filepath.Join(directory, n)
// }
// return ret
// }
// parsePackage analyzes the single package constructed from the patterns and tags.
// parsePackage exits if there is an error.
func (g *Generator) parsePackage(patterns []string, tags []string) {
cfg := &packages.Config{
Mode: packages.LoadSyntax,
// TODO: Need to think about constants in test files. Maybe write type_string_test.go
// in a separate pass? For later.
// names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
names = append(names, pkg.SFiles...)
names = prefixDirectory(directory, names)
g.parsePackage(directory, names, nil)
Tests: false,
}
pkgs, err := packages.Load(cfg, patterns...)
if err != nil {
log.Fatal(err)
}
if len(pkgs) != 1 {
log.Fatalf("error: %d packages found", len(pkgs))
}
g.addPackage(pkgs[0])
}
// parsePackageFiles parses the package occupying the named files.
func (g *Generator) parsePackageFiles(names []string) {
g.parsePackage(".", names, nil)
// addPackage adds a type checked Package and its syntax files to the generator.
func (g *Generator) addPackage(pkg *packages.Package) {
g.pkg = &Package{
name: pkg.Name,
defs: pkg.TypesInfo.Defs,
files: make([]*File, len(pkg.Syntax)),
}
// prefixDirectory places the directory name on the beginning of each name in the list.
func prefixDirectory(directory string, names []string) []string {
if directory == "." {
return names
for i, file := range pkg.Syntax {
g.pkg.files[i] = &File{
file: file,
pkg: g.pkg,
}
ret := make([]string, len(names))
for i, name := range names {
ret[i] = filepath.Join(directory, name)
}
return ret
}
// parsePackage analyzes the single package constructed from the named files.
// If text is non-nil, it is a string to be used instead of the content of the file,
// to be used for testing. parsePackage exits if there is an error.
func (g *Generator) parsePackage(directory string, names []string, text interface{}) {
var files []*File
var astFiles []*ast.File
g.pkg = new(Package)
fs := token.NewFileSet()
for _, name := range names {
if !strings.HasSuffix(name, ".go") {
continue
}
parsedFile, err := parser.ParseFile(fs, name, text, 0)
if err != nil {
log.Fatalf("parsing package: %s: %s", name, err)
}
astFiles = append(astFiles, parsedFile)
files = append(files, &File{
file: parsedFile,
pkg: g.pkg,
})
}
if len(astFiles) == 0 {
log.Fatalf("%s: no buildable Go files", directory)
}
g.pkg.name = astFiles[0].Name.Name
g.pkg.files = files
g.pkg.dir = directory
// Type check the package.
g.pkg.check(fs, astFiles)
}
// func (g *Generator) parsePackagee(directory string, names []string, text interface{}) {
// var files []*File
// var astFiles []*ast.File
// g.pkg = new(Package)
// fs := token.NewFileSet()
// for _, n := range names {
// if !strings.HasSuffix(n, ".go") {
// continue
// }
// parsedFile, err := parser.ParseFile(fs, n, text, 0)
// if err != nil {
// log.Fatalf("parsing package: %s: %s", n, err)
// }
// astFiles = append(astFiles, parsedFile)
// files = append(files, &File{
// file: parsedFile,
// pkg: g.pkg,
// })
// }
// if len(astFiles) == 0 {
// log.Fatalf("%s: no buildable Go files", directory)
// }
// g.pkg.name = astFiles[0].Name.Name
// g.pkg.files = files
// g.pkg.dir = directory
// // Type check the package.
// g.pkg.check(fs, astFiles)
// }
// check type-checks the package. The package must be OK to proceed.
func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
pkg.defs = make(map[*ast.Ident]types.Object)
config := types.Config{Importer: defaultImporter(), FakeImportC: true}
config := types.Config{Importer: importer.Default(), FakeImportC: true}
info := &types.Info{
Defs: pkg.defs,
}
@ -273,18 +325,76 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
}
func (g *Generator) transformValueNames(values []Value, transformMethod string) {
var sep rune
var fn func(src string) string
switch transformMethod {
case "snake":
sep = '_'
fn = func(s string) string {
return strings.ToLower(name.Delimit(s, '_'))
}
case "snake_upper", "snake-upper":
fn = func(s string) string {
return strings.ToUpper(name.Delimit(s, '_'))
}
case "kebab":
sep = '-'
fn = func(s string) string {
return strings.ToLower(name.Delimit(s, '-'))
}
case "kebab_upper", "kebab-upper":
fn = func(s string) string {
return strings.ToUpper(name.Delimit(s, '-'))
}
case "upper":
fn = func(s string) string {
return strings.ToUpper(s)
}
case "lower":
fn = func(s string) string {
return strings.ToLower(s)
}
case "title":
fn = func(s string) string {
return strings.Title(s)
}
case "title-lower":
fn = func(s string) string {
title := []rune(strings.Title(s))
title[0] = unicode.ToLower(title[0])
return string(title)
}
case "first":
fn = func(s string) string {
r, _ := utf8.DecodeRuneInString(s)
return string(r)
}
case "first_upper", "first-upper":
fn = func(s string) string {
r, _ := utf8.DecodeRuneInString(s)
return strings.ToUpper(string(r))
}
case "first_lower", "first-lower":
fn = func(s string) string {
r, _ := utf8.DecodeRuneInString(s)
return strings.ToLower(string(r))
}
case "whitespace":
fn = func(s string) string {
return strings.ToLower(name.Delimit(s, ' '))
}
default:
return
}
for i := range values {
values[i].name = strings.ToLower(name.Delimit(values[i].name, sep))
for i, v := range values {
after := fn(v.name)
// If the original one was "" or the one before the transformation
// was "" (most commonly if linecomment defines it as empty) we
// do not care if it's empty.
// But if any of them was not empty before then it means that
// the transformed emptied the value
if v.originalName != "" && v.name != "" && after == "" {
log.Fatalf("transformation of %q (%s) got an empty result", v.name, v.originalName)
}
values[i].name = after
}
}
@ -295,10 +405,20 @@ func (g *Generator) trimValueNames(values []Value, prefix string) {
}
}
// prefixValueNames adds a prefix to each name
func (g *Generator) prefixValueNames(values []Value, prefix string) {
for i := range values {
values[i].name = prefix + values[i].name
}
}
// generate produces the String method for the named type.
func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL, includeText bool, transformMethod string, trimPrefix string) {
func (g *Generator) generate(typeName string,
includeJSON, includeYAML, includeSQL, includeText, includeGQLGen bool,
transformMethod string, trimPrefix string, addPrefix string, lineComment bool, includeValuesMethod bool) {
values := make([]Value, 0, 100)
for _, file := range g.pkg.files {
file.lineComment = lineComment
// Set the state for this run of the walker.
file.typeName = typeName
file.values = nil
@ -312,10 +432,14 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS
log.Fatalf("no values defined for type %s", typeName)
}
g.trimValueNames(values, trimPrefix)
for _, prefix := range strings.Split(trimPrefix, ",") {
g.trimValueNames(values, prefix)
}
g.transformValueNames(values, transformMethod)
g.prefixValueNames(values, addPrefix)
runs := splitIntoRuns(values)
// The decision of which pattern to use depends on the number of
// runs in the numbers. If there's only one, it's easy. For more than
@ -338,6 +462,11 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS
default:
g.buildMap(runs, typeName)
}
if includeValuesMethod {
g.buildAltStringValuesMethod(typeName)
}
g.buildNoOpOrderChangeDetect(runs, typeName)
g.buildBasicExtras(runs, typeName, runsThreshold)
if includeJSON {
@ -352,6 +481,9 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS
if includeSQL {
g.addValueAndScanMethod(typeName)
}
if includeGQLGen {
g.buildGQLGenMethods(runs, typeName)
}
}
// splitIntoRuns breaks the values into runs of contiguous sequences.
@ -401,6 +533,7 @@ func (g *Generator) format() []byte {
// Value represents a declared constant.
type Value struct {
originalName string // The name of the constant before transformation
name string // The name of the constant after transformation (i.e. camel case => snake case)
// The value is stored as a bit pattern alone. The boolean tells us
// whether to interpret it as an int64 or a uint64; the only place
@ -467,16 +600,16 @@ func (f *File) genDecl(node ast.Node) bool {
// We now have a list of names (from one line of source code) all being
// declared with the desired type.
// Grab their names and actual values and store them in f.values.
for _, name := range vspec.Names {
if name.Name == "_" {
for _, n := range vspec.Names {
if n.Name == "_" {
continue
}
// This dance lets the type checker find the values for us. It's a
// bit tricky: look up the object declared by the name, find its
// bit tricky: look up the object declared by the n, find its
// types.Const, and extract its value.
obj, ok := f.pkg.defs[name]
obj, ok := f.pkg.defs[n]
if !ok {
log.Fatalf("no value for constant %s", name)
log.Fatalf("no value for constant %s", n)
}
info := obj.Type().Underlying().(*types.Basic).Info()
if info&types.IsInteger == 0 {
@ -484,22 +617,27 @@ func (f *File) genDecl(node ast.Node) bool {
}
value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
if value.Kind() != exact.Int {
log.Fatalf("can't happen: constant is not an integer %s", name)
log.Fatalf("can't happen: constant is not an integer %s", n)
}
i64, isInt := exact.Int64Val(value)
u64, isUint := exact.Uint64Val(value)
if !isInt && !isUint {
log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
log.Fatalf("internal error: value of %s is not an integer: %s", n, value.String())
}
if !isInt {
u64 = uint64(i64)
}
v := Value{
name: name.Name,
originalName: n.Name,
name: n.Name,
value: u64,
signed: info&types.IsUnsigned == 0,
str: value.String(),
}
if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 {
v.name = strings.TrimSpace(c.Text())
}
f.values = append(f.values, v)
}
}
@ -528,13 +666,15 @@ func usize(n int) int {
func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
var indexes, names []string
for i, run := range runs {
index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
index, n := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
indexes = append(indexes, index)
names = append(names, name)
names = append(names, n)
_, n = g.createLowerIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i))
names = append(names, n)
}
g.Printf("const (\n")
for _, name := range names {
g.Printf("\t%s\n", name)
for _, n := range names {
g.Printf("\t%s\n", n)
}
g.Printf(")\n\n")
g.Printf("var (")
@ -546,9 +686,34 @@ func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) {
// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars
func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) {
index, name := g.createIndexAndNameDecl(run, typeName, "")
g.Printf("const %s\n", name)
index, n := g.createIndexAndNameDecl(run, typeName, "")
g.Printf("const %s\n", n)
g.Printf("var %s\n", index)
index, n = g.createLowerIndexAndNameDecl(run, typeName, "")
g.Printf("const %s\n", n)
//g.Printf("var %s\n", index)
}
// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
func (g *Generator) createLowerIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) {
b := new(bytes.Buffer)
indexes := make([]int, len(run))
for i := range run {
b.WriteString(strings.ToLower(run[i].name))
indexes[i] = b.Len()
}
nameConst := fmt.Sprintf("_%sLowerName%s = %q", typeName, suffix, b.String())
nameLen := b.Len()
b.Reset()
_, _ = fmt.Fprintf(b, "_%sLowerIndex%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
for i, v := range indexes {
if i > 0 {
_, _ = fmt.Fprintf(b, ", ")
}
_, _ = fmt.Fprintf(b, "%d", v)
}
_, _ = fmt.Fprintf(b, "}")
return b.String(), nameConst
}
// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var".
@ -562,14 +727,14 @@ func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix
nameConst := fmt.Sprintf("_%sName%s = %q", typeName, suffix, b.String())
nameLen := b.Len()
b.Reset()
fmt.Fprintf(b, "_%sIndex%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
_, _ = fmt.Fprintf(b, "_%sIndex%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen))
for i, v := range indexes {
if i > 0 {
fmt.Fprintf(b, ", ")
_, _ = fmt.Fprintf(b, ", ")
}
fmt.Fprintf(b, "%d", v)
_, _ = fmt.Fprintf(b, "%d", v)
}
fmt.Fprintf(b, "}")
_, _ = fmt.Fprintf(b, "}")
return b.String(), nameConst
}
@ -582,6 +747,13 @@ func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix stri
}
}
g.Printf("\"\n")
g.Printf("const _%sLowerName%s = \"", typeName, suffix)
for _, run := range runs {
for i := range run {
g.Printf("%s", strings.ToLower(run[i].name))
}
}
g.Printf("\"\n")
}
// buildOneRun generates the variables and String method for a single run of contiguous values.
@ -618,8 +790,6 @@ const stringOneRun = `func (i %[1]s) String() string {
// [2]: lowest defined value for type, as a string
// [3]: size of index element (8 for uint8 etc.)
// [4]: less than zero check (for signed types)
/*
*/
const stringOneRunWithOffset = `func (i %[1]s) String() string {
i -= %[2]s
if %[4]si >= %[1]s(len(_%[1]sIndex)-1) {
@ -672,6 +842,24 @@ func (g *Generator) buildMap(runs [][]Value, typeName string) {
g.Printf(stringMap, typeName)
}
// buildNoOpOrderChangeDetect try to let the compiler and the user know if the order/value of the ENUMS have changed.
func (g *Generator) buildNoOpOrderChangeDetect(runs [][]Value, typeName string) {
g.Printf("\n")
g.Printf(`
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
`)
g.Printf("func _%sNoOp (){ ", typeName)
g.Printf("\n var x [1]struct{}\n")
for _, values := range runs {
for _, value := range values {
g.Printf("\t_ = x[%s-(%s)]\n", value.originalName, value.str)
}
}
g.Printf("}\n\n")
}
// Argument to format is the type name.
const stringMap = `func (i %[1]s) String() string {
if str, ok := _%[1]sMap[i]; ok {

14
testdata/day.go vendored
View File

@ -30,6 +30,9 @@ func main() {
ck(Sunday, "Sunday")
ck(-127, "Day(-127)")
ck(127, "Day(127)")
ckDayString(Sunday, "Sunday")
ckDayString(Sunday, "sunday")
}
func ck(day Day, str string) {
@ -37,3 +40,14 @@ func ck(day Day, str string) {
panic("day.go: " + str)
}
}
func ckDayString(day Day, str string) {
d, err := DayString(str)
if err != nil {
panic("day.go: " + err.Error())
}
if d != day {
panic("day.go: " + str)
}
}

94
testdata/day.golden vendored Normal file
View File

@ -0,0 +1,94 @@
const _DayName = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
var _DayIndex = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}
const _DayLowerName = "mondaytuesdaywednesdaythursdayfridaysaturdaysunday"
func (i Day) String() string {
if i < 0 || i >= Day(len(_DayIndex)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _DayName[_DayIndex[i]:_DayIndex[i+1]]
}
func (Day) Values() []string {
return DayStrings()
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _DayNoOp() {
var x [1]struct{}
_ = x[Monday-(0)]
_ = x[Tuesday-(1)]
_ = x[Wednesday-(2)]
_ = x[Thursday-(3)]
_ = x[Friday-(4)]
_ = x[Saturday-(5)]
_ = x[Sunday-(6)]
}
var _DayValues = []Day{Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}
var _DayNameToValueMap = map[string]Day{
_DayName[0:6]: Monday,
_DayLowerName[0:6]: Monday,
_DayName[6:13]: Tuesday,
_DayLowerName[6:13]: Tuesday,
_DayName[13:22]: Wednesday,
_DayLowerName[13:22]: Wednesday,
_DayName[22:30]: Thursday,
_DayLowerName[22:30]: Thursday,
_DayName[30:36]: Friday,
_DayLowerName[30:36]: Friday,
_DayName[36:44]: Saturday,
_DayLowerName[36:44]: Saturday,
_DayName[44:50]: Sunday,
_DayLowerName[44:50]: Sunday,
}
var _DayNames = []string{
_DayName[0:6],
_DayName[6:13],
_DayName[13:22],
_DayName[22:30],
_DayName[30:36],
_DayName[36:44],
_DayName[44:50],
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _DayNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Day values", s)
}
// DayValues returns all values of the enum
func DayValues() []Day {
return _DayValues
}
// DayStrings returns a slice of all String values of the enum
func DayStrings() []string {
strs := make([]string, len(_DayNames))
copy(strs, _DayNames)
return strs
}
// IsADay returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Day) IsADay() bool {
for _, v := range _DayValues {
if i == v {
return true
}
}
return false
}

90
testdata/dayTrimAndPrefix.golden vendored Normal file
View File

@ -0,0 +1,90 @@
const _DayName = "NightMondayNightTuesdayNightWednesdayNightThursdayNightFridayNightSaturdayNightSunday"
var _DayIndex = [...]uint8{0, 11, 23, 37, 50, 61, 74, 85}
const _DayLowerName = "nightmondaynighttuesdaynightwednesdaynightthursdaynightfridaynightsaturdaynightsunday"
func (i Day) String() string {
if i < 0 || i >= Day(len(_DayIndex)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _DayName[_DayIndex[i]:_DayIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _DayNoOp() {
var x [1]struct{}
_ = x[DayMonday-(0)]
_ = x[DayTuesday-(1)]
_ = x[DayWednesday-(2)]
_ = x[DayThursday-(3)]
_ = x[DayFriday-(4)]
_ = x[DaySaturday-(5)]
_ = x[DaySunday-(6)]
}
var _DayValues = []Day{DayMonday, DayTuesday, DayWednesday, DayThursday, DayFriday, DaySaturday, DaySunday}
var _DayNameToValueMap = map[string]Day{
_DayName[0:11]: DayMonday,
_DayLowerName[0:11]: DayMonday,
_DayName[11:23]: DayTuesday,
_DayLowerName[11:23]: DayTuesday,
_DayName[23:37]: DayWednesday,
_DayLowerName[23:37]: DayWednesday,
_DayName[37:50]: DayThursday,
_DayLowerName[37:50]: DayThursday,
_DayName[50:61]: DayFriday,
_DayLowerName[50:61]: DayFriday,
_DayName[61:74]: DaySaturday,
_DayLowerName[61:74]: DaySaturday,
_DayName[74:85]: DaySunday,
_DayLowerName[74:85]: DaySunday,
}
var _DayNames = []string{
_DayName[0:11],
_DayName[11:23],
_DayName[23:37],
_DayName[37:50],
_DayName[50:61],
_DayName[61:74],
_DayName[74:85],
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _DayNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Day values", s)
}
// DayValues returns all values of the enum
func DayValues() []Day {
return _DayValues
}
// DayStrings returns a slice of all String values of the enum
func DayStrings() []string {
strs := make([]string, len(_DayNames))
copy(strs, _DayNames)
return strs
}
// IsADay returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Day) IsADay() bool {
for _, v := range _DayValues {
if i == v {
return true
}
}
return false
}

90
testdata/dayWithLinecomment.golden vendored Normal file
View File

@ -0,0 +1,90 @@
const _DayName = "lunesTuesdayWednesdayThursdayviernesSaturdaySunday"
var _DayIndex = [...]uint8{0, 5, 12, 21, 29, 36, 44, 50}
const _DayLowerName = "lunestuesdaywednesdaythursdayviernessaturdaysunday"
func (i Day) String() string {
if i < 0 || i >= Day(len(_DayIndex)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _DayName[_DayIndex[i]:_DayIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _DayNoOp() {
var x [1]struct{}
_ = x[Monday-(0)]
_ = x[Tuesday-(1)]
_ = x[Wednesday-(2)]
_ = x[Thursday-(3)]
_ = x[Friday-(4)]
_ = x[Saturday-(5)]
_ = x[Sunday-(6)]
}
var _DayValues = []Day{Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}
var _DayNameToValueMap = map[string]Day{
_DayName[0:5]: Monday,
_DayLowerName[0:5]: Monday,
_DayName[5:12]: Tuesday,
_DayLowerName[5:12]: Tuesday,
_DayName[12:21]: Wednesday,
_DayLowerName[12:21]: Wednesday,
_DayName[21:29]: Thursday,
_DayLowerName[21:29]: Thursday,
_DayName[29:36]: Friday,
_DayLowerName[29:36]: Friday,
_DayName[36:44]: Saturday,
_DayLowerName[36:44]: Saturday,
_DayName[44:50]: Sunday,
_DayLowerName[44:50]: Sunday,
}
var _DayNames = []string{
_DayName[0:5],
_DayName[5:12],
_DayName[12:21],
_DayName[21:29],
_DayName[29:36],
_DayName[36:44],
_DayName[44:50],
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _DayNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Day values", s)
}
// DayValues returns all values of the enum
func DayValues() []Day {
return _DayValues
}
// DayStrings returns a slice of all String values of the enum
func DayStrings() []string {
strs := make([]string, len(_DayNames))
copy(strs, _DayNames)
return strs
}
// IsADay returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Day) IsADay() bool {
for _, v := range _DayValues {
if i == v {
return true
}
}
return false
}

90
testdata/dayWithPrefix.golden vendored Normal file
View File

@ -0,0 +1,90 @@
const _DayName = "DayMondayDayTuesdayDayWednesdayDayThursdayDayFridayDaySaturdayDaySunday"
var _DayIndex = [...]uint8{0, 9, 19, 31, 42, 51, 62, 71}
const _DayLowerName = "daymondaydaytuesdaydaywednesdaydaythursdaydayfridaydaysaturdaydaysunday"
func (i Day) String() string {
if i < 0 || i >= Day(len(_DayIndex)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _DayName[_DayIndex[i]:_DayIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _DayNoOp() {
var x [1]struct{}
_ = x[Monday-(0)]
_ = x[Tuesday-(1)]
_ = x[Wednesday-(2)]
_ = x[Thursday-(3)]
_ = x[Friday-(4)]
_ = x[Saturday-(5)]
_ = x[Sunday-(6)]
}
var _DayValues = []Day{Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}
var _DayNameToValueMap = map[string]Day{
_DayName[0:9]: Monday,
_DayLowerName[0:9]: Monday,
_DayName[9:19]: Tuesday,
_DayLowerName[9:19]: Tuesday,
_DayName[19:31]: Wednesday,
_DayLowerName[19:31]: Wednesday,
_DayName[31:42]: Thursday,
_DayLowerName[31:42]: Thursday,
_DayName[42:51]: Friday,
_DayLowerName[42:51]: Friday,
_DayName[51:62]: Saturday,
_DayLowerName[51:62]: Saturday,
_DayName[62:71]: Sunday,
_DayLowerName[62:71]: Sunday,
}
var _DayNames = []string{
_DayName[0:9],
_DayName[9:19],
_DayName[19:31],
_DayName[31:42],
_DayName[42:51],
_DayName[51:62],
_DayName[62:71],
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _DayNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Day values", s)
}
// DayValues returns all values of the enum
func DayValues() []Day {
return _DayValues
}
// DayStrings returns a slice of all String values of the enum
func DayStrings() []string {
strs := make([]string, len(_DayNames))
copy(strs, _DayNames)
return strs
}
// IsADay returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Day) IsADay() bool {
for _, v := range _DayValues {
if i == v {
return true
}
}
return false
}

115
testdata/gap.golden vendored Normal file
View File

@ -0,0 +1,115 @@
const (
_GapName_0 = "TwoThree"
_GapLowerName_0 = "twothree"
_GapName_1 = "FiveSixSevenEightNine"
_GapLowerName_1 = "fivesixseveneightnine"
_GapName_2 = "Eleven"
_GapLowerName_2 = "eleven"
)
var (
_GapIndex_0 = [...]uint8{0, 3, 8}
_GapIndex_1 = [...]uint8{0, 4, 7, 12, 17, 21}
_GapIndex_2 = [...]uint8{0, 6}
)
func (i Gap) String() string {
switch {
case 2 <= i && i <= 3:
i -= 2
return _GapName_0[_GapIndex_0[i]:_GapIndex_0[i+1]]
case 5 <= i && i <= 9:
i -= 5
return _GapName_1[_GapIndex_1[i]:_GapIndex_1[i+1]]
case i == 11:
return _GapName_2
default:
return fmt.Sprintf("Gap(%d)", i)
}
}
func (Gap) Values() []string {
return GapStrings()
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _GapNoOp() {
var x [1]struct{}
_ = x[Two-(2)]
_ = x[Three-(3)]
_ = x[Five-(5)]
_ = x[Six-(6)]
_ = x[Seven-(7)]
_ = x[Eight-(8)]
_ = x[Nine-(9)]
_ = x[Eleven-(11)]
}
var _GapValues = []Gap{Two, Three, Five, Six, Seven, Eight, Nine, Eleven}
var _GapNameToValueMap = map[string]Gap{
_GapName_0[0:3]: Two,
_GapLowerName_0[0:3]: Two,
_GapName_0[3:8]: Three,
_GapLowerName_0[3:8]: Three,
_GapName_1[0:4]: Five,
_GapLowerName_1[0:4]: Five,
_GapName_1[4:7]: Six,
_GapLowerName_1[4:7]: Six,
_GapName_1[7:12]: Seven,
_GapLowerName_1[7:12]: Seven,
_GapName_1[12:17]: Eight,
_GapLowerName_1[12:17]: Eight,
_GapName_1[17:21]: Nine,
_GapLowerName_1[17:21]: Nine,
_GapName_2[0:6]: Eleven,
_GapLowerName_2[0:6]: Eleven,
}
var _GapNames = []string{
_GapName_0[0:3],
_GapName_0[3:8],
_GapName_1[0:4],
_GapName_1[4:7],
_GapName_1[7:12],
_GapName_1[12:17],
_GapName_1[17:21],
_GapName_2[0:6],
}
// GapString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func GapString(s string) (Gap, error) {
if val, ok := _GapNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _GapNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Gap values", s)
}
// GapValues returns all values of the enum
func GapValues() []Gap {
return _GapValues
}
// GapStrings returns a slice of all String values of the enum
func GapStrings() []string {
strs := make([]string, len(_GapNames))
copy(strs, _GapNames)
return strs
}
// IsAGap returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Gap) IsAGap() bool {
for _, v := range _GapValues {
if i == v {
return true
}
}
return false
}

87
testdata/num.golden vendored Normal file
View File

@ -0,0 +1,87 @@
const _NumName = "m_2m_1m0m1m2"
var _NumIndex = [...]uint8{0, 3, 6, 8, 10, 12}
const _NumLowerName = "m_2m_1m0m1m2"
func (i Num) String() string {
i -= -2
if i < 0 || i >= Num(len(_NumIndex)-1) {
return fmt.Sprintf("Num(%d)", i+-2)
}
return _NumName[_NumIndex[i]:_NumIndex[i+1]]
}
func (Num) Values() []string {
return NumStrings()
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _NumNoOp() {
var x [1]struct{}
_ = x[m_2-(-2)]
_ = x[m_1-(-1)]
_ = x[m0-(0)]
_ = x[m1-(1)]
_ = x[m2-(2)]
}
var _NumValues = []Num{m_2, m_1, m0, m1, m2}
var _NumNameToValueMap = map[string]Num{
_NumName[0:3]: m_2,
_NumLowerName[0:3]: m_2,
_NumName[3:6]: m_1,
_NumLowerName[3:6]: m_1,
_NumName[6:8]: m0,
_NumLowerName[6:8]: m0,
_NumName[8:10]: m1,
_NumLowerName[8:10]: m1,
_NumName[10:12]: m2,
_NumLowerName[10:12]: m2,
}
var _NumNames = []string{
_NumName[0:3],
_NumName[3:6],
_NumName[6:8],
_NumName[8:10],
_NumName[10:12],
}
// NumString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func NumString(s string) (Num, error) {
if val, ok := _NumNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _NumNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Num values", s)
}
// NumValues returns all values of the enum
func NumValues() []Num {
return _NumValues
}
// NumStrings returns a slice of all String values of the enum
func NumStrings() []string {
strs := make([]string, len(_NumNames))
copy(strs, _NumNames)
return strs
}
// IsANum returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Num) IsANum() bool {
for _, v := range _NumValues {
if i == v {
return true
}
}
return false
}

79
testdata/offset.golden vendored Normal file
View File

@ -0,0 +1,79 @@
const _NumberName = "OneTwoThree"
var _NumberIndex = [...]uint8{0, 3, 6, 11}
const _NumberLowerName = "onetwothree"
func (i Number) String() string {
i -= 1
if i < 0 || i >= Number(len(_NumberIndex)-1) {
return fmt.Sprintf("Number(%d)", i+1)
}
return _NumberName[_NumberIndex[i]:_NumberIndex[i+1]]
}
func (Number) Values() []string {
return NumberStrings()
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _NumberNoOp() {
var x [1]struct{}
_ = x[One-(1)]
_ = x[Two-(2)]
_ = x[Three-(3)]
}
var _NumberValues = []Number{One, Two, Three}
var _NumberNameToValueMap = map[string]Number{
_NumberName[0:3]: One,
_NumberLowerName[0:3]: One,
_NumberName[3:6]: Two,
_NumberLowerName[3:6]: Two,
_NumberName[6:11]: Three,
_NumberLowerName[6:11]: Three,
}
var _NumberNames = []string{
_NumberName[0:3],
_NumberName[3:6],
_NumberName[6:11],
}
// NumberString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func NumberString(s string) (Number, error) {
if val, ok := _NumberNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _NumberNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Number values", s)
}
// NumberValues returns all values of the enum
func NumberValues() []Number {
return _NumberValues
}
// NumberStrings returns a slice of all String values of the enum
func NumberStrings() []string {
strs := make([]string, len(_NumberNames))
copy(strs, _NumberNames)
return strs
}
// IsANumber returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Number) IsANumber() bool {
for _, v := range _NumberValues {
if i == v {
return true
}
}
return false
}

127
testdata/prime.golden vendored Normal file
View File

@ -0,0 +1,127 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
func (Prime) Values() []string {
return PrimeStrings()
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}

140
testdata/primeGQLGen.golden vendored Normal file
View File

@ -0,0 +1,140 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
// MarshalGQL implements the graphql.Marshaler interface for Prime
func (i Prime) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(i.String()))
}
// UnmarshalGQL implements the graphql.Unmarshaler interface for Prime
func (i *Prime) UnmarshalGQL(value interface{}) error {
str, ok := value.(string)
if !ok {
return fmt.Errorf("Prime should be a string, got %T", value)
}
var err error
*i, err = PrimeString(str)
return err
}

140
testdata/primeJson.golden vendored Normal file
View File

@ -0,0 +1,140 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
// MarshalJSON implements the json.Marshaler interface for Prime
func (i Prime) MarshalJSON() ([]byte, error) {
return json.Marshal(i.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface for Prime
func (i *Prime) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return fmt.Errorf("Prime should be a string, got %s", data)
}
var err error
*i, err = PrimeString(s)
return err
}

170
testdata/primeJsonAndSql.golden vendored Normal file
View File

@ -0,0 +1,170 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
// MarshalJSON implements the json.Marshaler interface for Prime
func (i Prime) MarshalJSON() ([]byte, error) {
return json.Marshal(i.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface for Prime
func (i *Prime) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return fmt.Errorf("Prime should be a string, got %s", data)
}
var err error
*i, err = PrimeString(s)
return err
}
func (i Prime) Value() (driver.Value, error) {
return i.String(), nil
}
func (i *Prime) Scan(value interface{}) error {
if value == nil {
return nil
}
var str string
switch v := value.(type) {
case []byte:
str = string(v)
case string:
str = v
case fmt.Stringer:
str = v.String()
default:
return fmt.Errorf("invalid value of Prime: %[1]T(%[1]v)", value)
}
val, err := PrimeString(str)
if err != nil {
return err
}
*i = val
return nil
}

153
testdata/primeSql.golden vendored Normal file
View File

@ -0,0 +1,153 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
func (i Prime) Value() (driver.Value, error) {
return i.String(), nil
}
func (i *Prime) Scan(value interface{}) error {
if value == nil {
return nil
}
var str string
switch v := value.(type) {
case []byte:
str = string(v)
case string:
str = v
case fmt.Stringer:
str = v.String()
default:
return fmt.Errorf("invalid value of Prime: %[1]T(%[1]v)", value)
}
val, err := PrimeString(str)
if err != nil {
return err
}
*i = val
return nil
}

135
testdata/primeText.golden vendored Normal file
View File

@ -0,0 +1,135 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
// MarshalText implements the encoding.TextMarshaler interface for Prime
func (i Prime) MarshalText() ([]byte, error) {
return []byte(i.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface for Prime
func (i *Prime) UnmarshalText(text []byte) error {
var err error
*i, err = PrimeString(string(text))
return err
}

140
testdata/primeYaml.golden vendored Normal file
View File

@ -0,0 +1,140 @@
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
const _PrimeLowerName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _PrimeNoOp() {
var x [1]struct{}
_ = x[p2-(2)]
_ = x[p3-(3)]
_ = x[p5-(5)]
_ = x[p7-(7)]
_ = x[p11-(11)]
_ = x[p13-(13)]
_ = x[p17-(17)]
_ = x[p19-(19)]
_ = x[p23-(23)]
_ = x[p29-(29)]
_ = x[p37-(31)]
_ = x[p41-(41)]
_ = x[p43-(43)]
}
var _PrimeValues = []Prime{p2, p3, p5, p7, p11, p13, p17, p19, p23, p29, p37, p41, p43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: p2,
_PrimeLowerName[0:2]: p2,
_PrimeName[2:4]: p3,
_PrimeLowerName[2:4]: p3,
_PrimeName[4:6]: p5,
_PrimeLowerName[4:6]: p5,
_PrimeName[6:8]: p7,
_PrimeLowerName[6:8]: p7,
_PrimeName[8:11]: p11,
_PrimeLowerName[8:11]: p11,
_PrimeName[11:14]: p13,
_PrimeLowerName[11:14]: p13,
_PrimeName[14:17]: p17,
_PrimeLowerName[14:17]: p17,
_PrimeName[17:20]: p19,
_PrimeLowerName[17:20]: p19,
_PrimeName[20:23]: p23,
_PrimeLowerName[20:23]: p23,
_PrimeName[23:26]: p29,
_PrimeLowerName[23:26]: p29,
_PrimeName[26:29]: p37,
_PrimeLowerName[26:29]: p37,
_PrimeName[29:32]: p41,
_PrimeLowerName[29:32]: p41,
_PrimeName[32:35]: p43,
_PrimeLowerName[32:35]: p43,
}
var _PrimeNames = []string{
_PrimeName[0:2],
_PrimeName[2:4],
_PrimeName[4:6],
_PrimeName[6:8],
_PrimeName[8:11],
_PrimeName[11:14],
_PrimeName[14:17],
_PrimeName[17:20],
_PrimeName[20:23],
_PrimeName[23:26],
_PrimeName[26:29],
_PrimeName[29:32],
_PrimeName[32:35],
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _PrimeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// PrimeStrings returns a slice of all String values of the enum
func PrimeStrings() []string {
strs := make([]string, len(_PrimeNames))
copy(strs, _PrimeNames)
return strs
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
// MarshalYAML implements a YAML Marshaler for Prime
func (i Prime) MarshalYAML() (interface{}, error) {
return i.String(), nil
}
// UnmarshalYAML implements a YAML Unmarshaler for Prime
func (i *Prime) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}
var err error
*i, err = PrimeString(s)
return err
}

47
testdata/thresholdeq.go vendored Normal file
View File

@ -0,0 +1,47 @@
package main
import "fmt"
type Thresholdeq int
const (
req1 Thresholdeq = 2
req2 Thresholdeq = 4
req3 Thresholdeq = 6
req4 Thresholdeq = 8
req5 Thresholdeq = 10
req6 Thresholdeq = 12
req7 Thresholdeq = 14
req8 Thresholdeq = 16
req9 Thresholdeq = 18
req10 Thresholdeq = 20
)
func main() {
ck(1, "Thresholdeq(1)")
ck(req1, "req1")
ck(3, "Thresholdeq(3)")
ck(req2, "req2")
ck(5, "Thresholdeq(5)")
ck(req3, "req3")
ck(7, "Thresholdeq(7)")
ck(req4, "req4")
ck(9, "Thresholdeq(9)")
ck(req5, "req5")
ck(11, "Thresholdeq(11)")
ck(req6, "req6")
ck(13, "Thresholdeq(13)")
ck(req7, "req7")
ck(15, "Thresholdeq(15)")
ck(req8, "req8")
ck(17, "Thresholdeq(17)")
ck(req9, "req9")
ck(19, "Thresholdeq(19)")
ck(req10, "req10")
}
func ck(thresholdeq Thresholdeq, str string) {
if fmt.Sprint(thresholdeq) != str {
panic("thresholdeq.go: " + str)
}
}

50
testdata/thresholdgt.go vendored Normal file
View File

@ -0,0 +1,50 @@
package main
import "fmt"
type Thresholdgt int
const (
rgt1 Thresholdgt = 2
rgt2 Thresholdgt = 4
rgt3 Thresholdgt = 6
rgt4 Thresholdgt = 8
rgt5 Thresholdgt = 10
rgt6 Thresholdgt = 12
rgt7 Thresholdgt = 14
rgt8 Thresholdgt = 16
rgt9 Thresholdgt = 18
rgt10 Thresholdgt = 20
rgt11 Thresholdgt = 22
)
func main() {
ck(1, "Thresholdgt(1)")
ck(rgt1, "rgt1")
ck(3, "Thresholdgt(3)")
ck(rgt2, "rgt2")
ck(5, "Thresholdgt(5)")
ck(rgt3, "rgt3")
ck(7, "Thresholdgt(7)")
ck(rgt4, "rgt4")
ck(9, "Thresholdgt(9)")
ck(rgt5, "rgt5")
ck(11, "Thresholdgt(11)")
ck(rgt6, "rgt6")
ck(13, "Thresholdgt(13)")
ck(rgt7, "rgt7")
ck(15, "Thresholdgt(15)")
ck(rgt8, "rgt8")
ck(17, "Thresholdgt(17)")
ck(rgt9, "rgt9")
ck(19, "Thresholdgt(19)")
ck(rgt10, "rgt10")
ck(21, "Thresholdgt(21)")
ck(rgt11, "rgt11")
}
func ck(thresholdgt Thresholdgt, str string) {
if fmt.Sprint(thresholdgt) != str {
panic("thresholdgt.go: " + str)
}
}

44
testdata/thresholdlt.go vendored Normal file
View File

@ -0,0 +1,44 @@
package main
import "fmt"
type Thresholdlt int
const (
rlt1 Thresholdlt = 2
rlt2 Thresholdlt = 4
rlt3 Thresholdlt = 6
rlt4 Thresholdlt = 8
rlt5 Thresholdlt = 10
rlt6 Thresholdlt = 12
rlt7 Thresholdlt = 14
rlt8 Thresholdlt = 16
rlt9 Thresholdlt = 18
)
func main() {
ck(1, "Thresholdlt(1)")
ck(rlt1, "rlt1")
ck(3, "Thresholdlt(3)")
ck(rlt2, "rlt2")
ck(5, "Thresholdlt(5)")
ck(rlt3, "rlt3")
ck(7, "Thresholdlt(7)")
ck(rlt4, "rlt4")
ck(9, "Thresholdlt(9)")
ck(rlt5, "rlt5")
ck(11, "Thresholdlt(11)")
ck(rlt6, "rlt6")
ck(13, "Thresholdlt(13)")
ck(rlt7, "rlt7")
ck(15, "Thresholdlt(15)")
ck(rlt8, "rlt8")
ck(17, "Thresholdlt(17)")
ck(rlt9, "rlt9")
}
func ck(thresholdlt Thresholdlt, str string) {
if fmt.Sprint(thresholdlt) != str {
panic("thresholdlt.go: " + str)
}
}

25
testdata/transform.go vendored
View File

@ -1,25 +0,0 @@
package main
import "fmt"
type CamelCaseValue int
const (
CamelCaseValueOne CamelCaseValue = iota
CamelCaseValueTwo
CamelCaseValueThree
)
func main() {
ck(CamelCaseValueOne, "camel_case_value_one")
ck(CamelCaseValueTwo, "camel_case_value_two")
ck(CamelCaseValueThree, "camel_case_value_three")
ck(-127, "CamelCaseValue(-127)")
ck(127, "CamelCaseValue(127)")
}
func ck(value CamelCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform.go: " + str)
}
}

25
testdata/transform_first.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type FirstCaseValue int
const (
Male FirstCaseValue = iota
Female
unknown
)
func main() {
ck(Male, "M")
ck(Female, "F")
ck(unknown, "u")
ck(-127, "FirstCaseValue(-127)")
ck(127, "FirstCaseValue(127)")
}
func ck(value FirstCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_first.go: " + str)
}
}

25
testdata/transform_first_lower.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type FirstLowerCaseValue int
const (
Male FirstLowerCaseValue = iota
Female
Unknown
)
func main() {
ck(Male, "m")
ck(Female, "f")
ck(Unknown, "u")
ck(-127, "FirstLowerCaseValue(-127)")
ck(127, "FirstLowerCaseValue(127)")
}
func ck(value FirstLowerCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_first_lower.go: " + str)
}
}

25
testdata/transform_first_upper.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type FirstUpperCaseValue int
const (
male FirstUpperCaseValue = iota
female
unknown
)
func main() {
ck(male, "M")
ck(female, "F")
ck(unknown, "U")
ck(-127, "FirstUpperCaseValue(-127)")
ck(127, "FirstUpperCaseValue(127)")
}
func ck(value FirstUpperCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_first_upper.go: " + str)
}
}

25
testdata/transform_kebab.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type KebabCaseValue int
const (
KebabCaseValueOne KebabCaseValue = iota
KebabCaseValueTwo
KebabCaseValueThree
)
func main() {
ck(KebabCaseValueOne, "kebab-case-value-one")
ck(KebabCaseValueTwo, "kebab-case-value-two")
ck(KebabCaseValueThree, "kebab-case-value-three")
ck(-127, "KebabCaseValue(-127)")
ck(127, "KebabCaseValue(127)")
}
func ck(value KebabCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_kebab.go: " + str)
}
}

25
testdata/transform_kebab_upper.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type KebabUpperCaseValue int
const (
KebabUpperCaseValueOne KebabUpperCaseValue = iota
KebabUpperCaseValueTwo
KebabUpperCaseValueThree
)
func main() {
ck(KebabUpperCaseValueOne, "KEBAB-UPPER-CASE-VALUE-ONE")
ck(KebabUpperCaseValueTwo, "KEBAB-UPPER-CASE-VALUE-TWO")
ck(KebabUpperCaseValueThree, "KEBAB-UPPER-CASE-VALUE-THREE")
ck(-127, "KebabUpperCaseValue(-127)")
ck(127, "KebabUpperCaseValue(127)")
}
func ck(value KebabUpperCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_kebab_upper.go: " + str)
}
}

25
testdata/transform_lower.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type LowerCaseValue int
const (
LowerCaseValueOne LowerCaseValue = iota
LowerCaseValueTwo
LowerCaseValueThree
)
func main() {
ck(LowerCaseValueOne, "lowercasevalueone")
ck(LowerCaseValueTwo, "lowercasevaluetwo")
ck(LowerCaseValueThree, "lowercasevaluethree")
ck(-127, "LowerCaseValue(-127)")
ck(127, "LowerCaseValue(127)")
}
func ck(value LowerCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_lower.go: " + str)
}
}

25
testdata/transform_snake.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type SnakeCaseValue int
const (
SnakeCaseValueOne SnakeCaseValue = iota
SnakeCaseValueTwo
SnakeCaseValueThree
)
func main() {
ck(SnakeCaseValueOne, "snake_case_value_one")
ck(SnakeCaseValueTwo, "snake_case_value_two")
ck(SnakeCaseValueThree, "snake_case_value_three")
ck(-127, "SnakeCaseValue(-127)")
ck(127, "SnakeCaseValue(127)")
}
func ck(value SnakeCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_snake.go: " + str)
}
}

25
testdata/transform_snake_upper.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type SnakeUpperCaseValue int
const (
SnakeUpperCaseValueOne SnakeUpperCaseValue = iota
SnakeUpperCaseValueTwo
SnakeUpperCaseValueThree
)
func main() {
ck(SnakeUpperCaseValueOne, "SNAKE_UPPER_CASE_VALUE_ONE")
ck(SnakeUpperCaseValueTwo, "SNAKE_UPPER_CASE_VALUE_TWO")
ck(SnakeUpperCaseValueThree, "SNAKE_UPPER_CASE_VALUE_THREE")
ck(-127, "SnakeUpperCaseValue(-127)")
ck(127, "SnakeUpperCaseValue(127)")
}
func ck(value SnakeUpperCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_snake_upper.go: " + str)
}
}

25
testdata/transform_title.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type TitleCaseValue int
const (
titlecasevalueone TitleCaseValue = iota
titlecasevaluetwo
titlecasevaluethree
)
func main() {
ck(titlecasevalueone, "Titlecasevalueone")
ck(titlecasevaluetwo, "Titlecasevaluetwo")
ck(titlecasevaluethree, "Titlecasevaluethree")
ck(-127, "TitleCaseValue(-127)")
ck(127, "TitleCaseValue(127)")
}
func ck(value TitleCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_title.go: " + str)
}
}

25
testdata/transform_upper.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type UpperCaseValue int
const (
UpperCaseValueOne UpperCaseValue = iota
UpperCaseValueTwo
UpperCaseValueThree
)
func main() {
ck(UpperCaseValueOne, "UPPERCASEVALUEONE")
ck(UpperCaseValueTwo, "UPPERCASEVALUETWO")
ck(UpperCaseValueThree, "UPPERCASEVALUETHREE")
ck(-127, "UpperCaseValue(-127)")
ck(127, "UpperCaseValue(127)")
}
func ck(value UpperCaseValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_upper.go: " + str)
}
}

25
testdata/transform_whitespace.go vendored Normal file
View File

@ -0,0 +1,25 @@
package main
import "fmt"
type WhitespaceSeparatedValue int
const (
WhitespaceSeparatedValueOne WhitespaceSeparatedValue = iota
WhitespaceSeparatedValueTwo
WhitespaceSeparatedValueThree
)
func main() {
ck(WhitespaceSeparatedValueOne, "whitespace separated value one")
ck(WhitespaceSeparatedValueTwo, "whitespace separated value two")
ck(WhitespaceSeparatedValueThree, "whitespace separated value three")
ck(-127, "WhitespaceSeparatedValue(-127)")
ck(127, "WhitespaceSeparatedValue(127)")
}
func ck(value WhitespaceSeparatedValue, str string) {
if fmt.Sprint(value) != str {
panic("transform_whitespace.go: " + str)
}
}

90
testdata/trimPrefix.golden vendored Normal file
View File

@ -0,0 +1,90 @@
const _DayName = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
var _DayIndex = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}
const _DayLowerName = "mondaytuesdaywednesdaythursdayfridaysaturdaysunday"
func (i Day) String() string {
if i < 0 || i >= Day(len(_DayIndex)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _DayName[_DayIndex[i]:_DayIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _DayNoOp() {
var x [1]struct{}
_ = x[DayMonday-(0)]
_ = x[DayTuesday-(1)]
_ = x[DayWednesday-(2)]
_ = x[DayThursday-(3)]
_ = x[DayFriday-(4)]
_ = x[DaySaturday-(5)]
_ = x[DaySunday-(6)]
}
var _DayValues = []Day{DayMonday, DayTuesday, DayWednesday, DayThursday, DayFriday, DaySaturday, DaySunday}
var _DayNameToValueMap = map[string]Day{
_DayName[0:6]: DayMonday,
_DayLowerName[0:6]: DayMonday,
_DayName[6:13]: DayTuesday,
_DayLowerName[6:13]: DayTuesday,
_DayName[13:22]: DayWednesday,
_DayLowerName[13:22]: DayWednesday,
_DayName[22:30]: DayThursday,
_DayLowerName[22:30]: DayThursday,
_DayName[30:36]: DayFriday,
_DayLowerName[30:36]: DayFriday,
_DayName[36:44]: DaySaturday,
_DayLowerName[36:44]: DaySaturday,
_DayName[44:50]: DaySunday,
_DayLowerName[44:50]: DaySunday,
}
var _DayNames = []string{
_DayName[0:6],
_DayName[6:13],
_DayName[13:22],
_DayName[22:30],
_DayName[30:36],
_DayName[36:44],
_DayName[44:50],
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _DayNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Day values", s)
}
// DayValues returns all values of the enum
func DayValues() []Day {
return _DayValues
}
// DayStrings returns a slice of all String values of the enum
func DayStrings() []string {
strs := make([]string, len(_DayNames))
copy(strs, _DayNames)
return strs
}
// IsADay returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Day) IsADay() bool {
for _, v := range _DayValues {
if i == v {
return true
}
}
return false
}

90
testdata/trimPrefixMultiple.golden vendored Normal file
View File

@ -0,0 +1,90 @@
const _DayName = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
var _DayIndex = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}
const _DayLowerName = "mondaytuesdaywednesdaythursdayfridaysaturdaysunday"
func (i Day) String() string {
if i < 0 || i >= Day(len(_DayIndex)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _DayName[_DayIndex[i]:_DayIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _DayNoOp() {
var x [1]struct{}
_ = x[DayMonday-(0)]
_ = x[NightTuesday-(1)]
_ = x[DayWednesday-(2)]
_ = x[NightThursday-(3)]
_ = x[DayFriday-(4)]
_ = x[NightSaturday-(5)]
_ = x[DaySunday-(6)]
}
var _DayValues = []Day{DayMonday, NightTuesday, DayWednesday, NightThursday, DayFriday, NightSaturday, DaySunday}
var _DayNameToValueMap = map[string]Day{
_DayName[0:6]: DayMonday,
_DayLowerName[0:6]: DayMonday,
_DayName[6:13]: NightTuesday,
_DayLowerName[6:13]: NightTuesday,
_DayName[13:22]: DayWednesday,
_DayLowerName[13:22]: DayWednesday,
_DayName[22:30]: NightThursday,
_DayLowerName[22:30]: NightThursday,
_DayName[30:36]: DayFriday,
_DayLowerName[30:36]: DayFriday,
_DayName[36:44]: NightSaturday,
_DayLowerName[36:44]: NightSaturday,
_DayName[44:50]: DaySunday,
_DayLowerName[44:50]: DaySunday,
}
var _DayNames = []string{
_DayName[0:6],
_DayName[6:13],
_DayName[13:22],
_DayName[22:30],
_DayName[30:36],
_DayName[36:44],
_DayName[44:50],
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _DayNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Day values", s)
}
// DayValues returns all values of the enum
func DayValues() []Day {
return _DayValues
}
// DayStrings returns a slice of all String values of the enum
func DayStrings() []string {
strs := make([]string, len(_DayNames))
copy(strs, _DayNames)
return strs
}
// IsADay returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Day) IsADay() bool {
for _, v := range _DayValues {
if i == v {
return true
}
}
return false
}

97
testdata/unum.golden vendored Normal file
View File

@ -0,0 +1,97 @@
const (
_UnumName_0 = "m0m1m2"
_UnumLowerName_0 = "m0m1m2"
_UnumName_1 = "m_2m_1"
_UnumLowerName_1 = "m_2m_1"
)
var (
_UnumIndex_0 = [...]uint8{0, 2, 4, 6}
_UnumIndex_1 = [...]uint8{0, 3, 6}
)
func (i Unum) String() string {
switch {
case 0 <= i && i <= 2:
return _UnumName_0[_UnumIndex_0[i]:_UnumIndex_0[i+1]]
case 253 <= i && i <= 254:
i -= 253
return _UnumName_1[_UnumIndex_1[i]:_UnumIndex_1[i+1]]
default:
return fmt.Sprintf("Unum(%d)", i)
}
}
func (Unum) Values() []string {
return UnumStrings()
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _UnumNoOp() {
var x [1]struct{}
_ = x[m0-(0)]
_ = x[m1-(1)]
_ = x[m2-(2)]
_ = x[m_2-(253)]
_ = x[m_1-(254)]
}
var _UnumValues = []Unum{m0, m1, m2, m_2, m_1}
var _UnumNameToValueMap = map[string]Unum{
_UnumName_0[0:2]: m0,
_UnumLowerName_0[0:2]: m0,
_UnumName_0[2:4]: m1,
_UnumLowerName_0[2:4]: m1,
_UnumName_0[4:6]: m2,
_UnumLowerName_0[4:6]: m2,
_UnumName_1[0:3]: m_2,
_UnumLowerName_1[0:3]: m_2,
_UnumName_1[3:6]: m_1,
_UnumLowerName_1[3:6]: m_1,
}
var _UnumNames = []string{
_UnumName_0[0:2],
_UnumName_0[2:4],
_UnumName_0[4:6],
_UnumName_1[0:3],
_UnumName_1[3:6],
}
// UnumString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func UnumString(s string) (Unum, error) {
if val, ok := _UnumNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _UnumNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Unum values", s)
}
// UnumValues returns all values of the enum
func UnumValues() []Unum {
return _UnumValues
}
// UnumStrings returns a slice of all String values of the enum
func UnumStrings() []string {
strs := make([]string, len(_UnumNames))
copy(strs, _UnumNames)
return strs
}
// IsAUnum returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Unum) IsAUnum() bool {
for _, v := range _UnumValues {
if i == v {
return true
}
}
return false
}

View File

@ -54,7 +54,7 @@ Outer:
for n, test := range splitTests {
values := make([]Value, len(test.input))
for i, v := range test.input {
values[i] = Value{"", v, test.signed, fmt.Sprint(v)}
values[i] = Value{"", "", v, test.signed, fmt.Sprint(v)}
}
runs := splitIntoRuns(values)
if len(runs) != len(test.output) {

View File

@ -1,3 +0,0 @@
To the extent possible under law, Pascal S. de Kloe has waived all
copyright and related or neighboring rights to Colfer. This work is
published from The Netherlands.

View File

@ -1,6 +0,0 @@
[![GoDoc](https://godoc.org/github.com/pascaldekloe/name?status.svg)](https://godoc.org/github.com/pascaldekloe/name)
Naming convention library for the Go programming language (golang).
This is free and unencumbered software released into the
[public domain](http://creativecommons.org/publicdomain/zero/1.0).

View File

@ -1,112 +0,0 @@
// Package name implements naming conventions.
package name
import "unicode"
// CamelCase returns the medial capitals form of word sequence s.
// The input can be any case or even just a bunch of words.
// Upper case abbreviations are preserved.
// Argument upper sets the casing for the first rune.
func CamelCase(s string, upper bool) string {
if s == "" {
return ""
}
out := make([]rune, 1, len(s)+5)
for i, r := range s {
if i == 0 {
if upper {
r = unicode.ToUpper(r)
}
out[0] = r
continue
}
if i == 1 {
if !upper && unicode.Is(unicode.Lower, r) {
out[0] = unicode.ToLower(out[0])
}
upper = false
}
switch {
case unicode.IsLetter(r):
if upper {
r = unicode.ToUpper(r)
}
fallthrough
case unicode.IsNumber(r):
upper = false
out = append(out, r)
default:
upper = true
}
}
return string(out)
}
// SnakeCase is an alias for Delimit(s, '_').
func SnakeCase(s string) string {
return Delimit(s, '_')
}
// DotSeparated is an alias for Delimit(s, '.').
func DotSeparated(s string) string {
return Delimit(s, '.')
}
// Delimit returns word sequence s delimited with sep.
// The input can be any case or even just a bunch of words.
// Upper case abbreviations are preserved. Use strings.ToLower
// and strings.ToUpper to enforce a letter case.
func Delimit(s string, sep rune) string {
out := make([]rune, 0, len(s)+5)
for _, r := range s {
switch {
case unicode.IsUpper(r):
if last := len(out) - 1; last >= 0 && unicode.IsLower(out[last]) {
out = append(out, sep)
}
case unicode.IsLetter(r):
if i := len(out) - 1; i >= 0 {
if last := out[i]; unicode.IsUpper(last) {
out = out[:i]
if i > 0 && out[i-1] != sep {
out = append(out, sep)
}
out = append(out, unicode.ToLower(last))
}
}
case !unicode.IsNumber(r):
if i := len(out); i != 0 && out[i-1] != sep {
out = append(out, sep)
}
continue
}
out = append(out, r)
}
if len(out) == 0 {
return ""
}
// trim tailing separator
if i := len(out) - 1; out[i] == sep {
out = out[:i]
}
if len(out) == 1 {
out[0] = unicode.ToLower(out[0])
}
return string(out)
}

View File

@ -1,103 +0,0 @@
package name
import (
"testing"
)
type goldenCase struct {
snake, lowerCamel, upperCamel string
}
var goldenCases = []goldenCase{
{"", "", ""},
{"i", "i", "I"},
{"name", "name", "Name"},
{"ID", "ID", "ID"},
{"wi_fi", "wiFi", "WiFi"},
// single outer abbreviation
{"vitamin_C", "vitaminC", "VitaminC"},
{"T_cell", "TCell", "TCell"},
// double outer abbreviation
{"master_DB", "masterDB", "MasterDB"},
{"IO_bounds", "IOBounds", "IOBounds"},
// tripple outer abbreviation
{"main_API", "mainAPI", "MainAPI"},
{"TCP_conn", "TCPConn", "TCPConn"},
// inner abbreviation
{"raw_URL_query", "rawURLQuery", "RawURLQuery"},
// numbers
{"4x4", "4x4", "4x4"},
{"no5", "no5", "No5"},
{"DB2", "DB2", "DB2"},
{"3M", "3M", "3M"},
{"7_up", "7Up", "7Up"},
{"20th", "20th", "20th"},
}
func TestSnakeToSnake(t *testing.T) {
for _, golden := range goldenCases {
s := golden.snake
if got := SnakeCase(s); got != s {
t.Errorf("%q: got %q", s, got)
}
}
}
func TestLowerCamelToLowerCamel(t *testing.T) {
for _, golden := range goldenCases {
s := golden.lowerCamel
if got := CamelCase(s, false); got != s {
t.Errorf("%q: got %q", s, got)
}
}
}
func TestUpperCamelToUpperCamel(t *testing.T) {
for _, golden := range goldenCases {
s := golden.upperCamel
if got := CamelCase(s, true); got != s {
t.Errorf("%q: got %q", s, got)
}
}
}
func TestSnakeToLowerCamel(t *testing.T) {
for _, golden := range goldenCases {
snake, want := golden.snake, golden.lowerCamel
if got := CamelCase(snake, false); got != want {
t.Errorf("%q: got %q, want %q", snake, got, want)
}
}
}
func TestSnakeToUpperCamel(t *testing.T) {
for _, golden := range goldenCases {
snake, want := golden.snake, golden.upperCamel
if got := CamelCase(snake, true); got != want {
t.Errorf("%q: got %q, want %q", snake, got, want)
}
}
}
func TestLowerCamelToSnake(t *testing.T) {
for _, golden := range goldenCases {
camel, want := golden.lowerCamel, golden.snake
if got := SnakeCase(camel); got != want {
t.Errorf("%q: got %q, want %q", camel, got, want)
}
}
}
func TestUpperCamelToSnake(t *testing.T) {
for _, golden := range goldenCases {
camel, want := golden.upperCamel, golden.snake
if got := SnakeCase(camel); got != want {
t.Errorf("%q: got %q, want %q", camel, got, want)
}
}
}

View File

@ -1,27 +0,0 @@
package name_test
import (
"fmt"
"github.com/pascaldekloe/name"
)
func ExampleCamelCase() {
fmt.Println(name.CamelCase("pascal case", true))
fmt.Println(name.CamelCase("snake_to_camel AND CamelToCamel?", false))
// Output:
// PascalCase
// snakeToCamelANDCamelToCamel
}
func ExampleDelimit() {
// Garbage to Lisp-case:
fmt.Println(name.Delimit("* All Hype is aGoodThing (TM)", '-'))
// Builds a Java property key:
fmt.Println(name.DotSeparated("WebCrawler#socketTimeout"))
// Output:
// all-hype-is-a-good-thing-TM
// web.crawler.socket.timeout
}