Merge remote-tracking branch 'origin/master' into mono-2018-06
This commit is contained in:
Коммит
28347f9167
|
@ -378,6 +378,20 @@ will be shown.
|
||||||
|
|
||||||
Reference: https://github.com/xamarin/xamarin-macios/issues/4072
|
Reference: https://github.com/xamarin/xamarin-macios/issues/4072
|
||||||
|
|
||||||
|
### <a name="MM4176"/>MM4176: Unable to locate the delegate to block conversion type for the return value of the method {method}.
|
||||||
|
|
||||||
|
This is a warning indicating that the static registrar couldn't find the type
|
||||||
|
used to convert a delegate to an Objective-C block. An attempt will be made at
|
||||||
|
runtime to find the method, but it will likely fail as well (with an MM8009
|
||||||
|
exception).
|
||||||
|
|
||||||
|
One possible reason for this warning is when manually writing bindings for API
|
||||||
|
that uses blocks. It's recommended to use a binding project to bind
|
||||||
|
Objective-C code, in particular when it involves blocks, since it's quite
|
||||||
|
complicated to get it right when doing it manually.
|
||||||
|
|
||||||
|
If this is not the case, please file a bug at [https://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=Xamarin.Mac) with a test case.
|
||||||
|
|
||||||
# MM5xxx: GCC and toolchain
|
# MM5xxx: GCC and toolchain
|
||||||
|
|
||||||
## MM51xx: compilation
|
## MM51xx: compilation
|
||||||
|
|
|
@ -1787,6 +1787,20 @@ will be shown.
|
||||||
|
|
||||||
Reference: https://github.com/xamarin/xamarin-macios/issues/4072
|
Reference: https://github.com/xamarin/xamarin-macios/issues/4072
|
||||||
|
|
||||||
|
### <a name="MT4176"/>MT4176: Unable to locate the delegate to block conversion type for the return value of the method {method}.
|
||||||
|
|
||||||
|
This is a warning indicating that the static registrar couldn't find the type
|
||||||
|
used to convert a delegate to an Objective-C block. An attempt will be made at
|
||||||
|
runtime to find the method, but it will likely fail as well (with an MT8009
|
||||||
|
exception).
|
||||||
|
|
||||||
|
One possible reason for this warning is when manually writing bindings for API
|
||||||
|
that uses blocks. It's recommended to use a binding project to bind
|
||||||
|
Objective-C code, in particular when it involves blocks, since it's quite
|
||||||
|
complicated to get it right when doing it manually.
|
||||||
|
|
||||||
|
If this is not the case, please file a bug at [https://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS) with a test case.
|
||||||
|
|
||||||
# MT5xxx: GCC and toolchain error messages
|
# MT5xxx: GCC and toolchain error messages
|
||||||
|
|
||||||
### MT51xx: Compilation
|
### MT51xx: Compilation
|
||||||
|
|
|
@ -21,7 +21,10 @@
|
||||||
<_DebugFileExt Condition="'$(_DebugFileExt)' == ''">.mdb</_DebugFileExt>
|
<_DebugFileExt Condition="'$(_DebugFileExt)' == ''">.mdb</_DebugFileExt>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Import Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets')"
|
<Import Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')"
|
||||||
|
Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets" />
|
||||||
|
|
||||||
|
<Import Condition="!$(MSBuildAllProjects.Contains('Microsoft.FSharp.Targets')) and Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets')"
|
||||||
Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets" />
|
Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.1\Framework\v4.0\Microsoft.FSharp.Targets" />
|
||||||
|
|
||||||
<Import Condition="!$(MSBuildAllProjects.Contains('Microsoft.FSharp.Targets')) and Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')"
|
<Import Condition="!$(MSBuildAllProjects.Contains('Microsoft.FSharp.Targets')) and Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')"
|
||||||
|
|
|
@ -69,7 +69,8 @@
|
||||||
new XDelegate ("id", "IntPtr", "xamarin_create_delegate_proxy",
|
new XDelegate ("id", "IntPtr", "xamarin_create_delegate_proxy",
|
||||||
"MonoObject *", "IntPtr", "method",
|
"MonoObject *", "IntPtr", "method",
|
||||||
"MonoObject *", "IntPtr", "block",
|
"MonoObject *", "IntPtr", "block",
|
||||||
"const char *", "IntPtr", "signature"
|
"const char *", "IntPtr", "signature",
|
||||||
|
"unsigned int", "uint", "token_ref"
|
||||||
) {
|
) {
|
||||||
WrappedManagedFunction = "CreateDelegateProxy",
|
WrappedManagedFunction = "CreateDelegateProxy",
|
||||||
OnlyDynamicUsage = false,
|
OnlyDynamicUsage = false,
|
||||||
|
|
|
@ -2187,10 +2187,10 @@ xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref,
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature, guint32 *exception_gchandle)
|
xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature, guint32 token_ref, guint32 *exception_gchandle)
|
||||||
{
|
{
|
||||||
// COOP: accesses managed memory: unsafe mode.
|
// COOP: accesses managed memory: unsafe mode.
|
||||||
return delegates.create_delegate_proxy ((MonoObject *) mono_method_get_object (mono_domain_get (), method, NULL), delegate, signature, exception_gchandle);
|
return delegates.create_delegate_proxy ((MonoObject *) mono_method_get_object (mono_domain_get (), method, NULL), delegate, signature, token_ref, exception_gchandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -60,7 +60,7 @@ xamarin_marshal_return_value (MonoType *mtype, const char *type, MonoObject *ret
|
||||||
case _C_PTR: {
|
case _C_PTR: {
|
||||||
MonoClass *klass = mono_class_from_mono_type (mtype);
|
MonoClass *klass = mono_class_from_mono_type (mtype);
|
||||||
if (mono_class_is_delegate (klass)) {
|
if (mono_class_is_delegate (klass)) {
|
||||||
return xamarin_get_block_for_delegate (method, retval, NULL, exception_gchandle);
|
return xamarin_get_block_for_delegate (method, retval, NULL, INVALID_TOKEN_REF, exception_gchandle);
|
||||||
} else {
|
} else {
|
||||||
return *(void **) mono_object_unbox (retval);
|
return *(void **) mono_object_unbox (retval);
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ MonoType * xamarin_get_parameter_type (MonoMethod *managed_method, int index);
|
||||||
MonoObject * xamarin_get_nsobject_with_type_for_ptr (id self, bool owns, MonoType* type, SEL selector, MonoMethod *managed_method, guint32 *exception_gchandle);
|
MonoObject * xamarin_get_nsobject_with_type_for_ptr (id self, bool owns, MonoType* type, SEL selector, MonoMethod *managed_method, guint32 *exception_gchandle);
|
||||||
MonoObject * xamarin_get_nsobject_with_type_for_ptr_created (id self, bool owns, MonoType *type, int32_t *created, SEL selector, MonoMethod *managed_method, guint32 *exception_gchandle);
|
MonoObject * xamarin_get_nsobject_with_type_for_ptr_created (id self, bool owns, MonoType *type, int32_t *created, SEL selector, MonoMethod *managed_method, guint32 *exception_gchandle);
|
||||||
int * xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref, int par, void *nativeBlock, guint32 *exception_gchandle);
|
int * xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref, int par, void *nativeBlock, guint32 *exception_gchandle);
|
||||||
id xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature /* NULL allowed, but requires the dynamic registrar at runtime to compute */, guint32 *exception_gchandle);
|
id xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature /* NULL allowed, but requires the dynamic registrar at runtime to compute */, guint32 token_ref /* INVALID_TOKEN_REF allowed, but requires the dynamic registrar at runtime */, guint32 *exception_gchandle);
|
||||||
id xamarin_get_nsobject_handle (MonoObject *obj);
|
id xamarin_get_nsobject_handle (MonoObject *obj);
|
||||||
void xamarin_set_nsobject_handle (MonoObject *obj, id handle);
|
void xamarin_set_nsobject_handle (MonoObject *obj, id handle);
|
||||||
uint8_t xamarin_get_nsobject_flags (MonoObject *obj);
|
uint8_t xamarin_get_nsobject_flags (MonoObject *obj);
|
||||||
|
|
|
@ -59,6 +59,7 @@ namespace Foundation {
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Selector { get; set; }
|
public string Selector { get; set; }
|
||||||
public Type ReturnType { get; set; }
|
public Type ReturnType { get; set; }
|
||||||
|
public Type ReturnTypeDelegateProxy { get; set; }
|
||||||
public Type[] ParameterType { get; set; }
|
public Type[] ParameterType { get; set; }
|
||||||
public bool[] ParameterByRef { get; set; }
|
public bool[] ParameterByRef { get; set; }
|
||||||
public Type[] ParameterBlockProxy { get; set; }
|
public Type[] ParameterBlockProxy { get; set; }
|
||||||
|
|
25
src/Makefile
25
src/Makefile
|
@ -168,11 +168,7 @@ $(IOS_BUILD_DIR)/reference/System.Drawing.dll: $(IOS_SYSTEM_DRAWING_SOURCES) mon
|
||||||
$(IOS_SYSTEM_DRAWING_SOURCES)
|
$(IOS_SYSTEM_DRAWING_SOURCES)
|
||||||
|
|
||||||
$(IOS_BUILD_DIR)/reference/Xamarin.iOS.dll: $(IOS_BUILD_DIR)/native-64/Xamarin.iOS.dll | $(IOS_BUILD_DIR)/reference
|
$(IOS_BUILD_DIR)/reference/Xamarin.iOS.dll: $(IOS_BUILD_DIR)/native-64/Xamarin.iOS.dll | $(IOS_BUILD_DIR)/reference
|
||||||
@# Don't strip, btouch-native needs to execute code from Xamarin.iOS,
|
$(Q_GEN) mono-cil-strip $< $@
|
||||||
@# and that'll break if we strip out the code from the reference assembly.
|
|
||||||
@# Note that there is only btouch-native executable for both 32 and 64 bits.
|
|
||||||
@#$(Q_GEN) mono-cil-strip $< $@
|
|
||||||
$(Q) cp $< $@
|
|
||||||
|
|
||||||
$(IOS_BUILD_DIR)/reference/Xamarin.iOS.pdb: $(IOS_BUILD_DIR)/native-64/Xamarin.iOS.pdb | $(IOS_BUILD_DIR)/reference
|
$(IOS_BUILD_DIR)/reference/Xamarin.iOS.pdb: $(IOS_BUILD_DIR)/native-64/Xamarin.iOS.pdb | $(IOS_BUILD_DIR)/reference
|
||||||
$(Q) cp $< $@
|
$(Q) cp $< $@
|
||||||
|
@ -753,11 +749,7 @@ $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS%dll $(WATCH_BUILD_DIR)/watch-32/Xama
|
||||||
$(WATCHOS_SOURCES) @$(WATCH_BUILD_DIR)/watch/generated_sources
|
$(WATCHOS_SOURCES) @$(WATCH_BUILD_DIR)/watch/generated_sources
|
||||||
|
|
||||||
$(WATCH_BUILD_DIR)/reference/Xamarin.WatchOS.dll: $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS.dll | $(WATCH_BUILD_DIR)/reference
|
$(WATCH_BUILD_DIR)/reference/Xamarin.WatchOS.dll: $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS.dll | $(WATCH_BUILD_DIR)/reference
|
||||||
@# Don't strip, bwatch needs to execute code from Xamarin.WatchOS (attributes),
|
$(Q_GEN) mono-cil-strip $< $@
|
||||||
@# and that'll break if we strip out the code from the reference assembly.
|
|
||||||
@# Note that there is only bwatch executable for both 32 and 64 bits.
|
|
||||||
@#$(Q_GEN) mono-cil-strip $< $@
|
|
||||||
$(Q) cp $< $@
|
|
||||||
|
|
||||||
$(WATCH_BUILD_DIR)/reference/Xamarin.WatchOS.pdb: $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS.pdb | $(WATCH_BUILD_DIR)/reference
|
$(WATCH_BUILD_DIR)/reference/Xamarin.WatchOS.pdb: $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS.pdb | $(WATCH_BUILD_DIR)/reference
|
||||||
$(Q) cp $< $@
|
$(Q) cp $< $@
|
||||||
|
@ -966,10 +958,7 @@ $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS%dll $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVO
|
||||||
$(TVOS_SOURCES) @$(TVOS_BUILD_DIR)/tvos/generated_sources
|
$(TVOS_SOURCES) @$(TVOS_BUILD_DIR)/tvos/generated_sources
|
||||||
|
|
||||||
$(TVOS_BUILD_DIR)/reference/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(TVOS_BUILD_DIR)/reference
|
$(TVOS_BUILD_DIR)/reference/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(TVOS_BUILD_DIR)/reference
|
||||||
@# Don't strip, btv needs to execute code from Xamarin.TVOS (attributes),
|
$(Q_GEN) mono-cil-strip $< $@
|
||||||
@# and that'll break if we strip out the code from the reference assembly.
|
|
||||||
@#$(Q_GEN) mono-cil-strip $< $@
|
|
||||||
$(Q) cp $< $@
|
|
||||||
|
|
||||||
$(TVOS_BUILD_DIR)/reference/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(TVOS_BUILD_DIR)/reference
|
$(TVOS_BUILD_DIR)/reference/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(TVOS_BUILD_DIR)/reference
|
||||||
$(Q) cp $< $@
|
$(Q) cp $< $@
|
||||||
|
@ -1060,8 +1049,8 @@ TVOS_TARGETS += \
|
||||||
$(PROJECT_DIR)/MonoTouch.NUnitLite.tvos.csproj \
|
$(PROJECT_DIR)/MonoTouch.NUnitLite.tvos.csproj \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/Xamarin.TVOS.pdb \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/Xamarin.TVOS.pdb \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.dll \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.dll \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.pdb \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.pdb \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/System.Net.Http.dll \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/System.Net.Http.dll \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/System.Net.Http.pdb \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/System.Net.Http.pdb \
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/OpenTK-1.0.dll \
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/OpenTK-1.0.dll \
|
||||||
|
@ -1088,10 +1077,10 @@ $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/%.config: $(TVOS_BUILD_D
|
||||||
$(Q) install -m 0644 $< $@
|
$(Q) install -m 0644 $< $@
|
||||||
|
|
||||||
# the actual architecture-specific versions
|
# the actual architecture-specific versions
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits
|
||||||
$(Q) install -m 0755 $< $@
|
$(Q) install -m 0755 $< $@
|
||||||
|
|
||||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits
|
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits
|
||||||
$(Q) install -m 0644 $< $@
|
$(Q) install -m 0644 $< $@
|
||||||
|
|
||||||
$(TVOS_TARGETS_DIRS):
|
$(TVOS_TARGETS_DIRS):
|
||||||
|
|
|
@ -247,8 +247,50 @@ namespace ObjCRuntime {
|
||||||
return descriptor->copy_helper == ((BlockDescriptor *) literal->block_descriptor)->copy_helper;
|
return descriptor->copy_helper == ((BlockDescriptor *) literal->block_descriptor)->copy_helper;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BindingImpl (BindingImplOptions.Optimizable)]
|
static Type GetDelegateProxyType (MethodInfo minfo, uint token_ref, out MethodInfo baseMethod)
|
||||||
internal static IntPtr GetBlockForDelegate (MethodInfo minfo, object @delegate, string signature)
|
{
|
||||||
|
// A mirror of this method is also implemented in StaticRegistrar:GetDelegateProxyType
|
||||||
|
// If this method is changed, that method will probably have to be updated too (tests!!!)
|
||||||
|
baseMethod = null;
|
||||||
|
|
||||||
|
if (token_ref != Runtime.INVALID_TOKEN_REF)
|
||||||
|
return (Type) Class.ResolveTokenReference (token_ref, 0x02000000 /* TypeDef */);
|
||||||
|
|
||||||
|
baseMethod = minfo.GetBaseDefinition ();
|
||||||
|
var delegateProxies = baseMethod.ReturnTypeCustomAttributes.GetCustomAttributes (typeof (DelegateProxyAttribute), false);
|
||||||
|
if (delegateProxies.Length > 0)
|
||||||
|
return ((DelegateProxyAttribute) delegateProxies [0]).DelegateType;
|
||||||
|
|
||||||
|
// We might be implementing a protocol, find any DelegateProxy attributes on the corresponding interface as well.
|
||||||
|
string selector = null;
|
||||||
|
foreach (var iface in minfo.DeclaringType.GetInterfaces ()) {
|
||||||
|
if (!iface.IsDefined (typeof (ProtocolAttribute), false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var map = minfo.DeclaringType.GetInterfaceMap (iface);
|
||||||
|
for (int i = 0; i < map.TargetMethods.Length; i++) {
|
||||||
|
if (map.TargetMethods [i] == minfo) {
|
||||||
|
delegateProxies = map.InterfaceMethods [i].ReturnTypeCustomAttributes.GetCustomAttributes (typeof (DelegateProxyAttribute), false);
|
||||||
|
if (delegateProxies.Length > 0)
|
||||||
|
return ((DelegateProxyAttribute) delegateProxies [0]).DelegateType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It might be an optional method/property, in which case we need to check any ProtocolMember attributes
|
||||||
|
if (selector == null)
|
||||||
|
selector = Runtime.GetExportAttribute (minfo)?.Selector ?? string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty (selector)) {
|
||||||
|
var attrib = Runtime.GetProtocolMemberAttribute (iface, selector, minfo);
|
||||||
|
if (attrib?.ReturnTypeDelegateProxy != null)
|
||||||
|
return attrib.ReturnTypeDelegateProxy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ErrorHelper.CreateError (8011, "Unable to locate the delegate to block conversion attribute ([DelegateProxy]) for the return value for the method {0}.{1}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BindingImpl(BindingImplOptions.Optimizable)]
|
||||||
|
internal static IntPtr GetBlockForDelegate (MethodInfo minfo, object @delegate, uint token_ref, string signature)
|
||||||
{
|
{
|
||||||
if (@delegate == null)
|
if (@delegate == null)
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
|
@ -256,26 +298,22 @@ namespace ObjCRuntime {
|
||||||
if (!(@delegate is Delegate))
|
if (!(@delegate is Delegate))
|
||||||
throw ErrorHelper.CreateError (8016, "Unable to convert delegate to block for the return value for the method {0}.{1}, because the input isn't a delegate, it's a {1}. Please file a bug at http://bugzilla.xamarin.com.", minfo.DeclaringType.FullName, minfo.Name, @delegate.GetType ().FullName);
|
throw ErrorHelper.CreateError (8016, "Unable to convert delegate to block for the return value for the method {0}.{1}, because the input isn't a delegate, it's a {1}. Please file a bug at http://bugzilla.xamarin.com.", minfo.DeclaringType.FullName, minfo.Name, @delegate.GetType ().FullName);
|
||||||
|
|
||||||
var baseMethod = minfo.GetBaseDefinition ();
|
Type delegateProxyType = GetDelegateProxyType (minfo, token_ref, out var baseMethod);
|
||||||
|
if (baseMethod == null)
|
||||||
var delegateProxies = baseMethod.ReturnTypeCustomAttributes.GetCustomAttributes (typeof (DelegateProxyAttribute), false);
|
baseMethod = minfo; // 'baseMethod' is only used in error messages, and if it's null, we just use the closest alternative we have (minfo).
|
||||||
if (delegateProxies.Length == 0)
|
if (delegateProxyType == null)
|
||||||
throw ErrorHelper.CreateError (8011, "Unable to locate the delegate to block conversion attribute ([DelegateProxy]) for the return value for the method {0}.{1}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
|
||||||
|
|
||||||
var delegateProxy = (DelegateProxyAttribute) delegateProxies [0];
|
|
||||||
if (delegateProxy.DelegateType == null)
|
|
||||||
throw ErrorHelper.CreateError (8012, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
throw ErrorHelper.CreateError (8012, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
||||||
|
|
||||||
var delegateProxyField = delegateProxy.DelegateType.GetField ("Handler", BindingFlags.NonPublic | BindingFlags.Static);
|
var delegateProxyField = delegateProxyType.GetField ("Handler", BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
if (delegateProxyField == null)
|
if (delegateProxyField == null)
|
||||||
throw ErrorHelper.CreateError (8013, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType ({2}) specifies a type without a 'Handler' field. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxy.DelegateType.FullName);
|
throw ErrorHelper.CreateError (8013, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType ({2}) specifies a type without a 'Handler' field. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxyType.FullName);
|
||||||
|
|
||||||
var handlerDelegate = delegateProxyField.GetValue (null);
|
var handlerDelegate = delegateProxyField.GetValue (null);
|
||||||
if (handlerDelegate == null)
|
if (handlerDelegate == null)
|
||||||
throw ErrorHelper.CreateError (8014, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxy.DelegateType.FullName);
|
throw ErrorHelper.CreateError (8014, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxyType.FullName);
|
||||||
|
|
||||||
if (!(handlerDelegate is Delegate))
|
if (!(handlerDelegate is Delegate))
|
||||||
throw ErrorHelper.CreateError (8015, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is not a delegate, it's a {3}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxy.DelegateType.FullName, handlerDelegate.GetType ().FullName);
|
throw ErrorHelper.CreateError (8015, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is not a delegate, it's a {3}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxyType.FullName, handlerDelegate.GetType ().FullName);
|
||||||
|
|
||||||
// We now have the information we need to create the block.
|
// We now have the information we need to create the block.
|
||||||
// Note that we must create a heap-allocated block, so we
|
// Note that we must create a heap-allocated block, so we
|
||||||
|
|
|
@ -32,6 +32,7 @@ using ProductException=MonoMac.RuntimeException;
|
||||||
using ObjCRuntime;
|
using ObjCRuntime;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
|
using System.Linq;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -297,6 +298,26 @@ namespace ObjCRuntime {
|
||||||
Show (new ProductException (code, false, innerException, message, args));
|
Show (new ProductException (code, false, innerException, message, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MMP || MTOUCH
|
||||||
|
// Shows any warnings, and if there are any errors, throws an AggregateException.
|
||||||
|
public static void ThrowIfErrors (IList<Exception> exceptions)
|
||||||
|
{
|
||||||
|
if (exceptions?.Any () != true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Separate warnings from errors
|
||||||
|
var grouped = exceptions.GroupBy ((v) => (v as ProductException)?.Error == false);
|
||||||
|
|
||||||
|
var warnings = grouped.SingleOrDefault ((v) => v.Key);
|
||||||
|
if (warnings?.Any () == true)
|
||||||
|
Show (warnings);
|
||||||
|
|
||||||
|
var errors = grouped.SingleOrDefault ((v) => !v.Key);
|
||||||
|
if (errors?.Any () == true)
|
||||||
|
throw new AggregateException (errors);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static void Show (IEnumerable<Exception> list)
|
public static void Show (IEnumerable<Exception> list)
|
||||||
{
|
{
|
||||||
List<Exception> exceptions = new List<Exception> ();
|
List<Exception> exceptions = new List<Exception> ();
|
||||||
|
|
|
@ -447,9 +447,9 @@ namespace ObjCRuntime {
|
||||||
return ObjectWrapper.Convert (CreateBlockProxy ((MethodInfo) ObjectWrapper.Convert (method), block));
|
return ObjectWrapper.Convert (CreateBlockProxy ((MethodInfo) ObjectWrapper.Convert (method), block));
|
||||||
}
|
}
|
||||||
|
|
||||||
static IntPtr CreateDelegateProxy (IntPtr method, IntPtr @delegate, IntPtr signature)
|
static IntPtr CreateDelegateProxy (IntPtr method, IntPtr @delegate, IntPtr signature, uint token_ref)
|
||||||
{
|
{
|
||||||
return BlockLiteral.GetBlockForDelegate ((MethodInfo) ObjectWrapper.Convert (method), ObjectWrapper.Convert (@delegate), Marshal.PtrToStringAuto (signature));
|
return BlockLiteral.GetBlockForDelegate ((MethodInfo) ObjectWrapper.Convert (method), ObjectWrapper.Convert (@delegate), token_ref, Marshal.PtrToStringAuto (signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsafe Assembly GetEntryAssembly ()
|
static unsafe Assembly GetEntryAssembly ()
|
||||||
|
@ -776,6 +776,48 @@ namespace ObjCRuntime {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static ProtocolMemberAttribute GetProtocolMemberAttribute (Type type, string selector, MethodInfo method)
|
||||||
|
{
|
||||||
|
var memberAttributes = type.GetCustomAttributes<ProtocolMemberAttribute> ();
|
||||||
|
if (memberAttributes == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
foreach (var attrib in memberAttributes) {
|
||||||
|
if (attrib.IsStatic != method.IsStatic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (attrib.Selector != selector)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!attrib.IsProperty) {
|
||||||
|
var methodParameters = method.GetParameters ();
|
||||||
|
if ((attrib.ParameterType?.Length ?? 0) != methodParameters.Length)
|
||||||
|
continue;
|
||||||
|
var notApplicable = false;
|
||||||
|
for (int i = 0; i < methodParameters.Length; i++) {
|
||||||
|
var paramType = methodParameters [i].ParameterType;
|
||||||
|
var isByRef = paramType.IsByRef;
|
||||||
|
if (isByRef)
|
||||||
|
paramType = paramType.GetElementType ();
|
||||||
|
if (isByRef != attrib.ParameterByRef [i]) {
|
||||||
|
notApplicable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (paramType != attrib.ParameterType [i]) {
|
||||||
|
notApplicable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notApplicable)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns a MethodInfo that represents the method that can be used to turn
|
// Returns a MethodInfo that represents the method that can be used to turn
|
||||||
// a the block in the given method at the given parameter into a strongly typed
|
// a the block in the given method at the given parameter into a strongly typed
|
||||||
|
@ -824,39 +866,11 @@ namespace ObjCRuntime {
|
||||||
// We may run into binding assemblies built with earlier versions of the generator,
|
// We may run into binding assemblies built with earlier versions of the generator,
|
||||||
// which means we can't rely on finding the BlockProxy attribute in the ProtocolMemberAttribute.
|
// which means we can't rely on finding the BlockProxy attribute in the ProtocolMemberAttribute.
|
||||||
if (selector == null)
|
if (selector == null)
|
||||||
selector = method.GetCustomAttribute<ExportAttribute> ()?.Selector ?? string.Empty;
|
selector = GetExportAttribute (method)?.Selector ?? string.Empty;
|
||||||
if (!string.IsNullOrEmpty (selector)) {
|
if (!string.IsNullOrEmpty (selector)) {
|
||||||
var memberAttributes = iface.GetCustomAttributes<ProtocolMemberAttribute> ();
|
var attrib = GetProtocolMemberAttribute (iface, selector, method);
|
||||||
foreach (var attrib in memberAttributes) {
|
if (attrib != null && attrib.ParameterBlockProxy.Length > parameter && attrib.ParameterBlockProxy [parameter] != null)
|
||||||
if (attrib.ParameterBlockProxy == null || attrib.ParameterBlockProxy.Length <= parameter || attrib.ParameterBlockProxy [parameter] == null)
|
|
||||||
continue; // no need to check anything if what we want isn't there
|
|
||||||
if (attrib.Selector != selector)
|
|
||||||
continue;
|
|
||||||
if (attrib.IsStatic != method.IsStatic)
|
|
||||||
continue;
|
|
||||||
var methodParameters = method.GetParameters ();
|
|
||||||
if (attrib.ParameterType.Length != methodParameters.Length)
|
|
||||||
continue;
|
|
||||||
var notApplicable = false;
|
|
||||||
for (int i = 0; i < methodParameters.Length; i++) {
|
|
||||||
var paramType = methodParameters [i].ParameterType;
|
|
||||||
var isByRef = paramType.IsByRef;
|
|
||||||
if (isByRef)
|
|
||||||
paramType = paramType.GetElementType ();
|
|
||||||
if (isByRef != attrib.ParameterByRef [i]) {
|
|
||||||
notApplicable = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (paramType != attrib.ParameterType [i]) {
|
|
||||||
notApplicable = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (notApplicable)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return attrib.ParameterBlockProxy [parameter].GetMethod ("Create");
|
return attrib.ParameterBlockProxy [parameter].GetMethod ("Create");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Might be an implementation of an optional protocol member.
|
// Might be an implementation of an optional protocol member.
|
||||||
|
@ -1010,6 +1024,31 @@ namespace ObjCRuntime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static PropertyInfo FindPropertyInfo (MethodInfo accessor)
|
||||||
|
{
|
||||||
|
if (!accessor.IsSpecialName)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
foreach (var pi in accessor.DeclaringType.GetProperties ()) {
|
||||||
|
if (pi.GetGetMethod () == accessor)
|
||||||
|
return pi;
|
||||||
|
if (pi.GetSetMethod () == accessor)
|
||||||
|
return pi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ExportAttribute GetExportAttribute (MethodInfo method)
|
||||||
|
{
|
||||||
|
var attrib = method.GetCustomAttribute<ExportAttribute> ();
|
||||||
|
if (attrib == null) {
|
||||||
|
var pinfo = FindPropertyInfo (method);
|
||||||
|
if (pinfo != null)
|
||||||
|
attrib = pinfo.GetCustomAttribute<ExportAttribute> ();
|
||||||
|
}
|
||||||
|
return attrib;
|
||||||
|
}
|
||||||
|
|
||||||
static NSObject IgnoreConstructionError (IntPtr ptr, IntPtr klass, Type type)
|
static NSObject IgnoreConstructionError (IntPtr ptr, IntPtr klass, Type type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4778,6 +4778,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
sel = ba.Selector;
|
sel = ba.Selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintBlockProxy (pi.PropertyType);
|
||||||
PrintAttributes (pi, platform:true);
|
PrintAttributes (pi, platform:true);
|
||||||
|
|
||||||
if (not_implemented_attr == null && (!minfo.is_sealed || !minfo.is_wrapper))
|
if (not_implemented_attr == null && (!minfo.is_sealed || !minfo.is_wrapper))
|
||||||
|
@ -5101,6 +5102,15 @@ public partial class Generator : IMemberGatherer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintBlockProxy (Type type)
|
||||||
|
{
|
||||||
|
type = GetCorrectGenericType (type);
|
||||||
|
if (type.IsSubclassOf (TypeManager.System_Delegate)) {
|
||||||
|
var ti = MakeTrampoline (type);
|
||||||
|
print ("[param: BlockProxy (typeof ({0}.Trampolines.{1}))]", ns.CoreObjCRuntime, ti.NativeInvokerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PrintExport (MemberInformation minfo)
|
void PrintExport (MemberInformation minfo)
|
||||||
{
|
{
|
||||||
if (minfo.is_export)
|
if (minfo.is_export)
|
||||||
|
@ -5418,8 +5428,14 @@ public partial class Generator : IMemberGatherer {
|
||||||
sb.Append (", IsStatic = ").Append (AttributeManager.HasAttribute<StaticAttribute> (mi) ? "true" : "false");
|
sb.Append (", IsStatic = ").Append (AttributeManager.HasAttribute<StaticAttribute> (mi) ? "true" : "false");
|
||||||
sb.Append (", Name = \"").Append (mi.Name).Append ("\"");
|
sb.Append (", Name = \"").Append (mi.Name).Append ("\"");
|
||||||
sb.Append (", Selector = \"").Append (attrib.Selector).Append ("\"");
|
sb.Append (", Selector = \"").Append (attrib.Selector).Append ("\"");
|
||||||
if (mi.ReturnType != TypeManager.System_Void)
|
if (mi.ReturnType != TypeManager.System_Void) {
|
||||||
sb.Append (", ReturnType = typeof (").Append (RenderType (GetCorrectGenericType (mi.ReturnType))).Append(")");
|
var retType = GetCorrectGenericType (mi.ReturnType);
|
||||||
|
sb.Append (", ReturnType = typeof (").Append (RenderType (retType)).Append (")");
|
||||||
|
if (retType.IsSubclassOf (TypeManager.System_Delegate)) {
|
||||||
|
var ti = MakeTrampoline (retType);
|
||||||
|
sb.Append ($", ReturnTypeDelegateProxy = typeof ({ns.CoreObjCRuntime}.Trampolines.{ti.StaticName})");
|
||||||
|
}
|
||||||
|
}
|
||||||
var parameters = mi.GetParameters ();
|
var parameters = mi.GetParameters ();
|
||||||
if (parameters != null && parameters.Length > 0) {
|
if (parameters != null && parameters.Length > 0) {
|
||||||
sb.Append (", ParameterType = new Type [] { ");
|
sb.Append (", ParameterType = new Type [] { ");
|
||||||
|
@ -5489,6 +5505,15 @@ public partial class Generator : IMemberGatherer {
|
||||||
sb.Append (", SetterSelector = \"").Append (ba != null ? ba.Selector : ea.Selector).Append ("\"");
|
sb.Append (", SetterSelector = \"").Append (ba != null ? ba.Selector : ea.Selector).Append ("\"");
|
||||||
}
|
}
|
||||||
sb.Append (", ArgumentSemantic = ArgumentSemantic.").Append (attrib.ArgumentSemantic);
|
sb.Append (", ArgumentSemantic = ArgumentSemantic.").Append (attrib.ArgumentSemantic);
|
||||||
|
// Check for block/delegate proxies
|
||||||
|
var propType = GetCorrectGenericType (pi.PropertyType);
|
||||||
|
if (propType.IsSubclassOf (TypeManager.System_Delegate)) {
|
||||||
|
var ti = MakeTrampoline (propType);
|
||||||
|
if (pi.SetMethod != null)
|
||||||
|
sb.Append ($", ParameterBlockProxy = new Type [] {{ typeof ({ns.CoreObjCRuntime}.Trampolines.{ti.NativeInvokerName}) }}");
|
||||||
|
if (pi.GetMethod != null)
|
||||||
|
sb.Append ($", ReturnTypeDelegateProxy = typeof ({ns.CoreObjCRuntime}.Trampolines.{ti.StaticName})");
|
||||||
|
}
|
||||||
sb.Append (")]");
|
sb.Append (")]");
|
||||||
print (sb.ToString ());
|
print (sb.ToString ());
|
||||||
}
|
}
|
||||||
|
@ -5565,6 +5590,7 @@ public partial class Generator : IMemberGatherer {
|
||||||
}
|
}
|
||||||
if (pi.CanWrite) {
|
if (pi.CanWrite) {
|
||||||
var setMethod = pi.GetSetMethod ();
|
var setMethod = pi.GetSetMethod ();
|
||||||
|
PrintBlockProxy (pi.PropertyType);
|
||||||
PrintAttributes (setMethod, notImplemented:true);
|
PrintAttributes (setMethod, notImplemented:true);
|
||||||
if (!AttributeManager.HasAttribute<NotImplementedAttribute> (setMethod))
|
if (!AttributeManager.HasAttribute<NotImplementedAttribute> (setMethod))
|
||||||
PrintExport (minfo, GetSetterExportAttribute (pi));
|
PrintExport (minfo, GetSetterExportAttribute (pi));
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
<MtouchLink>None</MtouchLink>
|
<MtouchLink>None</MtouchLink>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<MtouchArch>i386, x86_64</MtouchArch>
|
<MtouchArch>i386, x86_64</MtouchArch>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
<MtouchLink>None</MtouchLink>
|
<MtouchLink>None</MtouchLink>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<MtouchArch>i386, x86_64</MtouchArch>
|
<MtouchArch>i386, x86_64</MtouchArch>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
|
||||||
<DebugSymbols>True</DebugSymbols>
|
<DebugSymbols>True</DebugSymbols>
|
||||||
|
@ -52,6 +54,7 @@
|
||||||
<MtouchDebug>True</MtouchDebug>
|
<MtouchDebug>True</MtouchDebug>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug32|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug32|iPhone' ">
|
||||||
<DebugSymbols>True</DebugSymbols>
|
<DebugSymbols>True</DebugSymbols>
|
||||||
|
@ -65,6 +68,7 @@
|
||||||
<MtouchDebug>True</MtouchDebug>
|
<MtouchDebug>True</MtouchDebug>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<MtouchArch>ARMv7</MtouchArch>
|
<MtouchArch>ARMv7</MtouchArch>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug64|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug64|iPhone' ">
|
||||||
<DebugSymbols>True</DebugSymbols>
|
<DebugSymbols>True</DebugSymbols>
|
||||||
|
@ -78,6 +82,7 @@
|
||||||
<MtouchDebug>True</MtouchDebug>
|
<MtouchDebug>True</MtouchDebug>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<MtouchArch>ARM64</MtouchArch>
|
<MtouchArch>ARM64</MtouchArch>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -91,6 +96,7 @@
|
||||||
<DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH;FULL_AOT_RUNTIME;DISABLE_CAS_USE;$(DefineConstants)</DefineConstants>
|
<DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH;FULL_AOT_RUNTIME;DISABLE_CAS_USE;$(DefineConstants)</DefineConstants>
|
||||||
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
||||||
<MtouchUseLlvm>true</MtouchUseLlvm>
|
<MtouchUseLlvm>true</MtouchUseLlvm>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release32|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release32|iPhone' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -104,6 +110,7 @@
|
||||||
<DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH;FULL_AOT_RUNTIME;DISABLE_CAS_USE;$(DefineConstants)</DefineConstants>
|
<DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH;FULL_AOT_RUNTIME;DISABLE_CAS_USE;$(DefineConstants)</DefineConstants>
|
||||||
<MtouchArch>ARMv7</MtouchArch>
|
<MtouchArch>ARMv7</MtouchArch>
|
||||||
<MtouchUseLlvm>true</MtouchUseLlvm>
|
<MtouchUseLlvm>true</MtouchUseLlvm>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release64|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release64|iPhone' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -117,6 +124,7 @@
|
||||||
<DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH;FULL_AOT_RUNTIME;DISABLE_CAS_USE;$(DefineConstants)</DefineConstants>
|
<DefineConstants>NET_1_1;NET_2_0;NET_3_0;NET_3_5;NET_4_0;NET_4_5;NET_2_1;MOBILE;MONOTOUCH;FULL_AOT_RUNTIME;DISABLE_CAS_USE;$(DefineConstants)</DefineConstants>
|
||||||
<MtouchArch>ARM64</MtouchArch>
|
<MtouchArch>ARM64</MtouchArch>
|
||||||
<MtouchUseLlvm>true</MtouchUseLlvm>
|
<MtouchUseLlvm>true</MtouchUseLlvm>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-bitcode|iPhone' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-bitcode|iPhone' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -131,6 +139,7 @@
|
||||||
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
<MtouchArch>ARMv7, ARM64</MtouchArch>
|
||||||
<MtouchExtraArgs>--bitcode:full</MtouchExtraArgs>
|
<MtouchExtraArgs>--bitcode:full</MtouchExtraArgs>
|
||||||
<MtouchUseLlvm>true</MtouchUseLlvm>
|
<MtouchUseLlvm>true</MtouchUseLlvm>
|
||||||
|
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|
|
@ -289,6 +289,22 @@ namespace Bindings.Test {
|
||||||
[Static]
|
[Static]
|
||||||
[Export ("optionalStaticCallback:")]
|
[Export ("optionalStaticCallback:")]
|
||||||
void OptionalStaticCallback (Action<int> completionHandler);
|
void OptionalStaticCallback (Action<int> completionHandler);
|
||||||
|
|
||||||
|
[Abstract]
|
||||||
|
[Export ("requiredReturnValue")]
|
||||||
|
Action<int> RequiredReturnValue ();
|
||||||
|
|
||||||
|
[Abstract]
|
||||||
|
[Static]
|
||||||
|
[Export ("requiredStaticReturnValue")]
|
||||||
|
Action<int> RequiredStaticReturnValue ();
|
||||||
|
|
||||||
|
[Export ("optionalReturnValue")]
|
||||||
|
Action<int> OptionalReturnValue ();
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Export ("optionalStaticReturnValue")]
|
||||||
|
Action<int> OptionalStaticReturnValue ();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IObjCProtocolBlockTest { }
|
interface IObjCProtocolBlockTest { }
|
||||||
|
@ -339,6 +355,23 @@ namespace Bindings.Test {
|
||||||
[Static]
|
[Static]
|
||||||
[Export ("freedBlockCount")]
|
[Export ("freedBlockCount")]
|
||||||
int FreedBlockCount { get; }
|
int FreedBlockCount { get; }
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Export ("calledBlockCount")]
|
||||||
|
int CalledBlockCount { get; }
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Export ("callProtocolWithBlockProperties:required:instance:")]
|
||||||
|
void CallProtocolWithBlockProperties (IProtocolWithBlockProperties obj, bool required, bool instance);
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Export ("callProtocolWithBlockReturnValue:required:instance:")]
|
||||||
|
void CallProtocolWithBlockReturnValue (IObjCProtocolBlockTest obj, bool required, bool instance);
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Export ("setProtocolWithBlockProperties:required:instance:")]
|
||||||
|
void SetProtocolWithBlockProperties (IProtocolWithBlockProperties obj, bool required, bool instance);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate void InnerBlock (int magic_number);
|
delegate void InnerBlock (int magic_number);
|
||||||
|
@ -350,6 +383,28 @@ namespace Bindings.Test {
|
||||||
[Export ("evilCallback")]
|
[Export ("evilCallback")]
|
||||||
Action<int> EvilCallback { get; set; }
|
Action<int> EvilCallback { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delegate void SimpleCallback ();
|
||||||
|
[BaseType (typeof (NSObject))]
|
||||||
|
[Protocol]
|
||||||
|
interface ProtocolWithBlockProperties {
|
||||||
|
[Abstract]
|
||||||
|
[Export ("myRequiredProperty")]
|
||||||
|
SimpleCallback MyRequiredProperty { get; set; }
|
||||||
|
|
||||||
|
[Export ("myOptionalProperty")]
|
||||||
|
SimpleCallback MyOptionalProperty { get; set; }
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Abstract]
|
||||||
|
[Export ("myRequiredStaticProperty")]
|
||||||
|
SimpleCallback MyRequiredStaticProperty { get; set; }
|
||||||
|
|
||||||
|
[Static]
|
||||||
|
[Export ("myOptionalStaticProperty")]
|
||||||
|
SimpleCallback MyOptionalStaticProperty { get; set; }
|
||||||
|
}
|
||||||
|
interface IProtocolWithBlockProperties { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,37 @@ namespace Xamarin.BindingTests
|
||||||
{
|
{
|
||||||
completionHandler (42);
|
completionHandler (42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Action<int> RequiredReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export ("optionalReturnValue")]
|
||||||
|
public Action<int> OptionalReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export ("requiredStaticReturnValue")]
|
||||||
|
public static Action<int> RequiredStaticReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export ("optionalStaticReturnValue")]
|
||||||
|
public static Action<int> OptionalStaticReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlockCallbackClassExplicit : NSObject, IObjCProtocolBlockTest
|
class BlockCallbackClassExplicit : NSObject, IObjCProtocolBlockTest
|
||||||
|
@ -92,6 +123,38 @@ namespace Xamarin.BindingTests
|
||||||
{
|
{
|
||||||
completionHandler (42);
|
completionHandler (42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Explicitly implemented interface member
|
||||||
|
Action<int> IObjCProtocolBlockTest.RequiredReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export ("optionalReturnValue")]
|
||||||
|
public Action<int> OptionalReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export ("requiredStaticReturnValue")]
|
||||||
|
public static Action<int> RequiredStaticReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export ("optionalStaticReturnValue")]
|
||||||
|
public static Action<int> OptionalStaticReturnValue ()
|
||||||
|
{
|
||||||
|
return new Action<int> ((v) => {
|
||||||
|
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlockCallbackTester : ObjCBlockTester
|
public class BlockCallbackTester : ObjCBlockTester
|
||||||
|
@ -101,5 +164,86 @@ namespace Xamarin.BindingTests
|
||||||
completionHandler (42);
|
completionHandler (42);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PropertyBlock : NSObject, IProtocolWithBlockProperties {
|
||||||
|
[Export ("myOptionalProperty")]
|
||||||
|
public SimpleCallback MyOptionalProperty { get; set; }
|
||||||
|
|
||||||
|
public SimpleCallback MyRequiredProperty { get; set; }
|
||||||
|
|
||||||
|
[Export ("myOptionalStaticProperty")]
|
||||||
|
public static SimpleCallback MyOptionalStaticProperty { get; set; }
|
||||||
|
|
||||||
|
[Export ("myRequiredStaticProperty")]
|
||||||
|
public static SimpleCallback MyRequiredStaticProperty { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase (true, true)]
|
||||||
|
[TestCase (true, false)]
|
||||||
|
[TestCase (false, true)]
|
||||||
|
[TestCase (false, false)]
|
||||||
|
public void ProtocolWithBlockProperties (bool required, bool instance)
|
||||||
|
{
|
||||||
|
using (var pb = new PropertyBlock ()) {
|
||||||
|
var callbackCalled = false;
|
||||||
|
SimpleCallback action = () => {
|
||||||
|
callbackCalled = true;
|
||||||
|
};
|
||||||
|
if (required) {
|
||||||
|
if (instance) {
|
||||||
|
pb.MyRequiredProperty = action;
|
||||||
|
} else {
|
||||||
|
PropertyBlock.MyRequiredStaticProperty = action;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (instance) {
|
||||||
|
pb.MyOptionalProperty = action;
|
||||||
|
} else {
|
||||||
|
PropertyBlock.MyOptionalStaticProperty = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjCBlockTester.CallProtocolWithBlockProperties (pb, required, instance);
|
||||||
|
Assert.IsTrue (callbackCalled, "Callback");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase (true, true)]
|
||||||
|
[TestCase (true, false)]
|
||||||
|
[TestCase (false, true)]
|
||||||
|
[TestCase (false, false)]
|
||||||
|
public void ProtocolWithNativeBlockProperties (bool required, bool instance)
|
||||||
|
{
|
||||||
|
using (var pb = new PropertyBlock ()) {
|
||||||
|
var calledCounter = ObjCBlockTester.CalledBlockCount;
|
||||||
|
ObjCBlockTester.SetProtocolWithBlockProperties (pb, required, instance);
|
||||||
|
if (required) {
|
||||||
|
if (instance) {
|
||||||
|
pb.MyRequiredProperty ();
|
||||||
|
} else {
|
||||||
|
PropertyBlock.MyRequiredStaticProperty ();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (instance) {
|
||||||
|
pb.MyOptionalProperty ();
|
||||||
|
} else {
|
||||||
|
PropertyBlock.MyOptionalStaticProperty ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.AreEqual (calledCounter + 1, ObjCBlockTester.CalledBlockCount, "Blocks called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
[TestCase (true, true)]
|
||||||
|
[TestCase (true, false)]
|
||||||
|
[TestCase (false, true)]
|
||||||
|
[TestCase (false, false)]
|
||||||
|
public void ProtocolWithReturnValues (bool required, bool instance)
|
||||||
|
{
|
||||||
|
using (var pb = new BlockCallbackClass ()) {
|
||||||
|
ObjCBlockTester.CallProtocolWithBlockReturnValue (pb, required, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,11 @@ namespace Xamarin.Tests
|
||||||
[Test]
|
[Test]
|
||||||
public void MainThreadDeallocationTest ()
|
public void MainThreadDeallocationTest ()
|
||||||
{
|
{
|
||||||
|
#if OPTIMIZEALL
|
||||||
|
if (!TestRuntime.IsLinkAll)
|
||||||
|
Assert.Ignore ("This test must be processed by the linker if all optimizations are turned on.");
|
||||||
|
#endif
|
||||||
|
|
||||||
ObjCBlockTester.CallAssertMainThreadBlockRelease ((callback) => {
|
ObjCBlockTester.CallAssertMainThreadBlockRelease ((callback) => {
|
||||||
callback (42);
|
callback (42);
|
||||||
});
|
});
|
||||||
|
|
|
@ -259,8 +259,11 @@ class D : NSObject {
|
||||||
bundler.AssertWarning (4173, "The registrar can't compute the block signature for the delegate of type System.Delegate in the method D.D4 because System.Delegate doesn't have a specific signature.", "testApp.cs", 24);
|
bundler.AssertWarning (4173, "The registrar can't compute the block signature for the delegate of type System.Delegate in the method D.D4 because System.Delegate doesn't have a specific signature.", "testApp.cs", 24);
|
||||||
bundler.AssertWarning (4173, "The registrar can't compute the block signature for the delegate of type System.MulticastDelegate in the method D.D5 because System.MulticastDelegate doesn't have a specific signature.", "testApp.cs", 30);
|
bundler.AssertWarning (4173, "The registrar can't compute the block signature for the delegate of type System.MulticastDelegate in the method D.D5 because System.MulticastDelegate doesn't have a specific signature.", "testApp.cs", 30);
|
||||||
bundler.AssertWarning (4174, "Unable to locate the block to delegate conversion method for the method D.D3's parameter #1.", "testApp.cs", 18);
|
bundler.AssertWarning (4174, "Unable to locate the block to delegate conversion method for the method D.D3's parameter #1.", "testApp.cs", 18);
|
||||||
|
bundler.AssertWarning (4176, "Unable to locate the delegate to block conversion type for the return value of the method D.D4.", "testApp.cs", 24);
|
||||||
|
bundler.AssertWarning (4176, "Unable to locate the delegate to block conversion type for the return value of the method D.D5.", "testApp.cs", 30);
|
||||||
|
bundler.AssertWarning (4176, "Unable to locate the delegate to block conversion type for the return value of the method D.D6.", "testApp.cs", 36);
|
||||||
bundler.AssertErrorCount (2);
|
bundler.AssertErrorCount (2);
|
||||||
bundler.AssertWarningCount (3);
|
bundler.AssertWarningCount (6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace LinkSdk {
|
||||||
|
|
||||||
public Task<string> LoadCategories ()
|
public Task<string> LoadCategories ()
|
||||||
{
|
{
|
||||||
return Task.Run (async () => await (new HttpClient ()).GetStringAsync ("http://google.com"));
|
return Task.Run (async () => await (new HttpClient ()).GetStringAsync ("https://google.com"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -747,6 +747,13 @@ namespace LinkSdk {
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
// https://bugzilla.novell.com/show_bug.cgi?id=650402
|
// https://bugzilla.novell.com/show_bug.cgi?id=650402
|
||||||
|
#if __WATCHOS__
|
||||||
|
// Fails with:
|
||||||
|
// System.ExecutionEngineException : Attempting to JIT compile method 'System.Data.DataColumn:set_Expression (string)' while running in aot-only mode.
|
||||||
|
// because DataColumn.set_Expression uses filter clauses, which we don't support with bitcode:
|
||||||
|
// LLVM failed for 'DataColumn.set_Expression': non-finally/catch/fault clause.
|
||||||
|
[Ignore ("https://bugzilla.xamarin.com/show_bug.cgi?id=59987")]
|
||||||
|
#endif
|
||||||
public void ForeignKey_650402 ()
|
public void ForeignKey_650402 ()
|
||||||
{
|
{
|
||||||
DataSet data = new DataSet ();
|
DataSet data = new DataSet ();
|
||||||
|
|
|
@ -1182,6 +1182,45 @@ namespace NS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MT4176 ()
|
||||||
|
{
|
||||||
|
using (var mtouch = new MTouchTool ()) {
|
||||||
|
var code = @"
|
||||||
|
namespace NS {
|
||||||
|
using System;
|
||||||
|
using Foundation;
|
||||||
|
using ObjCRuntime;
|
||||||
|
|
||||||
|
public class Consumer : NSObject
|
||||||
|
{
|
||||||
|
[Export (""getAction"")]
|
||||||
|
public Action GetFunction ()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export (""getProperty"")]
|
||||||
|
public Action GetProperty {
|
||||||
|
get {
|
||||||
|
throw new NotImplementedException ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
";
|
||||||
|
mtouch.Linker = MTouchLinker.DontLink; // faster
|
||||||
|
mtouch.Registrar = MTouchRegistrar.Static;
|
||||||
|
mtouch.CreateTemporaryApp (extraCode: code, extraArg: "-debug");
|
||||||
|
mtouch.WarnAsError = new int [] { 4176 };
|
||||||
|
mtouch.AssertExecuteFailure ("build");
|
||||||
|
mtouch.AssertError (4176, "Unable to locate the delegate to block conversion type for the return value of the method NS.Consumer.GetFunction.", "testApp.cs", 11);
|
||||||
|
mtouch.AssertError (4176, "Unable to locate the delegate to block conversion type for the return value of the method NS.Consumer.get_GetProperty.", "testApp.cs", 17);
|
||||||
|
mtouch.AssertErrorCount (2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void NoWarnings ()
|
public void NoWarnings ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,15 +148,29 @@ typedef unsigned int (^RegistrarTestBlock) (unsigned int magic);
|
||||||
-(void) idAsIntPtr: (id)p1;
|
-(void) idAsIntPtr: (id)p1;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
typedef void (^int_callback)(int32_t magic_number);
|
||||||
@protocol ObjCProtocolBlockTest
|
@protocol ObjCProtocolBlockTest
|
||||||
@required
|
@required
|
||||||
-(void) requiredCallback: (void (^)(int32_t magic_number))completionHandler;
|
-(void) requiredCallback: (int_callback)completionHandler;
|
||||||
+(void) requiredStaticCallback: (void (^)(int32_t magic_number))completionHandler;
|
+(void) requiredStaticCallback: (int_callback)completionHandler;
|
||||||
|
-(int_callback) requiredReturnValue;
|
||||||
|
+(int_callback) requiredStaticReturnValue;
|
||||||
@optional
|
@optional
|
||||||
-(void) optionalCallback: (void (^)(int32_t magic_number))completionHandler;
|
-(void) optionalCallback: (int_callback)completionHandler;
|
||||||
+(void) optionalStaticCallback: (void (^)(int32_t magic_number))completionHandler;
|
+(void) optionalStaticCallback: (int_callback)completionHandler;
|
||||||
|
-(int_callback) optionalReturnValue;
|
||||||
|
+(int_callback) optionalStaticReturnValue;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
typedef void (^simple_callback)();
|
||||||
|
@protocol ProtocolWithBlockProperties
|
||||||
|
@required
|
||||||
|
@property simple_callback myRequiredProperty;
|
||||||
|
@property (class) simple_callback myRequiredStaticProperty;
|
||||||
|
@optional
|
||||||
|
@property simple_callback myOptionalProperty;
|
||||||
|
@property (class) simple_callback myOptionalStaticProperty;
|
||||||
|
@end
|
||||||
@interface ObjCBlockTester : NSObject {
|
@interface ObjCBlockTester : NSObject {
|
||||||
}
|
}
|
||||||
@property (retain) NSObject<ObjCProtocolBlockTest>* TestObject;
|
@property (retain) NSObject<ObjCProtocolBlockTest>* TestObject;
|
||||||
|
@ -175,6 +189,12 @@ typedef void (^outerBlock) (innerBlock callback);
|
||||||
|
|
||||||
-(void) testFreedBlocks;
|
-(void) testFreedBlocks;
|
||||||
+(int) freedBlockCount;
|
+(int) freedBlockCount;
|
||||||
|
|
||||||
|
+(void) callProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
|
||||||
|
+(void) callProtocolWithBlockReturnValue: (id<ObjCProtocolBlockTest>) obj required: (bool) required instance: (bool) instance;
|
||||||
|
|
||||||
|
+(void) setProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
|
||||||
|
+(int) calledBlockCount;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface FreedNotifier : NSObject {
|
@interface FreedNotifier : NSObject {
|
||||||
|
|
|
@ -527,6 +527,7 @@ static UltimateMachine *shared;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static volatile int freed_blocks = 0;
|
static volatile int freed_blocks = 0;
|
||||||
|
static volatile int called_blocks = 0;
|
||||||
|
|
||||||
@implementation ObjCBlockTester
|
@implementation ObjCBlockTester
|
||||||
static Class _TestClass = NULL;
|
static Class _TestClass = NULL;
|
||||||
|
@ -654,6 +655,73 @@ static Class _TestClass = NULL;
|
||||||
{
|
{
|
||||||
return freed_blocks;
|
return freed_blocks;
|
||||||
}
|
}
|
||||||
|
+(int) calledBlockCount
|
||||||
|
{
|
||||||
|
return called_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void block_called ()
|
||||||
|
{
|
||||||
|
OSAtomicIncrement32 (&called_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
+(void) callProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
|
||||||
|
{
|
||||||
|
if (required) {
|
||||||
|
if (instance) {
|
||||||
|
obj.myRequiredProperty ();
|
||||||
|
} else {
|
||||||
|
[[(NSObject *) obj class] myRequiredStaticProperty] ();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (instance) {
|
||||||
|
obj.myOptionalProperty ();
|
||||||
|
} else {
|
||||||
|
[[(NSObject *) obj class] myOptionalStaticProperty] ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+(void) callProtocolWithBlockReturnValue: (id<ObjCProtocolBlockTest>) obj required: (bool) required instance: (bool) instance;
|
||||||
|
{
|
||||||
|
if (required) {
|
||||||
|
if (instance) {
|
||||||
|
[obj requiredReturnValue] (42);
|
||||||
|
} else {
|
||||||
|
[[(NSObject *) obj class] requiredStaticReturnValue] (42);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (instance) {
|
||||||
|
[obj optionalReturnValue] (42);
|
||||||
|
} else {
|
||||||
|
[[(NSObject *) obj class] optionalStaticReturnValue] (42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+(void) callProtocolWithBlockPropertiesRequired: (id<ProtocolWithBlockProperties>) obj
|
||||||
|
{
|
||||||
|
obj.myRequiredProperty ();
|
||||||
|
}
|
||||||
|
|
||||||
|
+(void) setProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance
|
||||||
|
{
|
||||||
|
simple_callback callback = ^{ block_called (); };
|
||||||
|
if (required) {
|
||||||
|
if (instance) {
|
||||||
|
obj.myRequiredProperty = callback;
|
||||||
|
} else {
|
||||||
|
[[(NSObject *) obj class] setMyRequiredStaticProperty: callback];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (instance) {
|
||||||
|
obj.myOptionalProperty = callback;
|
||||||
|
} else {
|
||||||
|
[[(NSObject *) obj class] setMyOptionalStaticProperty: callback];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FreedNotifier
|
@implementation FreedNotifier
|
||||||
|
|
|
@ -194,7 +194,7 @@ namespace xharness
|
||||||
void LoadConfig ()
|
void LoadConfig ()
|
||||||
{
|
{
|
||||||
ParseConfigFiles ();
|
ParseConfigFiles ();
|
||||||
var src_root = Path.GetDirectoryName (RootDirectory);
|
var src_root = Path.GetDirectoryName (Path.GetFullPath (RootDirectory));
|
||||||
MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "external", "mono"));
|
MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "external", "mono"));
|
||||||
WATCH_MONO_PATH = make_config ["WATCH_MONO_PATH"];
|
WATCH_MONO_PATH = make_config ["WATCH_MONO_PATH"];
|
||||||
TVOS_MONO_PATH = MONO_PATH;
|
TVOS_MONO_PATH = MONO_PATH;
|
||||||
|
|
|
@ -2708,7 +2708,7 @@ function toggleAll (show)
|
||||||
xbuild.StartInfo.EnvironmentVariables ["MSBuildExtensionsPath"] = null;
|
xbuild.StartInfo.EnvironmentVariables ["MSBuildExtensionsPath"] = null;
|
||||||
LogEvent (log, "Building {0} ({1})", TestName, Mode);
|
LogEvent (log, "Building {0} ({1})", TestName, Mode);
|
||||||
if (!Harness.DryRun) {
|
if (!Harness.DryRun) {
|
||||||
var timeout = TimeSpan.FromMinutes (15);
|
var timeout = TimeSpan.FromMinutes (60);
|
||||||
var result = await xbuild.RunAsync (log, true, timeout);
|
var result = await xbuild.RunAsync (log, true, timeout);
|
||||||
if (result.TimedOut) {
|
if (result.TimedOut) {
|
||||||
ExecutionResult = TestExecutingResult.TimedOut;
|
ExecutionResult = TestExecutingResult.TimedOut;
|
||||||
|
|
|
@ -366,6 +366,15 @@ namespace xharness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override StreamReader GetReader ()
|
||||||
|
{
|
||||||
|
if (File.Exists (CapturePath)) {
|
||||||
|
return new StreamReader (new FileStream (CapturePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||||
|
} else {
|
||||||
|
return new StreamReader (new MemoryStream ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Flush ()
|
public override void Flush ()
|
||||||
{
|
{
|
||||||
base.Flush ();
|
base.Flush ();
|
||||||
|
|
|
@ -380,6 +380,11 @@ namespace xharness
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetMtouchLink (this XmlDocument csproj, string platform, string configuration)
|
||||||
|
{
|
||||||
|
return GetNode (csproj, "MtouchLink", platform, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
public static void SetMtouchUseLlvm (this XmlDocument csproj, bool value, string platform, string configuration)
|
public static void SetMtouchUseLlvm (this XmlDocument csproj, bool value, string platform, string configuration)
|
||||||
{
|
{
|
||||||
SetNode (csproj, "MtouchUseLlvm", true ? "true" : "false", platform, configuration);
|
SetNode (csproj, "MtouchUseLlvm", true ? "true" : "false", platform, configuration);
|
||||||
|
@ -390,6 +395,17 @@ namespace xharness
|
||||||
SetNode (csproj, "MtouchEnableBitcode", true ? "true" : "false", platform, configuration);
|
SetNode (csproj, "MtouchEnableBitcode", true ? "true" : "false", platform, configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<XmlNode> GetPropertyGroups (this XmlDocument csproj, string platform, string configuration)
|
||||||
|
{
|
||||||
|
var propertyGroups = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup' and @Condition]");
|
||||||
|
foreach (XmlNode node in propertyGroups) {
|
||||||
|
if (!EvaluateCondition (node, platform, configuration))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
yield return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void SetNode (this XmlDocument csproj, string node, string value, string platform, string configuration)
|
public static void SetNode (this XmlDocument csproj, string node, string value, string platform, string configuration)
|
||||||
{
|
{
|
||||||
var projnode = csproj.SelectElementNodes (node);
|
var projnode = csproj.SelectElementNodes (node);
|
||||||
|
@ -417,6 +433,16 @@ namespace xharness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetNode (this XmlDocument csproj, string name, string platform, string configuration)
|
||||||
|
{
|
||||||
|
foreach (var pg in GetPropertyGroups (csproj, platform, configuration)) {
|
||||||
|
foreach (XmlNode node in pg.ChildNodes)
|
||||||
|
if (node.Name == name)
|
||||||
|
return node.InnerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetImport (this XmlDocument csproj)
|
public static string GetImport (this XmlDocument csproj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,6 +84,13 @@ namespace xharness
|
||||||
csproj.SetMtouchUseBitcode (true, "iPhone", "Release");
|
csproj.SetMtouchUseBitcode (true, "iPhone", "Release");
|
||||||
csproj.SetMtouchUseLlvm (true, "iPhone", "Release");
|
csproj.SetMtouchUseLlvm (true, "iPhone", "Release");
|
||||||
|
|
||||||
|
// Not linking a watch extensions requires passing -Os to the native compiler.
|
||||||
|
// https://github.com/mono/mono/issues/9867
|
||||||
|
var configurations = new string [] { "Debug", "Debug32", "Release", "Release32", "Release-bitcode" };
|
||||||
|
foreach (var c in configurations)
|
||||||
|
if (csproj.GetMtouchLink ("iPhone", c) == "None")
|
||||||
|
csproj.AddExtraMtouchArgs ("--gcc_flags=-Os", "iPhone", c);
|
||||||
|
|
||||||
Harness.Save (csproj, WatchOSExtensionProjectPath);
|
Harness.Save (csproj, WatchOSExtensionProjectPath);
|
||||||
|
|
||||||
WatchOSExtensionGuid = csproj.GetProjectGuid ();
|
WatchOSExtensionGuid = csproj.GetProjectGuid ();
|
||||||
|
|
|
@ -45,6 +45,14 @@
|
||||||
<Variable name="MONO_ENV_OPTIONS" value="--trace=E:all" />
|
<Variable name="MONO_ENV_OPTIONS" value="--trace=E:all" />
|
||||||
</EnvironmentVariables>
|
</EnvironmentVariables>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Makefile.inc' ">
|
||||||
|
<StartAction>Project</StartAction>
|
||||||
|
<StartArguments>--configure --autoconf --rootdir ..</StartArguments>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Makefile-mac.inc' ">
|
||||||
|
<StartAction>Project</StartAction>
|
||||||
|
<StartArguments>--configure --autoconf --rootdir .. --mac </StartArguments>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
|
|
|
@ -1397,12 +1397,64 @@ namespace Registrar {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DelegateProxyAttribute GetDelegateProxyAttribute (MethodDefinition method)
|
||||||
|
{
|
||||||
|
if (!TryGetAttribute (method.MethodReturnType, ObjCRuntime, "DelegateProxyAttribute", out var attrib))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var rv = new DelegateProxyAttribute ();
|
||||||
|
|
||||||
|
switch (attrib.ConstructorArguments.Count) {
|
||||||
|
case 1:
|
||||||
|
rv.DelegateType = ((TypeReference) attrib.ConstructorArguments [0].Value).Resolve ();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw ErrorHelper.CreateError (4124, "Invalid DelegateProxyAttribute found on '{0}'. Please file a bug report at https://bugzilla.xamarin.com", ((MethodReference) method)?.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
protected override string PlatformName {
|
protected override string PlatformName {
|
||||||
get {
|
get {
|
||||||
return App.PlatformName;
|
return App.PlatformName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProtocolMemberAttribute GetProtocolMemberAttribute (TypeReference type, string selector, ObjCMethod obj_method, MethodDefinition method)
|
||||||
|
{
|
||||||
|
var memberAttributes = GetProtocolMemberAttributes (type);
|
||||||
|
foreach (var attrib in memberAttributes) {
|
||||||
|
if (attrib.IsStatic != method.IsStatic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (attrib.IsProperty) {
|
||||||
|
if (method.IsSetter && attrib.SetterSelector != selector)
|
||||||
|
continue;
|
||||||
|
else if (method.IsGetter && attrib.GetterSelector != selector)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (attrib.Selector != selector)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj_method.IsPropertyAccessor) {
|
||||||
|
var attribParameters = new TypeReference [attrib.ParameterType?.Length ?? 0];
|
||||||
|
for (var i = 0; i < attribParameters.Length; i++) {
|
||||||
|
attribParameters [i] = attrib.ParameterType [i];
|
||||||
|
if (attrib.ParameterByRef [i])
|
||||||
|
attribParameters [i] = new ByReferenceType (attribParameters [i]);
|
||||||
|
}
|
||||||
|
if (!ParametersMatch (method.Parameters, attribParameters))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected override IEnumerable<ProtocolMemberAttribute> GetProtocolMemberAttributes (TypeReference type)
|
protected override IEnumerable<ProtocolMemberAttribute> GetProtocolMemberAttributes (TypeReference type)
|
||||||
{
|
{
|
||||||
var td = type.Resolve ();
|
var td = type.Resolve ();
|
||||||
|
@ -1434,6 +1486,9 @@ namespace Registrar {
|
||||||
case "ReturnType":
|
case "ReturnType":
|
||||||
rv.ReturnType = (TypeReference)prop.Argument.Value;
|
rv.ReturnType = (TypeReference)prop.Argument.Value;
|
||||||
break;
|
break;
|
||||||
|
case "ReturnTypeDelegateProxy":
|
||||||
|
rv.ReturnTypeDelegateProxy = (TypeReference) prop.Argument.Value;
|
||||||
|
break;
|
||||||
case "ParameterType":
|
case "ParameterType":
|
||||||
if (prop.Argument.Value != null) {
|
if (prop.Argument.Value != null) {
|
||||||
var arr = (CustomAttributeArgument[])prop.Argument.Value;
|
var arr = (CustomAttributeArgument[])prop.Argument.Value;
|
||||||
|
@ -3071,8 +3126,7 @@ namespace Registrar {
|
||||||
sb.WriteLine (map.ToString ());
|
sb.WriteLine (map.ToString ());
|
||||||
sb.WriteLine (map_init.ToString ());
|
sb.WriteLine (map_init.ToString ());
|
||||||
|
|
||||||
if (exceptions.Count > 0)
|
ErrorHelper.ThrowIfErrors (exceptions);
|
||||||
throw new AggregateException (exceptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HasIntPtrBoolCtor (TypeDefinition type)
|
static bool HasIntPtrBoolCtor (TypeDefinition type)
|
||||||
|
@ -3680,7 +3734,7 @@ namespace Registrar {
|
||||||
if (creatorMethod != null) {
|
if (creatorMethod != null) {
|
||||||
token = $"0x{CreateTokenReference (creatorMethod, TokenType.Method):X} /* {creatorMethod.FullName} */ ";
|
token = $"0x{CreateTokenReference (creatorMethod, TokenType.Method):X} /* {creatorMethod.FullName} */ ";
|
||||||
} else {
|
} else {
|
||||||
ErrorHelper.Show (ErrorHelper.CreateWarning (App, 4174, method.Method, "Unable to locate the block to delegate conversion method for the method {0}'s parameter #{1}.",
|
exceptions.Add (ErrorHelper.CreateWarning (App, 4174, method.Method, "Unable to locate the block to delegate conversion method for the method {0}'s parameter #{1}.",
|
||||||
method.DescriptiveMethodName, i + 1));
|
method.DescriptiveMethodName, i + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3832,6 +3886,7 @@ namespace Registrar {
|
||||||
setup_return.AppendLine ("res = nsstr;");
|
setup_return.AppendLine ("res = nsstr;");
|
||||||
} else if (IsDelegate (type.Resolve ())) {
|
} else if (IsDelegate (type.Resolve ())) {
|
||||||
var signature = "NULL";
|
var signature = "NULL";
|
||||||
|
var token = "INVALID_TOKEN_REF";
|
||||||
if (App.Optimizations.OptimizeBlockLiteralSetupBlock == true) {
|
if (App.Optimizations.OptimizeBlockLiteralSetupBlock == true) {
|
||||||
if (type.Is ("System", "Delegate") || type.Is ("System", "MulticastDelegate")) {
|
if (type.Is ("System", "Delegate") || type.Is ("System", "MulticastDelegate")) {
|
||||||
ErrorHelper.Show (ErrorHelper.CreateWarning (App, 4173, method.Method, $"The registrar can't compute the block signature for the delegate of type {type.FullName} in the method {descriptiveMethodName} because {type.FullName} doesn't have a specific signature."));
|
ErrorHelper.Show (ErrorHelper.CreateWarning (App, 4173, method.Method, $"The registrar can't compute the block signature for the delegate of type {type.FullName} in the method {descriptiveMethodName} because {type.FullName} doesn't have a specific signature."));
|
||||||
|
@ -3843,8 +3898,14 @@ namespace Registrar {
|
||||||
signature = "\"" + ComputeSignature (method.DeclaringType.Type, null, method, isBlockSignature: true) + "\"";
|
signature = "\"" + ComputeSignature (method.DeclaringType.Type, null, method, isBlockSignature: true) + "\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var delegateProxyType = GetDelegateProxyType (method);
|
||||||
|
if (delegateProxyType != null) {
|
||||||
|
token = $"0x{CreateTokenReference (delegateProxyType, TokenType.TypeDef):X} /* {delegateProxyType.FullName} */ ";
|
||||||
|
} else {
|
||||||
|
exceptions.Add (ErrorHelper.CreateWarning (App, 4176, method.Method, "Unable to locate the delegate to block conversion type for the return value of the method {0}.", method.DescriptiveMethodName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setup_return.AppendLine ("res = xamarin_get_block_for_delegate (managed_method, retval, {0}, &exception_gchandle);", signature);
|
setup_return.AppendLine ("res = xamarin_get_block_for_delegate (managed_method, retval, {0}, {1}, &exception_gchandle);", signature, token);
|
||||||
setup_return.AppendLine ("if (exception_gchandle != 0) goto exception_handling;");
|
setup_return.AppendLine ("if (exception_gchandle != 0) goto exception_handling;");
|
||||||
} else {
|
} else {
|
||||||
throw ErrorHelper.CreateError (4104,
|
throw ErrorHelper.CreateError (4104,
|
||||||
|
@ -4049,6 +4110,52 @@ namespace Registrar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeDefinition GetDelegateProxyType (ObjCMethod obj_method)
|
||||||
|
{
|
||||||
|
// A mirror of this method is also implemented in BlockLiteral:GetDelegateProxyType
|
||||||
|
// If this method is changed, that method will probably have to be updated too (tests!!!)
|
||||||
|
MethodDefinition method = obj_method.Method;
|
||||||
|
MethodDefinition first = method;
|
||||||
|
MethodDefinition last = null;
|
||||||
|
while (method != last) {
|
||||||
|
last = method;
|
||||||
|
var delegateProxyType = GetDelegateProxyAttribute (method);
|
||||||
|
if (delegateProxyType?.DelegateType != null)
|
||||||
|
return delegateProxyType.DelegateType;
|
||||||
|
|
||||||
|
method = GetBaseMethodInTypeHierarchy (method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Might be the implementation of an interface method, so find the corresponding
|
||||||
|
// MethodDefinition for the interface, and check for DelegateProxy attributes there as well.
|
||||||
|
var map = PrepareMethodMapping (first.DeclaringType);
|
||||||
|
if (map != null && map.TryGetValue (first, out var list)) {
|
||||||
|
if (list.Count != 1)
|
||||||
|
throw Shared.GetMT4127 (first, list);
|
||||||
|
var delegateProxyType = GetDelegateProxyAttribute (list [0]);
|
||||||
|
if (delegateProxyType?.DelegateType != null)
|
||||||
|
return delegateProxyType.DelegateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Might be an implementation of an optional protocol member.
|
||||||
|
if (obj_method.DeclaringType.Protocols != null) {
|
||||||
|
string selector = null;
|
||||||
|
|
||||||
|
foreach (var proto in obj_method.DeclaringType.Protocols) {
|
||||||
|
// We store the DelegateProxy type in the ProtocolMemberAttribute, so check those.
|
||||||
|
if (selector == null)
|
||||||
|
selector = obj_method.Selector ?? string.Empty;
|
||||||
|
if (selector != null) {
|
||||||
|
var attrib = GetProtocolMemberAttribute (proto.Type, selector, obj_method, method);
|
||||||
|
if (attrib?.ReturnTypeDelegateProxy != null)
|
||||||
|
return attrib.ReturnTypeDelegateProxy.Resolve ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
MethodDefinition GetBlockWrapperCreator (ObjCMethod obj_method, int parameter)
|
MethodDefinition GetBlockWrapperCreator (ObjCMethod obj_method, int parameter)
|
||||||
{
|
{
|
||||||
// A mirror of this method is also implemented in Runtime:GetBlockWrapperCreator
|
// A mirror of this method is also implemented in Runtime:GetBlockWrapperCreator
|
||||||
|
@ -4087,48 +4194,35 @@ namespace Registrar {
|
||||||
if (selector == null)
|
if (selector == null)
|
||||||
selector = obj_method.Selector ?? string.Empty;
|
selector = obj_method.Selector ?? string.Empty;
|
||||||
if (selector != null) {
|
if (selector != null) {
|
||||||
var memberAttributes = GetProtocolMemberAttributes (proto.Type);
|
var attrib = GetProtocolMemberAttribute (proto.Type, selector, obj_method, method);
|
||||||
foreach (var attrib in memberAttributes) {
|
if (attrib?.ParameterBlockProxy?.Length > parameter && attrib.ParameterBlockProxy [parameter] != null)
|
||||||
if (attrib.ParameterBlockProxy == null || attrib.ParameterBlockProxy.Length <= parameter || attrib.ParameterBlockProxy [parameter] == null)
|
|
||||||
continue; // no need to check anything if what we want isn't there
|
|
||||||
if (attrib.Selector != selector)
|
|
||||||
continue;
|
|
||||||
if (attrib.IsStatic != method.IsStatic)
|
|
||||||
continue;
|
|
||||||
var attribParameters = new TypeReference [attrib.ParameterType?.Length ?? 0];
|
|
||||||
for (var i = 0; i < attribParameters.Length; i++) {
|
|
||||||
attribParameters [i] = attrib.ParameterType [i];
|
|
||||||
if (attrib.ParameterByRef [i])
|
|
||||||
attribParameters [i] = new ByReferenceType (attribParameters [i]);
|
|
||||||
}
|
|
||||||
if (!ParametersMatch (method.Parameters, attribParameters))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return attrib.ParameterBlockProxy [parameter].Resolve ().Methods.First ((v) => v.Name == "Create");
|
return attrib.ParameterBlockProxy [parameter].Resolve ().Methods.First ((v) => v.Name == "Create");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proto.Methods != null) {
|
||||||
|
foreach (var pMethod in proto.Methods) {
|
||||||
|
if (!pMethod.IsOptional)
|
||||||
|
continue;
|
||||||
|
if (pMethod.Name != method.Name)
|
||||||
|
continue;
|
||||||
|
if (!TypeMatch (pMethod.ReturnType, method.ReturnType))
|
||||||
|
continue;
|
||||||
|
if (ParametersMatch (method.Parameters, pMethod.Parameters))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MethodDefinition extensionMethod = pMethod.Method;
|
||||||
|
if (extensionMethod == null) {
|
||||||
|
MapProtocolMember (obj_method.Method, out extensionMethod);
|
||||||
|
if (extensionMethod == null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var createMethod = GetBlockProxyAttributeMethod (extensionMethod, parameter + 1);
|
||||||
|
if (createMethod != null)
|
||||||
|
return createMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var pMethod in proto.Methods) {
|
|
||||||
if (!pMethod.IsOptional)
|
|
||||||
continue;
|
|
||||||
if (pMethod.Name != method.Name)
|
|
||||||
continue;
|
|
||||||
if (!TypeMatch (pMethod.ReturnType, method.ReturnType))
|
|
||||||
continue;
|
|
||||||
if (ParametersMatch (method.Parameters, pMethod.Parameters))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
MethodDefinition extensionMethod = pMethod.Method;
|
|
||||||
if (extensionMethod == null) {
|
|
||||||
MapProtocolMember (obj_method.Method, out extensionMethod);
|
|
||||||
if (extensionMethod == null)
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var createMethod = GetBlockProxyAttributeMethod (extensionMethod, parameter + 1);
|
|
||||||
if (createMethod != null)
|
|
||||||
return createMethod;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4843,6 +4937,11 @@ namespace Registrar {
|
||||||
public TypeDefinition Type { get; set; }
|
public TypeDefinition Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DelegateProxyAttribute : Attribute
|
||||||
|
{
|
||||||
|
public TypeDefinition DelegateType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
class BindAsAttribute : Attribute
|
class BindAsAttribute : Attribute
|
||||||
{
|
{
|
||||||
public BindAsAttribute (TypeReference type)
|
public BindAsAttribute (TypeReference type)
|
||||||
|
@ -4863,6 +4962,7 @@ namespace Registrar {
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Selector { get; set; }
|
public string Selector { get; set; }
|
||||||
public TypeReference ReturnType { get; set; }
|
public TypeReference ReturnType { get; set; }
|
||||||
|
public TypeReference ReturnTypeDelegateProxy { get; set; }
|
||||||
public TypeReference[] ParameterType { get; set; }
|
public TypeReference[] ParameterType { get; set; }
|
||||||
public bool[] ParameterByRef { get; set; }
|
public bool[] ParameterByRef { get; set; }
|
||||||
public TypeReference [] ParameterBlockProxy { get; set; }
|
public TypeReference [] ParameterBlockProxy { get; set; }
|
||||||
|
|
Загрузка…
Ссылка в новой задаче