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 spi visibility #1308
Add spi visibility #1308
Conversation
self = .internal | ||
} else if rawValue == "Public" { | ||
self = .public | ||
} else if rawValue.hasPrefix("_SPI(") && rawValue.hasSuffix(")") { |
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 would recommend against using parens (shell special characters) here. It is unpleasant when you try to cut and past commands, or everyone needs to deal with escape characters, etc. I wonder if a separate parameter is in order, even though it's not orthogonal.
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.
Valid point, since this should be rarely used I am unsure if making this more complicated is worth it.
I went with the parenthesis to keep it in line with how the actual attribute works, but we can also just switch it to something like SPI/Foo
@@ -89,6 +114,8 @@ class GeneratorOptions { | |||
visibilitySourceSnippet = "" | |||
case .public: | |||
visibilitySourceSnippet = "public " | |||
case .spi(let identifier): | |||
visibilitySourceSnippet = "@_spi(\(identifier)) public " |
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.
Will this start spraying @_spi
everywhere? Would we want it to appear only on type declarations and extension members?
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.
It will spray everywhere and we also need it to. It is kinda like inlinability once you start adding it, everything needs to become spi.
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.
Do we have an opinion about what happens when the string is not a swift identifier?
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.
Users could supply bad inputs here like (); however, I don't think it is worth validating anything on our side. First, this should only be used by people who know what they want. Second, it will result in compiler errors when building the generated code.
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.
You can use isValidSwiftIdentifier
to do some very basic validation here if you want.
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 it is worth validating whether this is an identifier before we write it. Earlier errors are better.
I am thinking through scenarios here and one thing that I keep coming back to is the amount of control that is likely to be desired once you start producing API/SPI with generated pb types. A major example is availability annotation, which has the potential to be very complicated. In fact, I would probably advise most people to keep these types away from your API/SPI. Combined with the limited audience for |
Insertion points would be a good approach for this. |
@FranzBusch As a rule, all PRs should be based against |
I'd have to double check the stance on insertion points these days. The one thing I can think of is they might interact poorly with the indexing of the sources as they are comments, so they would show up in IDEs, or prevent a real comment from getting associated with an api point, etc. 😞 |
Based on protocolbuffers/protobuf#5721, it sounds like there is some interest in auditing what insertion points are provided by the existing implementations, but no concerns about the use of insertion points in principle. Since we keep getting asked about different ways to adjust the visibility modifiers on generated message types, an insertion point might be a natural answer. |
@thomasvl @tbkka While I understand that there are various annotations that users would want to add I think there is tremendous complexity behind this in where we want to allow such insertions points to be. Just the two examples we have here are quite different. Maybe it is a better to support these annotations on a one by one basis since they all have their own semantics where and how they should be used. Of course we can group them together where it makes sense like with |
# Motivation The Swift compiler added `@_spi() public` visibility annotations in Swift 5.3 which allows you to create a system programming interface. This is often preferred to be used over `@testable` since `@testable` only works in debug modes or when passing specific compiler flags. Right now `protoc-gen-swift` only allows to generate `internal` or `public` visibility levels. However sometimes you want to use the generated proto types also in your test without `public` and without `@testable` # Modification Added a new visibility modifier to the code gen plugin called `_SPI(foo)`. I intentionally made it underscored and did not document it since it is not a stable annotation. Users that reach out to use it should know what they are doing. # Result You can now generate types with `@_spi(foo) public` access level.
8123009
to
520408b
Compare
Looking around, I think the issues I was remember with insertion points is the concern of opening up too many things making maintenance of harder. I can't say I've ever looked at writing a plugin or even using protoc's support for insertion points. So I have no idea how easy/hard that is. I'm not sure if we'd need to consider adding anything to our plugin lib to help someone write a plugin to work on insertion points in Swift. One last though on insertion points - since we just got SwiftPM support, if this goes the insertion points path, does that imply we should support that in the SwiftPM space also? i.e. - do does build system support at all factor into any of this? My reference to But back to @FranzBusch question - support |
In my opinion, any option that we surface on the
Agreed, I think @tbkka @Lukasa What do you think about adding support for |
I'm more than happy to add support for |
If we add direct support for |
|
Closing this since it's gone cold for a year, we can always reopen if this gets picked up again. |
Motivation
The Swift compiler added
@_spi() public
visibility annotations in Swift 5.3 which allows you to create a system programming interface. This is often preferred to be used over@testable
since@testable
only works in debug modes or when passing specific compiler flags. Right nowprotoc-gen-swift
only allows to generateinternal
orpublic
visibility levels. However sometimes you want to use the generated proto types also in your test withoutpublic
and without@testable
Modification
Added a new visibility modifier to the code gen plugin called
_SPI(foo)
. I intentionally made it underscored and did not document it since it is not a stable annotation. Users that reach out to use it should know what they are doing.Result
You can now generate types with
@_spi(foo) public
access level.