[registrar] Make the generated static registrar code implement protocols from [Adopts] attributes.
Make the generated static registrar code implement protocols from [Adopts] attributes, so that we can just query the ObjC runtime to see if a type implements a protocol instead of keeping this information around ourselves.
This commit is contained in:
Родитель
0fa2aa0fb5
Коммит
14daaad78e
|
@ -378,6 +378,11 @@ namespace Registrar {
|
||||||
return attr == null ? null : attr.WrapperType;
|
return attr == null ? null : attr.WrapperType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override IList<AdoptsAttribute> GetAdoptsAttributes (Type type)
|
||||||
|
{
|
||||||
|
return (AdoptsAttribute[]) type.GetCustomAttributes (typeof (AdoptsAttribute), false);
|
||||||
|
}
|
||||||
|
|
||||||
protected override string GetAssemblyName (Assembly assembly)
|
protected override string GetAssemblyName (Assembly assembly)
|
||||||
{
|
{
|
||||||
return assembly.GetName ().Name;
|
return assembly.GetName ().Name;
|
||||||
|
|
|
@ -135,6 +135,7 @@ namespace Registrar {
|
||||||
public TType Type;
|
public TType Type;
|
||||||
public ObjCType BaseType;
|
public ObjCType BaseType;
|
||||||
public ObjCType [] Protocols;
|
public ObjCType [] Protocols;
|
||||||
|
public string [] AdoptedProtocols;
|
||||||
public bool IsModel;
|
public bool IsModel;
|
||||||
// if this type represents an ObjC protocol (!= has the protocol attribute, since that can be applied to all kinds of things).
|
// if this type represents an ObjC protocol (!= has the protocol attribute, since that can be applied to all kinds of things).
|
||||||
public bool IsProtocol;
|
public bool IsProtocol;
|
||||||
|
@ -1028,6 +1029,7 @@ namespace Registrar {
|
||||||
protected abstract TType GetProtocolAttributeWrapperType (TType type); // Return null if no attribute is found. Do not consider base types.
|
protected abstract TType GetProtocolAttributeWrapperType (TType type); // Return null if no attribute is found. Do not consider base types.
|
||||||
protected abstract BindAsAttribute GetBindAsAttribute (TMethod method, int parameter_index); // If parameter_index = -1 then get the attribute for the return type. Return null if no attribute is found. Must consider base method.
|
protected abstract BindAsAttribute GetBindAsAttribute (TMethod method, int parameter_index); // If parameter_index = -1 then get the attribute for the return type. Return null if no attribute is found. Must consider base method.
|
||||||
protected abstract BindAsAttribute GetBindAsAttribute (TProperty property);
|
protected abstract BindAsAttribute GetBindAsAttribute (TProperty property);
|
||||||
|
protected abstract IList<AdoptsAttribute> GetAdoptsAttributes (TType type);
|
||||||
public abstract TType GetNullableType (TType type); // For T? returns T. For T returns null.
|
public abstract TType GetNullableType (TType type); // For T? returns T. For T returns null.
|
||||||
protected abstract bool HasReleaseAttribute (TMethod method); // Returns true of the method's return type/value has a [Release] attribute.
|
protected abstract bool HasReleaseAttribute (TMethod method); // Returns true of the method's return type/value has a [Release] attribute.
|
||||||
protected abstract bool IsINativeObject (TType type);
|
protected abstract bool IsINativeObject (TType type);
|
||||||
|
@ -1640,6 +1642,17 @@ namespace Registrar {
|
||||||
return protocolList.ToArray ();
|
return protocolList.ToArray ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string [] GetAdoptedProtocols (ObjCType type)
|
||||||
|
{
|
||||||
|
var attribs = GetAdoptsAttributes (type.Type);
|
||||||
|
if (attribs == null || attribs.Count == 0)
|
||||||
|
return null;
|
||||||
|
var rv = new string [attribs.Count];
|
||||||
|
for (var i = 0; i < attribs.Count; i++)
|
||||||
|
rv [i] = attribs [i].ProtocolType;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
ObjCType RegisterCategory (TType type, CategoryAttribute attrib, ref List<Exception> exceptions)
|
ObjCType RegisterCategory (TType type, CategoryAttribute attrib, ref List<Exception> exceptions)
|
||||||
{
|
{
|
||||||
if (IsINativeObject (type)) {
|
if (IsINativeObject (type)) {
|
||||||
|
@ -1823,6 +1836,7 @@ namespace Registrar {
|
||||||
};
|
};
|
||||||
objcType.VerifyRegisterAttribute (ref exceptions);
|
objcType.VerifyRegisterAttribute (ref exceptions);
|
||||||
objcType.Protocols = GetProtocols (objcType, ref exceptions);
|
objcType.Protocols = GetProtocols (objcType, ref exceptions);
|
||||||
|
objcType.AdoptedProtocols = GetAdoptedProtocols (objcType);
|
||||||
objcType.BaseType = isProtocol ? null : (baseObjCType ?? objcType);
|
objcType.BaseType = isProtocol ? null : (baseObjCType ?? objcType);
|
||||||
objcType.IsWrapper = (isProtocol && !isInformalProtocol) ? (GetProtocolAttributeWrapperType (objcType.Type) != null) : (objcType.RegisterAttribute != null && objcType.RegisterAttribute.IsWrapper);
|
objcType.IsWrapper = (isProtocol && !isInformalProtocol) ? (GetProtocolAttributeWrapperType (objcType.Type) != null) : (objcType.RegisterAttribute != null && objcType.RegisterAttribute.IsWrapper);
|
||||||
|
|
||||||
|
|
|
@ -1602,6 +1602,28 @@ namespace Registrar {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override IList<AdoptsAttribute> GetAdoptsAttributes (TypeReference type)
|
||||||
|
{
|
||||||
|
var attributes = GetCustomAttributes (type.Resolve (), ObjCRuntime, "AdoptsAttribute");
|
||||||
|
if (attributes == null || !attributes.Any ())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var rv = new List<AdoptsAttribute> ();
|
||||||
|
foreach (var ca in attributes) {
|
||||||
|
var attrib = new AdoptsAttribute ();
|
||||||
|
switch (ca.ConstructorArguments.Count) {
|
||||||
|
case 1:
|
||||||
|
attrib.ProtocolType = (string) ca.ConstructorArguments [0].Value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw ErrorHelper.CreateError (4124, "Invalid AdoptsAttribute found on '{0}': expected 1 constructor arguments, got {1}. Please file a bug report at https://bugzilla.xamarin.com", type.FullName, 1, ca.ConstructorArguments.Count);
|
||||||
|
}
|
||||||
|
rv.Add (attrib);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
protected override BindAsAttribute GetBindAsAttribute (PropertyDefinition property)
|
protected override BindAsAttribute GetBindAsAttribute (PropertyDefinition property)
|
||||||
{
|
{
|
||||||
if (property == null)
|
if (property == null)
|
||||||
|
@ -2652,6 +2674,15 @@ namespace Registrar {
|
||||||
CheckNamespace (tp.Protocols [p], exceptions);
|
CheckNamespace (tp.Protocols [p], exceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (App.Optimizations.RegisterProtocols == true && tp.AdoptedProtocols != null) {
|
||||||
|
for (int p = 0; p < tp.AdoptedProtocols.Length; p++) {
|
||||||
|
if (tp.AdoptedProtocols [p] == "UIAppearance")
|
||||||
|
continue; // This is not a real protocol
|
||||||
|
iface.Append (any_protocols ? ", " : "<");
|
||||||
|
any_protocols = true;
|
||||||
|
iface.Append (tp.AdoptedProtocols [p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
tp = tp.BaseType;
|
tp = tp.BaseType;
|
||||||
}
|
}
|
||||||
if (any_protocols)
|
if (any_protocols)
|
||||||
|
@ -4497,4 +4528,9 @@ namespace Registrar {
|
||||||
public bool IsWrapper { get; set; }
|
public bool IsWrapper { get; set; }
|
||||||
public bool SkipRegistration { get; set; }
|
public bool SkipRegistration { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AdoptsAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string ProtocolType { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче