Skip to content

Commit e06bf25

Browse files
Csla.Generator.AutoSerialization.* nullable aware
#1233
1 parent 7eab515 commit e06bf25

14 files changed

+90
-82
lines changed

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.Attributes.CSharp/Csla.Generator.AutoSerialization.Attributes.CSharp.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
<IsPackable>false</IsPackable>
1515
<BaseOutputPath>..\..\..\..\..\Bin</BaseOutputPath>
1616
<OutputPath>..\..\..\..\..\bin\packages\</OutputPath>
17+
<Nullable>enable</Nullable>
18+
<WarningsAsErrors>nullable</WarningsAsErrors>
1719
</PropertyGroup>
1820

1921
<ItemGroup>

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/Discovery/ContainerDefinitionsExtractor.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,17 @@ internal static class ContainerDefinitionsExtractor
2222
/// <returns>The definitions of all of the containers of the type for which generation is being performed</returns>
2323
public static IReadOnlyList<ExtractedContainerDefinition> GetContainerDefinitions(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
2424
{
25-
NamespaceDeclarationSyntax namespaceDeclaration;
26-
TypeDeclarationSyntax containingTypeDeclaration;
27-
List<ExtractedContainerDefinition> containers = new List<ExtractedContainerDefinition>();
25+
List<ExtractedContainerDefinition> containers = [];
2826

2927
// Iterate through the containing types should the target type be nested inside other types
30-
containingTypeDeclaration = targetTypeDeclaration;
28+
var containingTypeDeclaration = targetTypeDeclaration;
3129
while (containingTypeDeclaration.Parent is TypeDeclarationSyntax syntax)
3230
{
3331
containingTypeDeclaration = syntax;
3432
containers.Add(GetContainerDefinition(containingTypeDeclaration));
3533
}
3634

37-
namespaceDeclaration = containingTypeDeclaration.Parent as NamespaceDeclarationSyntax;
35+
var namespaceDeclaration = containingTypeDeclaration.Parent as NamespaceDeclarationSyntax;
3836
if (namespaceDeclaration is not null)
3937
{
4038
containers.Add(GetContainerDefinition(namespaceDeclaration));

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/Discovery/DefinitionExtractionContext.cs

+27-32
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,8 @@ public DefinitionExtractionContext(SemanticModel semanticModel)
3939
/// <returns>The namespace in which the type is declared, or an empty string if it is global</returns>
4040
public string GetTypeNamespace(TypeDeclarationSyntax typeDeclarationSyntax)
4141
{
42-
INamedTypeSymbol typeSymbol;
43-
44-
typeSymbol = _semanticModel.GetDeclaredSymbol(typeDeclarationSyntax) as INamedTypeSymbol;
45-
if (typeSymbol is null || typeSymbol.ContainingNamespace is null) return string.Empty;
46-
return typeSymbol.ContainingNamespace.ToString();
42+
var typeSymbol = _semanticModel.GetDeclaredSymbol(typeDeclarationSyntax) as INamedTypeSymbol;
43+
return typeSymbol?.ContainingNamespace?.ToString() ?? string.Empty;
4744
}
4845

4946
/// <summary>
@@ -53,16 +50,12 @@ public string GetTypeNamespace(TypeDeclarationSyntax typeDeclarationSyntax)
5350
/// <returns>The namespace in which the type is declared, or an empty string if it is global</returns>
5451
public string GetTypeNamespace(TypeSyntax typeSyntax)
5552
{
56-
INamedTypeSymbol typeSymbol;
57-
5853
if (typeSyntax is NullableTypeSyntax nullableTypeSyntax)
5954
{
6055
typeSyntax = nullableTypeSyntax.ElementType;
6156
}
62-
63-
typeSymbol = _semanticModel.GetSymbolInfo(typeSyntax).Symbol as INamedTypeSymbol;
64-
if (typeSymbol is null || typeSymbol.ContainingNamespace is null) return string.Empty;
65-
return typeSymbol.ContainingNamespace.ToString();
57+
var typeSymbol = _semanticModel.GetSymbolInfo(typeSyntax).Symbol as INamedTypeSymbol;
58+
return typeSymbol?.ContainingNamespace?.ToString() ?? string.Empty;
6659
}
6760

6861
/// <summary>
@@ -72,9 +65,11 @@ public string GetTypeNamespace(TypeSyntax typeSyntax)
7265
/// <returns>Boolean true if the type is decorated with the AutoSerializable attribute, otherwise false</returns>
7366
public bool IsTypeAutoSerializable(TypeDeclarationSyntax typeDeclarationSyntax)
7467
{
75-
INamedTypeSymbol typeSymbol;
76-
77-
typeSymbol = _semanticModel.GetDeclaredSymbol(typeDeclarationSyntax) as INamedTypeSymbol;
68+
if (_semanticModel.GetDeclaredSymbol(typeDeclarationSyntax) is not INamedTypeSymbol typeSymbol)
69+
{
70+
return false;
71+
}
72+
7873
return IsTypeDecoratedBy(typeSymbol, _autoSerializableAttributeName, _serializationNamespace);
7974
}
8075

@@ -85,10 +80,11 @@ public bool IsTypeAutoSerializable(TypeDeclarationSyntax typeDeclarationSyntax)
8580
/// <returns>Boolean true if the type is decorated with the AutoSerializable attribute, otherwise false</returns>
8681
public bool IsTypeAutoSerializable(TypeSyntax typeSyntax)
8782
{
88-
INamedTypeSymbol typeSymbol;
89-
90-
typeSymbol = _semanticModel.GetSymbolInfo(typeSyntax).Symbol as INamedTypeSymbol;
91-
if (typeSymbol is null) return false;
83+
if(_semanticModel.GetSymbolInfo(typeSyntax).Symbol is not INamedTypeSymbol typeSymbol)
84+
{
85+
return false;
86+
}
87+
9288
return IsTypeDecoratedBy(typeSymbol, _autoSerializableAttributeName, _serializationNamespace);
9389
}
9490

@@ -100,10 +96,10 @@ public bool IsTypeAutoSerializable(TypeSyntax typeSyntax)
10096
/// <returns>Boolean true if the type implements the IMobileObject interface, otherwise false</returns>
10197
public bool DoesTypeImplementIMobileObject(TypeSyntax typeSyntax)
10298
{
103-
INamedTypeSymbol typeSymbol;
104-
105-
typeSymbol = _semanticModel.GetSymbolInfo(typeSyntax).Symbol as INamedTypeSymbol;
106-
if (typeSymbol is null) return false;
99+
if (_semanticModel.GetSymbolInfo(typeSyntax).Symbol is not INamedTypeSymbol typeSymbol)
100+
{
101+
return false;
102+
}
107103

108104
foreach (ITypeSymbol interfaceSymbol in typeSymbol.AllInterfaces)
109105
{
@@ -180,11 +176,9 @@ private bool IsTypeDecoratedBy(INamedTypeSymbol typeSymbol, string desiredAttrib
180176
/// <returns>Boolean true if the type is decorated with the attribute, otherwise false</returns>
181177
private bool IsPropertyDecoratedWith(PropertyDeclarationSyntax propertyDeclaration, string desiredAttributeTypeName, string desiredAttributeTypeNamespace)
182178
{
183-
INamedTypeSymbol appliedAttributeSymbol;
184-
185179
foreach (AttributeSyntax attributeSyntax in propertyDeclaration.AttributeLists.SelectMany(al => al.Attributes))
186180
{
187-
appliedAttributeSymbol = _semanticModel.GetTypeInfo(attributeSyntax).Type as INamedTypeSymbol;
181+
var appliedAttributeSymbol = _semanticModel.GetTypeInfo(attributeSyntax).Type as INamedTypeSymbol;
188182
if (IsMatchingTypeSymbol(appliedAttributeSymbol, desiredAttributeTypeName, desiredAttributeTypeNamespace))
189183
{
190184
return true;
@@ -202,11 +196,9 @@ private bool IsPropertyDecoratedWith(PropertyDeclarationSyntax propertyDeclarati
202196
/// <returns>Boolean true if the type is decorated with the attribute, otherwise false</returns>
203197
private bool IsFieldDecoratedWith(FieldDeclarationSyntax fieldDeclaration, string desiredAttributeTypeName, string desiredAttributeTypeNamespace)
204198
{
205-
INamedTypeSymbol appliedAttributeSymbol;
206-
207199
foreach (AttributeSyntax attributeSyntax in fieldDeclaration.AttributeLists.SelectMany(al => al.Attributes))
208200
{
209-
appliedAttributeSymbol = _semanticModel.GetTypeInfo(attributeSyntax).Type as INamedTypeSymbol;
201+
var appliedAttributeSymbol = _semanticModel.GetTypeInfo(attributeSyntax).Type as INamedTypeSymbol;
210202
if (IsMatchingTypeSymbol(appliedAttributeSymbol, desiredAttributeTypeName, desiredAttributeTypeNamespace))
211203
{
212204
return true;
@@ -222,15 +214,18 @@ private bool IsFieldDecoratedWith(FieldDeclarationSyntax fieldDeclaration, strin
222214
/// <param name="desiredTypeName">The name of the attribute whose presence we are testing for</param>
223215
/// <param name="desiredTypeNamespace">The namespace of the attribute whose presence we are testing for</param>
224216
/// <returns>Boolean true if the symbol seems to represent the desired type by name and namespace</returns>
225-
private bool IsMatchingTypeSymbol(INamedTypeSymbol appliedAttributeSymbol, string desiredTypeName, string desiredTypeNamespace)
217+
private bool IsMatchingTypeSymbol(INamedTypeSymbol? appliedAttributeSymbol, string desiredTypeName, string desiredTypeNamespace)
226218
{
227-
INamespaceSymbol namespaceSymbol;
219+
if (appliedAttributeSymbol is null)
220+
{
221+
return false;
222+
}
228223

229224
// Match on the type name
230225
if (!appliedAttributeSymbol.Name.Equals(desiredTypeName, StringComparison.InvariantCultureIgnoreCase)) return false;
231-
226+
232227
// Match on the namespace of the type
233-
namespaceSymbol = appliedAttributeSymbol.ContainingNamespace;
228+
INamespaceSymbol namespaceSymbol = appliedAttributeSymbol.ContainingNamespace;
234229
if (namespaceSymbol is null) return false;
235230
return IsMatchingNamespaceSymbol(namespaceSymbol, desiredTypeNamespace);
236231
}

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/Discovery/FieldDefinitionExtractor.cs

+12-8
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,18 @@ internal static class FieldDefinitionExtractor
2626
/// <returns>A readonly list of ExtractedFieldDefinition containing the data extracted from the syntax tree</returns>
2727
public static ExtractedFieldDefinition ExtractFieldDefinition(DefinitionExtractionContext extractionContext, FieldDeclarationSyntax fieldDeclaration)
2828
{
29-
ExtractedFieldDefinition fieldDefinition = new ExtractedFieldDefinition();
30-
31-
fieldDefinition.FieldName = GetFieldName(fieldDeclaration);
32-
fieldDefinition.TypeDefinition.TypeName = GetFieldTypeName(fieldDeclaration);
33-
fieldDefinition.TypeDefinition.TypeNamespace = extractionContext.GetTypeNamespace(fieldDeclaration.Declaration.Type);
34-
fieldDefinition.TypeDefinition.IsAutoSerializable = extractionContext.IsTypeAutoSerializable(fieldDeclaration.Declaration.Type);
35-
fieldDefinition.TypeDefinition.ImplementsIMobileObject = extractionContext.DoesTypeImplementIMobileObject(fieldDeclaration.Declaration.Type);
36-
fieldDefinition.TypeDefinition.Nullable = GetFieldTypeNullable(fieldDeclaration);
29+
var fieldDefinition = new ExtractedFieldDefinition
30+
{
31+
FieldName = GetFieldName(fieldDeclaration),
32+
TypeDefinition = new ExtractedMemberTypeDefinition
33+
{
34+
TypeName = GetFieldTypeName(fieldDeclaration),
35+
TypeNamespace = extractionContext.GetTypeNamespace(fieldDeclaration.Declaration.Type),
36+
IsAutoSerializable = extractionContext.IsTypeAutoSerializable(fieldDeclaration.Declaration.Type),
37+
ImplementsIMobileObject = extractionContext.DoesTypeImplementIMobileObject(fieldDeclaration.Declaration.Type),
38+
Nullable = GetFieldTypeNullable(fieldDeclaration)
39+
}
40+
};
3741
return fieldDefinition;
3842
}
3943

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/Discovery/PropertyDefinitionExtractor.cs

+12-8
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,18 @@ internal static class PropertyDefinitionExtractor
2626
/// <returns>A readonly list of ExtractedPropertyDefinition containing the data extracted from the syntax tree</returns>
2727
public static ExtractedPropertyDefinition ExtractPropertyDefinition(DefinitionExtractionContext extractionContext, PropertyDeclarationSyntax propertyDeclaration)
2828
{
29-
ExtractedPropertyDefinition propertyDefinition = new ExtractedPropertyDefinition();
30-
31-
propertyDefinition.PropertyName = GetPropertyName(propertyDeclaration);
32-
propertyDefinition.TypeDefinition.TypeName = GetPropertyTypeName(propertyDeclaration);
33-
propertyDefinition.TypeDefinition.TypeNamespace = extractionContext.GetTypeNamespace(propertyDeclaration.Type);
34-
propertyDefinition.TypeDefinition.IsAutoSerializable = extractionContext.IsTypeAutoSerializable(propertyDeclaration.Type);
35-
propertyDefinition.TypeDefinition.ImplementsIMobileObject = extractionContext.DoesTypeImplementIMobileObject(propertyDeclaration.Type);
36-
propertyDefinition.TypeDefinition.Nullable = GetFieldTypeNullable(propertyDeclaration);
29+
ExtractedPropertyDefinition propertyDefinition = new ExtractedPropertyDefinition
30+
{
31+
PropertyName = GetPropertyName(propertyDeclaration),
32+
TypeDefinition = new ExtractedMemberTypeDefinition
33+
{
34+
TypeName = GetPropertyTypeName(propertyDeclaration),
35+
TypeNamespace = extractionContext.GetTypeNamespace(propertyDeclaration.Type),
36+
IsAutoSerializable = extractionContext.IsTypeAutoSerializable(propertyDeclaration.Type),
37+
ImplementsIMobileObject = extractionContext.DoesTypeImplementIMobileObject(propertyDeclaration.Type),
38+
Nullable = GetFieldTypeNullable(propertyDeclaration)
39+
}
40+
};
3741

3842
return propertyDefinition;
3943
}

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/Discovery/TypeDefinitionExtractor.cs

+10-11
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,20 @@ internal static class TypeDefinitionExtractor
2727
/// <returns>ExtractedTypeDefinition containing the data extracted from the syntax tree</returns>
2828
public static ExtractedTypeDefinition ExtractTypeDefinition(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
2929
{
30-
ExtractedTypeDefinition definition = new ExtractedTypeDefinition();
3130
StringBuilder fullyQualifiedNameBuilder = new StringBuilder();
3231

33-
definition.TypeName = GetTypeName(targetTypeDeclaration);
34-
definition.TypeKind = GetTypeKind(targetTypeDeclaration);
35-
definition.Namespace = GetNamespace(targetTypeDeclaration);
36-
definition.Scope = GetScopeDefinition(targetTypeDeclaration);
32+
var definition = new ExtractedTypeDefinition
33+
{
34+
TypeName = GetTypeName(targetTypeDeclaration),
35+
TypeKind = GetTypeKind(targetTypeDeclaration),
36+
Namespace = GetNamespace(targetTypeDeclaration),
37+
Scope = GetScopeDefinition(targetTypeDeclaration),
38+
};
3739

3840
foreach (ExtractedContainerDefinition containerDefinition in ContainerDefinitionsExtractor.GetContainerDefinitions(extractionContext, targetTypeDeclaration))
3941
{
4042
definition.ContainerDefinitions.Add(containerDefinition);
41-
fullyQualifiedNameBuilder.Append(containerDefinition.Name);
42-
fullyQualifiedNameBuilder.Append('.');
43+
fullyQualifiedNameBuilder.Append(containerDefinition.Name).Append('.');
4344
}
4445

4546
foreach (ExtractedPropertyDefinition propertyDefinition in PropertyDefinitionsExtractor.ExtractPropertyDefinitions(extractionContext, targetTypeDeclaration))
@@ -73,13 +74,11 @@ private static string GetNamespace(TypeDeclarationSyntax targetTypeDeclaration)
7374

7475
// Get the containing syntax node for the type declaration
7576
// (could be a nested type, for example)
76-
SyntaxNode potentialNamespaceParent = targetTypeDeclaration.Parent;
77+
SyntaxNode? potentialNamespaceParent = targetTypeDeclaration.Parent;
7778

7879
// Keep moving "out" of nested classes etc until we get to a namespace
7980
// or until we run out of parents
80-
while (potentialNamespaceParent != null &&
81-
potentialNamespaceParent is not NamespaceDeclarationSyntax
82-
&& potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
81+
while (potentialNamespaceParent != null && potentialNamespaceParent is not NamespaceDeclarationSyntax && potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
8382
{
8483
potentialNamespaceParent = potentialNamespaceParent.Parent;
8584
}

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/ExtractedContainerDefinition.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public class ExtractedContainerDefinition
1818
/// <summary>
1919
/// The name of the container, such as the class name or namespace name
2020
/// </summary>
21-
public string Name { get; set; }
21+
public required string Name { get; init; }
2222

2323
/// <summary>
2424
/// The full definition of the container for use in source generation
2525
/// </summary>
26-
public string FullDefinition { get; set; }
26+
public required string FullDefinition { get; init; }
2727

2828
}
2929
}

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/ExtractedFieldDefinition.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public class ExtractedFieldDefinition : IMemberDefinition
1818
/// <summary>
1919
/// The name of the field
2020
/// </summary>
21-
public string FieldName { get; set; }
21+
public required string FieldName { get; init; }
2222

2323
/// <summary>
2424
/// The definition of the type of this field
2525
/// </summary>
26-
public ExtractedMemberTypeDefinition TypeDefinition { get; } = new();
26+
public required ExtractedMemberTypeDefinition TypeDefinition { get; init; }
2727

2828
/// <summary>
2929
/// The member name for the field

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/ExtractedMemberTypeDefinition.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public class ExtractedMemberTypeDefinition
1818
/// <summary>
1919
/// The name of the type
2020
/// </summary>
21-
public string TypeName { get; set; }
21+
public required string TypeName { get; init; }
2222

2323
/// <summary>
2424
/// The namespace in which the type is defined
2525
/// </summary>
26-
public string TypeNamespace { get; set; }
26+
public required string TypeNamespace { get; init; }
2727

2828
/// <summary>
2929
/// Whether the type is marked as AutoSerializable

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/ExtractedPropertyDefinition.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public class ExtractedPropertyDefinition : IMemberDefinition
1818
/// <summary>
1919
/// The name of the property
2020
/// </summary>
21-
public string PropertyName { get; set; }
21+
public required string PropertyName { get; init; }
2222

2323
/// <summary>
2424
/// The definition of the type of this property
2525
/// </summary>
26-
public ExtractedMemberTypeDefinition TypeDefinition { get; } = new();
26+
public required ExtractedMemberTypeDefinition TypeDefinition { get; init; }
2727

2828
/// <summary>
2929
/// The member name for the field

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/ExtractedTypeDefinition.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class ExtractedTypeDefinition
1818
/// <summary>
1919
/// The namespace in which the type resides
2020
/// </summary>
21-
public string Namespace { get; set; }
21+
public required string Namespace { get; init; }
2222

2323
/// <summary>
2424
/// The scope of the class
@@ -28,32 +28,32 @@ public class ExtractedTypeDefinition
2828
/// <summary>
2929
/// The name of the type, excluding any namespace
3030
/// </summary>
31-
public string TypeName { get; set; }
31+
public required string TypeName { get; init; }
3232

3333
/// <summary>
3434
/// The name of the kind of type being represented
3535
/// </summary>
36-
public string TypeKind { get; set; }
36+
public required string TypeKind { get; init; }
3737

3838
/// <summary>
3939
/// The fully qualified name of the type, including namespace
4040
/// </summary>
41-
public string FullyQualifiedName { get; set; }
41+
public string FullyQualifiedName { get; set; } = string.Empty;
4242

4343
/// <summary>
4444
/// The container definitions for this type
4545
/// </summary>
46-
public IList<ExtractedContainerDefinition> ContainerDefinitions { get; private set; } = new List<ExtractedContainerDefinition>();
46+
public IList<ExtractedContainerDefinition> ContainerDefinitions { get; private set; } = [];
4747

4848
/// <summary>
4949
/// The properties to be included in serialization
5050
/// </summary>
51-
public IList<ExtractedPropertyDefinition> Properties { get; private set; } = new List<ExtractedPropertyDefinition>();
51+
public IList<ExtractedPropertyDefinition> Properties { get; private set; } = [];
5252

5353
/// <summary>
5454
/// The fields to be included in serialization
5555
/// </summary>
56-
public IList<ExtractedFieldDefinition> Fields { get; private set; } = new List<ExtractedFieldDefinition>();
56+
public IList<ExtractedFieldDefinition> Fields { get; private set; } = [];
5757

5858
}
5959

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/GenerationResults.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ public class GenerationResults
1818
/// <summary>
1919
/// The fully qualified name of the generated type
2020
/// </summary>
21-
public string FullyQualifiedName { get; set; }
21+
public required string FullyQualifiedName { get; init; }
2222

2323
/// <summary>
2424
/// The source code that has been generated by the builder
2525
/// </summary>
26-
public string GeneratedSource { get; set; }
26+
public required string GeneratedSource { get; init; }
2727

2828
}
2929

Source/Csla.Generators/cs/AutoSerialization/Csla.Generator.AutoSerialization.CSharp/AutoSerializable/IncrementalSerializationPartialsGenerator.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
3030
{
3131
return TypeDefinitionExtractor.ExtractTypeDefinition(new DefinitionExtractionContext(ctx.SemanticModel), typeDeclarationSyntax);
3232
}
33-
return null;
33+
return default!;
3434
})
3535
.Where(static m => m is not null);
3636

0 commit comments

Comments
 (0)