Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use enumer to generate String() methods for most enums #25705

Merged
merged 4 commits into from
Apr 17, 2024
Merged

Conversation

swenson
Copy link
Contributor

@swenson swenson commented Feb 28, 2024

We have many hand-written String() methods (and similar) for enums. These require more maintenance and are more error-prone than using automatically generated methods. In addition, the auto-generated versions can be more efficient.

Here, we switch to using https://github.com/loggerhead/enumer, itself a fork of https://github.com/diegostamigni/enumer, no longer maintained, and a fork of the mostly standard tool
https://pkg.go.dev/golang.org/x/tools/cmd/stringer. We use this fork of enumer for Go 1.20+ compatibility and because we require the -transform flag to be able to generate constants that match our current code base.

Some enums were not targeted for this change:

  • Bit sets, which are not supported by enumer or stringer.
  • Enums with non-standard naming schemes, like having a common suffix instead of a prefix, or using spaces instead of underscores or dashes.
  • Enums that don't have a type associated

We have many hand-written String() methods (and similar) for enums.
These require more maintenance and are more error-prone than using
automatically generated methods. In addition, the auto-generated
versions can be more efficient.

Here, we switch to using https://github.com/loggerhead/enumer, itself
a fork of https://github.com/diegostamigni/enumer, no longer maintained,
and a fork of the mostly standard tool
https://pkg.go.dev/golang.org/x/tools/cmd/stringer.
We use this fork of enumer for Go 1.20+ compatibility and because
we require the `-transform` flag to be able to generate
constants that match our current code base.

Some enums were not targeted for this change:

* Bit sets, which are not supported by enumer or stringer.
* Enums with non-standard naming schemes, like having a common suffix
  instead of a prefix, or using spaces instead of underscores or dashes.
* Enums that don't have a type associated
@github-actions github-actions bot added the hashicorp-contributed-pr If the PR is HashiCorp (i.e. not-community) contributed label Feb 28, 2024
Copy link

github-actions bot commented Feb 28, 2024

CI Results:
All Go tests succeeded! ✅

@swenson swenson marked this pull request as ready for review February 29, 2024 00:02
@swenson swenson requested review from a team as code owners February 29, 2024 00:02
Copy link

github-actions bot commented Feb 29, 2024

Build Results:
All builds succeeded! ✅

Copy link
Collaborator

@sgmiller sgmiller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat transform, but my concern is it doesn't preserve the default case for String(), which code may be relying on.

case PluginRuntimeTypeContainer:
return "container"
default:
return "unsupported"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious how enumer handles the defaults?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default will be TypeName(number). For most of these, I tried to ensure that the default wasn't really used, or that the particular String() value wasn't relied on.

@swenson
Copy link
Contributor Author

swenson commented Mar 4, 2024

@sgmiller it doesn't preserve the default case we were using, which was lowercase, but where that mattered, I used the snake option to match the current String() values.

I didn't convert any enums that we couldn't match the current String() values for, like ones that have suffixes.

@swenson swenson requested a review from sgmiller April 16, 2024 15:44
type tidyStatusState int

const (
tidyStatusInactive tidyStatusState = iota
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess my other question is whether it's necessary to add full enum functionality to those that were simply used with iota. Adds code that isn't used...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the code isn't used then it will be trimmed out by the compiler at build time, so I'm not super worried about it adding to the binary. And I figured it is better to be as complete as possible in this conversion in case someone needs the extra functions for debugging.

@@ -252,6 +252,7 @@ type Check interface {
Evaluate(e *Executor) ([]*Result, error)
}

//go:generate enumer -type=ResultStatus -trimprefix=Result -transform=snake
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contrast with this one where we're definitely cleaning up things using enumer.

@sgmiller sgmiller self-requested a review April 17, 2024 17:56
@swenson
Copy link
Contributor Author

swenson commented Apr 17, 2024

Thanks!

@swenson swenson merged commit 961bf20 into main Apr 17, 2024
87 checks passed
@swenson swenson deleted the enum-string branch April 17, 2024 18:14
swenson pushed a commit that referenced this pull request Apr 17, 2024
We have many hand-written String() methods (and similar) for enums.
These require more maintenance and are more error-prone than using
automatically generated methods. In addition, the auto-generated
versions can be more efficient.

Here, we switch to using https://github.com/loggerhead/enumer, itself
a fork of https://github.com/diegostamigni/enumer, no longer maintained,
and a fork of the mostly standard tool
https://pkg.go.dev/golang.org/x/tools/cmd/stringer.
We use this fork of enumer for Go 1.20+ compatibility and because
we require the `-transform` flag to be able to generate
constants that match our current code base.

Some enums were not targeted for this change:
swenson pushed a commit that referenced this pull request Apr 18, 2024
We have many hand-written String() methods (and similar) for enums.
These require more maintenance and are more error-prone than using
automatically generated methods. In addition, the auto-generated
versions can be more efficient.

Here, we switch to using https://github.com/loggerhead/enumer, itself
a fork of https://github.com/diegostamigni/enumer, no longer maintained,
and a fork of the mostly standard tool
https://pkg.go.dev/golang.org/x/tools/cmd/stringer.
We use this fork of enumer for Go 1.20+ compatibility and because
we require the `-transform` flag to be able to generate
constants that match our current code base.

Some enums were not targeted for this change:

Co-authored-by: Christopher Swenson <christopher.swenson@hashicorp.com>
@peteski22
Copy link
Contributor

peteski22 commented Apr 22, 2024

If you encountered an error during make dev along the lines of:

running "enumer": exec: "enumer": executable file not found in $PATH

Please run make tools (make bootstrap likely needs a missing dependency so won't work).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hashicorp-contributed-pr If the PR is HashiCorp (i.e. not-community) contributed pr/no-changelog pr/no-milestone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants