From dd40cc1e350860fc934c53973c6ecaf11a3aad1d Mon Sep 17 00:00:00 2001 From: Edward Trouw Date: Thu, 28 Jul 2022 08:52:34 +0200 Subject: [PATCH] Getting the full metadata name to use as the hint and check if its already been used (for e.g. a partial) --- InterfaceGenerator/AutoInterfaceGenerator.cs | 20 ++++++++- InterfaceGenerator/SymbolExtensions.cs | 44 ++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/InterfaceGenerator/AutoInterfaceGenerator.cs b/InterfaceGenerator/AutoInterfaceGenerator.cs index 026ed36..a027903 100644 --- a/InterfaceGenerator/AutoInterfaceGenerator.cs +++ b/InterfaceGenerator/AutoInterfaceGenerator.cs @@ -1,6 +1,7 @@ using System; using System.CodeDom.Compiler; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -21,6 +22,13 @@ namespace InterfaceGenerator public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); + +#if DEBUG + if (!Debugger.IsAttached) + { + Debugger.Launch(); + } +#endif } public void Execute(GeneratorExecutionContext context) @@ -83,6 +91,8 @@ namespace InterfaceGenerator var classSymbols = GetImplTypeSymbols(compilation, receiver); + List classSymbolNames = new List(); + foreach (var implTypeSymbol in classSymbols) { if (!implTypeSymbol.TryGetAttribute(_generateAutoInterfaceAttribute, out var attributes)) @@ -90,9 +100,17 @@ namespace InterfaceGenerator continue; } + if(classSymbolNames.Contains(implTypeSymbol.GetFullMetadataName(useNameWhenNotFound: true))) + { + continue; // partial class, already added + } + + classSymbolNames.Add(implTypeSymbol.GetFullMetadataName(useNameWhenNotFound: true)); + var attribute = attributes.Single(); var source = SourceText.From(GenerateInterfaceCode(implTypeSymbol, attribute), Encoding.UTF8); - context.AddSource($"{implTypeSymbol.Name}_AutoInterface.cs", source); + + context.AddSource($"{implTypeSymbol.GetFullMetadataName(useNameWhenNotFound: true)}_AutoInterface.cs", source); } } diff --git a/InterfaceGenerator/SymbolExtensions.cs b/InterfaceGenerator/SymbolExtensions.cs index bb1fbce..ec84fdd 100644 --- a/InterfaceGenerator/SymbolExtensions.cs +++ b/InterfaceGenerator/SymbolExtensions.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; namespace InterfaceGenerator @@ -21,5 +22,48 @@ namespace InterfaceGenerator return symbol.GetAttributes() .Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attributeType)); } + + //Ref: https://stackoverflow.com/questions/27105909/get-fully-qualified-metadata-name-in-roslyn + public static string GetFullMetadataName(this ISymbol s, bool useNameWhenNotFound = false) + { + if (s == null || IsRootNamespace(s)) + { + if (useNameWhenNotFound) + { + return s.Name; + } + return string.Empty; + } + + var sb = new StringBuilder(s.MetadataName); + var last = s; + + s = s.ContainingSymbol; + + while (!IsRootNamespace(s)) + { + if (s is ITypeSymbol && last is ITypeSymbol) + { + sb.Insert(0, '+'); + } + else + { + sb.Insert(0, '.'); + } + + sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)); + //sb.Insert(0, s.MetadataName); + s = s.ContainingSymbol; + } + + var retval = sb.ToString(); + return string.IsNullOrEmpty(retval) && useNameWhenNotFound ? s.Name : retval; + } + + private static bool IsRootNamespace(ISymbol symbol) + { + INamespaceSymbol s = null; + return ((s = symbol as INamespaceSymbol) != null) && s.IsGlobalNamespace; + } } } \ No newline at end of file