2016-05-05 03:14:32 +03:00
using System ;
using System.IO ;
using System.Collections.Generic ;
using System.Reflection ;
using NUnit.Framework ;
using Foundation ;
using ObjCRuntime ;
namespace Introspection {
[Preserve (AllMembers = true)]
public abstract class ApiWeakPropertyTest : ApiBaseTest {
/// <summary>
/// Override if you want to skip testing the specified type.
/// </summary>
/// <param name="type">Type to be tested</param>
protected virtual bool Skip ( Type type )
{
switch ( type . Name ) {
2022-06-27 17:01:29 +03:00
case "LinkWithAttribute" : // LinkWithAttribute.WeakFrameworks
return true ;
// Xcode 14, this properties have been added as a compat layer
case "GKPeerPickerController" :
2016-05-05 03:14:32 +03:00
return true ;
}
2020-03-02 17:20:29 +03:00
return SkipDueToRejectedTypes ( type ) ;
2016-05-05 03:14:32 +03:00
}
/// <summary>
/// Override if you want to skip testing the specified property.
/// </summary>
/// <param name="property">Property candidate.</param>
protected virtual bool Skip ( PropertyInfo property )
{
2016-12-02 01:25:30 +03:00
switch ( property . Name ) {
// the selector starts with `weak`
case "WeakRelatedUniqueIdentifier" :
return property . DeclaringType . Name = = "CSSearchableItemAttributeSet" ;
2017-11-22 04:50:33 +03:00
// this is a weakly typed API (not a weak reference) with a [NotImplemented] so there's no [Export]
case "WeakSignificantEvent" :
return property . DeclaringType . Name = = "HMSignificantTimeEvent" ;
2023-03-15 12:47:11 +03:00
case "WeakMeasurementUnits" :
// this is a weakly typed API (not a weak reference), so there's no [Export]
return property . DeclaringType . Name = = "NSRulerView" ;
2023-11-21 09:59:13 +03:00
#if ! XAMCORE_5_0
case "WeakEnabled" :
// this is from a strongly typed dictionary, and "Weak" here means nullable (bool) as opposed to a plain bool - and this is fixed in XAMCORE_5_0 so that the Enabled property is nullable and thus we won't need the WeakEnabled version anymore.
return property . DeclaringType . Name = = "CTFontDescriptorAttributes" ;
#endif
2016-12-02 01:25:30 +03:00
}
2016-05-05 03:14:32 +03:00
return false ;
}
[Test]
public void WeakPropertiesHaveArgumentSemantic ( )
{
var failed_properties = new List < string > ( ) ;
Errors = 0 ;
int c = 0 , n = 0 ;
foreach ( Type t in Assembly . GetTypes ( ) ) {
if ( Skip ( t ) | | SkipDueToAttribute ( t ) )
continue ;
if ( LogProgress )
Console . WriteLine ( "{0}. {1}" , c + + , t . FullName ) ;
foreach ( var p in t . GetProperties ( BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic ) ) {
// looking for properties with setters only
if ( ! p . CanWrite )
continue ;
if ( SkipDueToAttribute ( p ) )
continue ;
if ( Skip ( p ) )
continue ;
string name = p . Name ;
2016-12-02 01:25:30 +03:00
if ( ! name . StartsWith ( "Weak" , StringComparison . Ordinal ) )
2016-05-05 03:14:32 +03:00
continue ;
string error ;
if ( CheckArgumentSemantic ( p . GetMethod , out error ) ) {
ReportError ( error ) ;
failed_properties . Add ( p . ToString ( ) ) ;
}
if ( CheckArgumentSemantic ( p . SetMethod , out error ) ) {
ReportError ( error ) ;
failed_properties . Add ( p . ToString ( ) ) ;
}
n + + ;
}
}
Assert . AreEqual ( 0 , Errors , "{0} errors found in {1} fields validated: {2}" , Errors , n , string . Join ( ", " , failed_properties ) ) ;
}
bool CheckArgumentSemantic ( MethodInfo meth , out string error )
{
error = null ;
var export = meth . GetCustomAttribute < ExportAttribute > ( ) ;
2023-05-05 18:52:19 +03:00
if ( export is null ) {
2016-05-05 03:14:32 +03:00
error = String . Format ( "{0}.{1} has no [Export]" , meth . DeclaringType . FullName , meth . Name ) ;
return true ;
}
switch ( export . ArgumentSemantic ) {
case ArgumentSemantic . Assign : // Also case ArgumentSemantic.UnsafeUnretained:
case ArgumentSemantic . Copy :
case ArgumentSemantic . Retain : // case ArgumentSemantic.Strong:
case ArgumentSemantic . Weak :
return false ;
default :
error = String . Format ( "{0}.{1} has incorrect ArgumentSemantics: {2}" , meth . DeclaringType . FullName , meth . Name , export . ArgumentSemantic ) ;
return true ;
}
}
}
2021-08-11 11:06:46 +03:00
}