Skip to content

Commit 4be3916

Browse files
committed
Unconditionally generate C# classes with nullable reference types
Fixes #3944
1 parent 95a6c2a commit 4be3916

File tree

6 files changed

+20
-49
lines changed

6 files changed

+20
-49
lines changed

src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs

-17
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,6 @@ public class CSharpConventionService : CommonLanguageConventionService
1919
public static string NullableMarkerAsString => "?";
2020
public override string ParseNodeInterfaceName => "IParseNode";
2121

22-
public static void WriteNullableOpening(LanguageWriter writer)
23-
{
24-
ArgumentNullException.ThrowIfNull(writer);
25-
writer.WriteLine($"#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER", false);
26-
writer.WriteLine($"#nullable enable", false);
27-
}
28-
public static void WriteNullableMiddle(LanguageWriter writer)
29-
{
30-
ArgumentNullException.ThrowIfNull(writer);
31-
writer.WriteLine($"#nullable restore", false);
32-
writer.WriteLine("#else", false);
33-
}
34-
public static void WriteNullableClosing(LanguageWriter writer)
35-
{
36-
ArgumentNullException.ThrowIfNull(writer);
37-
writer.WriteLine("#endif", false);
38-
}
3922
public override void WriteShortDescription(string description, LanguageWriter writer)
4023
{
4124
ArgumentNullException.ThrowIfNull(writer);

src/Kiota.Builder/Writers/CSharp/CodeClassDeclarationWriter.cs

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Kiota.Builder.Writers.CSharp;
77
public class CodeClassDeclarationWriter : BaseElementWriter<ClassDeclaration, CSharpConventionService>
88
{
99
public static string AutoGenerationHeader => "// <auto-generated/>";
10+
public static string NullableHeader => "#nullable enable";
1011
public CodeClassDeclarationWriter(CSharpConventionService conventionService) : base(conventionService) { }
1112
public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWriter writer)
1213
{
@@ -17,6 +18,7 @@ public override void WriteCodeElement(ClassDeclaration codeElement, LanguageWrit
1718
if (codeElement.Parent?.Parent is CodeNamespace)
1819
{
1920
writer.WriteLine(AutoGenerationHeader);
21+
writer.WriteLine(NullableHeader);
2022
codeElement.Usings
2123
.Where(x => (x.Declaration?.IsExternal ?? true) || !x.Declaration.Name.Equals(codeElement.Name, StringComparison.OrdinalIgnoreCase)) // needed for circular requests patterns like message folder
2224
.Select(static x => x.Declaration?.IsExternal ?? false ?

src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs

+4-8
Original file line numberDiff line numberDiff line change
@@ -611,16 +611,12 @@ private void WriteMethodPrototype(CodeMethod code, CodeClass parentClass, Langua
611611
GetParameterSignatureWithNullableRefType(p, code) :
612612
conventions.GetParameterSignature(p, code))
613613
.ToList());
614-
CSharpConventionService.WriteNullableOpening(writer);
615614
writer.WriteLine($"{conventions.GetAccessModifier(code.Access)} {staticModifier}{hideModifier}{completeReturnTypeWithNullable}{methodName}({nullableParameters}){baseSuffix} {{");
616-
CSharpConventionService.WriteNullableMiddle(writer);
617615
}
618-
619-
writer.WriteLine($"{conventions.GetAccessModifier(code.Access)} {staticModifier}{hideModifier}{completeReturnType}{methodName}({parameters}){baseSuffix} {{");
620-
621-
if (includeNullableReferenceType)
622-
CSharpConventionService.WriteNullableClosing(writer);
623-
616+
else
617+
{
618+
writer.WriteLine($"{conventions.GetAccessModifier(code.Access)} {staticModifier}{hideModifier}{completeReturnType}{methodName}({parameters}){baseSuffix} {{");
619+
}
624620
}
625621

626622
private string GetParameterSignatureWithNullableRefType(CodeParameter parameter, CodeElement targetElement)

src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs

+1-11
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,7 @@ public override void WriteCodeElement(CodeProperty codeElement, LanguageWriter w
1818
CodePropertyKind.QueryParameter);// Other property types are appropriately constructor initialized
1919
conventions.WriteShortDescription(codeElement.Documentation.Description, writer);
2020
conventions.WriteDeprecationAttribute(codeElement, writer);
21-
if (isNullableReferenceType)
22-
{
23-
CSharpConventionService.WriteNullableOpening(writer);
24-
WritePropertyInternal(codeElement, writer, $"{propertyType}?");
25-
CSharpConventionService.WriteNullableMiddle(writer);
26-
}
27-
28-
WritePropertyInternal(codeElement, writer, propertyType);// Always write the normal way
29-
30-
if (isNullableReferenceType)
31-
CSharpConventionService.WriteNullableClosing(writer);
21+
WritePropertyInternal(codeElement, writer, isNullableReferenceType ? $"{propertyType}?" : propertyType);
3222
}
3323

3424
private void WritePropertyInternal(CodeProperty codeElement, LanguageWriter writer, string propertyType)

tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs

+11-11
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ public void WritesRequestExecutorBody()
478478
Assert.Contains(AsyncKeyword, result);
479479
Assert.Contains("await", result);
480480
Assert.Contains("cancellationToken", result);
481-
AssertExtensions.CurlyBracesAreClosed(result, 1);
481+
AssertExtensions.CurlyBracesAreClosed(result);
482482
}
483483
[Fact]
484484
public void WritesRequestGeneratorBodyForMultipart()
@@ -492,7 +492,7 @@ public void WritesRequestGeneratorBodyForMultipart()
492492
writer.Write(method);
493493
var result = tw.ToString();
494494
Assert.Contains("SetContentFromParsable", result);
495-
AssertExtensions.CurlyBracesAreClosed(result, 1);
495+
AssertExtensions.CurlyBracesAreClosed(result);
496496
}
497497
[Fact]
498498
public void WritesRequestExecutorBodyForCollection()
@@ -517,7 +517,7 @@ public void WritesRequestExecutorBodyForCollection()
517517
Assert.Contains("SendCollectionAsync", result);
518518
Assert.Contains("return collectionResult?.ToList()", result);
519519
Assert.Contains($"{ReturnTypeName}.CreateFromDiscriminatorValue", result);
520-
AssertExtensions.CurlyBracesAreClosed(result, 1);
520+
AssertExtensions.CurlyBracesAreClosed(result);
521521
}
522522
[Fact]
523523
public void DoesntCreateDictionaryOnEmptyErrorMapping()
@@ -530,7 +530,7 @@ public void DoesntCreateDictionaryOnEmptyErrorMapping()
530530
var result = tw.ToString();
531531
Assert.DoesNotContain("var errorMapping = new Dictionary<string, Func<IParsable>>", result);
532532
Assert.Contains("default", result);
533-
AssertExtensions.CurlyBracesAreClosed(result, 1);
533+
AssertExtensions.CurlyBracesAreClosed(result);
534534
}
535535
[Fact]
536536
public void WritesModelFactoryBodyForUnionModels()
@@ -916,7 +916,7 @@ public void WritesRequestExecutorBodyForCollections()
916916
var result = tw.ToString();
917917
Assert.Contains("SendCollectionAsync", result);
918918
Assert.Contains("cancellationToken", result);
919-
AssertExtensions.CurlyBracesAreClosed(result, 1);
919+
AssertExtensions.CurlyBracesAreClosed(result);
920920
}
921921
[Fact]
922922
public void WritesRequestGeneratorBodyForNullableScalar()
@@ -934,7 +934,7 @@ public void WritesRequestGeneratorBodyForNullableScalar()
934934
Assert.Contains("requestInfo.Configure(config)", result);
935935
Assert.Contains("SetContentFromScalar", result);
936936
Assert.Contains("return requestInfo;", result);
937-
AssertExtensions.CurlyBracesAreClosed(result, 1);
937+
AssertExtensions.CurlyBracesAreClosed(result);
938938
}
939939
[Fact]
940940
public void WritesRequestGeneratorBodyForScalar()
@@ -955,7 +955,7 @@ public void WritesRequestGeneratorBodyForScalar()
955955
Assert.Contains("return requestInfo;", result);
956956
Assert.Contains("async Task<double?>", result);//verify we only have one nullable marker
957957
Assert.DoesNotContain("async Task<double??>", result);//verify we only have one nullable marker
958-
AssertExtensions.CurlyBracesAreClosed(result, 1);
958+
AssertExtensions.CurlyBracesAreClosed(result);
959959
}
960960
[Fact]
961961
public void WritesRequestGeneratorBodyForParsable()
@@ -973,7 +973,7 @@ public void WritesRequestGeneratorBodyForParsable()
973973
Assert.Contains("requestInfo.Configure(config)", result);
974974
Assert.Contains("SetContentFromParsable", result);
975975
Assert.Contains("return requestInfo;", result);
976-
AssertExtensions.CurlyBracesAreClosed(result, 1);
976+
AssertExtensions.CurlyBracesAreClosed(result);
977977
}
978978
[Fact]
979979
public void WritesRequestGeneratorBodyForScalarCollection()
@@ -994,7 +994,7 @@ public void WritesRequestGeneratorBodyForScalarCollection()
994994
writer.Write(method);
995995
var result = tw.ToString();
996996
Assert.Contains("SetContentFromScalarCollection", result);
997-
AssertExtensions.CurlyBracesAreClosed(result, 1);
997+
AssertExtensions.CurlyBracesAreClosed(result);
998998
}
999999
[Fact]
10001000
public void WritesRequestGeneratorBodyKnownRequestBodyType()
@@ -1014,7 +1014,7 @@ public void WritesRequestGeneratorBodyKnownRequestBodyType()
10141014
var result = tw.ToString();
10151015
Assert.Contains("SetStreamContent", result, StringComparison.OrdinalIgnoreCase);
10161016
Assert.Contains("application/json", result, StringComparison.OrdinalIgnoreCase);
1017-
AssertExtensions.CurlyBracesAreClosed(result, 1);
1017+
AssertExtensions.CurlyBracesAreClosed(result);
10181018
}
10191019
[Fact]
10201020
public void WritesRequestGeneratorBodyUnknownRequestBodyType()
@@ -1044,7 +1044,7 @@ public void WritesRequestGeneratorBodyUnknownRequestBodyType()
10441044
Assert.Contains("SetStreamContent", result, StringComparison.OrdinalIgnoreCase);
10451045
Assert.DoesNotContain("application/json", result, StringComparison.OrdinalIgnoreCase);
10461046
Assert.Contains(", requestContentType", result, StringComparison.OrdinalIgnoreCase);
1047-
AssertExtensions.CurlyBracesAreClosed(result, 1);
1047+
AssertExtensions.CurlyBracesAreClosed(result);
10481048
}
10491049
[Fact]
10501050
public void WritesInheritedDeSerializerBody()

tests/Kiota.Builder.Tests/Writers/CSharp/CodePropertyWriterTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void WritesCustomProperty()
8484
property.Kind = CodePropertyKind.Custom;
8585
writer.Write(property);
8686
var result = tw.ToString();
87-
Assert.Contains($"{TypeName} {PropertyName}", result);
87+
Assert.Contains($"{TypeName}? {PropertyName}", result);
8888
Assert.Contains("get; set;", result);
8989
}
9090
[Fact]
@@ -103,7 +103,7 @@ public void MapsCustomPropertiesToBackingStore()
103103
property.Kind = CodePropertyKind.Custom;
104104
writer.Write(property);
105105
var result = tw.ToString();
106-
Assert.Contains("get { return BackingStore?.Get<SomeCustomClass>(\"propertyName\"); }", result);
106+
Assert.Contains("get { return BackingStore?.Get<SomeCustomClass?>(\"propertyName\"); }", result);
107107
Assert.Contains("set { BackingStore?.Set(\"propertyName\", value);", result);
108108
}
109109
[Fact]

0 commit comments

Comments
 (0)