Skip to content

Commit 197bd59

Browse files
[RGen] Remove boxing of Nullable<FieldInfo> in properties. (#23439)
1 parent 5041978 commit 197bd59

File tree

10 files changed

+85
-26
lines changed

10 files changed

+85
-26
lines changed

src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
<Compile Include="../Microsoft.Macios.Generator/DictionaryComparer.cs" >
4646
<Link>Generator/DictionaryComparer.cs</Link>
4747
</Compile>
48+
<Compile Include="../Microsoft.Macios.Generator/StructState.cs" >
49+
<Link>Generator/StructState.cs</Link>
50+
</Compile>
4851
<Compile Include="../Microsoft.Macios.Generator/Attributes/BindFromData.cs" >
4952
<Link>Generator/Attributes/BindFromData.cs</Link>
5053
</Compile>
@@ -72,9 +75,6 @@
7275
<Compile Include="../Microsoft.Macios.Generator/Attributes/UnsupportedOSPlatformData.cs" >
7376
<Link>Generator/Attributes/UnsupportedOSPlatformData.cs</Link>
7477
</Compile>
75-
<Compile Include="../Microsoft.Macios.Generator/DataModel/StructState.cs" >
76-
<Link>DataModel/StructState.cs</Link>
77-
</Compile>
7878
<Compile Include="../Microsoft.Macios.Generator/DataModel/AttributeCodeChange.cs" >
7979
<Link>DataModel/AttributeCodeChange.cs</Link>
8080
</Compile>

src/rgen/Microsoft.Macios.Generator/DataModel/Binding.Generator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ readonly partial struct Binding {
5555

5656
// return those libs needed by field properties
5757
foreach (var property in Properties) {
58-
if (property.ExportFieldData is null)
58+
if (property.ExportFieldData.IsNullOrDefault)
5959
continue;
60-
var (_, libraryName, libraryPath) = property.ExportFieldData.Value;
60+
var (_, libraryName, libraryPath) = property.ExportFieldData;
6161
if (visited.Add (libraryName)) // if already visited, we cannot add it
6262
yield return (libraryName, libraryPath);
6363
}

src/rgen/Microsoft.Macios.Generator/DataModel/FieldInfo.cs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ namespace Microsoft.Macios.Generator.DataModel;
1212
/// </summary>
1313
readonly struct FieldInfo<T> : IEquatable<FieldInfo<T>> where T : Enum {
1414

15+
/// <summary>
16+
/// The initialization state of the struct.
17+
/// </summary>
18+
StructState State { get; init; } = StructState.Default;
19+
20+
/// <summary>
21+
/// Gets the default, uninitialized instance of <see cref="FieldInfo{T}"/>.
22+
/// </summary>
23+
public static FieldInfo<T> Default { get; } = new (StructState.Default);
24+
25+
/// <summary>
26+
/// Gets a value indicating whether the instance is the default, uninitialized instance.
27+
/// </summary>
28+
public bool IsNullOrDefault => State == StructState.Default;
1529

1630
/// <summary>
1731
/// Name of the library that contains the smart enum definition.
@@ -28,13 +42,37 @@ namespace Microsoft.Macios.Generator.DataModel;
2842
/// </summary>
2943
public FieldData<T> FieldData { get; }
3044

31-
public FieldInfo (FieldData<T> fieldData, string libraryName, string? libraryPath = null)
45+
/// <summary>
46+
/// Initializes a new instance of the <see cref="FieldInfo{T}"/> struct.
47+
/// </summary>
48+
/// <param name="state">The initialization state.</param>
49+
public FieldInfo (StructState state)
50+
{
51+
State = state;
52+
LibraryName = string.Empty;
53+
LibraryPath = null;
54+
FieldData = default;
55+
}
56+
57+
/// <summary>
58+
/// Initializes a new instance of the <see cref="FieldInfo{T}"/> struct.
59+
/// </summary>
60+
/// <param name="fieldData">The field data.</param>
61+
/// <param name="libraryName">The library name.</param>
62+
/// <param name="libraryPath">The library path.</param>
63+
public FieldInfo (FieldData<T> fieldData, string libraryName, string? libraryPath = null) : this (StructState.Initialized)
3264
{
3365
LibraryName = libraryName;
3466
LibraryPath = libraryPath;
3567
FieldData = fieldData;
3668
}
3769

70+
/// <summary>
71+
/// Deconstructs the <see cref="FieldInfo{T}"/> into its components.
72+
/// </summary>
73+
/// <param name="fieldData">The field data.</param>
74+
/// <param name="libraryName">The library name.</param>
75+
/// <param name="libraryPath">The library path.</param>
3876
public void Deconstruct (out FieldData<T> fieldData, out string libraryName, out string? libraryPath)
3977
{
4078
fieldData = FieldData;
@@ -45,6 +83,8 @@ public void Deconstruct (out FieldData<T> fieldData, out string libraryName, out
4583
/// <inheritdoc />
4684
public bool Equals (FieldInfo<T> other)
4785
{
86+
if (State == StructState.Default && other.State == StructState.Default)
87+
return true;
4888
if (FieldData != other.FieldData)
4989
return false;
5090
if (LibraryName != other.LibraryName)
@@ -64,11 +104,23 @@ public override int GetHashCode ()
64104
return HashCode.Combine (FieldData, LibraryName, LibraryPath);
65105
}
66106

107+
/// <summary>
108+
/// Compares two <see cref="FieldInfo{T}"/> instances for equality.
109+
/// </summary>
110+
/// <param name="x">The first instance.</param>
111+
/// <param name="y">The second instance.</param>
112+
/// <returns><c>true</c> if the instances are equal, <c>false</c> otherwise.</returns>
67113
public static bool operator == (FieldInfo<T> x, FieldInfo<T> y)
68114
{
69115
return x.Equals (y);
70116
}
71117

118+
/// <summary>
119+
/// Compares two <see cref="FieldInfo{T}"/> instances for inequality.
120+
/// </summary>
121+
/// <param name="x">The first instance.</param>
122+
/// <param name="y">The second instance.</param>
123+
/// <returns><c>true</c> if the instances are not equal, <c>false</c> otherwise.</returns>
72124
public static bool operator != (FieldInfo<T> x, FieldInfo<T> y)
73125
{
74126
return !(x == y);
@@ -77,7 +129,7 @@ public override int GetHashCode ()
77129
/// <inheritdoc />
78130
public override string ToString ()
79131
{
80-
return $"FieldData = {FieldData}, LibraryName = {LibraryName}, LibraryPath = {LibraryPath ?? "null"}";
132+
return $"{{ State = {State}, FieldData = {FieldData}, LibraryName = {LibraryName}, LibraryPath = {LibraryPath ?? "null"} }}";
81133
}
82134

83135
}

src/rgen/Microsoft.Macios.Generator/DataModel/Property.Generator.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,18 @@ readonly partial struct Property {
2222
/// <summary>
2323
/// The data of the field attribute used to mark the value as a field binding.
2424
/// </summary>
25-
public FieldInfo<ObjCBindings.Property>? ExportFieldData { get; init; }
25+
public FieldInfo<ObjCBindings.Property> ExportFieldData { get; init; } = FieldInfo<ObjCBindings.Property>.Default;
2626

2727
/// <summary>
2828
/// True if the property represents a Objc field.
2929
/// </summary>
30-
[MemberNotNullWhen (true, nameof (ExportFieldData))]
31-
public bool IsField => ExportFieldData is not null;
30+
public bool IsField => !ExportFieldData.IsNullOrDefault;
3231

3332
/// <summary>
3433
/// Returns if the field was marked as a notification.
3534
/// </summary>
3635
public bool IsNotification
37-
=> IsField && ExportFieldData.Value.FieldData.Flags.HasFlag (ObjCBindings.Property.Notification);
36+
=> IsField && ExportFieldData.FieldData.Flags.HasFlag (ObjCBindings.Property.Notification);
3837

3938
/// <summary>
4039
/// The data of the field attribute used to mark the value as a property binding.
@@ -188,7 +187,7 @@ public bool RequiresDirtyCheck {
188187
public string? Selector {
189188
get {
190189
if (IsField) {
191-
return ExportFieldData.Value.FieldData.SymbolName;
190+
return ExportFieldData.FieldData.SymbolName;
192191
}
193192
if (IsProperty) {
194193
return ExportPropertyData.Value.Selector;
@@ -279,7 +278,7 @@ public static bool TryCreate (PropertyDeclarationSyntax declaration, RootContext
279278
accessors: accessorCodeChanges) {
280279
BindAs = propertySymbol.GetBindFromData (),
281280
ForcedType = propertySymbol.GetForceTypeData (),
282-
ExportFieldData = GetFieldInfo (context, propertySymbol),
281+
ExportFieldData = GetFieldInfo (context, propertySymbol) ?? FieldInfo<ObjCBindings.Property>.Default,
283282
ExportPropertyData = propertySymbol.GetExportData<ObjCBindings.Property> (),
284283
ExportStrongPropertyData = propertySymbol.GetExportData<ObjCBindings.StrongDictionaryProperty> (),
285284
};
@@ -371,8 +370,9 @@ public Property ToStrongDelegate ()
371370
/// <inheritdoc />
372371
public override string ToString ()
373372
{
373+
var fieldInfo = ExportFieldData.IsNullOrDefault ? "null" : ExportFieldData.ToString ();
374374
var sb = new StringBuilder (
375-
$"Name: '{Name}', Type: {ReturnType}, Supported Platforms: {SymbolAvailability}, ExportFieldData: '{ExportFieldData?.ToString () ?? "null"}', ExportPropertyData: '{ExportPropertyData?.ToString () ?? "null"}', ");
375+
$"Name: '{Name}', Type: {ReturnType}, Supported Platforms: {SymbolAvailability}, ExportFieldData: '{fieldInfo}', ExportPropertyData: '{ExportPropertyData?.ToString () ?? "null"}', ");
376376
sb.Append ($"IsTransient: '{IsTransient}', ");
377377
sb.Append ($"NeedsBackingField: '{NeedsBackingField}', ");
378378
sb.Append ($"RequiresDirtyCheck: '{RequiresDirtyCheck}', ");

src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Dlfcn.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,8 @@ public static ExpressionSyntax FieldConstantGetter (in Property property)
670670
throw new NotSupportedException ("Cannot retrieve getter for non field property.");
671671

672672
// retrieve all the necessary data from the info field of the property
673-
var libraryName = property.ExportFieldData.Value.LibraryName;
674-
var symbolName = property.ExportFieldData.Value.FieldData.SymbolName;
673+
var libraryName = property.ExportFieldData.LibraryName;
674+
var symbolName = property.ExportFieldData.FieldData.SymbolName;
675675
return FieldConstantGetterSetter (property).Getter (libraryName, symbolName);
676676
}
677677

@@ -692,8 +692,8 @@ public static ExpressionSyntax FieldConstantSetter (in Property property, string
692692
throw new NotSupportedException ("Cannot retrieve getter for non field property.");
693693

694694
// retrieve all the necessary data from the info field of the property
695-
var libraryName = property.ExportFieldData.Value.LibraryName;
696-
var symbolName = property.ExportFieldData.Value.FieldData.SymbolName;
695+
var libraryName = property.ExportFieldData.LibraryName;
696+
var symbolName = property.ExportFieldData.FieldData.SymbolName;
697697
return FieldConstantGetterSetter (property).Setter (libraryName, symbolName, variableName);
698698
}
699699
}

src/rgen/Microsoft.Macios.Generator/Emitters/ClassEmitter.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,12 @@ void EmitNotifications (in ImmutableArray<Property> properties, TabbedWriter<Str
294294
foreach (var notification in properties) {
295295
var count = 12; // == "Notification".Length;
296296
var name = $"Observe{notification.Name [..^count]}";
297-
var notificationCenter = notification.ExportFieldData?.FieldData.NotificationCenter ?? $"{NotificationCenter}.DefaultCenter";
298-
var eventType = notification.ExportFieldData?.FieldData.Type ?? NSNotificationEventArgs.ToString ();
297+
var notificationCenter = notification.ExportFieldData.IsNullOrDefault || notification.ExportFieldData.FieldData.NotificationCenter is null
298+
? $"{NotificationCenter}.DefaultCenter"
299+
: notification.ExportFieldData.FieldData.NotificationCenter;
300+
var eventType = notification.ExportFieldData.IsNullOrDefault || notification.ExportFieldData.FieldData.Type is null
301+
? NSNotificationEventArgs.ToString ()
302+
: notification.ExportFieldData.FieldData.Type;
299303
// use the raw writer which makes it easier to read in this case
300304
notificationClass.WriteRaw (
301305
@$"public static {NSObject} {name} ({EventHandler}<{eventType}> handler)

src/rgen/Microsoft.Macios.Generator/DataModel/StructState.cs renamed to src/rgen/Microsoft.Macios.Generator/StructState.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
namespace Microsoft.Macios.Generator.DataModel;
4+
namespace Microsoft.Macios.Generator;
55

66
/// <summary>
77
/// Represents the initialization state of a struct.

src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
<Compile Include="../Microsoft.Macios.Generator/CollectionComparer.cs">
4545
<Link>CollectionComparer.cs</Link>
4646
</Compile>
47+
<Compile Include="../Microsoft.Macios.Generator/StructState.cs" >
48+
<Link>Generator/StructState.cs</Link>
49+
</Compile>
4750
<Compile Include="../Microsoft.Macios.Generator/IO/TabbedWriter.cs">
4851
<Link>IO/TabbedWriter.cs</Link>
4952
</Compile>

tests/rgen/Microsoft.Macios.Generator.Tests/DataModel/EnumMemberCodeChangesTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public IEnumerator<object []> GetEnumerator ()
279279
attributes: []);
280280
yield return [
281281
fieldDataEnum,
282-
"{ Name: 'EnumValue' SymbolAvailability: [] FieldInfo: FieldData = { SymbolName: 'x', LibraryName: 'libName', Type: 'null', NotificationCenter: 'null', Flags: 'Default' }, LibraryName = Test, LibraryPath = /path/to/library Attributes: [] }",
282+
"{ Name: 'EnumValue' SymbolAvailability: [] FieldInfo: { State = Initialized, FieldData = { SymbolName: 'x', LibraryName: 'libName', Type: 'null', NotificationCenter: 'null', Flags: 'Default' }, LibraryName = Test, LibraryPath = /path/to/library } Attributes: [] }",
283283
];
284284

285285
var builder = SymbolAvailability.CreateBuilder ();
@@ -294,7 +294,7 @@ public IEnumerator<object []> GetEnumerator ()
294294
attributes: []);
295295
yield return [
296296
availabilityEnum,
297-
"{ Name: 'EnumValue' SymbolAvailability: [{ Platform: 'iOS', Supported: '0.0', Unsupported: [], Obsoleted: [] }] FieldInfo: FieldData = { SymbolName: 'x', LibraryName: 'libName', Type: 'null', NotificationCenter: 'null', Flags: 'Default' }, LibraryName = Test, LibraryPath = /path/to/library Attributes: [] }",
297+
"{ Name: 'EnumValue' SymbolAvailability: [{ Platform: 'iOS', Supported: '0.0', Unsupported: [], Obsoleted: [] }] FieldInfo: { State = Initialized, FieldData = { SymbolName: 'x', LibraryName: 'libName', Type: 'null', NotificationCenter: 'null', Flags: 'Default' }, LibraryName = Test, LibraryPath = /path/to/library } Attributes: [] }",
298298
];
299299

300300
var attrsEnum = new EnumMember (
@@ -309,7 +309,7 @@ public IEnumerator<object []> GetEnumerator ()
309309
]);
310310
yield return [
311311
attrsEnum,
312-
"{ Name: 'EnumValue' SymbolAvailability: [{ Platform: 'iOS', Supported: '0.0', Unsupported: [], Obsoleted: [] }] FieldInfo: FieldData = { SymbolName: 'x', LibraryName: 'libName', Type: 'null', NotificationCenter: 'null', Flags: 'Default' }, LibraryName = Test, LibraryPath = /path/to/library Attributes: [{ Name: Attribute1, Arguments: [] }, { Name: Attribute2, Arguments: [] }] }",
312+
"{ Name: 'EnumValue' SymbolAvailability: [{ Platform: 'iOS', Supported: '0.0', Unsupported: [], Obsoleted: [] }] FieldInfo: { State = Initialized, FieldData = { SymbolName: 'x', LibraryName: 'libName', Type: 'null', NotificationCenter: 'null', Flags: 'Default' }, LibraryName = Test, LibraryPath = /path/to/library } Attributes: [{ Name: Attribute1, Arguments: [] }, { Name: Attribute2, Arguments: [] }] }",
313313
];
314314
}
315315

tests/rgen/Microsoft.Macios.Generator.Tests/DataModel/PropertyTests/GeneralPropertyTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void BackingFieldStaticFieldTests (string propertyName)
2828
modifiers: [Token (SyntaxKind.StaticKeyword)],
2929
accessors: []
3030
) {
31-
ExportFieldData = new ()
31+
ExportFieldData = new (StructState.Initialized)
3232
};
3333
Assert.Equal ($"_{propertyName}", property.BackingField);
3434
}
@@ -47,7 +47,7 @@ public void BackingFieldTests (string propertyName, bool isStatic)
4747
modifiers: isStatic ? [Token (SyntaxKind.StaticKeyword)] : [],
4848
accessors: []
4949
) {
50-
ExportFieldData = null,
50+
ExportFieldData = FieldInfo<ObjCBindings.Property>.Default,
5151
};
5252
Assert.Equal (Nomenclator.GetPropertyBackingFieldName (propertyName, isStatic), property.BackingField);
5353
}

0 commit comments

Comments
 (0)