Skip to content

Commit 6b31e62

Browse files
committed
Fix nullable annotation for types with generics
1 parent 2d3a2fa commit 6b31e62

4 files changed

Lines changed: 32 additions & 29 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
8+
namespace AutomaticInterface
9+
{
10+
internal sealed class AddNullableAnnotationSyntaxRewriter : CSharpSyntaxRewriter
11+
{
12+
public override SyntaxNode? VisitParameter(ParameterSyntax node)
13+
{
14+
var newNode = node;
15+
if (node.Type != null)
16+
{
17+
newNode = node.WithType(SyntaxFactory.ParseTypeName(node.Type.GetLeadingTrivia() + node.Type.ToString() + "?" + node.Type.GetTrailingTrivia()));
18+
}
19+
return base.VisitParameter(newNode);
20+
}
21+
}
22+
}

AutomaticInterface/AutomaticInterface/Builder.cs

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -192,26 +192,6 @@ private static string GetParameterDisplayString(
192192
bool nullableContextEnabled
193193
)
194194
{
195-
var paramParts = param.ToDisplayParts(FullyQualifiedDisplayFormat);
196-
var typeSb = new StringBuilder();
197-
var restSb = new StringBuilder();
198-
var isInsideType = true;
199-
// The part before the first space is the parameter type
200-
foreach (var part in paramParts)
201-
{
202-
if (isInsideType && part.Kind == SymbolDisplayPartKind.Space)
203-
{
204-
isInsideType = false;
205-
}
206-
if (isInsideType)
207-
{
208-
typeSb.Append(part.ToString());
209-
}
210-
else
211-
{
212-
restSb.Append(part.ToString());
213-
}
214-
}
215195
// If this parameter has default value null and we're enabling the nullable context, we need to force the nullable annotation if there isn't one already
216196
if (
217197
param.HasExplicitDefaultValue
@@ -220,10 +200,11 @@ bool nullableContextEnabled
220200
&& param.Type.IsReferenceType
221201
&& nullableContextEnabled
222202
)
223-
{
224-
typeSb.Append('?');
203+
{
204+
var addNullable = new AddNullableAnnotationSyntaxRewriter();
205+
return addNullable.Visit(param.DeclaringSyntaxReferences.First().GetSyntax()).ToFullString();
225206
}
226-
return typeSb.Append(restSb).ToString();
207+
return param.ToDisplayString(FullyQualifiedDisplayFormat);
227208
}
228209

229210
private static void AddEventsToInterface(List<ISymbol> members, InterfaceBuilder codeGenerator)

AutomaticInterface/Tests/Methods/Methods.WorksWithMixedOptionalNullParameters.verified.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ namespace AutomaticInterfaceExample
1212
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
1313
public partial interface IDemoClass
1414
{
15-
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.TryStartTransaction(int?, int, string)" />
16-
bool TryStartTransaction(int? param, int param2 = 0, string? data = null);
15+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.TryStartTransaction(int?, int, string, Func{int, int})" />
16+
bool TryStartTransaction(int? param, int param2 = 0, string? data = null, Func<int, int>? func = null);
1717

1818
}
1919
}

AutomaticInterface/Tests/Methods/Methods.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ namespace AutomaticInterfaceExample;
8888
[GenerateAutomaticInterface]
8989
public class DemoClass
9090
{
91-
public bool TryStartTransaction(int? param, int param2 = 0, string data = null)
92-
{
93-
return true;
94-
}
91+
public bool TryStartTransaction(int? param, int param2 = 0, string data = null, Func<int, int> func = null)
92+
{
93+
return true;
94+
}
9595
}
9696
9797

0 commit comments

Comments
 (0)