[Generator] Move MemberInformation out of the generator and enable nullability. (#17448)
This commit is contained in:
Родитель
6bd26fad0a
Коммит
ab61de421f
|
@ -54,211 +54,6 @@ using ObjCRuntime;
|
||||||
using Foundation;
|
using Foundation;
|
||||||
using Xamarin.Utils;
|
using Xamarin.Utils;
|
||||||
|
|
||||||
|
|
||||||
public class MemberInformation {
|
|
||||||
Generator Generator;
|
|
||||||
AttributeManager AttributeManager { get { return Generator.AttributeManager; } }
|
|
||||||
public readonly MemberInfo mi;
|
|
||||||
public readonly Type type;
|
|
||||||
public readonly Type category_extension_type;
|
|
||||||
internal readonly WrapPropMemberInformation wpmi;
|
|
||||||
public readonly bool is_abstract, is_protected, is_internal, is_unified_internal, is_override, is_new, is_sealed, is_static, is_thread_static, is_autorelease, is_wrapper, is_forced;
|
|
||||||
public readonly bool ignore_category_static_warnings, is_basewrapper_protocol_method;
|
|
||||||
public readonly bool has_inner_wrap_attribute;
|
|
||||||
public readonly Generator.ThreadCheck threadCheck;
|
|
||||||
public bool is_unsafe, is_virtual_method, is_export, is_category_extension, is_variadic, is_interface_impl, is_extension_method, is_appearance, is_model, is_ctor;
|
|
||||||
public bool is_return_release;
|
|
||||||
public bool is_type_sealed;
|
|
||||||
public bool protocolize;
|
|
||||||
public string selector, wrap_method, is_forced_owns;
|
|
||||||
public bool is_bindAs => Generator.HasBindAsAttribute (mi);
|
|
||||||
|
|
||||||
public MethodInfo method { get { return (MethodInfo) mi; } }
|
|
||||||
public PropertyInfo property { get { return (PropertyInfo) mi; } }
|
|
||||||
|
|
||||||
MemberInformation (Generator generator, IMemberGatherer gather, MemberInfo mi, Type type, bool is_interface_impl, bool is_extension_method, bool is_appearance, bool is_model)
|
|
||||||
{
|
|
||||||
Generator = generator;
|
|
||||||
var method = mi as MethodInfo;
|
|
||||||
|
|
||||||
is_ctor = mi is MethodInfo && mi.Name == "Constructor";
|
|
||||||
is_abstract = AttributeManager.HasAttribute<AbstractAttribute> (mi) && mi.DeclaringType == type;
|
|
||||||
is_protected = AttributeManager.HasAttribute<ProtectedAttribute> (mi);
|
|
||||||
is_internal = mi.IsInternal (generator);
|
|
||||||
is_unified_internal = AttributeManager.HasAttribute<UnifiedInternalAttribute> (mi);
|
|
||||||
is_override = AttributeManager.HasAttribute<OverrideAttribute> (mi) || !Generator.MemberBelongsToType (mi.DeclaringType, type);
|
|
||||||
is_new = AttributeManager.HasAttribute<NewAttribute> (mi);
|
|
||||||
is_sealed = AttributeManager.HasAttribute<SealedAttribute> (mi);
|
|
||||||
is_static = AttributeManager.HasAttribute<StaticAttribute> (mi);
|
|
||||||
is_thread_static = AttributeManager.HasAttribute<IsThreadStaticAttribute> (mi);
|
|
||||||
is_autorelease = AttributeManager.HasAttribute<AutoreleaseAttribute> (mi);
|
|
||||||
is_wrapper = !AttributeManager.HasAttribute<SyntheticAttribute> (mi.DeclaringType);
|
|
||||||
is_type_sealed = AttributeManager.HasAttribute<SealedAttribute> (mi.DeclaringType);
|
|
||||||
is_return_release = method != null && AttributeManager.HasAttribute<ReleaseAttribute> (AttributeManager.GetReturnTypeCustomAttributes (method));
|
|
||||||
is_forced = Generator.HasForcedAttribute (mi, out is_forced_owns);
|
|
||||||
|
|
||||||
var tsa = AttributeManager.GetCustomAttribute<ThreadSafeAttribute> (mi);
|
|
||||||
// if there's an attribute then it overrides the parent (e.g. type attribute) or namespace default
|
|
||||||
if (tsa != null) {
|
|
||||||
threadCheck = tsa.Safe ? Generator.ThreadCheck.Off : Generator.ThreadCheck.On;
|
|
||||||
} else {
|
|
||||||
threadCheck = Generator.ThreadCheck.Default; // will be based on the type decision
|
|
||||||
}
|
|
||||||
this.is_interface_impl = is_interface_impl;
|
|
||||||
this.is_extension_method = is_extension_method;
|
|
||||||
this.type = type;
|
|
||||||
this.is_appearance = is_appearance;
|
|
||||||
this.is_model = is_model;
|
|
||||||
this.mi = mi;
|
|
||||||
|
|
||||||
if (is_interface_impl || is_extension_method || is_type_sealed) {
|
|
||||||
is_abstract = false;
|
|
||||||
is_virtual_method = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// To avoid a warning, we should determine whether we should insert a "new" in the
|
|
||||||
// declaration. If this is an inlined method, then we need to see if this was
|
|
||||||
// also inlined in any of the base classes.
|
|
||||||
if (mi.DeclaringType != type) {
|
|
||||||
for (var baseType = ReflectionExtensions.GetBaseType (type, generator); baseType != null && baseType != Generator.TypeManager.System_Object; baseType = ReflectionExtensions.GetBaseType (baseType, generator)) {
|
|
||||||
foreach (var baseMethod in gather.GetTypeContractMethods (baseType)) {
|
|
||||||
if (baseMethod.DeclaringType != baseType && baseMethod == mi) {
|
|
||||||
// We found a case, we need to flag it as new.
|
|
||||||
is_new = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemberInformation (Generator generator, IMemberGatherer gather, MethodInfo mi, Type type, Type category_extension_type, bool is_interface_impl = false, bool is_extension_method = false, bool is_appearance = false, bool is_model = false, string selector = null, bool isBaseWrapperProtocolMethod = false)
|
|
||||||
: this (generator, gather, (MemberInfo) mi, type, is_interface_impl, is_extension_method, is_appearance, is_model)
|
|
||||||
{
|
|
||||||
is_basewrapper_protocol_method = isBaseWrapperProtocolMethod;
|
|
||||||
foreach (ParameterInfo pi in mi.GetParameters ())
|
|
||||||
if (pi.ParameterType.IsSubclassOf (Generator.TypeManager.System_Delegate))
|
|
||||||
is_unsafe = true;
|
|
||||||
|
|
||||||
if (!is_unsafe && mi.ReturnType.IsSubclassOf (Generator.TypeManager.System_Delegate))
|
|
||||||
is_unsafe = true;
|
|
||||||
|
|
||||||
if (selector != null) {
|
|
||||||
this.selector = selector;
|
|
||||||
if (!is_sealed && !is_wrapper) {
|
|
||||||
is_export = !is_extension_method;
|
|
||||||
is_virtual_method = !is_ctor;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
object [] attr = AttributeManager.GetCustomAttributes<ExportAttribute> (mi);
|
|
||||||
if (attr.Length != 1) {
|
|
||||||
attr = AttributeManager.GetCustomAttributes<BindAttribute> (mi);
|
|
||||||
if (attr.Length != 1) {
|
|
||||||
attr = AttributeManager.GetCustomAttributes<WrapAttribute> (mi);
|
|
||||||
if (attr.Length != 1)
|
|
||||||
throw new BindingException (1012, true, type, mi.Name);
|
|
||||||
|
|
||||||
var wrapAtt = (WrapAttribute) attr [0];
|
|
||||||
wrap_method = wrapAtt.MethodName;
|
|
||||||
is_virtual_method = wrapAtt.IsVirtual;
|
|
||||||
} else {
|
|
||||||
BindAttribute ba = (BindAttribute) attr [0];
|
|
||||||
this.selector = ba.Selector;
|
|
||||||
is_virtual_method = ba.Virtual;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ExportAttribute ea = (ExportAttribute) attr [0];
|
|
||||||
this.selector = ea.Selector;
|
|
||||||
is_variadic = ea.IsVariadic;
|
|
||||||
|
|
||||||
if (!is_sealed || !is_wrapper) {
|
|
||||||
is_virtual_method = !is_ctor;
|
|
||||||
is_export = !is_extension_method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.category_extension_type = category_extension_type;
|
|
||||||
if (category_extension_type != null) {
|
|
||||||
is_category_extension = true;
|
|
||||||
#if NET
|
|
||||||
ignore_category_static_warnings = is_internal || type.IsInternal (generator);
|
|
||||||
#else
|
|
||||||
ignore_category_static_warnings = is_internal || type.IsInternal (generator) || Generator.AttributeManager.GetCustomAttribute<CategoryAttribute> (type).AllowStaticMembers;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_static || is_category_extension || is_interface_impl || is_extension_method || is_type_sealed)
|
|
||||||
is_virtual_method = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemberInformation (Generator generator, IMemberGatherer gather, PropertyInfo pi, Type type, bool is_interface_impl = false)
|
|
||||||
: this (generator, gather, (MemberInfo) pi, type, is_interface_impl, false, false, false)
|
|
||||||
{
|
|
||||||
if (pi.PropertyType.IsSubclassOf (Generator.TypeManager.System_Delegate))
|
|
||||||
is_unsafe = true;
|
|
||||||
|
|
||||||
var export = Generator.GetExportAttribute (pi, out wrap_method);
|
|
||||||
if (export != null)
|
|
||||||
selector = export.Selector;
|
|
||||||
|
|
||||||
if (wrap_method != null) {
|
|
||||||
var wrapAtt = Generator.AttributeManager.GetCustomAttribute<WrapAttribute> (pi);
|
|
||||||
is_virtual_method = wrapAtt?.IsVirtual ?? false;
|
|
||||||
} else if (is_interface_impl || is_type_sealed)
|
|
||||||
is_virtual_method = false;
|
|
||||||
else
|
|
||||||
is_virtual_method = !is_static;
|
|
||||||
|
|
||||||
// Properties can have WrapAttribute on getter/setter so we need to check for this
|
|
||||||
// but only if no Export is already found on property level.
|
|
||||||
if (export is null) {
|
|
||||||
wpmi = new WrapPropMemberInformation (pi, generator);
|
|
||||||
has_inner_wrap_attribute = wpmi.HasWrapOnGetter || wpmi.HasWrapOnSetter;
|
|
||||||
|
|
||||||
// Wrap can only be used either at property level or getter/setter level at a given time.
|
|
||||||
if (wrap_method != null && has_inner_wrap_attribute)
|
|
||||||
throw new BindingException (1063, true, pi.DeclaringType, pi.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetVisibility ()
|
|
||||||
{
|
|
||||||
if (is_interface_impl || is_extension_method)
|
|
||||||
return "public";
|
|
||||||
|
|
||||||
var mod = is_protected ? "protected" : null;
|
|
||||||
mod += is_internal ? "internal" : null;
|
|
||||||
if (string.IsNullOrEmpty (mod))
|
|
||||||
mod = "public";
|
|
||||||
return mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetModifiers ()
|
|
||||||
{
|
|
||||||
string mods = "";
|
|
||||||
|
|
||||||
mods += is_unsafe ? "unsafe " : null;
|
|
||||||
mods += is_new ? "new " : "";
|
|
||||||
|
|
||||||
if (is_sealed) {
|
|
||||||
mods += "";
|
|
||||||
} else if (is_static || is_category_extension || is_extension_method) {
|
|
||||||
mods += "static ";
|
|
||||||
} else if (is_abstract) {
|
|
||||||
#if NET
|
|
||||||
mods += "virtual ";
|
|
||||||
#else
|
|
||||||
mods += "abstract ";
|
|
||||||
#endif
|
|
||||||
} else if (is_virtual_method && !is_type_sealed) {
|
|
||||||
mods += is_override ? "override " : "virtual ";
|
|
||||||
}
|
|
||||||
|
|
||||||
return mods;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class Frameworks {
|
public partial class Frameworks {
|
||||||
HashSet<string> frameworks;
|
HashSet<string> frameworks;
|
||||||
readonly PlatformName CurrentPlatform;
|
readonly PlatformName CurrentPlatform;
|
||||||
|
@ -3490,7 +3285,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
//
|
//
|
||||||
public string MakeSignature (MemberInformation minfo)
|
public string MakeSignature (MemberInformation minfo)
|
||||||
{
|
{
|
||||||
return MakeSignature (minfo, false, minfo.method.GetParameters ());
|
return MakeSignature (minfo, false, minfo.Method.GetParameters ());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -3498,7 +3293,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
//
|
//
|
||||||
public string MakeSignature (MemberInformation minfo, bool alreadyPreserved)
|
public string MakeSignature (MemberInformation minfo, bool alreadyPreserved)
|
||||||
{
|
{
|
||||||
return MakeSignature (minfo, false, minfo.method.GetParameters (), "", alreadyPreserved);
|
return MakeSignature (minfo, false, minfo.Method.GetParameters (), "", alreadyPreserved);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetAsyncName (MethodInfo mi)
|
public string GetAsyncName (MethodInfo mi)
|
||||||
|
@ -3531,7 +3326,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
public string MakeSignature (MemberInformation minfo, bool is_async, ParameterInfo [] parameters, string extra = "", bool alreadyPreserved = false)
|
public string MakeSignature (MemberInformation minfo, bool is_async, ParameterInfo [] parameters, string extra = "", bool alreadyPreserved = false)
|
||||||
{
|
{
|
||||||
var mi = minfo.method;
|
var mi = minfo.Method;
|
||||||
var category_class = minfo.category_extension_type;
|
var category_class = minfo.category_extension_type;
|
||||||
StringBuilder sb = new StringBuilder ();
|
StringBuilder sb = new StringBuilder ();
|
||||||
string name = minfo.is_ctor ? GetGeneratedTypeName (mi.DeclaringType) : is_async ? GetAsyncName (mi) : mi.Name;
|
string name = minfo.is_ctor ? GetGeneratedTypeName (mi.DeclaringType) : is_async ? GetAsyncName (mi) : mi.Name;
|
||||||
|
@ -3542,21 +3337,21 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (!minfo.is_ctor && !is_async) {
|
if (!minfo.is_ctor && !is_async) {
|
||||||
var prefix = "";
|
var prefix = "";
|
||||||
if (!BindThirdPartyLibrary) {
|
if (!BindThirdPartyLibrary) {
|
||||||
var hasReturnTypeProtocolize = Protocolize (AttributeManager.GetReturnTypeCustomAttributes (minfo.method));
|
var hasReturnTypeProtocolize = Protocolize (AttributeManager.GetReturnTypeCustomAttributes (minfo.Method));
|
||||||
if (hasReturnTypeProtocolize) {
|
if (hasReturnTypeProtocolize) {
|
||||||
if (!IsProtocol (minfo.method.ReturnType)) {
|
if (!IsProtocol (minfo.Method.ReturnType)) {
|
||||||
ErrorHelper.Warning (1108, minfo.method.DeclaringType, minfo.method, minfo.method.ReturnType.FullName);
|
ErrorHelper.Warning (1108, minfo.Method.DeclaringType, minfo.Method, minfo.Method.ReturnType.FullName);
|
||||||
} else {
|
} else {
|
||||||
prefix = "I";
|
prefix = "I";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (minfo.method.ReturnType.IsArray) {
|
if (minfo.Method.ReturnType.IsArray) {
|
||||||
var et = minfo.method.ReturnType.GetElementType ();
|
var et = minfo.Method.ReturnType.GetElementType ();
|
||||||
if (IsModel (et))
|
if (IsModel (et))
|
||||||
ErrorHelper.Warning (1109, minfo.method.DeclaringType, minfo.method.Name, et, et.Namespace, et.Name);
|
ErrorHelper.Warning (1109, minfo.Method.DeclaringType, minfo.Method.Name, et, et.Namespace, et.Name);
|
||||||
}
|
}
|
||||||
if (IsModel (minfo.method.ReturnType) && !hasReturnTypeProtocolize)
|
if (IsModel (minfo.Method.ReturnType) && !hasReturnTypeProtocolize)
|
||||||
ErrorHelper.Warning (1107, minfo.method.DeclaringType, minfo.method.Name, minfo.method.ReturnType, minfo.method.ReturnType.Namespace, minfo.method.ReturnType.Name);
|
ErrorHelper.Warning (1107, minfo.Method.DeclaringType, minfo.Method.Name, minfo.Method.ReturnType, minfo.Method.ReturnType.Namespace, minfo.Method.ReturnType.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minfo.is_bindAs) {
|
if (minfo.is_bindAs) {
|
||||||
|
@ -3577,7 +3372,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
sb.Append (" ");
|
sb.Append (" ");
|
||||||
}
|
}
|
||||||
// Unified internal methods automatically get a _ appended
|
// Unified internal methods automatically get a _ appended
|
||||||
if (minfo.is_extension_method && minfo.method.IsSpecialName) {
|
if (minfo.is_extension_method && minfo.Method.IsSpecialName) {
|
||||||
if (name.StartsWith ("get_", StringComparison.Ordinal))
|
if (name.StartsWith ("get_", StringComparison.Ordinal))
|
||||||
name = "Get" + name.Substring (4);
|
name = "Get" + name.Substring (4);
|
||||||
else if (name.StartsWith ("set_", StringComparison.Ordinal))
|
else if (name.StartsWith ("set_", StringComparison.Ordinal))
|
||||||
|
@ -5178,7 +4973,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
string extra = "";
|
string extra = "";
|
||||||
|
|
||||||
if (asyncKind == AsyncMethodKind.WithResultOutParameter) {
|
if (asyncKind == AsyncMethodKind.WithResultOutParameter) {
|
||||||
if (minfo.method.GetParameters ().Count () > 1)
|
if (minfo.Method.GetParameters ().Count () > 1)
|
||||||
extra = ", ";
|
extra = ", ";
|
||||||
extra += "out " + FormatType (minfo.MethodInfo.DeclaringType, minfo.MethodInfo.ReturnType) + " " + minfo.GetUniqueParamName ("result");
|
extra += "out " + FormatType (minfo.MethodInfo.DeclaringType, minfo.MethodInfo.ReturnType) + " " + minfo.GetUniqueParamName ("result");
|
||||||
}
|
}
|
||||||
|
@ -5196,7 +4991,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
void GenerateAsyncMethod (MemberInformation original_minfo, AsyncMethodKind asyncKind)
|
void GenerateAsyncMethod (MemberInformation original_minfo, AsyncMethodKind asyncKind)
|
||||||
{
|
{
|
||||||
var mi = original_minfo.method;
|
var mi = original_minfo.Method;
|
||||||
var minfo = new AsyncMethodInfo (this, this, original_minfo.type, mi, original_minfo.category_extension_type, original_minfo.is_extension_method);
|
var minfo = new AsyncMethodInfo (this, this, original_minfo.type, mi, original_minfo.category_extension_type, original_minfo.is_extension_method);
|
||||||
var is_void = mi.ReturnType == TypeManager.System_Void;
|
var is_void = mi.ReturnType == TypeManager.System_Void;
|
||||||
|
|
||||||
|
@ -5289,7 +5084,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
void PrintMethodAttributes (MemberInformation minfo)
|
void PrintMethodAttributes (MemberInformation minfo)
|
||||||
{
|
{
|
||||||
MethodInfo mi = minfo.method;
|
MethodInfo mi = minfo.Method;
|
||||||
var editor_browsable_attribute = false;
|
var editor_browsable_attribute = false;
|
||||||
|
|
||||||
foreach (var sa in AttributeManager.GetCustomAttributes<ThreadSafeAttribute> (mi))
|
foreach (var sa in AttributeManager.GetCustomAttributes<ThreadSafeAttribute> (mi))
|
||||||
|
@ -5310,12 +5105,12 @@ public partial class Generator : IMemberGatherer {
|
||||||
print ("[return: ReleaseAttribute ()]");
|
print ("[return: ReleaseAttribute ()]");
|
||||||
|
|
||||||
// when we inline methods (e.g. from a protocol)
|
// when we inline methods (e.g. from a protocol)
|
||||||
if (minfo.type != minfo.method.DeclaringType) {
|
if (minfo.type != minfo.Method.DeclaringType) {
|
||||||
// we must look if the type has an [Availability] attribute
|
// we must look if the type has an [Availability] attribute
|
||||||
// but we must not duplicate existing attributes for a platform, see https://github.com/xamarin/xamarin-macios/issues/7194
|
// but we must not duplicate existing attributes for a platform, see https://github.com/xamarin/xamarin-macios/issues/7194
|
||||||
PrintPlatformAttributesNoDuplicates (minfo.type, minfo.method);
|
PrintPlatformAttributesNoDuplicates (minfo.type, minfo.Method);
|
||||||
} else {
|
} else {
|
||||||
PrintPlatformAttributes (minfo.method);
|
PrintPlatformAttributes (minfo.Method);
|
||||||
}
|
}
|
||||||
|
|
||||||
// in theory we could check for `minfo.is_ctor` but some manual bindings are using methods for `init*`
|
// in theory we could check for `minfo.is_ctor` but some manual bindings are using methods for `init*`
|
||||||
|
@ -5332,7 +5127,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
void PrintDelegateProxy (MemberInformation minfo)
|
void PrintDelegateProxy (MemberInformation minfo)
|
||||||
{
|
{
|
||||||
PrintDelegateProxy (minfo.method);
|
PrintDelegateProxy (minfo.Method);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintDelegateProxy (MethodInfo mi)
|
void PrintDelegateProxy (MethodInfo mi)
|
||||||
|
@ -5368,7 +5163,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
bool output_semantics = semantic != ArgumentSemantic.None;
|
bool output_semantics = semantic != ArgumentSemantic.None;
|
||||||
// it does not make sense on every properties, depending on the their types
|
// it does not make sense on every properties, depending on the their types
|
||||||
if (output_semantics && (minfo.mi is PropertyInfo)) {
|
if (output_semantics && (minfo.mi is PropertyInfo)) {
|
||||||
var t = minfo.property.PropertyType;
|
var t = minfo.Property.PropertyType;
|
||||||
output_semantics = !t.IsPrimitive || t == TypeManager.System_IntPtr;
|
output_semantics = !t.IsPrimitive || t == TypeManager.System_IntPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5380,7 +5175,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
void GenerateMethod (MemberInformation minfo)
|
void GenerateMethod (MemberInformation minfo)
|
||||||
{
|
{
|
||||||
var mi = minfo.method;
|
var mi = minfo.Method;
|
||||||
|
|
||||||
// skip if we provide a manual implementation that would conflict with the generated code
|
// skip if we provide a manual implementation that would conflict with the generated code
|
||||||
if (AttributeManager.HasAttribute<ManualAttribute> (mi))
|
if (AttributeManager.HasAttribute<ManualAttribute> (mi))
|
||||||
|
@ -5399,9 +5194,9 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (c == ':')
|
if (c == ':')
|
||||||
argCount++;
|
argCount++;
|
||||||
}
|
}
|
||||||
if (minfo.method.GetParameters ().Length != argCount) {
|
if (minfo.Method.GetParameters ().Length != argCount) {
|
||||||
ErrorHelper.Warning (1105,
|
ErrorHelper.Warning (1105,
|
||||||
minfo.selector, argCount, minfo.method, minfo.method.GetParameters ().Length);
|
minfo.selector, argCount, minfo.Method, minfo.Method.GetParameters ().Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5447,7 +5242,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
print ("{");
|
print ("{");
|
||||||
|
|
||||||
var is32BitNotSupported = Is64BitiOSOnly ((ICustomAttributeProvider) minfo.method ?? minfo.property);
|
var is32BitNotSupported = Is64BitiOSOnly ((ICustomAttributeProvider) minfo.Method ?? minfo.Property);
|
||||||
if (is32BitNotSupported) {
|
if (is32BitNotSupported) {
|
||||||
print ("#if ARCH_32");
|
print ("#if ARCH_32");
|
||||||
print ("\tthrow new PlatformNotSupportedException (\"This API is not supported on this version of iOS\");");
|
print ("\tthrow new PlatformNotSupportedException (\"This API is not supported on this version of iOS\");");
|
||||||
|
@ -5472,7 +5267,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
print ("using (var autorelease_pool = new NSAutoreleasePool ()) {");
|
print ("using (var autorelease_pool = new NSAutoreleasePool ()) {");
|
||||||
}
|
}
|
||||||
PropertyInfo pinfo = null;
|
PropertyInfo pinfo = null;
|
||||||
MethodInfo method = minfo.method;
|
MethodInfo method = minfo.Method;
|
||||||
bool null_allowed = false;
|
bool null_allowed = false;
|
||||||
if (method.IsSpecialName) {
|
if (method.IsSpecialName) {
|
||||||
// could be a property setter where [NullAllowed] is _allowed_
|
// could be a property setter where [NullAllowed] is _allowed_
|
||||||
|
@ -5481,7 +5276,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (pinfo != null)
|
if (pinfo != null)
|
||||||
null_allowed = AttributeManager.HasAttribute<NullAllowedAttribute> (pinfo);
|
null_allowed = AttributeManager.HasAttribute<NullAllowedAttribute> (pinfo);
|
||||||
}
|
}
|
||||||
GenerateMethodBody (minfo, minfo.method, minfo.selector, null_allowed, null, BodyOption.None, pinfo);
|
GenerateMethodBody (minfo, minfo.Method, minfo.selector, null_allowed, null, BodyOption.None, pinfo);
|
||||||
if (minfo.is_autorelease) {
|
if (minfo.is_autorelease) {
|
||||||
print ("}");
|
print ("}");
|
||||||
indent--;
|
indent--;
|
||||||
|
@ -5502,7 +5297,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
GenerateAsyncMethod (minfo, AsyncMethodKind.Plain);
|
GenerateAsyncMethod (minfo, AsyncMethodKind.Plain);
|
||||||
|
|
||||||
// Generate the overload with the out parameter
|
// Generate the overload with the out parameter
|
||||||
if (minfo.method.ReturnType != TypeManager.System_Void) {
|
if (minfo.Method.ReturnType != TypeManager.System_Void) {
|
||||||
GenerateAsyncMethod (minfo, AsyncMethodKind.WithResultOutParameter);
|
GenerateAsyncMethod (minfo, AsyncMethodKind.WithResultOutParameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5903,11 +5698,11 @@ public partial class Generator : IMemberGatherer {
|
||||||
|
|
||||||
// Generate Extension Methods of required [Async] decorated methods (we already do optional)
|
// Generate Extension Methods of required [Async] decorated methods (we already do optional)
|
||||||
foreach (var ami in requiredInstanceAsyncMethods) {
|
foreach (var ami in requiredInstanceAsyncMethods) {
|
||||||
var minfo = new MemberInformation (this, this, ami, type, null, is_extension_method: true);
|
var minfo = new MemberInformation (this, this, ami, type, null, isExtensionMethod: true);
|
||||||
GenerateAsyncMethod (minfo, AsyncMethodKind.Plain);
|
GenerateAsyncMethod (minfo, AsyncMethodKind.Plain);
|
||||||
|
|
||||||
// Generate the overload with the out parameter
|
// Generate the overload with the out parameter
|
||||||
if (minfo.method.ReturnType != TypeManager.System_Void)
|
if (minfo.Method.ReturnType != TypeManager.System_Void)
|
||||||
GenerateAsyncMethod (minfo, AsyncMethodKind.WithResultOutParameter);
|
GenerateAsyncMethod (minfo, AsyncMethodKind.WithResultOutParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6752,7 +6547,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
if (appearance_selectors != null && AttributeManager.HasAttribute<AppearanceAttribute> (mi))
|
if (appearance_selectors != null && AttributeManager.HasAttribute<AppearanceAttribute> (mi))
|
||||||
appearance_selectors.Add (mi);
|
appearance_selectors.Add (mi);
|
||||||
|
|
||||||
var minfo = new MemberInformation (this, this, mi, type, is_category_class ? bta.BaseType : null, is_model: is_model);
|
var minfo = new MemberInformation (this, this, mi, type, is_category_class ? bta.BaseType : null, isModel: is_model);
|
||||||
// the type above is not the the we're generating, e.g. it would be `NSCopying` for `Copy(NSZone?)`
|
// the type above is not the the we're generating, e.g. it would be `NSCopying` for `Copy(NSZone?)`
|
||||||
minfo.is_type_sealed = is_sealed;
|
minfo.is_type_sealed = is_sealed;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Foundation;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
public class MemberInformation {
|
||||||
|
Generator Generator;
|
||||||
|
AttributeManager AttributeManager { get { return Generator.AttributeManager; } }
|
||||||
|
public readonly MemberInfo mi;
|
||||||
|
public readonly Type type;
|
||||||
|
public readonly Type? category_extension_type;
|
||||||
|
internal readonly WrapPropMemberInformation? wpmi;
|
||||||
|
public readonly bool is_abstract;
|
||||||
|
public readonly bool is_protected;
|
||||||
|
public readonly bool is_internal;
|
||||||
|
public readonly bool is_unified_internal;
|
||||||
|
public readonly bool is_override;
|
||||||
|
public readonly bool is_new;
|
||||||
|
public readonly bool is_sealed;
|
||||||
|
public readonly bool is_static;
|
||||||
|
public readonly bool is_thread_static;
|
||||||
|
public readonly bool is_autorelease;
|
||||||
|
public readonly bool is_wrapper;
|
||||||
|
public readonly bool is_forced;
|
||||||
|
public readonly bool ignore_category_static_warnings;
|
||||||
|
public readonly bool is_basewrapper_protocol_method;
|
||||||
|
public readonly bool has_inner_wrap_attribute;
|
||||||
|
public readonly Generator.ThreadCheck threadCheck;
|
||||||
|
public bool is_unsafe;
|
||||||
|
public bool is_virtual_method;
|
||||||
|
public bool is_export;
|
||||||
|
public bool is_category_extension;
|
||||||
|
public bool is_variadic;
|
||||||
|
public bool is_interface_impl;
|
||||||
|
public bool is_extension_method;
|
||||||
|
public bool is_appearance;
|
||||||
|
public bool is_model;
|
||||||
|
public bool is_ctor;
|
||||||
|
public bool is_return_release;
|
||||||
|
public bool is_type_sealed;
|
||||||
|
public bool protocolize;
|
||||||
|
public string? selector;
|
||||||
|
public string? wrap_method;
|
||||||
|
public string is_forced_owns;
|
||||||
|
public bool is_bindAs => Generator.HasBindAsAttribute (mi);
|
||||||
|
|
||||||
|
public MethodInfo? Method { get { return mi as MethodInfo; } }
|
||||||
|
public PropertyInfo? Property { get { return mi as PropertyInfo; } }
|
||||||
|
|
||||||
|
MemberInformation (Generator generator, IMemberGatherer gather, MemberInfo mi, Type type, bool is_interface_impl, bool is_extension_method, bool is_appearance, bool is_model)
|
||||||
|
{
|
||||||
|
Generator = generator;
|
||||||
|
var methodInfo = mi as MethodInfo;
|
||||||
|
|
||||||
|
is_ctor = mi is MethodInfo && mi.Name == "Constructor";
|
||||||
|
is_abstract = AttributeManager.HasAttribute<AbstractAttribute> (mi) && mi.DeclaringType == type;
|
||||||
|
is_protected = AttributeManager.HasAttribute<ProtectedAttribute> (mi);
|
||||||
|
is_internal = mi.IsInternal (generator);
|
||||||
|
is_unified_internal = AttributeManager.HasAttribute<UnifiedInternalAttribute> (mi);
|
||||||
|
is_override = AttributeManager.HasAttribute<OverrideAttribute> (mi) || !Generator.MemberBelongsToType (mi.DeclaringType, type);
|
||||||
|
is_new = AttributeManager.HasAttribute<NewAttribute> (mi);
|
||||||
|
is_sealed = AttributeManager.HasAttribute<SealedAttribute> (mi);
|
||||||
|
is_static = AttributeManager.HasAttribute<StaticAttribute> (mi);
|
||||||
|
is_thread_static = AttributeManager.HasAttribute<IsThreadStaticAttribute> (mi);
|
||||||
|
is_autorelease = AttributeManager.HasAttribute<AutoreleaseAttribute> (mi);
|
||||||
|
is_wrapper = !AttributeManager.HasAttribute<SyntheticAttribute> (mi.DeclaringType);
|
||||||
|
is_type_sealed = AttributeManager.HasAttribute<SealedAttribute> (mi.DeclaringType);
|
||||||
|
is_return_release = methodInfo is not null && AttributeManager.HasAttribute<ReleaseAttribute> (AttributeManager.GetReturnTypeCustomAttributes (methodInfo));
|
||||||
|
is_forced = Generator.HasForcedAttribute (mi, out is_forced_owns);
|
||||||
|
|
||||||
|
var tsa = AttributeManager.GetCustomAttribute<ThreadSafeAttribute> (mi);
|
||||||
|
// if there's an attribute then it overrides the parent (e.g. type attribute) or namespace default
|
||||||
|
if (tsa is not null) {
|
||||||
|
threadCheck = tsa.Safe ? Generator.ThreadCheck.Off : Generator.ThreadCheck.On;
|
||||||
|
} else {
|
||||||
|
threadCheck = Generator.ThreadCheck.Default; // will be based on the type decision
|
||||||
|
}
|
||||||
|
this.is_interface_impl = is_interface_impl;
|
||||||
|
this.is_extension_method = is_extension_method;
|
||||||
|
this.type = type;
|
||||||
|
this.is_appearance = is_appearance;
|
||||||
|
this.is_model = is_model;
|
||||||
|
this.mi = mi;
|
||||||
|
|
||||||
|
if (is_interface_impl || is_extension_method || is_type_sealed) {
|
||||||
|
is_abstract = false;
|
||||||
|
is_virtual_method = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To avoid a warning, we should determine whether we should insert a "new" in the
|
||||||
|
// declaration. If this is an inlined method, then we need to see if this was
|
||||||
|
// also inlined in any of the base classes.
|
||||||
|
if (mi.DeclaringType != type) {
|
||||||
|
for (var baseType = ReflectionExtensions.GetBaseType (type, generator); baseType != Generator.TypeManager.System_Object; baseType = ReflectionExtensions.GetBaseType (baseType, generator)) {
|
||||||
|
foreach (var baseMethod in gather.GetTypeContractMethods (baseType)) {
|
||||||
|
if (baseMethod.DeclaringType != baseType && baseMethod == mi) {
|
||||||
|
// We found a case, we need to flag it as new.
|
||||||
|
is_new = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberInformation (Generator generator, IMemberGatherer gather, MethodInfo mi, Type type,
|
||||||
|
Type? categoryExtensionType, bool isInterfaceImpl = false, bool isExtensionMethod = false,
|
||||||
|
bool isAppearance = false, bool isModel = false, string? selector = null,
|
||||||
|
bool isBaseWrapperProtocolMethod = false)
|
||||||
|
: this (generator, gather, mi, type, isInterfaceImpl, isExtensionMethod, isAppearance, isModel)
|
||||||
|
{
|
||||||
|
is_basewrapper_protocol_method = isBaseWrapperProtocolMethod;
|
||||||
|
foreach (ParameterInfo pi in mi.GetParameters ())
|
||||||
|
if (pi.ParameterType.IsSubclassOf (Generator.TypeManager.System_Delegate))
|
||||||
|
is_unsafe = true;
|
||||||
|
|
||||||
|
if (!is_unsafe && mi.ReturnType.IsSubclassOf (Generator.TypeManager.System_Delegate))
|
||||||
|
is_unsafe = true;
|
||||||
|
|
||||||
|
if (selector is not null) {
|
||||||
|
this.selector = selector;
|
||||||
|
if (!is_sealed && !is_wrapper) {
|
||||||
|
is_export = !isExtensionMethod;
|
||||||
|
is_virtual_method = !is_ctor;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
object [] attr = AttributeManager.GetCustomAttributes<ExportAttribute> (mi);
|
||||||
|
if (attr.Length != 1) {
|
||||||
|
attr = AttributeManager.GetCustomAttributes<BindAttribute> (mi);
|
||||||
|
if (attr.Length != 1) {
|
||||||
|
attr = AttributeManager.GetCustomAttributes<WrapAttribute> (mi);
|
||||||
|
if (attr.Length != 1)
|
||||||
|
throw new BindingException (1012, true, type, mi.Name);
|
||||||
|
|
||||||
|
var wrapAtt = (WrapAttribute) attr [0];
|
||||||
|
wrap_method = wrapAtt.MethodName;
|
||||||
|
is_virtual_method = wrapAtt.IsVirtual;
|
||||||
|
} else {
|
||||||
|
BindAttribute ba = (BindAttribute) attr [0];
|
||||||
|
this.selector = ba.Selector;
|
||||||
|
is_virtual_method = ba.Virtual;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ExportAttribute ea = (ExportAttribute) attr [0];
|
||||||
|
this.selector = ea.Selector;
|
||||||
|
is_variadic = ea.IsVariadic;
|
||||||
|
|
||||||
|
if (!is_sealed || !is_wrapper) {
|
||||||
|
is_virtual_method = !is_ctor;
|
||||||
|
is_export = !isExtensionMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.category_extension_type = categoryExtensionType;
|
||||||
|
if (categoryExtensionType is not null) {
|
||||||
|
is_category_extension = true;
|
||||||
|
#if NET
|
||||||
|
ignore_category_static_warnings = is_internal || type.IsInternal (generator);
|
||||||
|
#else
|
||||||
|
ignore_category_static_warnings = is_internal || type.IsInternal (generator) || Generator.AttributeManager.GetCustomAttribute<CategoryAttribute> (type).AllowStaticMembers;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_static || is_category_extension || isInterfaceImpl || isExtensionMethod || is_type_sealed)
|
||||||
|
is_virtual_method = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberInformation (Generator generator, IMemberGatherer gather, PropertyInfo pi, Type type, bool is_interface_impl = false)
|
||||||
|
: this (generator, gather, pi, type, is_interface_impl, false, false, false)
|
||||||
|
{
|
||||||
|
if (pi.PropertyType.IsSubclassOf (Generator.TypeManager.System_Delegate))
|
||||||
|
is_unsafe = true;
|
||||||
|
|
||||||
|
var export = Generator.GetExportAttribute (pi, out wrap_method);
|
||||||
|
if (export is not null)
|
||||||
|
selector = export.Selector;
|
||||||
|
|
||||||
|
if (wrap_method is not null) {
|
||||||
|
var wrapAtt = Generator.AttributeManager.GetCustomAttribute<WrapAttribute> (pi);
|
||||||
|
is_virtual_method = wrapAtt?.IsVirtual ?? false;
|
||||||
|
} else if (is_interface_impl || is_type_sealed)
|
||||||
|
is_virtual_method = false;
|
||||||
|
else
|
||||||
|
is_virtual_method = !is_static;
|
||||||
|
|
||||||
|
// Properties can have WrapAttribute on getter/setter so we need to check for this
|
||||||
|
// but only if no Export is already found on property level.
|
||||||
|
if (export is null) {
|
||||||
|
wpmi = new WrapPropMemberInformation (pi, generator);
|
||||||
|
has_inner_wrap_attribute = wpmi.HasWrapOnGetter || wpmi.HasWrapOnSetter;
|
||||||
|
|
||||||
|
// Wrap can only be used either at property level or getter/setter level at a given time.
|
||||||
|
if (wrap_method is not null && has_inner_wrap_attribute)
|
||||||
|
throw new BindingException (1063, true, pi.DeclaringType, pi.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetVisibility ()
|
||||||
|
{
|
||||||
|
if (is_interface_impl || is_extension_method)
|
||||||
|
return "public";
|
||||||
|
|
||||||
|
var mod = is_protected ? "protected" : null;
|
||||||
|
mod += is_internal ? "internal" : null;
|
||||||
|
if (string.IsNullOrEmpty (mod))
|
||||||
|
mod = "public";
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetModifiers ()
|
||||||
|
{
|
||||||
|
string mods = "";
|
||||||
|
|
||||||
|
mods += is_unsafe ? "unsafe " : null;
|
||||||
|
mods += is_new ? "new " : "";
|
||||||
|
|
||||||
|
if (is_sealed) {
|
||||||
|
mods += "";
|
||||||
|
} else if (is_static || is_category_extension || is_extension_method) {
|
||||||
|
mods += "static ";
|
||||||
|
} else if (is_abstract) {
|
||||||
|
#if NET
|
||||||
|
mods += "virtual ";
|
||||||
|
#else
|
||||||
|
mods += "abstract ";
|
||||||
|
#endif
|
||||||
|
} else if (is_virtual_method && !is_type_sealed) {
|
||||||
|
mods += is_override ? "override " : "virtual ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,6 +105,7 @@
|
||||||
<Compile Include="..\src\bgen\Generator.cs" />
|
<Compile Include="..\src\bgen\Generator.cs" />
|
||||||
<Compile Include="..\src\bgen\MarshalInfo.cs" />
|
<Compile Include="..\src\bgen\MarshalInfo.cs" />
|
||||||
<Compile Include="..\src\bgen\IMemberGatherer.cs" />
|
<Compile Include="..\src\bgen\IMemberGatherer.cs" />
|
||||||
|
<Compile Include="..\src\bgen\MemberInformation.cs" />
|
||||||
<Compile Include="..\src\bgen\NamespaceManager.cs" />
|
<Compile Include="..\src\bgen\NamespaceManager.cs" />
|
||||||
<Compile Include="..\src\bgen\NullabilityInfoContext.cs" />
|
<Compile Include="..\src\bgen\NullabilityInfoContext.cs" />
|
||||||
<Compile Include="..\src\bgen\TrampolineInfo.cs" />
|
<Compile Include="..\src\bgen\TrampolineInfo.cs" />
|
||||||
|
|
Загрузка…
Ссылка в новой задаче