[Generator] Move MemberInformation out of the generator and enable nullability. (#17448)

This commit is contained in:
Manuel de la Pena 2023-02-09 12:17:59 -05:00 коммит произвёл GitHub
Родитель 6bd26fad0a
Коммит ab61de421f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 266 добавлений и 235 удалений

Просмотреть файл

@ -54,211 +54,6 @@ using ObjCRuntime;
using Foundation;
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 {
HashSet<string> frameworks;
readonly PlatformName CurrentPlatform;
@ -3490,7 +3285,7 @@ public partial class Generator : IMemberGatherer {
//
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)
{
return MakeSignature (minfo, false, minfo.method.GetParameters (), "", alreadyPreserved);
return MakeSignature (minfo, false, minfo.Method.GetParameters (), "", alreadyPreserved);
}
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)
{
var mi = minfo.method;
var mi = minfo.Method;
var category_class = minfo.category_extension_type;
StringBuilder sb = new StringBuilder ();
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) {
var prefix = "";
if (!BindThirdPartyLibrary) {
var hasReturnTypeProtocolize = Protocolize (AttributeManager.GetReturnTypeCustomAttributes (minfo.method));
var hasReturnTypeProtocolize = Protocolize (AttributeManager.GetReturnTypeCustomAttributes (minfo.Method));
if (hasReturnTypeProtocolize) {
if (!IsProtocol (minfo.method.ReturnType)) {
ErrorHelper.Warning (1108, minfo.method.DeclaringType, minfo.method, minfo.method.ReturnType.FullName);
if (!IsProtocol (minfo.Method.ReturnType)) {
ErrorHelper.Warning (1108, minfo.Method.DeclaringType, minfo.Method, minfo.Method.ReturnType.FullName);
} else {
prefix = "I";
}
}
if (minfo.method.ReturnType.IsArray) {
var et = minfo.method.ReturnType.GetElementType ();
if (minfo.Method.ReturnType.IsArray) {
var et = minfo.Method.ReturnType.GetElementType ();
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)
ErrorHelper.Warning (1107, minfo.method.DeclaringType, minfo.method.Name, minfo.method.ReturnType, minfo.method.ReturnType.Namespace, minfo.method.ReturnType.Name);
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);
}
if (minfo.is_bindAs) {
@ -3577,7 +3372,7 @@ public partial class Generator : IMemberGatherer {
sb.Append (" ");
}
// 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))
name = "Get" + name.Substring (4);
else if (name.StartsWith ("set_", StringComparison.Ordinal))
@ -5178,7 +4973,7 @@ public partial class Generator : IMemberGatherer {
string extra = "";
if (asyncKind == AsyncMethodKind.WithResultOutParameter) {
if (minfo.method.GetParameters ().Count () > 1)
if (minfo.Method.GetParameters ().Count () > 1)
extra = ", ";
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)
{
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 is_void = mi.ReturnType == TypeManager.System_Void;
@ -5289,7 +5084,7 @@ public partial class Generator : IMemberGatherer {
void PrintMethodAttributes (MemberInformation minfo)
{
MethodInfo mi = minfo.method;
MethodInfo mi = minfo.Method;
var editor_browsable_attribute = false;
foreach (var sa in AttributeManager.GetCustomAttributes<ThreadSafeAttribute> (mi))
@ -5310,12 +5105,12 @@ public partial class Generator : IMemberGatherer {
print ("[return: ReleaseAttribute ()]");
// 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
// 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 {
PrintPlatformAttributes (minfo.method);
PrintPlatformAttributes (minfo.Method);
}
// 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)
{
PrintDelegateProxy (minfo.method);
PrintDelegateProxy (minfo.Method);
}
void PrintDelegateProxy (MethodInfo mi)
@ -5368,7 +5163,7 @@ public partial class Generator : IMemberGatherer {
bool output_semantics = semantic != ArgumentSemantic.None;
// it does not make sense on every properties, depending on the their types
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;
}
@ -5380,7 +5175,7 @@ public partial class Generator : IMemberGatherer {
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
if (AttributeManager.HasAttribute<ManualAttribute> (mi))
@ -5399,9 +5194,9 @@ public partial class Generator : IMemberGatherer {
if (c == ':')
argCount++;
}
if (minfo.method.GetParameters ().Length != argCount) {
if (minfo.Method.GetParameters ().Length != argCount) {
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 ("{");
var is32BitNotSupported = Is64BitiOSOnly ((ICustomAttributeProvider) minfo.method ?? minfo.property);
var is32BitNotSupported = Is64BitiOSOnly ((ICustomAttributeProvider) minfo.Method ?? minfo.Property);
if (is32BitNotSupported) {
print ("#if ARCH_32");
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 ()) {");
}
PropertyInfo pinfo = null;
MethodInfo method = minfo.method;
MethodInfo method = minfo.Method;
bool null_allowed = false;
if (method.IsSpecialName) {
// could be a property setter where [NullAllowed] is _allowed_
@ -5481,7 +5276,7 @@ public partial class Generator : IMemberGatherer {
if (pinfo != null)
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) {
print ("}");
indent--;
@ -5502,7 +5297,7 @@ public partial class Generator : IMemberGatherer {
GenerateAsyncMethod (minfo, AsyncMethodKind.Plain);
// 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);
}
}
@ -5903,11 +5698,11 @@ public partial class Generator : IMemberGatherer {
// Generate Extension Methods of required [Async] decorated methods (we already do optional)
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);
// 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);
}
@ -6752,7 +6547,7 @@ public partial class Generator : IMemberGatherer {
if (appearance_selectors != null && AttributeManager.HasAttribute<AppearanceAttribute> (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?)`
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\MarshalInfo.cs" />
<Compile Include="..\src\bgen\IMemberGatherer.cs" />
<Compile Include="..\src\bgen\MemberInformation.cs" />
<Compile Include="..\src\bgen\NamespaceManager.cs" />
<Compile Include="..\src\bgen\NullabilityInfoContext.cs" />
<Compile Include="..\src\bgen\TrampolineInfo.cs" />