Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

Commit f359e73

Browse files
authored
[generator] Generate more [SupportedOSPlatform] attributes (#868)
Fixes: #863 In commits da12df4 and 412e974 (and others) we added support to emit the `[SupportedOSPlatformAttribute]` custom attribute when targeting .NET 6+ builds, using the Android API-level that the member was introduced: [global::System.Runtime.Versioning.SupportedOSPlatformAttribute ("android23.0")] [global::Android.Runtime.Register ("android/telecom/InCallService", DoNotGenerateAcw=true, ApiSince = 23)] public abstract partial class InCallService : Android.App.Service { } However, our "invoke" machinery uses this API without having the same guards: [global::Android.Runtime.Register ("android/telecom/InCallService", DoNotGenerateAcw=true, ApiSince = 23)] internal partial class InCallServiceInvoker : InCallService { } This results in build warnings when building e.g. `xamarin-android/src/Mono.Android`: …/xamarin-android/src/Mono.Android/obj/Release/net6.0/android-30/mcw/Android.Telecom.InCallService.cs(1287,76): warning CA1416: This call site is reachable on all platforms. 'InCallService' is only supported on: 'android' 23.0 and later. To fix these warnings, we need to emit the same `[SupportedOSPlatformAttribute]` for these members as well: [global::System.Runtime.Versioning.SupportedOSPlatformAttribute ("android23.0")] [global::Android.Runtime.Register ("android/telecom/InCallService", DoNotGenerateAcw=true, ApiSince = 23)] internal partial class InCallServiceInvoker : InCallService { } This change removes 4,699 `CA1416` warnings from our `Mono.Android.dll` build. The remaining 61 `CA1416` warnings are of the form: …\xamarin-android\src\Mono.Android\obj\Debug\net6.0\android-31\mcw\Java.Lang.Reflect.Method.cs(35,71): warning CA1416: This call site is reachable on all platforms. 'Executable' is only supported on: 'android' 26.0 and later. The problem here is that `Java.Lang.Reflect.Method` class is available since API-1, but it inherits from the `Java.Lang.Reflect.Executable` class which was added in API-26. See: - https://developer.android.com/reference/java/lang/reflect/Method - https://developer.android.com/reference/java/lang/reflect/Executable This seems like a `Mono.Android.dll` issue and not something we should attempt to fix in `generator`.
1 parent b7982e4 commit f359e73

12 files changed

Lines changed: 37 additions & 11 deletions

‎tools/generator/SourceWriters/BoundMethodExtensionStringOverload.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public BoundMethodExtensionStringOverload (Method method, CodeGenerationOptions
2929
if(method.Deprecated!=null)
3030
Attributes.Add(newObsoleteAttr(method.Deprecated.Replace("\"","\"\"").Trim()));
3131

32+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
33+
3234
Parameters.Add(newMethodParameterWriter("self",newTypeReferenceWriter(selfType)){IsExtension=true});
3335
this.AddMethodParametersStringOverloads(method.Parameters,opt);
3436
}

‎tools/generator/SourceWriters/BoundMethodStringOverload.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public BoundMethodStringOverload (Method method, CodeGenerationOptions opt)
2727
if(method.Deprecated!=null)
2828
Attributes.Add(newObsoleteAttr(method.Deprecated.Replace("\"","\"\"").Trim()));
2929

30+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
31+
3032
method.JavadocInfo?.AddJavadocs(Comments);
3133

3234
this.AddMethodParametersStringOverloads(method.Parameters,opt);

‎tools/generator/SourceWriters/BoundProperty.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ public BoundProperty (GenBase gen, Property property, CodeGenerationOptions opt,
6969
if(property.Getter.Deprecated!=null&&(property.Setter==null||property.Setter.Deprecated!=null))
7070
Attributes.Add(newObsoleteAttr(property.Getter.Deprecated.Replace("\"","\"\"").Trim()+(property.Setter!=null&&property.Setter.Deprecated!=property.Getter.Deprecated?" "+property.Setter.Deprecated.Replace("\"","\"\"").Trim():null)));
7171

72+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,property.Getter,opt);
73+
7274
SourceWriterExtensions.AddMethodCustomAttributes(GetterAttributes,property.Getter);
7375

7476
if(gen.IsGeneratable)
7577
GetterComments.Add($"// Metadata.xml XPath method reference: path=\"{gen.MetadataXPathReference}/method[@name='{property.Getter.JavaName}'{property.Getter.Parameters.GetMethodXPathPredicate()}]\"");
7678

77-
SourceWriterExtensions.AddSupportedOSPlatform(GetterAttributes,property.Getter,opt);
78-
7979
GetterAttributes.Add(newRegisterAttr(property.Getter.JavaName,property.Getter.JniSignature,property.Getter.IsVirtual?property.Getter.GetConnectorNameFull(opt):string.Empty,additionalProperties:property.Getter.AdditionalAttributeString()));
8080

8181
SourceWriterExtensions.AddMethodBody(GetBody,property.Getter,opt);

‎tools/generator/SourceWriters/BoundPropertyStringVariant.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public BoundPropertyStringVariant (Property property, CodeGenerationOptions opt)
2424

2525
SetVisibility((property.Setter??property.Getter).Visibility);
2626

27+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,property.Getter,opt);
28+
2729
HasGet=true;
2830

2931
if(is_array)

‎tools/generator/SourceWriters/ClassInvokerClass.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public ClassInvokerClass (ClassGen klass, CodeGenerationOptions opt)
2626

2727
Attributes.Add(newRegisterAttr(klass.RawJniName,noAcw:true,additionalProperties:klass.AdditionalAttributeString()){UseGlobal=true});
2828

29+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,klass,opt);
30+
2931
varctor=newConstructorWriter{
3032
Name=Name,
3133
IsPublic=true,

‎tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public static void AddInterfaceListenerEventsAndProperties (TypeWriter tw, Inter
8585

8686
AddInterfaceListenerEventsAndProperties(tw,iface,target,name,setter,
8787
string.Format("__v => {0} = __v",prop.Name),
88-
string.Format("__v => {0} = null",prop.Name),opt);
88+
string.Format("__v => {0} = null",prop.Name),opt,prop.Getter);
8989
}else{
9090
refs.Add(method.Name);
9191
stringrm=null;
@@ -103,7 +103,7 @@ public static void AddInterfaceListenerEventsAndProperties (TypeWriter tw, Inter
103103

104104
AddInterfaceListenerEventsAndProperties(tw,iface,target,name,method.Name,
105105
method.Name,
106-
remove,opt);
106+
remove,opt,method);
107107
}
108108
}
109109

@@ -113,7 +113,9 @@ public static void AddInterfaceListenerEventsAndProperties (TypeWriter tw, Inter
113113
tw.Methods.Add(newCreateImplementorMethod(iface,opt));
114114
}
115115

116-
publicstaticvoidAddInterfaceListenerEventsAndProperties(TypeWritertw,InterfaceGeniface,ClassGentarget,stringname,stringconnector_fmt,stringadd,stringremove,CodeGenerationOptionsopt)
116+
// Parameter 'setListenerMethod' refers to the method used to set the listener, like 'addOnRoutingChangedListener'/'setOnRoutingChangedListener'.
117+
// This is used to determine what API level the listener setter is available on.
118+
publicstaticvoidAddInterfaceListenerEventsAndProperties(TypeWritertw,InterfaceGeniface,ClassGentarget,stringname,stringconnector_fmt,stringadd,stringremove,CodeGenerationOptionsopt,MethodsetListenerMethod)
117119
{
118120
if(!iface.IsValid)
119121
return;
@@ -128,11 +130,11 @@ public static void AddInterfaceListenerEventsAndProperties (TypeWriter tw, Inter
128130
if(target.ContainsName(nameUnique))
129131
nameUnique+="Event";
130132

131-
AddInterfaceListenerEventOrProperty(tw,iface,method,target,nameUnique,connector_fmt,add,remove,opt);
133+
AddInterfaceListenerEventOrProperty(tw,iface,method,target,nameUnique,connector_fmt,add,remove,opt,setListenerMethod);
132134
}
133135
}
134136

135-
publicstaticvoidAddInterfaceListenerEventOrProperty(TypeWritertw,InterfaceGeniface,Methodmethod,ClassGentarget,stringname,stringconnector_fmt,stringadd,stringremove,CodeGenerationOptionsopt)
137+
publicstaticvoidAddInterfaceListenerEventOrProperty(TypeWritertw,InterfaceGeniface,Methodmethod,ClassGentarget,stringname,stringconnector_fmt,stringadd,stringremove,CodeGenerationOptionsopt,MethodsetListenerMethod)
136138
{
137139
if(method.EventName==string.Empty)
138140
return;
@@ -157,7 +159,7 @@ public static void AddInterfaceListenerEventOrProperty (TypeWriter tw, Interface
157159
varmt=target.Methods.Where(method =>string.Compare(method.Name,connector_fmt,StringComparison.OrdinalIgnoreCase)==0&&method.IsListenerConnector).FirstOrDefault();
158160
varhasHandlerArgument=mt!=null&&mt.IsListenerConnector&&mt.Parameters.Count==2&&mt.Parameters[1].Type=="Android.OS.Handler";
159161

160-
tw.Events.Add(newInterfaceListenerEvent(iface,name,nameSpec,full_delegate_name,connector_fmt,add,remove,hasHandlerArgument,opt));
162+
tw.Events.Add(newInterfaceListenerEvent(iface,setListenerMethod,name,nameSpec,full_delegate_name,connector_fmt,add,remove,hasHandlerArgument,opt));
161163
}
162164
}else{
163165
if(opt.GetSafeIdentifier(name)!=name){

‎tools/generator/SourceWriters/InterfaceInvokerMethod.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public InterfaceInvokerMethod (InterfaceGen iface, Method method, CodeGeneration
3030
method_callback=newMethodCallback(iface,method,opt,null,method.IsReturnCharSequence);
3131
context_this=context.ContextType.GetObjectHandleProperty("this");
3232

33+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
34+
3335
this.AddMethodParameters(method.Parameters,opt);
3436
}
3537

‎tools/generator/SourceWriters/InterfaceInvokerProperty.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public InterfaceInvokerProperty (InterfaceGen iface, Property property, CodeGene
2727
IsPublic=true;
2828
IsUnsafe=true;
2929

30+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,property.Getter,opt);
31+
3032
HasGet=property.Getter!=null;
3133

3234
if(property.Getter!=null){

‎tools/generator/SourceWriters/InterfaceListenerEvent.cs‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ public class InterfaceListenerEvent : EventWriter
1212
{
1313
readonlyInterfaceListenerEventHandlerHelperhelper_method;
1414

15-
publicInterfaceListenerEvent(InterfaceGeniface,stringname,stringnameSpec,stringfullDelegateName,stringwrefSuffix,stringadd,stringremove,boolhasHandlerArgument,CodeGenerationOptionsopt)
15+
publicInterfaceListenerEvent(InterfaceGeniface,Methodmethod,stringname,stringnameSpec,stringfullDelegateName,stringwrefSuffix,stringadd,stringremove,boolhasHandlerArgument,CodeGenerationOptionsopt)
1616
{
1717
Name=name;
1818
EventType=newTypeReferenceWriter(opt.GetOutputName(fullDelegateName));
1919

2020
IsPublic=true;
2121

22+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
23+
2224
HasAdd=true;
2325

2426
AddBody.Add($"global::Java.Interop.EventHelper.AddEventHandler<{opt.GetOutputName(iface.FullName)}, {opt.GetOutputName(iface.FullName)}Implementor>(");
@@ -36,7 +38,7 @@ public InterfaceListenerEvent (InterfaceGen iface, string name, string nameSpec,
3638
RemoveBody.Add($"__h => __h.{nameSpec}Handler -= value);");
3739

3840
if(hasHandlerArgument)
39-
helper_method=newInterfaceListenerEventHandlerHelper(iface,add,opt);
41+
helper_method=newInterfaceListenerEventHandlerHelper(iface,method,add,opt);
4042
}
4143

4244
publicoverridevoidWrite(CodeWriterwriter)
@@ -49,12 +51,14 @@ public override void Write (CodeWriter writer)
4951

5052
publicclassInterfaceListenerEventHandlerHelper:MethodWriter
5153
{
52-
publicInterfaceListenerEventHandlerHelper(InterfaceGeniface,stringadd,CodeGenerationOptionsopt)
54+
publicInterfaceListenerEventHandlerHelper(InterfaceGeniface,Methodmethod,stringadd,CodeGenerationOptionsopt)
5355
{
5456
Name=add+"_Event_With_Handler_Helper";
5557
Parameters.Add(newMethodParameterWriter("value",newTypeReferenceWriter(opt.GetOutputName(iface.FullName))));
5658
ReturnType=TypeReferenceWriter.Void;
5759

60+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
61+
5862
Body.Add($"{add} (value, null);");
5963
}
6064
}

‎tools/generator/SourceWriters/MethodAsyncWrapper.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public MethodAsyncWrapper (Method method, CodeGenerationOptions opt)
2828
if(!method.IsVoid)
2929
ReturnType.Name+="<"+opt.GetTypeReferenceName(method.RetVal)+">";
3030

31+
SourceWriterExtensions.AddSupportedOSPlatform(Attributes,method,opt);
32+
3133
Body.Add($"return global::System.Threading.Tasks.Task.Run (() => {method.AdjustedName} ({method.Parameters.GetCall(opt)}));");
3234

3335
this.AddMethodParameters(method.Parameters,opt);

0 commit comments

Comments
 (0)