diff --git a/AutomaticInterface/AutomaticInterface/Builder.cs b/AutomaticInterface/AutomaticInterface/Builder.cs index 1f028e9..fe13b94 100644 --- a/AutomaticInterface/AutomaticInterface/Builder.cs +++ b/AutomaticInterface/AutomaticInterface/Builder.cs @@ -52,11 +52,12 @@ is not ClassDeclarationSyntax classSyntax { return string.Empty; } - var namespaceName = GetNameSpace(typeSymbol); - + var generationAttribute = GetGenerationAttribute(typeSymbol); + var namespaceName = GetNameSpace(typeSymbol, generationAttribute); + var asInternal = GetAsInternal(generationAttribute); var interfaceName = $"I{classSyntax.GetClassName()}"; - var interfaceGenerator = new InterfaceBuilder(namespaceName, interfaceName); + var interfaceGenerator = new InterfaceBuilder(namespaceName, interfaceName, asInternal); interfaceGenerator.AddClassDocumentation(GetDocumentationForClass(classSyntax)); interfaceGenerator.AddGeneric(GetGeneric(classSyntax, namedTypeSymbol)); @@ -77,15 +78,18 @@ is not ClassDeclarationSyntax classSyntax return generatedCode; } - private static string GetNameSpace(ISymbol typeSymbol) - { - var generationAttribute = typeSymbol - .GetAttributes() - .FirstOrDefault(x => - x.AttributeClass != null - && x.AttributeClass.Name.Contains(AutomaticInterfaceGenerator.DefaultAttributeName) - ); + private static AttributeData? GetGenerationAttribute(ISymbol typeSymbol) + { + return typeSymbol + .GetAttributes() + .FirstOrDefault(x => + x.AttributeClass != null + && x.AttributeClass.Name.Contains(AutomaticInterfaceGenerator.DefaultAttributeName) + ); + } + private static string GetNameSpace(ISymbol typeSymbol, AttributeData? generationAttribute) + { if (generationAttribute == null) { return typeSymbol.ContainingNamespace.ToDisplayString(); @@ -96,6 +100,18 @@ private static string GetNameSpace(ISymbol typeSymbol) return string.IsNullOrWhiteSpace(customNs) ? typeSymbol.ContainingNamespace.ToDisplayString() : customNs!; + } + + private static bool GetAsInternal(AttributeData? generationAttribute) + { + if (generationAttribute == null) + { + return false; + } + + var asInternal = (bool?)generationAttribute.ConstructorArguments.Skip(1).FirstOrDefault().Value; + + return asInternal.GetValueOrDefault(); } private static void AddMethodsToInterface(List members, InterfaceBuilder codeGenerator) diff --git a/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs b/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs index b43b128..654a129 100644 --- a/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs +++ b/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs @@ -24,7 +24,7 @@ internal sealed record MethodInfo( public record EventInfo(string Name, string Type, string Documentation); - public class InterfaceBuilder(string nameSpaceName, string interfaceName) + public class InterfaceBuilder(string nameSpaceName, string interfaceName, bool asInternal) { private const string Autogenerated = """ //-------------------------------------------------------------------------------------------------- @@ -104,7 +104,7 @@ public string Build() cb.AppendLine( "[global::System.CodeDom.Compiler.GeneratedCode(\"AutomaticInterface\", \"\")]" ); - cb.AppendLine($"public partial interface {interfaceName}{genericType}"); + cb.AppendLine($"{(asInternal ? "internal" : "public")} partial interface {interfaceName}{genericType}"); cb.AppendLine("{"); cb.Indent(); diff --git a/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs b/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs index d18d044..de8278e 100644 --- a/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs +++ b/AutomaticInterface/AutomaticInterface/RegisterAttributesExtensions.cs @@ -27,7 +27,7 @@ namespace AutomaticInterface [AttributeUsage(AttributeTargets.Class)] internal sealed class {{{AutomaticInterfaceGenerator.DefaultAttributeName}}}Attribute : Attribute { - internal {{{AutomaticInterfaceGenerator.DefaultAttributeName}}}Attribute(string namespaceName = "") { } + internal {{{AutomaticInterfaceGenerator.DefaultAttributeName}}}Attribute(string namespaceName = "", bool asInternal = false) { } } } """, diff --git a/AutomaticInterface/AutomaticInterfaceExample/DemoClassWithAsInternal.cs b/AutomaticInterface/AutomaticInterfaceExample/DemoClassWithAsInternal.cs new file mode 100644 index 0000000..3223f51 --- /dev/null +++ b/AutomaticInterface/AutomaticInterfaceExample/DemoClassWithAsInternal.cs @@ -0,0 +1,22 @@ +using System; +using AutomaticInterface; + +namespace AutomaticInterfaceExample +{ + /// + /// Class Documentation will be copied + /// + [GenerateAutomaticInterface(asInternal: true)] + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Major Code Smell", + "S1144:Unused private types or members should be removed", + Justification = "Demo class" + )] + public class DemoClass3 : IDemoClass3 + { + /// + /// This is a test method + /// + public void Test() { } + } +} diff --git a/AutomaticInterface/Tests/Misc/Misc.AsInternal.verified.txt b/AutomaticInterface/Tests/Misc/Misc.AsInternal.verified.txt new file mode 100644 index 0000000..c93d219 --- /dev/null +++ b/AutomaticInterface/Tests/Misc/Misc.AsInternal.verified.txt @@ -0,0 +1,20 @@ +//-------------------------------------------------------------------------------------------------- +// +// 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 +{ + [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] + internal partial interface IDemoClass + { + /// + string AMethod(global::AutomaticInterfaceExample.DemoClass? x, string y); + + } +} +#nullable restore diff --git a/AutomaticInterface/Tests/Misc/Misc.AsInternalExplicitFalse.verified.txt b/AutomaticInterface/Tests/Misc/Misc.AsInternalExplicitFalse.verified.txt new file mode 100644 index 0000000..5202ec3 --- /dev/null +++ b/AutomaticInterface/Tests/Misc/Misc.AsInternalExplicitFalse.verified.txt @@ -0,0 +1,20 @@ +//-------------------------------------------------------------------------------------------------- +// +// 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 +{ + [global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")] + public partial interface IDemoClass + { + /// + string AMethod(global::AutomaticInterfaceExample.DemoClass? x, string y); + + } +} +#nullable restore diff --git a/AutomaticInterface/Tests/Misc/Misc.cs b/AutomaticInterface/Tests/Misc/Misc.cs index c573a0b..34a6cae 100644 --- a/AutomaticInterface/Tests/Misc/Misc.cs +++ b/AutomaticInterface/Tests/Misc/Misc.cs @@ -292,4 +292,44 @@ class DemoClass await Verify(Infrastructure.GenerateCode(code)); } + + [Fact] + public async Task AsInternal() + { + const string code = """ + + using AutomaticInterface; + namespace AutomaticInterfaceExample; + [GenerateAutomaticInterface(asInternal: true)] + public class DemoClass + { + public string AMethod(DemoClass? x, string y) + { + return "Ok"; + } + } + + """; + await Verify(Infrastructure.GenerateCode(code)); + } + + [Fact] + public async Task AsInternalExplicitFalse() + { + const string code = """ + + using AutomaticInterface; + namespace AutomaticInterfaceExample; + [GenerateAutomaticInterface(asInternal: false)] + public class DemoClass + { + public string AMethod(DemoClass? x, string y) + { + return "Ok"; + } + } + + """; + await Verify(Infrastructure.GenerateCode(code)); + } }