diff --git a/AutomaticInterface/AutomaticInterface/AddNullableAnnotationSyntaxRewriter.cs b/AutomaticInterface/AutomaticInterface/AddNullableAnnotationSyntaxRewriter.cs new file mode 100644 index 0000000..5798a90 --- /dev/null +++ b/AutomaticInterface/AutomaticInterface/AddNullableAnnotationSyntaxRewriter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace AutomaticInterface +{ + internal sealed class AddNullableAnnotationSyntaxRewriter : CSharpSyntaxRewriter + { + public override SyntaxNode? VisitParameter(ParameterSyntax node) + { + var newNode = node; + if (node.Type != null) + { + newNode = node.WithType( + SyntaxFactory.ParseTypeName( + node.Type.GetLeadingTrivia() + + node.Type.ToString() + + "?" + + node.Type.GetTrailingTrivia() + ) + ); + } + return base.VisitParameter(newNode); + } + } +} diff --git a/AutomaticInterface/AutomaticInterface/Builder.cs b/AutomaticInterface/AutomaticInterface/Builder.cs index 49893ee..0883803 100644 --- a/AutomaticInterface/AutomaticInterface/Builder.cs +++ b/AutomaticInterface/AutomaticInterface/Builder.cs @@ -192,26 +192,6 @@ private static string GetParameterDisplayString( bool nullableContextEnabled ) { - var paramParts = param.ToDisplayParts(FullyQualifiedDisplayFormat); - var typeSb = new StringBuilder(); - var restSb = new StringBuilder(); - var isInsideType = true; - // The part before the first space is the parameter type - foreach (var part in paramParts) - { - if (isInsideType && part.Kind == SymbolDisplayPartKind.Space) - { - isInsideType = false; - } - if (isInsideType) - { - typeSb.Append(part.ToString()); - } - else - { - restSb.Append(part.ToString()); - } - } // 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 if ( param.HasExplicitDefaultValue @@ -221,9 +201,12 @@ bool nullableContextEnabled && nullableContextEnabled ) { - typeSb.Append('?'); + var addNullable = new AddNullableAnnotationSyntaxRewriter(); + return addNullable + .Visit(param.DeclaringSyntaxReferences.First().GetSyntax()) + .ToFullString(); } - return typeSb.Append(restSb).ToString(); + return param.ToDisplayString(FullyQualifiedDisplayFormat); } private static void AddEventsToInterface(List members, InterfaceBuilder codeGenerator) diff --git a/AutomaticInterface/Tests/Methods/Methods.WorksWithMixedOptionalNullParameters.verified.txt b/AutomaticInterface/Tests/Methods/Methods.WorksWithMixedOptionalNullParameters.verified.txt index a8728ce..1b13cf9 100644 --- a/AutomaticInterface/Tests/Methods/Methods.WorksWithMixedOptionalNullParameters.verified.txt +++ b/AutomaticInterface/Tests/Methods/Methods.WorksWithMixedOptionalNullParameters.verified.txt @@ -12,8 +12,8 @@ namespace AutomaticInterfaceExample [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] public partial interface IDemoClass { - /// - bool TryStartTransaction(int? param, int param2 = 0, string? data = null); + /// + bool TryStartTransaction(int? param, int param2 = 0, string? data = null, Func? func = null); } } diff --git a/AutomaticInterface/Tests/Methods/Methods.cs b/AutomaticInterface/Tests/Methods/Methods.cs index f751257..361c440 100644 --- a/AutomaticInterface/Tests/Methods/Methods.cs +++ b/AutomaticInterface/Tests/Methods/Methods.cs @@ -88,10 +88,10 @@ namespace AutomaticInterfaceExample; [GenerateAutomaticInterface] public class DemoClass { - public bool TryStartTransaction(int? param, int param2 = 0, string data = null) - { - return true; - } + public bool TryStartTransaction(int? param, int param2 = 0, string data = null, Func func = null) + { + return true; + } }