Getting the full metadata name to use as the hint and check if its already been used (for e.g. a partial)

This commit is contained in:
Edward Trouw
2022-07-28 08:52:34 +02:00
parent 2862881192
commit dd40cc1e35
2 changed files with 63 additions and 1 deletions
+19 -1
View File
@@ -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<string> classSymbolNames = new List<string>();
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);
}
}
+44
View File
@@ -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;
}
}
}