dotnet / java-interop

Java.Interop provides open-source bindings of Java's Java Native Interface (JNI) for use with .NET managed languages such as C#
Other
196 stars 51 forks source link

Deduplicate //attr/@path? #983

Open jonpryor opened 2 years ago

jonpryor commented 2 years ago

It's quite common to need to modify multiple attributes on a given element via Metadata. Consider:

Updating ContentProvider.setReadPermission(): https://github.com/xamarin/xamarin-android/blob/d260d035a840dd314ddc7ef194489933a9929794/src/Mono.Android/metadata#L72-L75

Update ActivityInstrumentationTestCase.getActivity(): https://github.com/xamarin/xamarin-android/blob/d260d035a840dd314ddc7ef194489933a9929794/src/Mono.Android/metadata#L223-L224

Update RemoteController.OnClientUpdateListener.onClientPlaybackStateUpdate(): https://github.com/xamarin/xamarin-android/blob/d260d035a840dd314ddc7ef194489933a9929794/src/Mono.Android/metadata#L835-L837

See also #981, in which a plausible fix for IAnnotatedArrayType.AnnotatedOwnerType will require setting both propertyName and managedOverride.

Would it be useful to allow setting multiple attributes as part of one larger element?

For example, instead of:

<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedArrayType']/method[@name='getAnnotatedOwnerType' and count(parameter)=0]"
    name="propertyName">IAnnotatedType.AnnotatedOwnerType</attr>
<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedArrayType']/method[@name='getAnnotatedOwnerType' and count(parameter)=0]"
    name="managedOverride">abstract</attr>

Have:

<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedArrayType']/method[@name='getAnnotatedOwnerType' and count(parameter)=0]">
  <name>propertyName</name><value>IAnnotatedType.AnnotatedOwnerType</value>
  <name>managedOverride</name><value>abstract</value>
</attr>

Or perhaps "commonly suffixed" attribute values?

<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedArrayType']/method[@name='getAnnotatedOwnerType' and count(parameter)=0]"
    name1="propertyName" value1="IAnnotatedType.AnnotatedOwnerType"
    name2="managedOverride" value2="abstract"
/>

Would this be at all worthwhile? Is there a better and shorter syntax to consider?

jonpryor commented 2 years ago

Yet another idea: allow <attr/> to work as a scope, with an optional name attribute, and allow it contain child <attr/> nodes:

<attr path="/api/package[@name='java.lang.reflect']/interface[@name='AnnotatedArrayType']/method[@name='getAnnotatedOwnerType' and count(parameter)=0]">
  <attr path="." name="propertyName">IAnnotatedType.AnnotatedOwnerType</attr>
  <attr path="." name="managedOverride">abstract</attr>
</attr>

"Nesting" in this fashion would allow "common sub-expressions" to be shared, possibly reducing mental effort, e.g. replace https://github.com/xamarin/xamarin-android/blob/d260d035a840dd314ddc7ef194489933a9929794/src/Mono.Android/metadata#L14-L15

<attr path="/api/package[@name='android.view.accessibility']/class[@name='AccessibilityEvent']/method[@name='getAction']" name="propertyName"></attr>
<attr path="/api/package[@name='android.view.accessibility']/class[@name='AccessibilityEvent']/method[@name='setAction']" name="propertyName"></attr>

with:

<attr path="/api/package[@name='android.view.accessibility']/class[@name='AccessibilityEvent']">
  <attr path="./method[@name='getAction']" name="propertyName"></attr>
  <attr path="./method[@name='setAction']" name="propertyName"></attr>
</attr>