diff --git a/external/Java.Interop/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/external/Java.Interop/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
index bc7adf68e67..a12dc402216 100644
--- a/external/Java.Interop/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
+++ b/external/Java.Interop/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
@@ -1563,6 +1563,123 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides ()
StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", ifaceActual, "Should not contain UnsupportedOSPlatform on interface property override!");
}
+ [Test]
+ public void UnsupportedOSPlatformIgnoresPropertySetterMovedToStandaloneBaseMethod ()
+ {
+ var xml = @$"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ";
+
+ var gens = ParseApiDefinition (xml);
+ var klass = gens.Single (g => g.Name == "Derived");
+ var property = klass.Properties.Single (p => p.Name == "Value");
+ var actual = GetGeneratedTypeOutput (klass);
+
+ Assert.IsNotNull (property.Setter, "The removed setter must be tested as a property accessor.");
+ StringAssert.Contains ("public virtual unsafe Java.Lang.Object Value {", actual);
+ StringAssert.Contains ("set {", actual);
+ StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual);
+ }
+
+ [Test]
+ public void UnsupportedOSPlatformIgnoresSpecializedGenericBasePropertySetter ()
+ {
+ var xml = @$"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ";
+
+ var gens = ParseApiDefinition (xml);
+ var klass = gens.Single (g => g.Name == "GridView");
+ var property = klass.Properties.Single (p => p.Name == "Adapter");
+ var actual = GetGeneratedTypeOutput (klass);
+
+ Assert.IsNotNull (property.Setter, "The specialized setter must be tested as a property accessor.");
+ StringAssert.Contains ("set {", actual);
+ StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual);
+ }
+
+ [Test]
+ public void UnsupportedOSPlatformPreservesPropertySetterForDifferentGenericBaseParameter ()
+ {
+ var xml = @$"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ";
+
+ var gens = ParseApiDefinition (xml);
+ var baseSetter = gens.Single (g => g.Name == "Base").GetAllMethods ().Single (m => m.JavaName == "setValue");
+ var klass = gens.Single (g => g.Name == "Derived");
+ var property = klass.Properties.Single (p => p.Name == "Value");
+ var actual = GetGeneratedTypeOutput (klass);
+
+ Assert.IsTrue (baseSetter.Parameters [0].IsGeneric, $"Expected a concrete generic parameter, but found {baseSetter.Parameters [0].Symbol.GetType ().FullName}.");
+ Assert.IsNotNull (property.Setter, "The removed setter must be tested as a property accessor.");
+ StringAssert.Contains ("set {", actual);
+ StringAssert.Contains ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual);
+ }
+
[Test]
public void StringPropertyOverride ([Values ("true", "false")] string final)
{
diff --git a/external/Java.Interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/external/Java.Interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs
index 4f0ca0b8e01..d4a8dc8ba7c 100644
--- a/external/Java.Interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs
+++ b/external/Java.Interop/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs
@@ -339,37 +339,30 @@ public void FixupMethodOverrides (CodeGenerationOptions opt)
}
}
- // Process property getter/setter methods for ApiRemovedSince fixup
+ // A property accessor can correspond to a standalone method in a base class
+ // when the accessor types differ. Compare the underlying Java methods.
foreach (var prop in Properties) {
- for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) {
- var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Type == prop.Type);
- if (baseProp == null) {
+ foreach (var m in new [] { prop.Getter, prop.Setter }) {
+ if (m == null || m.ApiRemovedSince == 0) {
continue;
}
- bool shouldBreak = false;
- if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0 && baseProp.Getter != null && baseProp.Getter.ApiRemovedSince == 0) {
- if (baseProp.Getter.Visibility == prop.Getter.Visibility &&
- ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) &&
- baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) {
- // If a "removed" property getter overrides a "not removed" getter, the method was
- // likely moved to a base class, so don't mark it as removed.
- prop.Getter.ApiRemovedSince = default;
- shouldBreak = true;
- }
- }
- if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0 && baseProp.Setter != null && baseProp.Setter.ApiRemovedSince == 0) {
- if (baseProp.Setter.Visibility == prop.Setter.Visibility &&
- ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) {
- // If a "removed" property setter overrides a "not removed" setter, the method was
- // likely moved to a base class, so don't mark it as removed.
- prop.Setter.ApiRemovedSince = default;
- shouldBreak = true;
+ for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) {
+ var bm = bt.GetAllMethods ().FirstOrDefault (mm =>
+ mm.ApiRemovedSince == 0 &&
+ mm.JavaName == m.JavaName &&
+ mm.Visibility == m.Visibility &&
+ ((m == prop.Getter &&
+ mm.RetVal.FullName == m.RetVal.FullName &&
+ ParameterList.Equals (mm.Parameters, m.Parameters)) ||
+ (m == prop.Setter &&
+ (ParameterList.Equals (mm.Parameters, m.Parameters) ||
+ (mm.Parameters.Count == 1 && mm.Parameters [0].Symbol is GenericTypeParameter)))));
+ if (bm != null) {
+ m.ApiRemovedSince = default;
+ break;
}
}
- if (shouldBreak) {
- break;
- }
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs
index 91bbece641a..305a65d6de5 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs
@@ -478,6 +478,18 @@ public void BuildHasNoWarnings (bool isRelease, bool multidex, string packageFor
proj.SetProperty ("XamarinAndroidSupportSkipVerifyVersions", "True"); // Disables API 29 warning in Xamarin.Build.Download
proj.SetProperty ("AndroidPackageFormat", packageFormat);
proj.SetProperty ("TrimmerSingleWarn", "false");
+ // Regression tests for:
+ // https://github.com/dotnet/android/issues/10509
+ // https://github.com/dotnet/android/issues/12107
+ proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}",
+ """
+ // These should not cause warnings
+ new FrameLayout (this).Foreground = null;
+ new GridView (this).Adapter = null;
+ new ListView (this).Adapter = null;
+ Console.WriteLine (Android.Provider.MediaStore.Video.IVideoColumns.DateTaken);
+ Console.WriteLine (Android.Provider.MediaStore.Images.IImageColumns.DateTaken);
+ """);
using (var b = CreateApkBuilder ()) {
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");