-
Notifications
You must be signed in to change notification settings - Fork 90
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
Update for Go 1.19 and support generics. #49
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked at this in any depth, just took a superficial pass. Gotta return to family now. Will look more carefully once the first round trip is complete. :)
Thanks for the review! I'll follow up on it when the chosen fam isn't making cookies with me, so I'll likely get to it this week. It's your repo so I'll do whatever you like, just want to explain a couple of the choices I made you raised questions about to make sure the suggested fix is actually what you want. 🙂 I am using this in anger locally, and while I think there are some iterative improvements that could happen (I'd love to be able to inject the types into the generated comments! Though I think some design work there may be needed...) it's been awesome to have working. (Though I gotta follow up with a highly suspect PR to vim-go as well. 😬) Enjoy the family time! This will keep. 🙂 |
Absolutely. Code review is an iterative process in which multiple people collectively try to write clear, simple code. :)
Indeed. :) Happy holidays! |
go.mod
Outdated
golang.org/x/tools v0.4.0 | ||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect | ||
) | ||
require golang.org/x/tools v0.4.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is just the result of running go mod tidy
on main
. If you get something different, please shout?
Think I resolved all the comments. Sorry, this has evolved a bit (I realized my handling of parsing out the type params was a bit too naive and switched it up for proper AST parsing) but hopefully I've commented things well enough that it's easier to follow, and hopefully the expansion makes it more robust. |
Hi! Just letting you know I haven't forgotten about this. :) |
Appreciate the update, but also no worries! You set clear expectations at the outset that it would get reviewed when you had time, and I'm content using my fork (and giving it some mileage in anger, seeing if I can break it/if I missed anything), so no pressure here. 😄 |
a year passed, is the project abandoned? |
No, its maintainer is just pretty seriously distractible. But amenable to gentle pings. I'll aim to take a look sometime over the coming weeks. Do you need this particular improvement? |
@josharian I'd really appreciate it, although, as @paddycarver stated, not a blocker, I've built it with his changes :) |
It happens to all of us! I'll take a look at the conflicts here and see if I can resolve them quickly, but I know this turned into more of A Thing than I had originally expected. If it's too invasive/too complicated, I'd love that feedback, and I'll see if I can find a less-technically-correct-but-easier-to-implement version. I have been using the version of impl this PR represents for about a year now, with some pretty heavy generics usage, and it seems to be working for me. vim-go requires some updates to allow quoting the input, but that's not a problem for this repo. 😁 |
Update go.mod to indicate support for Go 1.19. Add support for generic interfaces, i.e. interfaces that accept a type parameter. For example, you can now have this kind of interface: ```go type Interface[Kind any] interface { DoTheThing() Kind } ``` and if you run `impl 's StringImpl' 'Interface[string]` it will generate the following code: ```go func (s StringImpl) DoTheThing() string { // normal impl stub here } ``` Fixes josharian#44.
Turns out we need to use 1.18 because we have generics in our testdata package now, meaning `go test` won't run unless our go.mod is set to 1.18.
Add a comment documenting the purpose of parseTypeParams. Add tests exercising parseTypeParams. Simplify parseTypeParams by using strings.Cut instead of index math.
Instead of parsing generic types using string manipulation, parse them using the go/parse package to get the AST. Rather than bespokely handling the AST stuff everywhere, pull it out into a recursive helper function (we need it to be recursive because generics allow for some pretty complex AST constructs). Rather than passing around a type ID and its params everywhere, create a Type struct that contains both. Pull our type param matching out into a helper function.
Add a test for the interface assertion that was failing.
Had a lingering type assertion that should have used the ID from the parsed AST type instead. Also noticed that we were losing the package names on the type parameters, which would lead to potentially-subtle incorrect results; we should always be using the package if the user submits it. This requires an update to typeFromAST to preserve the package, and then updating findInterface to strip the package off when dealing with qualified interfaces.
Think I got the conflicts resolved. 😄 Tests still pass. |
and let gofumpt scribble on the files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a handful of fixes / nitpicks. Just a few open questions...
impl.go
Outdated
} | ||
prefix := "[" | ||
if specType.Len != nil { | ||
prefix += specType.Len.(*ast.BasicLit).Value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work when the type is [...]T
?
impl.go
Outdated
return Type{}, err | ||
} | ||
return Type{ | ||
ID: "map[" + key.String() + "]" + value.String(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in other places you're careful to only touch the ID, not the params, of subtypes but here, the params get clobbered. makes me feel unsure i understand what this code is doing.
impl.go
Outdated
} | ||
|
||
func typeFromAST(in ast.Expr) (Type, error) { | ||
switch specType := in.(type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any way to avoid rebuilding an entire node printing infrastructure? it'd be nice to somehow use go/format or go/printer.
impl.go
Outdated
// func Foo[Param1, Param2](context.Context, Param1) Param2 | ||
// We're gonna need to complicate everything to support that | ||
// construction, and we don't actually need the deconstructed | ||
// bits, so we're just... not going to deconstruct it at all. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use go/printer or go/format here? this is an awful lot of new code.
Oops. Of course, I can't push changes to your fork. The changes I added are in the generics branch on this repo: main...generics |
Congrats! Go be a father, I'll just wrap this up now. The code can in fact be considerably simplified. I'll do that and then merge. |
Thanks a lot for this one @paddycarver @josharian <3 |
Thank you! I'm glad you knew of a simpler way, that part of the PR is where I looked up and realized this might've gotten away from me a bit, so I appreciate the pointer to where the reusable functionality lives. 😀 |
Update go.mod to indicate support for Go 1.19.
Add support for generic interfaces, i.e. interfaces that accept a type parameter.
For example, you can now have this kind of interface:
and if you run
impl 's StringImpl' 'Interface[string]
it will generate the following code:Fixes #44.