-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Today, when generator creates a .NET namespace from a Java package, it applies a simple pascal case transformation to make the namespace match established .NET naming standards.
For example: package android.database becomes namespace Android.Database.
However there are a few scenarios that this is not a good fit for.
(1) Words where Pascal case is not desired: androidx -> AndroidX
(2) Java package names are often longer than C# namespaces: com.google.android.material.animation -> Google.Android.Material.Animation.
Both of these scenarios can lead to many repeated metadata lines to fix:
<attr path="/api/package[@name='androidx.core.accessibilityservice']" name="managedName">AndroidX.Core.AccessibilityService</attr>
<attr path="/api/package[@name='androidx.core.app']" name="managedName">AndroidX.Core.App</attr>
<attr path="/api/package[@name='androidx.core.content']" name="managedName">AndroidX.Core.Content</attr>
<attr path="/api/package[@name='androidx.core.database']" name="managedName">AndroidX.Core.Database</attr>
<attr path="/api/package[@name='androidx.core.graphics']" name="managedName">AndroidX.Core.Graphics</attr>
<attr path="/api/package[@name='androidx.core.graphics.drawable']" name="managedName">AndroidX.Core.Graphics.Drawable</attr>
<attr path="/api/package[@name='androidx.core.hardware.display']" name="managedName">AndroidX.Core.Hardware.Display</attr>
<attr path="/api/package[@name='androidx.core.hardware.fingerprint']" name="managedName">AndroidX.Core.Hardware.Fingerprint</attr>
<attr path="/api/package[@name='androidx.core.internal']" name="managedName">AndroidX.Core.Internal</attr>
<attr path="/api/package[@name='androidx.core.internal.view']" name="managedName">AndroidX.Core.Internal.View</attr>
etc..
(Source)
Proposal
To help these scenarios, we could introduce a new MSBuild item that would allow simple replacements. Using MSBuild gives users the flexibility of MSBuild like conditionally specifying replacements based on target framework or importing it to multiple projects via Directory.Build.targets. Additionally it might spare some users from the complexity of metadata.
Examples:
<ItemGroup>
<AndroidNamespaceReplacement Include='Androidx' Replacement='AndroidX' />
<AndroidNamespaceReplacement Include='Com' Replacement='' />
<AndroidNamespaceReplacement Include='Com.Google.' Replacement='Google' />
</ItemGroup>Implementation Notes
These replacements would only be run for <package> elements that do not specify a @managedName attribute. If you use @managedName you are opting to provide the exact name, we will not process it further.
Unlike unused metadata, these replacement will not raise a warning if they are unused.
Case Sensitivity
Replacements take place after the automatic Pascal case transform, but the compare is case-insensitive.
Thus, both of the following are equivalent:
<AndroidNamespaceReplacement Include='Androidx' Replacement='AndroidX' />
<AndroidNamespaceReplacement Include='androidx' Replacement='AndroidX' />Word Bounds
Replacements take place only on full words (namespace parts).
Thus,
<AndroidNamespaceReplacement Include='Com' Replacement='' />Matches matches Com.Google.Library, but not Common.Google.Library or Google.Imaging.Dicom.
Multiple full words can be used:
<AndroidNamespaceReplacement Include='Com.Google' Replacement='Google' />
<AndroidNamespaceReplacement Include='Com.Androidx' Replacement='Xamarin.AndroidX' />Word Position
The word part match can be constrained to the beginning or end of a namespace by appending a . or prepending a ., respectively.
<AndroidNamespaceReplacement Include='Androidx.' Replacement='Xamarin.AndroidX' />matches Androidx.Core, but not Square.OkHttp.Androidx.
Similarly,
<AndroidNamespaceReplacement Include='.Compose' Replacement='ComposeUI' />matches Google.AndroidX.Compose, but not Google.Compose.Writer.
Replacement Order
Replacements run in the order specified by the <ItemGroup>, however adding to this group at different times may result in an unintended order.
Replacements are run sequentially, and multiple replacements may affect a single namespace.
<AndroidNamespaceReplacement Include='Androidx' Replacement='Xamarin.AndroidX' />
<AndroidNamespaceReplacement Include='View' Replacement='Views' />changes Androidx.View to Xamarin.AndroidX.Views.