Skip to content

Commit cc9adaf

Browse files
Merge pull request #85 from paramamue/defaultvalue-null
Fix handling of parameters with default null
2 parents 50a1ef0 + fda1b06 commit cc9adaf

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;
@@ -115,7 +116,7 @@ private static void AddMethod(InterfaceBuilder codeGenerator, IMethodSymbol meth
115116

116117
var paramResult = new HashSet<string>();
117118
method
118-
.Parameters.Select(x => x.ToDisplayString(FullyQualifiedDisplayFormat))
119+
.Parameters.Select(p => GetParameterDisplayString(p, codeGenerator.HasNullable))
119120
.ToList()
120121
.ForEach(x => paramResult.Add(x));
121122

@@ -186,6 +187,45 @@ private static bool IsNullable(ITypeSymbol typeSymbol)
186187
return false;
187188
}
188189

190+
private static string GetParameterDisplayString(
191+
IParameterSymbol param,
192+
bool nullableContextEnabled
193+
)
194+
{
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+
}
215+
// 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
216+
if (
217+
param.HasExplicitDefaultValue
218+
&& param.ExplicitDefaultValue is null
219+
&& param.NullableAnnotation != NullableAnnotation.Annotated
220+
&& param.Type.IsReferenceType
221+
&& nullableContextEnabled
222+
)
223+
{
224+
typeSb.Append('?');
225+
}
226+
return typeSb.Append(restSb).ToString();
227+
}
228+
189229
private static void AddEventsToInterface(List<ISymbol> members, InterfaceBuilder codeGenerator)
190230
{
191231
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)