From 14202cd2e5d306d87de2d1112869db708a14f686 Mon Sep 17 00:00:00 2001 From: Ihor Kuzmychov Date: Thu, 13 Nov 2025 23:26:40 +0100 Subject: [PATCH 1/4] Add support for wildcard usage within namespace --- .../GeneratedSymbolDetails.cs | 19 ++++++++- ...c.CustomNameSpaceWithWildcard.verified.txt | 23 ++++++++++ ...thWildcardWithinFileNamespace.verified.txt | 18 ++++++++ AutomaticInterface/Tests/Misc/Misc.cs | 42 +++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt create mode 100644 AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinFileNamespace.verified.txt diff --git a/AutomaticInterface/AutomaticInterface/GeneratedSymbolDetails.cs b/AutomaticInterface/AutomaticInterface/GeneratedSymbolDetails.cs index 258134e..27cd54f 100644 --- a/AutomaticInterface/AutomaticInterface/GeneratedSymbolDetails.cs +++ b/AutomaticInterface/AutomaticInterface/GeneratedSymbolDetails.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -16,9 +17,8 @@ ClassDeclarationSyntax classSyntax /// to the containing namespace of the type symbol. /// public string NamespaceName { get; } = - PrepareValue( + PrepareNamespaceName( generationAttribute, - AutomaticInterfaceGenerator.NamespaceParameterName, typeSymbol.ContainingNamespace.ToDisplayString() ); @@ -78,4 +78,19 @@ private static T PrepareValue(AttributeData? generationAttribute, string key, return defaultValue; } + + private static string PrepareNamespaceName(AttributeData? generationAttribute, string containingNamespaceName) + { + var namespacePattern = PrepareValue( + generationAttribute, + AutomaticInterfaceGenerator.NamespaceParameterName, + containingNamespaceName + ); + + Debug.Assert(namespacePattern != null); + + var namespaceName = namespacePattern!.Replace("*", containingNamespaceName); + + return namespaceName; + } } diff --git a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt new file mode 100644 index 0000000..b1c8e1b --- /dev/null +++ b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt @@ -0,0 +1,23 @@ +//-------------------------------------------------------------------------------------------------- +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//-------------------------------------------------------------------------------------------------- + +#nullable enable +namespace AutomaticInterfaceExample.CustomNameSpaceSuffix +{ + /// + /// Bla bla + /// + [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] + 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)); + + } +} +#nullable restore diff --git a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinFileNamespace.verified.txt b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinFileNamespace.verified.txt new file mode 100644 index 0000000..ae56a17 --- /dev/null +++ b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinFileNamespace.verified.txt @@ -0,0 +1,18 @@ +//-------------------------------------------------------------------------------------------------- +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//-------------------------------------------------------------------------------------------------- + +namespace AutomaticInterfaceExample.CustomNameSpaceSuffix +{ + [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] + public partial interface IDemoClass + { + /// + int DemoMethod(); + + } +} diff --git a/AutomaticInterface/Tests/Misc/Misc.cs b/AutomaticInterface/Tests/Misc/Misc.cs index d1b0677..a9ace1b 100644 --- a/AutomaticInterface/Tests/Misc/Misc.cs +++ b/AutomaticInterface/Tests/Misc/Misc.cs @@ -365,6 +365,48 @@ class DemoClass await Verify(Infrastructure.GenerateCode(code)); } + + [Fact] + public async Task CustomNameSpaceWithWildcardWithinBrackedNamespace() + { + const string code = """ + + using AutomaticInterface; + + namespace AutomaticInterfaceExample + { + [GenerateAutomaticInterface("*.CustomNameSpaceSuffix")] + class DemoClass + { + public int DemoMethod() => 5; + } + } + + """; + + await Verify(Infrastructure.GenerateCode(code)); + } + + [Fact] + public async Task CustomNameSpaceWithWildcardWithinFileNamespace() + { + const string code = """ + + using AutomaticInterface; + + namespace AutomaticInterfaceExample; + + [GenerateAutomaticInterface("*.CustomNameSpaceSuffix")] + class DemoClass + { + public int DemoMethod() => 5; + } + + """; + + await Verify(Infrastructure.GenerateCode(code)); + } + [Fact] public async Task AsInternal() { From 63d4f6d47886abfd786e2eea8e3e0d01751c0482 Mon Sep 17 00:00:00 2001 From: Ihor Kuzmychov Date: Thu, 13 Nov 2025 23:30:15 +0100 Subject: [PATCH 2/4] fix tests --- ...WildcardWithinBrackedNamespace.verified.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinBrackedNamespace.verified.txt diff --git a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinBrackedNamespace.verified.txt b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinBrackedNamespace.verified.txt new file mode 100644 index 0000000..ae56a17 --- /dev/null +++ b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcardWithinBrackedNamespace.verified.txt @@ -0,0 +1,18 @@ +//-------------------------------------------------------------------------------------------------- +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +//-------------------------------------------------------------------------------------------------- + +namespace AutomaticInterfaceExample.CustomNameSpaceSuffix +{ + [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] + public partial interface IDemoClass + { + /// + int DemoMethod(); + + } +} From 1cefdaeafcbcf5d1ccffaf3862bc2d4d430fd9c0 Mon Sep 17 00:00:00 2001 From: Ihor Kuzmychov Date: Thu, 13 Nov 2025 23:31:03 +0100 Subject: [PATCH 3/4] delete trash file --- ...c.CustomNameSpaceWithWildcard.verified.txt | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt diff --git a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt b/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt deleted file mode 100644 index b1c8e1b..0000000 --- a/AutomaticInterface/Tests/Misc/Misc.CustomNameSpaceWithWildcard.verified.txt +++ /dev/null @@ -1,23 +0,0 @@ -//-------------------------------------------------------------------------------------------------- -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. -// -//-------------------------------------------------------------------------------------------------- - -#nullable enable -namespace AutomaticInterfaceExample.CustomNameSpaceSuffix -{ - /// - /// Bla bla - /// - [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] - 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)); - - } -} -#nullable restore From 28d6bc9a43a330e96b70231875edcd2e55dcaca5 Mon Sep 17 00:00:00 2001 From: Ihor Kuzmychov Date: Thu, 13 Nov 2025 23:41:14 +0100 Subject: [PATCH 4/4] Update package version and attribute summary --- AutomaticInterface/AutomaticInterface/AutomaticInterface.csproj | 2 +- .../AutomaticInterface/RegisterAttributesExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomaticInterface/AutomaticInterface/AutomaticInterface.csproj b/AutomaticInterface/AutomaticInterface/AutomaticInterface.csproj index f0b0404..6bdd40e 100644 --- a/AutomaticInterface/AutomaticInterface/AutomaticInterface.csproj +++ b/AutomaticInterface/AutomaticInterface/AutomaticInterface.csproj @@ -24,7 +24,7 @@ MIT True latest-Recommended - 5.2.6 + 5.3.0 README.md true 1701;1702;NU5128 diff --git a/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs b/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs index 66e0126..beee03f 100644 --- a/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs +++ b/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs @@ -32,7 +32,7 @@ internal sealed class {{AutomaticInterfaceGenerator.DefaultAttributeName}}Attrib /// /// Use source generator to automatically create a Interface from this class /// - /// Namespace name for the generated interface. Defaults to the same namespace as the class. + /// Namespace name for the generated interface. Defaults to the same namespace as the class. The '*' character may be used as a placeholder for the containing type's namespace, allowing you to specify only a prefix for the target namespace instead of its full name. /// Interface name for the generated interface. Defaults to an interface version of the class name, e.g ExampleClass -> IExampleClass. /// If true, the generated interface will be internal, otherwise public internal {{AutomaticInterfaceGenerator.DefaultAttributeName}}Attribute(string {{AutomaticInterfaceGenerator.NamespaceParameterName}} = default(string), string {{AutomaticInterfaceGenerator.InterfaceParameterName}} = default(string), bool {{AutomaticInterfaceGenerator.AsInternalParameterName}} = false) { }