-
Notifications
You must be signed in to change notification settings - Fork 64
[generator] Support using DIM to nest interface types. #589
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
Conversation
2f6a20f to
8bc0710
Compare
|
I like the idea, I'm not fond of the naming (negatives usually don't make for good names) or the implications. Naming wise, I'd prefer The implications being...how will this be used? In the context of Issue #509, we want to enable use of nested types by default for all types added in API-R/API-30, while disabling use of nested types for all types present in or before API-29. How will the Or just for the newly added Is the intention to "somehow" determine the API Level a type was added in, and provide a default What should be done for non- I'd like to understand the broader integration scenarios. |
I'm not a huge fan of
That is, the "default" is nested, so the override should be android.jarIntegration is pretty easy for the Leave the global flag off and add these Or we can turn the global flag on and add these The first way is shorter, but must be done every year with a new binding. The second way is more upfront, but will never need to be updated going forward. Third partiesThis does not provide complete tooling for 3rd parties to use, because we do not currently provide any support for tracking changes across |
Context: #509 Consider the following Java code: package example; public interface Parent { public interface Child { } } Before C#8, interfaces could not contain types. To bind `example.Parent.Child`, we had to "un-nest" the interface, *prefixing* the interface name with the name of the enclosing type: namespace Example { public interface IParent { } public interface IParentChild { } } With C#8, interfaces can now contain types. We can now emit: namespace Example { public interface IParent { public interface IChild { } } } Enable this new style of binding when `generator --lang-features=nested-interface-types` is used. This is *disabled* by default. However, even when `nested-interface-types` is enabled, not all interfaces should follow this new strategy. In the case of `Mono.Android.dll`, nested interface types should *only* be used for types added in API-R/API-30. Add support for a new `unnest` Metadata attribute which can be placed on nested types to explicitly emit the C#7-compatible bindings: <attr path="/api/package[@name='example']/interface[@name='Parent.Child']" name="unnest">true</attr> In a future integration with xamarin-android, [`src/Mono.Android/metadata`][0] can be updated so that all APIs prior to API-30 are unnested, and all APIs starting with API-30 are nested: <!-- Handle everything that has always existed --> <attr api-since="30" path="/api/package/interface[not(@merge.SourceFile)]" name="unnest">true</attr> <attr api-since="30" path="/api/package/class[not(@merge.SourceFile)]" name="unnest">true</attr> <!-- Need these 2 for each platform prior to 30 --> <attr api-since="30" path="/api/package/interface[contains(@merge.SourceFile,'api-29.xml.in')]" name="unnest">true</attr> <attr api-since="30" path="/api/package/class[contains(@merge.SourceFile,'api-29.xml.in')]" name="unnest">true</attr> This will ensure we preserve API compatibility. [0]: https://github.com/xamarin/xamarin-android/blob/b366ac1e6d411dc052dc8711d881d71b7e967685/src/Mono.Android/metadata
Traditionally we have not been able to support types nested inside an interface, as C# did not allow it. Cases like this:
had to be bound as:
With the addition of DIM in C#8, interfaces can now created with nested types. However this is a breaking changes if you've already been generating the old style types.
Therefore we add a new flag
--lang-features=nested-interface-typesthat defaults tofalseto preserve compatibility. Opting in to this flag will nest all interface types.Mixing Nested and Unnested
Additionally, users may have bindings that need to mix nested and unnested interface types. For example,
Mono.Android.dllcontains a decade of APIs that cannot be broken, however new APIs can be nested correctly, producing a binding that more closely mirrors its Java counterpart.To support this there is a new attribute available for
interfaceandclassnodes inapi.xmlcalledunnest. This attribute is not set by tooling such asclass-parse, but can be modified viametadatato force an interface-nested type to override the default setting. If the attribute is omitted, the default is used.Example: