Skip to content

Commit a5ac0ea

Browse files
authored
[generator] Add C#8 nullability into generated code (dotnet#7570)
Goals * Reflect Apple nullability annotations in our bindings using C#8 * No warnings when building bindings Non-Goals * Update (add or fix) `[NullAllowed]` to match Apple headers (next phase) * Make the generator or internal code fully nullable aware (`nowarn` is used) Notes * Apple's own annotations are not 100% accurate :( * Where known issue exists we have _fixed_ our attributes to match reality :) * We also do additional null-checks internally that might seems not required (better safe than sorry).
1 parent e668545 commit a5ac0ea

File tree

73 files changed

+673
-527
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+673
-527
lines changed

msbuild/tests/MyBindingsReferences/LibraryA/LibraryA.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<AssemblyName>LibraryA</AssemblyName>
1212
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
1313
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
14+
<LangVersion>latest</LangVersion>
1415
</PropertyGroup>
1516
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1617
<DebugSymbols>true</DebugSymbols>

msbuild/tests/MyBindingsReferences/LibraryB/LibraryB.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<AssemblyName>LibraryB</AssemblyName>
1212
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
1313
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
14+
<LangVersion>latest</LangVersion>
1415
</PropertyGroup>
1516
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1617
<DebugSymbols>true</DebugSymbols>

msbuild/tests/MySatelliteAssembliesBug/iOSBinding/iOSBinding.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<RootNamespace>iOSBinding</RootNamespace>
1010
<AssemblyName>iOSBinding</AssemblyName>
1111
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
12+
<LangVersion>latest</LangVersion>
1213
</PropertyGroup>
1314
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1415
<DebugSymbols>true</DebugSymbols>

msbuild/tests/MyiOSAppWithBinding/MyiOSAppWithBinding.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<RootNamespace>MyiOSAppWithBinding</RootNamespace>
1010
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
1111
<AssemblyName>MyiOSAppWithBinding</AssemblyName>
12+
<LangVersion>latest</LangVersion>
1213
</PropertyGroup>
1314
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
1415
<DebugSymbols>true</DebugSymbols>

msbuild/tests/MyiOSFrameworkBinding/MyiOSFrameworkBinding.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<RootNamespace>MyiOSFrameworkBinding</RootNamespace>
1111
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
1212
<AssemblyName>MyiOSFrameworkBinding</AssemblyName>
13+
<LangVersion>latest</LangVersion>
1314
</PropertyGroup>
1415
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
1516
<DebugSymbols>true</DebugSymbols>

src/Foundation/DictionaryContainer.cs

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#endif // !WATCH
4141
#endif
4242

43+
#nullable enable
44+
4345
namespace Foundation {
4446

4547
public abstract class DictionaryContainer
@@ -50,16 +52,14 @@ protected DictionaryContainer ()
5052
Dictionary = new NSMutableDictionary ();
5153
}
5254

53-
protected DictionaryContainer (NSDictionary dictionary)
55+
protected DictionaryContainer (NSDictionary? dictionary)
5456
{
55-
if (dictionary == null)
56-
throw new ArgumentNullException ("dictionary");
57-
Dictionary = dictionary;
57+
Dictionary = dictionary ?? new NSMutableDictionary ();
5858
}
5959

6060
public NSDictionary Dictionary { get; private set; }
6161

62-
protected T[] GetArray<T> (NSString key) where T : NSObject
62+
protected T[]? GetArray<T> (NSString key) where T : NSObject
6363
{
6464
if (key == null)
6565
throw new ArgumentNullException ("key");
@@ -71,7 +71,7 @@ protected T[] GetArray<T> (NSString key) where T : NSObject
7171
return NSArray.ArrayFromHandle<T> (value);
7272
}
7373

74-
protected T[] GetArray<T> (NSString key, Func<IntPtr, T> creator)
74+
protected T[]? GetArray<T> (NSString key, Func<IntPtr, T> creator)
7575
{
7676
if (key == null)
7777
throw new ArgumentNullException ("key");
@@ -199,15 +199,15 @@ protected T[] GetArray<T> (NSString key, Func<IntPtr, T> creator)
199199
return CFBoolean.GetValue (value);
200200
}
201201

202-
protected T GetNativeValue<T> (NSString key) where T : class, INativeObject
202+
protected T? GetNativeValue<T> (NSString key) where T : class, INativeObject
203203
{
204204
if (key == null)
205205
throw new ArgumentNullException ("key");
206206

207207
return Runtime.GetINativeObject<T> (Dictionary.LowlevelObjectForKey (key.Handle), false);
208208
}
209209

210-
protected NSDictionary GetNSDictionary (NSString key)
210+
protected NSDictionary? GetNSDictionary (NSString key)
211211
{
212212
if (key == null)
213213
throw new ArgumentNullException ("key");
@@ -218,7 +218,7 @@ protected NSDictionary GetNSDictionary (NSString key)
218218
}
219219

220220
#if XAMCORE_2_0
221-
protected NSDictionary <TKey, TValue> GetNSDictionary <TKey, TValue> (NSString key)
221+
protected NSDictionary <TKey, TValue>? GetNSDictionary <TKey, TValue> (NSString key)
222222
where TKey : class, INativeObject
223223
where TValue : class, INativeObject
224224
{
@@ -231,22 +231,20 @@ protected NSDictionary GetNSDictionary (NSString key)
231231
}
232232
#endif
233233

234-
protected T GetStrongDictionary<T> (NSString key) where T : DictionaryContainer
234+
protected T? GetStrongDictionary<T> (NSString key) where T : DictionaryContainer
235235
{
236236
if (key == null)
237237
throw new ArgumentNullException ("key");
238238

239239
var dict = GetNSDictionary (key);
240240
if (dict == null)
241241
return null;
242-
T value = (T)Activator.CreateInstance (typeof(T),
242+
return (T?) Activator.CreateInstance (typeof(T),
243243
new object[] { dict }
244244
);
245-
246-
return value;
247245
}
248246

249-
protected NSString GetNSStringValue (NSString key)
247+
protected NSString? GetNSStringValue (NSString key)
250248
{
251249
if (key == null)
252250
throw new ArgumentNullException ("key");
@@ -256,7 +254,7 @@ protected NSString GetNSStringValue (NSString key)
256254
return value as NSString;
257255
}
258256

259-
protected string GetStringValue (NSString key)
257+
protected string? GetStringValue (NSString key)
260258
{
261259
if (key == null)
262260
throw new ArgumentNullException ("key");
@@ -268,7 +266,7 @@ protected string GetStringValue (NSString key)
268266
return CFString.FetchString (value.Handle);
269267
}
270268

271-
protected string GetStringValue (string key)
269+
protected string? GetStringValue (string key)
272270
{
273271
if (key == null)
274272
throw new ArgumentNullException ("key");
@@ -330,36 +328,36 @@ bool NullCheckAndRemoveKey (NSString key, bool removeEntry)
330328
return !removeEntry;
331329
}
332330

333-
protected void SetArrayValue (NSString key, NSNumber[] values)
331+
protected void SetArrayValue (NSString key, NSNumber[]? values)
334332
{
335333
if (NullCheckAndRemoveKey (key, values == null))
336334
Dictionary [key] = NSArray.FromNSObjects (values);
337335
}
338336

339-
protected void SetArrayValue<T> (NSString key, T[] values)
337+
protected void SetArrayValue<T> (NSString key, T[]? values)
340338
{
341339
if (NullCheckAndRemoveKey (key, values == null))
342340
Dictionary [key] = NSArray.FromNSObjects (values.Select (x => NSObject.FromObject (x)).ToArray ());
343341
}
344342

345-
protected void SetArrayValue (NSString key, string[] values)
343+
protected void SetArrayValue (NSString key, string[]? values)
346344
{
347345
if (NullCheckAndRemoveKey (key, values == null))
348-
Dictionary [key] = NSArray.FromStrings (values);
346+
Dictionary [key!] = NSArray.FromStrings (values);
349347
}
350348

351-
protected void SetArrayValue (NSString key, INativeObject[] values)
349+
protected void SetArrayValue (NSString key, INativeObject[]? values)
352350
{
353351
if (NullCheckAndRemoveKey (key, values == null))
354-
CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, CFArray.FromNativeObjects (values).Handle);
352+
CFMutableDictionary.SetValue (Dictionary.Handle, key!.Handle, CFArray.FromNativeObjects (values).Handle);
355353
}
356354

357355
#region Sets CFBoolean value
358356

359357
protected void SetBooleanValue (NSString key, bool? value)
360358
{
361359
if (NullCheckAndRemoveKey (key, !value.HasValue))
362-
CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, value.Value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle);
360+
CFMutableDictionary.SetValue (Dictionary.Handle, key!.Handle, value!.Value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle);
363361
}
364362

365363
#endregion
@@ -369,67 +367,67 @@ protected void SetBooleanValue (NSString key, bool? value)
369367
protected void SetNumberValue (NSString key, int? value)
370368
{
371369
if (NullCheckAndRemoveKey (key, !value.HasValue))
372-
Dictionary [key] = new NSNumber (value.Value);
370+
Dictionary [key!] = new NSNumber (value!.Value);
373371
}
374372

375373
protected void SetNumberValue (NSString key, uint? value)
376374
{
377375
if (NullCheckAndRemoveKey (key, !value.HasValue))
378-
Dictionary [key] = new NSNumber (value.Value);
376+
Dictionary [key!] = new NSNumber (value!.Value);
379377
}
380378

381379
#if XAMCORE_2_0
382380
protected void SetNumberValue (NSString key, nint? value)
383381
{
384382
if (NullCheckAndRemoveKey (key, !value.HasValue))
385-
Dictionary [key] = new NSNumber (value.Value);
383+
Dictionary [key!] = new NSNumber (value!.Value);
386384
}
387385

388386
protected void SetNumberValue (NSString key, nuint? value)
389387
{
390388
if (NullCheckAndRemoveKey (key, !value.HasValue))
391-
Dictionary [key] = new NSNumber (value.Value);
389+
Dictionary [key!] = new NSNumber (value!.Value);
392390
}
393391
#endif
394392

395393
protected void SetNumberValue (NSString key, long? value)
396394
{
397395
if (NullCheckAndRemoveKey (key, !value.HasValue))
398-
Dictionary [key] = new NSNumber (value.Value);
396+
Dictionary [key!] = new NSNumber (value!.Value);
399397
}
400398

401399
protected void SetNumberValue (NSString key, float? value)
402400
{
403401
if (NullCheckAndRemoveKey (key, !value.HasValue))
404-
Dictionary [key] = new NSNumber (value.Value);
402+
Dictionary [key!] = new NSNumber (value!.Value);
405403
}
406404

407405
protected void SetNumberValue (NSString key, double? value)
408406
{
409407
if (NullCheckAndRemoveKey (key, !value.HasValue))
410-
Dictionary [key] = new NSNumber (value.Value);
408+
Dictionary [key!] = new NSNumber (value!.Value);
411409
}
412410

413411
#endregion
414412

415413
#region Sets NSString value
416414

417-
protected void SetStringValue (NSString key, string value)
415+
protected void SetStringValue (NSString key, string? value)
418416
{
419-
SetStringValue (key, value == null ? (NSString) null : new NSString (value));
417+
SetStringValue (key, value == null ? (NSString) null! : new NSString (value));
420418
}
421419

422-
protected void SetStringValue (NSString key, NSString value)
420+
protected void SetStringValue (NSString key, NSString? value)
423421
{
424422
if (NullCheckAndRemoveKey (key, value == null))
425-
Dictionary [key] = value;
423+
Dictionary [key!] = value;
426424
}
427425

428426
#endregion
429427

430428
#region Sets Native value
431429

432-
protected void SetNativeValue (NSString key, INativeObject value, bool removeNullValue = true)
430+
protected void SetNativeValue (NSString key, INativeObject? value, bool removeNullValue = true)
433431
{
434432
if (NullCheckAndRemoveKey (key, removeNullValue && value == null))
435433
CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, value == null ? IntPtr.Zero : value.Handle);
@@ -451,26 +449,26 @@ protected void RemoveValue (NSString key)
451449
protected void SetCGRectValue (NSString key, CGRect? value)
452450
{
453451
if (NullCheckAndRemoveKey (key, !value.HasValue))
454-
Dictionary [key] = value.Value.ToDictionary ();
452+
Dictionary [key!] = value!.Value.ToDictionary ();
455453
}
456454

457455
protected void SetCGSizeValue (NSString key, CGSize? value)
458456
{
459457
if (NullCheckAndRemoveKey (key, !value.HasValue))
460-
Dictionary [key] = value.Value.ToDictionary ();
458+
Dictionary [key!] = value!.Value.ToDictionary ();
461459
}
462460

463461
protected void SetCGPointValue (NSString key, CGPoint? value)
464462
{
465463
if (NullCheckAndRemoveKey (key, !value.HasValue))
466-
Dictionary [key] = value.Value.ToDictionary ();
464+
Dictionary [key!] = value!.Value.ToDictionary ();
467465
}
468466
#endif // XAMCORE_2_0
469467
#if !WATCH
470468
protected void SetCMTimeValue (NSString key, CMTime? value)
471469
{
472470
if (NullCheckAndRemoveKey (key, !value.HasValue))
473-
Dictionary [key] = value.Value.ToDictionary ();
471+
Dictionary [key!] = value!.Value.ToDictionary ();
474472
}
475473
#endif //!WATCH
476474
#endregion
@@ -482,14 +480,14 @@ static class DictionaryContainerHelper {
482480

483481
// helper to avoid the (common pattern)
484482
// var p = x == null ? IntPtr.Zero : h.Dictionary.Handle;
485-
static public IntPtr GetHandle (this DictionaryContainer self)
483+
static public IntPtr GetHandle (this DictionaryContainer? self)
486484
{
487485
return self == null ? IntPtr.Zero : self.Dictionary.Handle;
488486
}
489487

490488
// helper to avoid the (common pattern)
491489
// var p = x == null ? null : x.Dictionary;
492-
static public NSDictionary GetDictionary (this DictionaryContainer self)
490+
static public NSDictionary? GetDictionary (this DictionaryContainer? self)
493491
{
494492
return self == null ? null : self.Dictionary;
495493
}

src/Foundation/ProtocolAttribute.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,22 @@
2424

2525
using ObjCRuntime;
2626

27+
#nullable enable
28+
2729
namespace Foundation {
2830

2931
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Interface)]
3032
public sealed class ProtocolAttribute : Attribute {
3133

3234
public ProtocolAttribute () {}
3335

34-
public Type WrapperType { get; set; }
35-
public string Name { get; set; }
36+
public Type? WrapperType { get; set; }
37+
public string? Name { get; set; }
3638
public bool IsInformal { get; set; }
3739
// In which SDK version this protocol switched from being informal (i.e. a category) to a formal protocol.
3840
// System.Version is not a valid type for attributes, so we're using a string instead.
39-
string informal_until;
40-
public string FormalSince {
41+
string? informal_until;
42+
public string? FormalSince {
4143
get {
4244
return informal_until;
4345
}
@@ -56,18 +58,18 @@ public ProtocolMemberAttribute () {}
5658
public bool IsRequired { get; set; }
5759
public bool IsProperty { get; set; }
5860
public bool IsStatic { get; set; }
59-
public string Name { get; set; }
60-
public string Selector { get; set; }
61-
public Type ReturnType { get; set; }
62-
public Type ReturnTypeDelegateProxy { get; set; }
63-
public Type[] ParameterType { get; set; }
64-
public bool[] ParameterByRef { get; set; }
65-
public Type[] ParameterBlockProxy { get; set; }
61+
public string? Name { get; set; }
62+
public string? Selector { get; set; }
63+
public Type? ReturnType { get; set; }
64+
public Type? ReturnTypeDelegateProxy { get; set; }
65+
public Type[]? ParameterType { get; set; }
66+
public bool[]? ParameterByRef { get; set; }
67+
public Type?[]? ParameterBlockProxy { get; set; }
6668
public bool IsVariadic { get; set; }
6769

68-
public Type PropertyType { get; set; }
69-
public string GetterSelector { get; set; }
70-
public string SetterSelector { get; set; }
70+
public Type? PropertyType { get; set; }
71+
public string? GetterSelector { get; set; }
72+
public string? SetterSelector { get; set; }
7173
public ArgumentSemantic ArgumentSemantic { get; set; }
7274
}
7375
}

0 commit comments

Comments
 (0)