Skip to content

Commit 9148e56

Browse files
committed
Move Builder.GetParameterDisplayString into the RoslynExtensions class; refactor
This centralises the rendering logic plus simplifies the implementation to use `ITypeSymbol.WithNullableAnnotation` and hands the rendering off to the default `ToDisplayString` implementation
1 parent 31aa5a0 commit 9148e56

File tree

2 files changed

+42
-45
lines changed

2 files changed

+42
-45
lines changed

AutomaticInterface/AutomaticInterface/Builder.cs

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Text;
54
using Microsoft.CodeAnalysis;
65
using Microsoft.CodeAnalysis.CSharp;
76
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -163,7 +162,13 @@ List<string> generatedInterfaceNames
163162

164163
var paramResult = new HashSet<string>();
165164
method
166-
.Parameters.Select(p => GetParameterDisplayString(p, codeGenerator.HasNullable))
165+
.Parameters.Select(p =>
166+
p.ToDisplayString(
167+
FullyQualifiedDisplayFormat,
168+
codeGenerator.HasNullable,
169+
generatedInterfaceNames
170+
)
171+
)
167172
.ToList()
168173
.ForEach(x => paramResult.Add(x));
169174

@@ -234,45 +239,6 @@ private static bool IsNullable(ITypeSymbol typeSymbol)
234239
return false;
235240
}
236241

237-
private static string GetParameterDisplayString(
238-
IParameterSymbol param,
239-
bool nullableContextEnabled
240-
)
241-
{
242-
var paramParts = param.ToDisplayParts(FullyQualifiedDisplayFormat);
243-
var typeSb = new StringBuilder();
244-
var restSb = new StringBuilder();
245-
var isInsideType = true;
246-
// The part before the first space is the parameter type
247-
foreach (var part in paramParts)
248-
{
249-
if (isInsideType && part.Kind == SymbolDisplayPartKind.Space)
250-
{
251-
isInsideType = false;
252-
}
253-
if (isInsideType)
254-
{
255-
typeSb.Append(part.ToString());
256-
}
257-
else
258-
{
259-
restSb.Append(part.ToString());
260-
}
261-
}
262-
// 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
263-
if (
264-
param.HasExplicitDefaultValue
265-
&& param.ExplicitDefaultValue is null
266-
&& param.NullableAnnotation != NullableAnnotation.Annotated
267-
&& param.Type.IsReferenceType
268-
&& nullableContextEnabled
269-
)
270-
{
271-
typeSb.Append('?');
272-
}
273-
return typeSb.Append(restSb).ToString();
274-
}
275-
276242
private static void AddEventsToInterface(
277243
List<ISymbol> members,
278244
InterfaceBuilder codeGenerator,

AutomaticInterface/AutomaticInterface/RoslynExtensions.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Text;
45
using System.Text.RegularExpressions;
@@ -85,8 +86,36 @@ List<string> generatedInterfaceNames
8586
public static string ToDisplayString(
8687
this IParameterSymbol symbol,
8788
SymbolDisplayFormat displayFormat,
89+
bool nullableContextEnabled,
8890
List<string> generatedInterfaceNames
89-
) => ToDisplayString((ISymbol)symbol, displayFormat, generatedInterfaceNames);
91+
)
92+
{
93+
string? RenderTypeSymbolWithNullableAnnotation(SymbolDisplayPart part) =>
94+
part.Symbol is ITypeSymbol typeSymbol
95+
? typeSymbol
96+
.WithNullableAnnotation(NullableAnnotation.Annotated)
97+
.ToDisplayString(displayFormat)
98+
: null;
99+
100+
// Special case for reference parameters with default value null (e.g. string x = null) - the nullable
101+
// context isn't applied automatically, so it must be forced explicitly
102+
var forceNullableAnnotation =
103+
nullableContextEnabled
104+
&& symbol
105+
is {
106+
Type.IsReferenceType: true,
107+
HasExplicitDefaultValue: true,
108+
ExplicitDefaultValue: null
109+
}
110+
&& symbol.NullableAnnotation != NullableAnnotation.Annotated;
111+
112+
return ToDisplayString(
113+
symbol,
114+
displayFormat,
115+
generatedInterfaceNames,
116+
forceNullableAnnotation ? RenderTypeSymbolWithNullableAnnotation : null
117+
);
118+
}
90119

91120
public static string ToDisplayString(
92121
this ITypeSymbol symbol,
@@ -100,7 +129,8 @@ List<string> generatedInterfaceNames
100129
private static string ToDisplayString(
101130
this ISymbol symbol,
102131
SymbolDisplayFormat displayFormat,
103-
List<string> generatedInterfaceNames
132+
List<string> generatedInterfaceNames,
133+
Func<SymbolDisplayPart, string?>? customRenderDisplayPart = null
104134
)
105135
{
106136
var displayStringBuilder = new StringBuilder();
@@ -122,7 +152,8 @@ List<string> generatedInterfaceNames
122152
}
123153
else
124154
{
125-
displayStringBuilder.Append(part);
155+
var customRender = customRenderDisplayPart?.Invoke(part);
156+
displayStringBuilder.Append(customRender ?? part.ToString());
126157
}
127158
}
128159

0 commit comments

Comments
 (0)