diff --git a/docs/website/generator-errors.md b/docs/website/generator-errors.md
index c6835ccf5e..0b95a9f08e 100644
--- a/docs/website/generator-errors.md
+++ b/docs/website/generator-errors.md
@@ -174,6 +174,8 @@ This usually indicates a bug in Xamarin.iOS/Xamarin.Mac; please [file a bug repo
### BI1061: The attribute '{attribute}' found on '{member}' is not a valid binding attribute. Please remove this attribute.
+### BI1062: The member '*' contains ref/out parameters and must not be decorated with [Async].
+
# BI11xx: warnings
@@ -210,6 +212,8 @@ This usually indicates a bug in Xamarin.iOS/Xamarin.Mac; please [file a bug repo
### BI1116: The parameter '*' in the delegate '*' does not have a [CCallback] or [BlockCallback] attribute. Defaulting to [CCallback]. Declare a custom delegate instead of using System.Action / System.Func and add the attribute on the corresponding parameter.
+### BI1117: The member '*' is decorated with [Static] and its container class * is decorated with [Category] this leads to hard to use code. Please inline * into * class.
+
diff --git a/src/generator.cs b/src/generator.cs
index 2e17a3cfab..90de5013e4 100644
--- a/src/generator.cs
+++ b/src/generator.cs
@@ -4110,7 +4110,7 @@ public partial class Generator : IMemberGatherer {
var hasStaticAtt = AttributeManager.HasAttribute (mi);
if (category_type != null && hasStaticAtt && !minfo.ignore_category_static_warnings) {
var baseTypeAtt = AttributeManager.GetCustomAttribute (minfo.type);
- ErrorHelper.Show (new BindingException (1117, "The {0} member is decorated with [Static] and its container class {1} is decorated with [Category] this leads to hard to use code. Please inline {0} into {2} class.", mi.Name, type.FullName, baseTypeAtt?.BaseType.FullName));
+ ErrorHelper.Show (new BindingException (1117, "The member '{0}' is decorated with [Static] and its container class {1} is decorated with [Category] this leads to hard to use code. Please inline {0} into {2} class.", mi.Name, type.FullName, baseTypeAtt?.BaseType.FullName));
}
indent++;
@@ -4885,6 +4885,21 @@ public partial class Generator : IMemberGatherer {
var mi = original_minfo.method;
var minfo = new AsyncMethodInfo (this, original_minfo.type, mi, original_minfo.category_extension_type, original_minfo.is_extension_method);
var is_void = mi.ReturnType == TypeManager.System_Void;
+
+ // Print a error if any of the method parameters or handler parameters is ref/out, it should not be asyncified.
+ if (minfo.async_initial_params != null) {
+ foreach (var param in minfo.async_initial_params) {
+ if (param.ParameterType.IsByRef) {
+ throw new BindingException (1062, true, $"The member '{original_minfo.type.Name}.{mi.Name}' contains ref/out parameters and must not be decorated with [Async].");
+ }
+ }
+ }
+ foreach (var param in minfo.async_completion_params) {
+ if (param.ParameterType.IsByRef) {
+ throw new BindingException (1062, true, $"The member '{original_minfo.type.Name}.{mi.Name}' contains ref/out parameters and must not be decorated with [Async].");
+ }
+ }
+
PrintMethodAttributes (minfo);
PrintAsyncHeader (minfo, asyncKind);
diff --git a/tests/generator/ErrorTests.cs b/tests/generator/ErrorTests.cs
index 5c5d3a1208..227bf8df78 100644
--- a/tests/generator/ErrorTests.cs
+++ b/tests/generator/ErrorTests.cs
@@ -221,7 +221,7 @@ namespace Bug52570Tests {
}
}");
bgen.AssertExecute ("build");
- bgen.AssertWarning (1117, "The SomeMethod member is decorated with [Static] and its container class Bug52570Tests.FooObject_Extensions is decorated with [Category] this leads to hard to use code. Please inline SomeMethod into Bug52570Tests.FooObject class.");
+ bgen.AssertWarning (1117, "The member 'SomeMethod' is decorated with [Static] and its container class Bug52570Tests.FooObject_Extensions is decorated with [Category] this leads to hard to use code. Please inline SomeMethod into Bug52570Tests.FooObject class.");
}
[Test]
@@ -445,12 +445,112 @@ namespace Bug57094 {
bgen.AssertError (1014, "Unsupported type for Fields: byte[] for 'Bug57094.FooObject SomeField'.");
}
+ [Test]
+ public void BI1062_NoAsyncMethodRefHandlerTest ()
+ {
+ var bgen = new BGenTool ();
+ bgen.Profile = Profile.iOS;
+ bgen.CreateTemporaryBinding (@"
+using System;
+using Foundation;
+
+namespace BI1062Tests {
+
+ delegate void MyHandler (ref bool staaph, NSError error);
+
+ [BaseType (typeof (NSObject))]
+ interface FooObject {
+
+ [Async]
+ [Export (""fooMethod:"")]
+ void FooMethod (MyHandler handler);
+ }
+}");
+ bgen.AssertExecuteError ("build");
+ bgen.AssertError (1062, "The member 'FooObject.FooMethod' contains ref/out parameters and must not be decorated with [Async].");
+ }
+
+ [Test]
+ public void BI1062_NoAsyncMethodOutHandlerTest ()
+ {
+ var bgen = new BGenTool ();
+ bgen.Profile = Profile.iOS;
+ bgen.CreateTemporaryBinding (@"
+using System;
+using Foundation;
+
+namespace BI1062Tests {
+
+ delegate void MyHandler (out bool staaph, NSError error);
+
+ [BaseType (typeof (NSObject))]
+ interface FooObject {
+
+ [Async]
+ [Export (""fooMethod:"")]
+ void FooMethod (MyHandler handler);
+ }
+}");
+ bgen.AssertExecuteError ("build");
+ bgen.AssertError (1062, "The member 'FooObject.FooMethod' contains ref/out parameters and must not be decorated with [Async].");
+ }
+
+ [Test]
+ public void BI1062_NoAsyncMethodOutParameterTest ()
+ {
+ var bgen = new BGenTool ();
+ bgen.Profile = Profile.iOS;
+ bgen.CreateTemporaryBinding (@"
+using System;
+using Foundation;
+
+namespace BI1062Tests {
+
+ delegate void MyHandler (bool staaph, NSError error);
+
+ [BaseType (typeof (NSObject))]
+ interface FooObject {
+
+ [Async]
+ [Export (""fooMethod:completion:"")]
+ void FooMethod (out NSObject obj, MyHandler handler);
+ }
+}");
+ bgen.AssertExecuteError ("build");
+ bgen.AssertError (1062, "The member 'FooObject.FooMethod' contains ref/out parameters and must not be decorated with [Async].");
+ }
+
+ [Test]
+ public void BI1062_NoAsyncMethodRefParameterTest ()
+ {
+ var bgen = new BGenTool ();
+ bgen.Profile = Profile.iOS;
+ bgen.CreateTemporaryBinding (@"
+using System;
+using Foundation;
+
+namespace BI1062Tests {
+
+ delegate void MyHandler (bool staaph, NSError error);
+
+ [BaseType (typeof (NSObject))]
+ interface FooObject {
+
+ [Async]
+ [Export (""fooMethod:completion:"")]
+ void FooMethod (ref NSObject obj, Action handler);
+ }
+}");
+ bgen.AssertExecuteError ("build");
+ bgen.AssertError (1062, "The member 'FooObject.FooMethod' contains ref/out parameters and must not be decorated with [Async].");
+ }
+
[Test]
[TestCase (Profile.iOS)]
[TestCase (Profile.macClassic)]
public void WarnAsError (Profile profile)
{
- const string message = "The SomeMethod member is decorated with [Static] and its container class warnaserrorTests.FooObject_Extensions is decorated with [Category] this leads to hard to use code. Please inline SomeMethod into warnaserrorTests.FooObject class.";
+ const string message = "The member 'SomeMethod' is decorated with [Static] and its container class warnaserrorTests.FooObject_Extensions is decorated with [Category] this leads to hard to use code. Please inline SomeMethod into warnaserrorTests.FooObject class.";
{
// Enabled
var bgen = new BGenTool ();
@@ -500,7 +600,7 @@ namespace Bug57094 {
[TestCase (Profile.macClassic)]
public void NoWarn (Profile profile)
{
- const string message = "The SomeMethod member is decorated with [Static] and its container class nowarnTests.FooObject_Extensions is decorated with [Category] this leads to hard to use code. Please inline SomeMethod into nowarnTests.FooObject class.";
+ const string message = "The member 'SomeMethod' is decorated with [Static] and its container class nowarnTests.FooObject_Extensions is decorated with [Category] this leads to hard to use code. Please inline SomeMethod into nowarnTests.FooObject class.";
{
// Enabled
var bgen = new BGenTool ();