Skip to content

Commit a9169dd

Browse files
committed
Fix handling of parameters with default null
1 parent becdf12 commit a9169dd

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

AutomaticInterface/AutomaticInterface/Builder.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Text;
45
using Microsoft.CodeAnalysis;
56
using Microsoft.CodeAnalysis.CSharp;
67
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -155,7 +156,7 @@ private static void AddMethod(InterfaceBuilder codeGenerator, IMethodSymbol meth
155156

156157
var paramResult = new HashSet<string>();
157158
method
158-
.Parameters.Select(x => x.ToDisplayString(FullyQualifiedDisplayFormat))
159+
.Parameters.Select(p => GetParameterDisplayString(p, codeGenerator))
159160
.ToList()
160161
.ForEach(x => paramResult.Add(x));
161162

@@ -226,6 +227,45 @@ private static bool IsNullable(ITypeSymbol typeSymbol)
226227
return false;
227228
}
228229

230+
private static string GetParameterDisplayString(
231+
IParameterSymbol param,
232+
InterfaceBuilder codeGenerator
233+
)
234+
{
235+
var paramParts = param.ToDisplayParts(FullyQualifiedDisplayFormat);
236+
var typeSb = new StringBuilder();
237+
var restSb = new StringBuilder();
238+
var isInsideType = true;
239+
// The part before the first space is the parameter type
240+
foreach (var part in paramParts)
241+
{
242+
if (isInsideType && part.Kind == SymbolDisplayPartKind.Space)
243+
{
244+
isInsideType = false;
245+
}
246+
if (isInsideType)
247+
{
248+
typeSb.Append(part.ToString());
249+
}
250+
else
251+
{
252+
restSb.Append(part.ToString());
253+
}
254+
}
255+
// 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
256+
if (
257+
param.HasExplicitDefaultValue
258+
&& param.ExplicitDefaultValue is null
259+
&& param.NullableAnnotation != NullableAnnotation.Annotated
260+
&& param.Type.IsReferenceType
261+
&& codeGenerator.HasNullable
262+
)
263+
{
264+
typeSb.Append('?');
265+
}
266+
return typeSb.Append(restSb).ToString();
267+
}
268+
229269
private static void AddEventsToInterface(List<ISymbol> members, InterfaceBuilder codeGenerator)
230270
{
231271
members
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
#nullable enable
10+
namespace AutomaticInterfaceExample
11+
{
12+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
13+
public partial interface IDemoClass
14+
{
15+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.TryStartTransaction(int?, int, string)" />
16+
bool TryStartTransaction(int? param, int param2 = 0, string? data = null);
17+
18+
}
19+
}
20+
#nullable restore

AutomaticInterface/Tests/Methods/Methods.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,29 @@ public bool TryStartTransaction(string data = null)
7676
await Verify(Infrastructure.GenerateCode(code));
7777
}
7878

79+
[Fact]
80+
public async Task WorksWithMixedOptionalNullParameters()
81+
{
82+
const string code = """
83+
84+
using AutomaticInterface;
85+
86+
namespace AutomaticInterfaceExample;
87+
88+
[GenerateAutomaticInterface]
89+
public class DemoClass
90+
{
91+
public bool TryStartTransaction(int? param, int param2 = 0, string data = null)
92+
{
93+
return true;
94+
}
95+
}
96+
97+
98+
""";
99+
await Verify(Infrastructure.GenerateCode(code));
100+
}
101+
79102
[Fact]
80103
public async Task AddsPublicMethodToInterface()
81104
{

0 commit comments

Comments
 (0)