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

Add type option #61

Merged
merged 11 commits into from
Nov 1, 2021
Merged

Add type option #61

merged 11 commits into from
Nov 1, 2021

Conversation

Adphi
Copy link
Contributor

@Adphi Adphi commented Sep 24, 2021

This pull request add a type field option:

        // The type option changes the generated field type.
	// All generated code assumes that this type is castable to the protocol buffer field type
	optional string type = 3;
  • scalar fields support

    type Name string
    message CastTypeMessage {
       string name = 1 [(go.field).type = "Name"]
    }
  • repeated fields support:

    type Names []string
    message CastTypeMessage {
        repeated string names = 1 [(go.field).type = "Names"]
    }

@Adphi Adphi force-pushed the casttype branch 2 times, most recently from a16c2e5 to 416f079 Compare September 24, 2021 09:38
@Adphi
Copy link
Contributor Author

Adphi commented Sep 24, 2021

@ydnar, I have allowed edits by maintainers, feel free to refactor as much as you think it needs.

@Adphi Adphi marked this pull request as ready for review September 24, 2021 11:26
Copy link
Contributor

@ydnar ydnar left a comment

Choose a reason for hiding this comment

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

This is pretty impressive. I'm in a phone so can't test it, but I'm generally inclined to accept this PR with some changes.

Thanks!

patch/go.proto Outdated Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
patch/casttype.go Outdated Show resolved Hide resolved
patch/casttype_test.go Outdated Show resolved Hide resolved
patch/casttype_test.go Outdated Show resolved Hide resolved
patch/patcher.go Outdated Show resolved Hide resolved
patch/patcher.go Outdated Show resolved Hide resolved
patch/patcher.go Outdated Show resolved Hide resolved
tests/message/message_casttypes.proto Outdated Show resolved Hide resolved
tests/message/message_renames.proto Outdated Show resolved Hide resolved
@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

@Adphi can it support slices of imported types? e.g.:

message CastTypeMessage {
   repeated string names = 1 [(go.field).casttype = "[]github.com/user/module/pkg.Name"]
}

@Adphi
Copy link
Contributor Author

Adphi commented Sep 27, 2021

@Adphi can it support slices of imported types? e.g.:

message CastTypeMessage {
   repeated string names = 1 [(go.field).casttype = "[]github.com/user/module/pkg.Name"]
}

There was an issue with the package import generation, it is fixed.
But it is not fully supported for the moment as []github.com/user/module/pkg.Name cannot be cast to []string.
The declaration patch is the easy part, the hard part is the refactoring of the generated code usage.
It would be possible to add support for this, but it's a lot more work because you would have to detect slice iterations and index access to cast the usage...

@Adphi Adphi changed the title Add casttype support for scalar types Add type option Sep 27, 2021
@Adphi Adphi requested a review from ydnar September 27, 2021 10:06
@Adphi Adphi force-pushed the casttype branch 2 times, most recently from 8ff3ef2 to f607bf3 Compare September 27, 2021 11:43
@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

There was an issue with the package import generation, it is fixed.

But it is not fully supported for the moment as []github.com/user/module/pkg.Name cannot be cast to []string.

The declaration patch is the easy part, the hard part is the refactoring of the generated code usage.

It would be possible to add support for this, but it's a lot more work because you would have to detect slice iterations and index access to cast the usage...

Got it.

Given that Go supports type aliases, where type A = package.A then the fully qualified version might not need to exist at all. That would simplify the API.

What do you think?

@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

Can you fix the go vet issues?

@Adphi
Copy link
Contributor Author

Adphi commented Sep 27, 2021

Actually, It's not about type alias (type A = B), but about named type (type A string or type A []string).
The fully qualified name has nothing to do with the limitation, it is the same issue that you may have encountered when trying to cast []interface{} to []string, I will remove the []Type from the comments.

@Adphi
Copy link
Contributor Author

Adphi commented Sep 27, 2021

Can you fix the go vet issues?

😬 I cannot reproduce the go vet issue, both on my local computer and inside a docker container...
Got it.

@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

Actually, It's not about type alias (type A = B), but about named type (type A string or type A []string).
The fully qualified name has nothing to do with the limitation, it is the same issue that you may have encountered when trying to cast []interface{} to []string, I will remove the []Type from the comments.

Sorry, I meant using type aliases for types declared in other packages.

Rather than have protopatch add additional imports, the caller can have a separate file that implements the named type in the package, e.g. instead of (go.field).type = 'github.com/org/repo.A', they can only declare package-defined types, which can be aliased in a Go file:

package myproto

import "github.com/org/repo"

type A = repo.A

This should make the implementation in protopatch significantly simpler.

@Adphi
Copy link
Contributor Author

Adphi commented Sep 27, 2021

@ydnar I'm sorry, I don't understand why you would want to use type aliases. I think I must have explained myself wrong. There is no problem with external package imports: please take a look at the plugin tests' generated code.

@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

@ydnar I'm sorry, I don't understand why you would want to use type aliases. I think I must have explained myself wrong. There is no problem with external package imports: please take a look at the plugin tests' generated code.

Oh, I know that it works. But it adds complexity to both the plugin interface and the implementation.

Is there any functionality that requires external package imports?

@Adphi
Copy link
Contributor Author

Adphi commented Sep 27, 2021

Is there any functionality that requires external package imports?

For example: I am working on multiple active directory based projects divided into several libraries, active directory uses an attribute called userAccountControl to store security related flags. The library defines the UserAccountControl as type UserAccountControl uint32, it exposes many methods managing the different flags, both to check the presence and to set them. This library is used in multiple gRPC services.

@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

Is there any functionality that requires external package imports?

For example: I am working on multiple active directory based projects divided into several libraries, active directory uses an attribute called userAccountControl to store security related flags. The library defines the UserAccountControl as type UserAccountControl uint32, it exposes many methods managing the different flags, both to check the presence and to set them. This library is used in multiple gRPC services.

Got it. Can you add a single Go file that aliases UserAccountControl into the package directory?

package foo

import "github.com/Adphi/ws"

type UserAccountControl = ws.UserAccountControl

@Adphi
Copy link
Contributor Author

Adphi commented Sep 27, 2021

Of course I can 😉. But I don't see any reason to do it as protopatch would allow to use the original type, and the implementation in protopatch is pretty straight forward...

@ydnar
Copy link
Contributor

ydnar commented Sep 27, 2021

Of course I can 😉. But I don't see any reason to do it as protopatch would allow to use the original type, and the implementation in protopatch is pretty straight forward...

My concerns are three-fold:

  1. It adds complexity to the interface. The scalar vs repeated type support is terrific, but the lack of support for repeated types from another package seems like a confusing omission. Something that I (or we) would have to document and handle inquiries about.
  2. The language provides a mechanism to bring a type declared in an import package into a locally declared type, via aliasing. I’m not sure we need protopatch to provide duplicate functionality for something that already can be done another way.
  3. This adds a lot of code and complexity to this package, which means more to maintain and debug over time.

I’d consider it if you could split out foreign types into a separate follow-up PR that we can evaluate in isolation. I agree that it provides some nice ergonomics to declare a fully-qualified type, but my concerns outlined above make me wary.

@Adphi
Copy link
Contributor Author

Adphi commented Sep 28, 2021

@ydnar Thanks for the detailed explanation. I'll move external packages support into another pull request.

patch/field_type_test.go Outdated Show resolved Hide resolved
@ydnar
Copy link
Contributor

ydnar commented Oct 1, 2021

@Adphi is the description in this PR up to date with the functionality?

e.g. has fully-qualified types and []T types been removed for future PRs?

@Adphi
Copy link
Contributor Author

Adphi commented Oct 1, 2021

@Adphi is the description in this PR up to date with the functionality?

It should be now 😉

Copy link
Contributor

@ydnar ydnar left a comment

Choose a reason for hiding this comment

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

Thanks! Just a few more comments.

patch/field_type.go Outdated Show resolved Hide resolved
patch/field_type.go Outdated Show resolved Hide resolved
Copy link
Contributor

@ydnar ydnar left a comment

Choose a reason for hiding this comment

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

Close! Looking forward to merging this one.

patch/field_type_test.go Show resolved Hide resolved
patch/patcher.go Outdated Show resolved Hide resolved
@ydnar
Copy link
Contributor

ydnar commented Oct 31, 2021

@Adphi can you rebase this against current main branch?

@Adphi
Copy link
Contributor Author

Adphi commented Oct 31, 2021

@ydnar it's done.

patch/go.proto Outdated
@@ -21,6 +21,10 @@ message Options {
// See https://golang.org/ref/spec#Struct_types.
optional bool embed = 2;

// The type option changes the generated field type.
// All generated code assumes that this type is castable to the protocol buffer field type,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// All generated code assumes that this type is castable to the protocol buffer field type,
// All generated code assumes that this type is castable to the protocol buffer field type.

@ydnar ydnar merged commit 8a60d52 into alta:main Nov 1, 2021
@ydnar
Copy link
Contributor

ydnar commented Nov 1, 2021

@Adphi merged and released in v0.5.0.

Could you make a follow-up PR that adds documentation for the type option to the README?

@Adphi Adphi deleted the casttype branch November 17, 2021 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants