[Generator] BindAs attribute for smart enums of an array of nullable values generates code that doesn't compile, Fixes bug 57797 (#2954)

* [Generator] BindAs attribute for smart enums of an array of nullable values generates code that doesn't compile, Fixes bug 57797

https://bugzilla.xamarin.com/show_bug.cgi?id=57797

We now correctly compiles the array nullabe types

* Disable Nullable array types in BindAs until we add registrar support
This commit is contained in:
Alex Soto 2017-11-13 10:54:21 -06:00 коммит произвёл GitHub
Родитель 84d63144f0
Коммит ee19c79feb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 107 добавлений и 9 удалений

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

@ -1307,13 +1307,13 @@ public partial class Generator : IMemberGatherer {
var arrRetType = TypeManager.GetUnderlyingNullableType (retType.GetElementType ()) ?? retType.GetElementType (); var arrRetType = TypeManager.GetUnderlyingNullableType (retType.GetElementType ()) ?? retType.GetElementType ();
var valueConverter = string.Empty; var valueConverter = string.Empty;
if (arrType == TypeManager.NSString) { if (arrType == TypeManager.NSString && !isNullable) {
valueConverter = isNullable ? "o == null ? null : " : string.Empty; valueConverter = isNullable ? "o == null ? null : " : string.Empty;
valueConverter += $"{FormatType (retType.DeclaringType, arrRetType)}Extensions.GetConstant (o), {parameterName});"; valueConverter += $"{FormatType (retType.DeclaringType, arrRetType)}Extensions.GetConstant ({(isNullable ? "o.Value" : "o")}), {parameterName});";
} else if (arrType == TypeManager.NSNumber) { } else if (arrType == TypeManager.NSNumber && !isNullable) {
var cast = arrRetType.IsEnum ? "(int)" : string.Empty; var cast = arrRetType.IsEnum ? "(int)" : string.Empty;
valueConverter = $"new NSNumber ({cast}o{denullify}), {parameterName});"; valueConverter = $"new NSNumber ({cast}o{denullify}), {parameterName});";
} else if (arrType == TypeManager.NSValue) { } else if (arrType == TypeManager.NSValue && !isNullable) {
var typeStr = string.Empty; var typeStr = string.Empty;
if (!NSValueCreateMap.TryGetValue (arrRetType, out typeStr)) { if (!NSValueCreateMap.TryGetValue (arrRetType, out typeStr)) {
if (arrRetType.Name == "RectangleF" || arrRetType.Name == "SizeF" || arrRetType.Name == "PointF") if (arrRetType.Name == "RectangleF" || arrRetType.Name == "SizeF" || arrRetType.Name == "PointF")
@ -1323,7 +1323,7 @@ public partial class Generator : IMemberGatherer {
} }
valueConverter = $"NSValue.From{typeStr} (o{denullify}), {parameterName});"; valueConverter = $"NSValue.From{typeStr} (o{denullify}), {parameterName});";
} else } else
throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", retType.Name); throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", isNullable ? arrRetType.Name + "?[]" : retType.Name);
temp = $"NSArray.FromNSObjects (o => {valueConverter}"; temp = $"NSArray.FromNSObjects (o => {valueConverter}";
} else } else
throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", retType.Name); throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", retType.Name);
@ -1449,16 +1449,16 @@ public partial class Generator : IMemberGatherer {
var arrIsNullable = nullableElementType != null; var arrIsNullable = nullableElementType != null;
var arrRetType = arrIsNullable ? nullableElementType : retType.GetElementType (); var arrRetType = arrIsNullable ? nullableElementType : retType.GetElementType ();
var valueFetcher = string.Empty; var valueFetcher = string.Empty;
if (arrType == TypeManager.NSString) if (arrType == TypeManager.NSString && !arrIsNullable)
append = $"ptr => {{\n\tusing (var str = Runtime.GetNSObject<NSString> (ptr)) {{\n\t\treturn {FormatType (arrRetType.DeclaringType, arrRetType)}Extensions.GetValue (str);\n\t}}\n}}"; append = $"ptr => {{\n\tusing (var str = Runtime.GetNSObject<NSString> (ptr)) {{\n\t\treturn {FormatType (arrRetType.DeclaringType, arrRetType)}Extensions.GetValue (str);\n\t}}\n}}";
else if (arrType == TypeManager.NSNumber) { else if (arrType == TypeManager.NSNumber && !arrIsNullable) {
if (NSNumberReturnMap.TryGetValue (arrRetType, out valueFetcher) || arrRetType.IsEnum) { if (NSNumberReturnMap.TryGetValue (arrRetType, out valueFetcher) || arrRetType.IsEnum) {
var getterStr = string.Format ("{0}{1}", arrIsNullable ? "?" : string.Empty, arrRetType.IsEnum ? ".Int32Value" : valueFetcher); var getterStr = string.Format ("{0}{1}", arrIsNullable ? "?" : string.Empty, arrRetType.IsEnum ? ".Int32Value" : valueFetcher);
append = string.Format ("ptr => {{\n\tusing (var num = Runtime.GetNSObject<NSNumber> (ptr)) {{\n\t\treturn ({1}) num{0};\n\t}}\n}}", getterStr, FormatType (arrRetType.DeclaringType, arrRetType)); append = string.Format ("ptr => {{\n\tusing (var num = Runtime.GetNSObject<NSNumber> (ptr)) {{\n\t\treturn ({1}) num{0};\n\t}}\n}}", getterStr, FormatType (arrRetType.DeclaringType, arrRetType));
} }
else else
throw new BindingException (1049, true, GetBindAsExceptionString ("unbox", retType.Name, arrType.Name, "array", minfo.mi)); throw new BindingException (1049, true, GetBindAsExceptionString ("unbox", retType.Name, arrType.Name, "array", minfo.mi));
} else if (arrType == TypeManager.NSValue) { } else if (arrType == TypeManager.NSValue && !arrIsNullable) {
if (arrRetType.Name == "RectangleF" || arrRetType.Name == "SizeF" || arrRetType.Name == "PointF") if (arrRetType.Name == "RectangleF" || arrRetType.Name == "SizeF" || arrRetType.Name == "PointF")
valueFetcher = $"{(arrIsNullable ? "?" : string.Empty)}.{arrRetType.Name}Value"; valueFetcher = $"{(arrIsNullable ? "?" : string.Empty)}.{arrRetType.Name}Value";
else if (!NSValueReturnMap.TryGetValue (arrRetType, out valueFetcher)) else if (!NSValueReturnMap.TryGetValue (arrRetType, out valueFetcher))
@ -1466,7 +1466,7 @@ public partial class Generator : IMemberGatherer {
append = string.Format ("ptr => {{\n\tusing (var val = Runtime.GetNSObject<NSValue> (ptr)) {{\n\t\treturn val{0};\n\t}}\n}}", valueFetcher); append = string.Format ("ptr => {{\n\tusing (var val = Runtime.GetNSObject<NSValue> (ptr)) {{\n\t\treturn val{0};\n\t}}\n}}", valueFetcher);
} else } else
throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", retType.Name); throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", arrIsNullable ? arrRetType.Name + "?[]" : retType.Name);
} else } else
throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", retType.Name); throw new BindingException (1048, true, "Unsupported type {0} decorated with [BindAs]", retType.Name);
return append; return append;

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

@ -23,6 +23,7 @@ namespace Xamarin.Tests
class BGenTool : Tool class BGenTool : Tool
{ {
public Profile Profile; public Profile Profile;
public bool ProcessEnums;
public List<string> ApiDefinitions = new List<string> (); public List<string> ApiDefinitions = new List<string> ();
public string TmpDirectory; public string TmpDirectory;
@ -73,6 +74,9 @@ namespace Xamarin.Tests
if (!string.IsNullOrEmpty (TmpDirectory)) if (!string.IsNullOrEmpty (TmpDirectory))
sb.Append (" --tmpdir=").Append (StringUtils.Quote (TmpDirectory)); sb.Append (" --tmpdir=").Append (StringUtils.Quote (TmpDirectory));
if (ProcessEnums)
sb.Append (" --process-enums");
return sb.ToString (); return sb.ToString ();
} }

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

@ -71,5 +71,99 @@ namespace Bug57795Tests {
bgen.AssertExecuteError ("build"); bgen.AssertExecuteError ("build");
bgen.AssertError (1048, "Unsupported type AVMediaTypes[,] decorated with [BindAs]"); bgen.AssertError (1048, "Unsupported type AVMediaTypes[,] decorated with [BindAs]");
} }
[Test]
public void BindAsNullableNSStringArrayError ()
{
// https://bugzilla.xamarin.com/show_bug.cgi?id=57797
var bgen = new BGenTool {
Profile = Profile.iOS
};
bgen.CreateTemporaryBinding (@"
using System;
using Foundation;
using ObjCRuntime;
using AVFoundation;
using CoreAnimation;
namespace Bug57797Tests {
[BaseType (typeof (NSObject))]
interface FooObject {
[BindAs (typeof (AVMediaTypes? []))]
[Export (""strongNullableAVMediaTypesProperties"")]
NSString [] StrongNullableAVMediaTypesProperties { get; set; }
}
}");
bgen.AssertExecuteError ("build");
bgen.AssertError (1048, "Unsupported type AVMediaTypes?[] decorated with [BindAs]");
}
[Test]
public void BindAsNullableNSValueArrayError ()
{
// https://bugzilla.xamarin.com/show_bug.cgi?id=57797
var bgen = new BGenTool {
Profile = Profile.iOS
};
bgen.CreateTemporaryBinding (@"
using System;
using Foundation;
using ObjCRuntime;
using AVFoundation;
using CoreAnimation;
namespace Bug57797Tests {
[BaseType (typeof (NSObject))]
interface FooObject {
[BindAs (typeof (CATransform3D? []))]
[Export (""PCATransform3DNullableArray"")]
NSValue [] PCATransform3DNullableArrayValue { get; set; }
}
}");
bgen.AssertExecuteError ("build");
bgen.AssertError (1048, "Unsupported type CATransform3D?[] decorated with [BindAs]");
}
[Test]
public void BindAsNullableNSNumberArrayError ()
{
// https://bugzilla.xamarin.com/show_bug.cgi?id=57797
var bgen = new BGenTool {
Profile = Profile.iOS,
ProcessEnums = true
};
bgen.CreateTemporaryBinding (@"
using System;
using Foundation;
using ObjCRuntime;
using AVFoundation;
using CoreAnimation;
namespace Bug57797Tests {
[Native]
enum Foo : long {
One,
Two
}
[BaseType (typeof (NSObject))]
interface FooObject {
[BindAs (typeof (Foo? []))]
[Export (""strongNullableAVMediaTypesProperties"")]
NSNumber[] StrongNullableFoo { get; set; }
}
}");
bgen.AssertExecuteError ("build");
bgen.AssertError (1048, "Unsupported type Foo?[] decorated with [BindAs]");
}
} }
} }