From bd316f38cc21346aaee8fcd032b88c1ed46024bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=BCller?= Date: Mon, 21 Jul 2025 16:26:39 +0200 Subject: [PATCH] Fix handling of parameters with default null --- .../AutomaticInterface/Builder.cs | 20 +++++++++++++++++-- .../Methods.BooleanWithNonNull.verified.txt | 2 +- ...rksWithOptionalNullParameters.verified.txt | 4 +++- .../Misc/Misc.CustomNameSpace.verified.txt | 2 +- ...sWithOptionalStructParameters.verified.txt | 4 +++- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/AutomaticInterface/AutomaticInterface/Builder.cs b/AutomaticInterface/AutomaticInterface/Builder.cs index 840657b..78d4504 100644 --- a/AutomaticInterface/AutomaticInterface/Builder.cs +++ b/AutomaticInterface/AutomaticInterface/Builder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -9,6 +10,9 @@ namespace AutomaticInterface; public static class Builder { + private static Regex ParamWithDefaultValueRegex { get; } = + new(pattern: @"^(?\S+)(?\s+\S+\s+=.+)$", options: RegexOptions.Compiled); + private static string InheritDoc(ISymbol source) => $"/// ', '}')}\" />"; // we use inherit doc because that should be able to fetch documentation from base classes. @@ -155,7 +159,19 @@ private static void AddMethod(InterfaceBuilder codeGenerator, IMethodSymbol meth var paramResult = new HashSet(); method - .Parameters.Select(x => x.ToDisplayString(FullyQualifiedDisplayFormat)) + .Parameters.Select(x => + { + var dispString = x.ToDisplayString(FullyQualifiedDisplayFormat); + if (x.HasExplicitDefaultValue && x.ExplicitDefaultValue is null && x.NullableAnnotation != NullableAnnotation.Annotated) + { + var match = ParamWithDefaultValueRegex.Match(dispString); + if (match.Success) + { + dispString = $"{match.Groups["type"].Value}?{match.Groups["rest"].Value}"; + } + } + return dispString; + }) .ToList() .ForEach(x => paramResult.Add(x)); @@ -193,7 +209,7 @@ private static void ActivateNullableIfNeeded( IMethodSymbol method ) { - var hasNullableParameter = method.Parameters.Any(x => IsNullable(x.Type)); + var hasNullableParameter = method.Parameters.Any(x => IsNullable(x.Type) || (x.HasExplicitDefaultValue && x.ExplicitDefaultValue is null)); var hasNullableReturn = IsNullable(method.ReturnType); diff --git a/AutomaticInterface/Tests/Methods/Methods.BooleanWithNonNull.verified.txt b/AutomaticInterface/Tests/Methods/Methods.BooleanWithNonNull.verified.txt index 9457940..03eb56a 100644 --- a/AutomaticInterface/Tests/Methods/Methods.BooleanWithNonNull.verified.txt +++ b/AutomaticInterface/Tests/Methods/Methods.BooleanWithNonNull.verified.txt @@ -16,7 +16,7 @@ namespace AutomaticInterfaceExample public partial interface IDemoClass { /// - global::System.Threading.Tasks.Task GetFinalDocumentsByIDFails(string agreementID, string docType, bool amt = false, bool? attachSupportingDocuments = true, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)); + global::System.Threading.Tasks.Task GetFinalDocumentsByIDFails(string agreementID, string docType, bool amt = false, bool? attachSupportingDocuments = true, global::System.Threading.CancellationToken? cancellationToken = default(global::System.Threading.CancellationToken)); } } diff --git a/AutomaticInterface/Tests/Methods/Methods.WorksWithOptionalNullParameters.verified.txt b/AutomaticInterface/Tests/Methods/Methods.WorksWithOptionalNullParameters.verified.txt index 8481e5a..b5854a1 100644 --- a/AutomaticInterface/Tests/Methods/Methods.WorksWithOptionalNullParameters.verified.txt +++ b/AutomaticInterface/Tests/Methods/Methods.WorksWithOptionalNullParameters.verified.txt @@ -6,13 +6,15 @@ // //-------------------------------------------------------------------------------------------------- +#nullable enable namespace AutomaticInterfaceExample { [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] public partial interface IDemoClass { /// - bool TryStartTransaction(string data = null); + bool TryStartTransaction(string? data = null); } } +#nullable restore diff --git a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpace.verified.txt b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpace.verified.txt index ebd51e1..fc762a6 100644 --- a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpace.verified.txt +++ b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpace.verified.txt @@ -16,7 +16,7 @@ namespace CustomNameSpace public partial interface IDemoClass { /// - global::System.Threading.Tasks.Task GetFinalDocumentsByIDFails(string agreementID, string docType, bool amt = false, bool? attachSupportingDocuments = true, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)); + global::System.Threading.Tasks.Task GetFinalDocumentsByIDFails(string agreementID, string docType, bool amt = false, bool? attachSupportingDocuments = true, global::System.Threading.CancellationToken? cancellationToken = default(global::System.Threading.CancellationToken)); } } diff --git a/AutomaticInterface/Tests/Misc/Misc.WorksWithOptionalStructParameters.verified.txt b/AutomaticInterface/Tests/Misc/Misc.WorksWithOptionalStructParameters.verified.txt index 91d9023..35c04af 100644 --- a/AutomaticInterface/Tests/Misc/Misc.WorksWithOptionalStructParameters.verified.txt +++ b/AutomaticInterface/Tests/Misc/Misc.WorksWithOptionalStructParameters.verified.txt @@ -6,13 +6,15 @@ // //-------------------------------------------------------------------------------------------------- +#nullable enable namespace AutomaticInterfaceExample { [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] public partial interface IDemoClass { /// - bool TryStartTransaction(global::AutomaticInterfaceExample.MyStruct data = default(global::AutomaticInterfaceExample.MyStruct)); + bool TryStartTransaction(global::AutomaticInterfaceExample.MyStruct? data = default(global::AutomaticInterfaceExample.MyStruct)); } } +#nullable restore