Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,164 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides ()
StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", ifaceActual, "Should not contain UnsupportedOSPlatform on interface property override!");
}

[Test]
public void UnsupportedOSPlatformIgnoresPropertySetterOverridesWhenBaseHasGetterOnly ()
{
// Given:
// public class AdapterView {
// public Object getAdapter () { ... }
// }
// public class ListView : AdapterView {
// public Object getAdapter () { ... } // removed-since = 15
// public void setAdapter (Object value) { ... } // removed-since = 15
// }
// We should not write [UnsupportedOSPlatform] on ListView.Adapter.set because the base property (via getter) isn't "removed".
var xml = @$"<api>
<package name='java.lang' jni-name='java/lang'>
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
</package>
<package name='android.widget' jni-name='android/widget'>
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' final='false' name='AdapterView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='java.lang.Object' static='false' synchronized='false' synthetic='false' visibility='public' />
</class>
<class abstract='false' deprecated='not deprecated' extends='android.widget.AdapterView' extends-generic-aware='android.widget.AdapterView' final='false' name='ListView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='java.lang.Object' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15' />
<method abstract='false' deprecated='not deprecated' final='false' name='setAdapter' bridge='false' native='false' return='void' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15'>
<parameter name='value' type='java.lang.Object' />
</method>
</class>
</package>
</api>";

var gens = ParseApiDefinition (xml);
var klass = gens.Single (g => g.Name == "ListView");
var actual = GetGeneratedTypeOutput (klass);

// Neither the getter nor the setter should have [UnsupportedOSPlatform] because the base property (getter) isn't removed
StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual, "Should not contain UnsupportedOSPlatform on property setter when base has getter only!");
}

[Test]
public void UnsupportedOSPlatformIgnoresStandaloneSetterMethodWhenBaseHasGetterOnly ()
{
// Given:
// public class AdapterView {
// public Object getAdapter () { ... }
// }
// public class ListView : AdapterView {
// // no getAdapter override
// public void setAdapter (Object value) { ... } // removed-since = 15
// }
// We should not write [UnsupportedOSPlatform] on ListView.SetAdapter because the base property (via getter) isn't "removed".
// The setAdapter remains a standalone method because there's no getAdapter to pair with in the derived class.
var xml = @$"<api>
<package name='java.lang' jni-name='java/lang'>
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
</package>
<package name='android.widget' jni-name='android/widget'>
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' final='false' name='AdapterView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='java.lang.Object' static='false' synchronized='false' synthetic='false' visibility='public' />
</class>
<class abstract='false' deprecated='not deprecated' extends='android.widget.AdapterView' extends-generic-aware='android.widget.AdapterView' final='false' name='ListView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='setAdapter' bridge='false' native='false' return='void' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15'>
<parameter name='value' type='java.lang.Object' />
</method>
</class>
</package>
</api>";

var gens = ParseApiDefinition (xml);
var klass = gens.Single (g => g.Name == "ListView");
var actual = GetGeneratedTypeOutput (klass);

// The standalone setter method should not have [UnsupportedOSPlatform] because the base property (getter) isn't removed
StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual, "Should not contain UnsupportedOSPlatform on standalone setter method when base has getter only!");
}

[Test]
public void UnsupportedOSPlatformIgnoresPropertySetterOverridesWhenBaseHasCovariantReturn ()
{
// Given:
// public class AdapterView {
// public Object getAdapter () { ... } // returns Object (generic erasure)
// }
// public class ListView : AdapterView {
// public ListAdapter getAdapter () { ... } // returns ListAdapter (covariant), removed-since = 15
// public void setAdapter (ListAdapter) { ... } // removed-since = 15
// }
// We should not write [UnsupportedOSPlatform] on ListView.Adapter.set because the base property (via getter) isn't "removed",
// even though the return types differ (covariant return).
var xml = @$"<api>
<package name='java.lang' jni-name='java/lang'>
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
</package>
<package name='android.widget' jni-name='android/widget'>
<interface abstract='true' deprecated='not deprecated' final='false' name='ListAdapter' static='false' visibility='public' jni-signature='Landroid/widget/ListAdapter;' />
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' final='false' name='AdapterView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='java.lang.Object' static='false' synchronized='false' synthetic='false' visibility='public' />
</class>
<class abstract='false' deprecated='not deprecated' extends='android.widget.AdapterView' extends-generic-aware='android.widget.AdapterView' final='false' name='ListView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='android.widget.ListAdapter' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15' />
<method abstract='false' deprecated='not deprecated' final='false' name='setAdapter' bridge='false' native='false' return='void' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15'>
<parameter name='value' type='android.widget.ListAdapter' />
</method>
</class>
</package>
</api>";

var gens = ParseApiDefinition (xml);
var klass = gens.Single (g => g.Name == "ListView");
var actual = GetGeneratedTypeOutput (klass);

// Neither the getter nor the setter should have [UnsupportedOSPlatform] because the base property (getter) isn't removed,
// even though the return types differ (covariant return).
StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual, "Should not contain UnsupportedOSPlatform on property setter when base has covariant getter only!");
}

[Test]
public void UnsupportedOSPlatformIgnoresPropertySetterWhenBaseHasDifferentPropertyName ()
{
// Given:
// public class AdapterView {
// public Object getAdapter () { ... } // becomes RawAdapter property (type Object)
// public void setAdapter (Object value) { ... }
// }
// public class ListView : AdapterView {
// public ListAdapter getAdapter () { ... } // becomes Adapter property (type ListAdapter), removed-since = 15
// public void setAdapter (ListAdapter) { ... } // removed-since = 15
// }
// Due to type refinement, AdapterView has 'RawAdapter' property and ListView has 'Adapter' property (different C# names).
// We should not write [UnsupportedOSPlatform] on ListView.Adapter.set because the base property (via Java setAdapter) isn't "removed".
var xml = @$"<api>
<package name='java.lang' jni-name='java/lang'>
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
</package>
<package name='android.widget' jni-name='android/widget'>
<interface abstract='true' deprecated='not deprecated' final='false' name='ListAdapter' static='false' visibility='public' jni-signature='Landroid/widget/ListAdapter;' />
<class abstract='false' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' final='false' name='AdapterView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='java.lang.Object' static='false' synchronized='false' synthetic='false' visibility='public' managedName='GetRawAdapter' propertyName='RawAdapter' />
<method abstract='false' deprecated='not deprecated' final='false' name='setAdapter' bridge='false' native='false' return='void' static='false' synchronized='false' synthetic='false' visibility='public' managedName='SetRawAdapter' propertyName='RawAdapter'>
<parameter name='value' type='java.lang.Object' />
</method>
</class>
<class abstract='false' deprecated='not deprecated' extends='android.widget.AdapterView' extends-generic-aware='android.widget.AdapterView' final='false' name='ListView' static='false' visibility='public'>
<method abstract='false' deprecated='not deprecated' final='false' name='getAdapter' bridge='false' native='false' return='android.widget.ListAdapter' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15' />
<method abstract='false' deprecated='not deprecated' final='false' name='setAdapter' bridge='false' native='false' return='void' static='false' synchronized='false' synthetic='false' visibility='public' removed-since='15'>
<parameter name='value' type='android.widget.ListAdapter' />
</method>
</class>
</package>
</api>";

var gens = ParseApiDefinition (xml);
var klass = gens.Single (g => g.Name == "ListView");
var actual = GetGeneratedTypeOutput (klass);

// Neither the getter nor the setter should have [UnsupportedOSPlatform] because the base property setter (Java setAdapter) isn't removed,
// even though they have different C# property names (RawAdapter vs Adapter).
StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android15.0\")]", actual, "Should not contain UnsupportedOSPlatform on property setter when base has different property name but same Java setter!");
}

[Test]
public void StringPropertyOverride ([Values ("true", "false")] string final)
{
Expand Down
Loading