You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

98 lines
3.1 KiB

using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace gaemstone.SourceGen.Utility;
public static class SymbolExtensions
{
public static bool IsNullable(this ITypeSymbol type) => type.IsValueType
? (type.OriginalDefinition?.SpecialType == SpecialType.System_Nullable_T)
: (type.NullableAnnotation == NullableAnnotation.Annotated);
public static bool IsPrimitiveType(this ITypeSymbol symbol)
=> symbol.SpecialType switch {
SpecialType.System_Boolean or
SpecialType.System_SByte or
SpecialType.System_Int16 or
SpecialType.System_Int32 or
SpecialType.System_Int64 or
SpecialType.System_Byte or
SpecialType.System_UInt16 or
SpecialType.System_UInt32 or
SpecialType.System_UInt64 or
SpecialType.System_Single or
SpecialType.System_Double or
SpecialType.System_Char or
SpecialType.System_String or
SpecialType.System_Object => true,
_ => false,
};
public static string GetFullName(
this ISymbol symbol, FullNameStyle style = FullNameStyle.Full)
{
var builder = new StringBuilder();
AppendFullName(symbol, builder, style);
return builder.ToString();
}
public static void AppendFullName(
this ISymbol symbol, StringBuilder builder,
FullNameStyle style = FullNameStyle.Full)
{
var withGeneric = (style != FullNameStyle.NoGeneric);
var withMetadata = (style == FullNameStyle.Metadata);
if ((symbol.Kind != SymbolKind.TypeParameter)
&& (symbol.ContainingSymbol is ISymbol parent)
&& (parent is not INamespaceSymbol { IsGlobalNamespace: true }))
{
AppendFullName(parent, builder, style);
builder.Append((withMetadata && (parent is ITypeSymbol)) ? '+' : '.');
}
if ((symbol is INamedTypeSymbol { IsGenericType: true } typeSymbol)
&& !(withGeneric && withMetadata))
{
var length = symbol.MetadataName.IndexOf('`');
builder.Append(symbol.MetadataName, 0, length);
if (withGeneric) {
builder.Append('<');
foreach (var arg in typeSymbol.TypeArguments) {
AppendFullName(arg, builder, style);
builder.Append(',');
}
builder.Length--; // Remove the last ',' character.
builder.Append('>');
}
}
else builder.Append(symbol.MetadataName);
}
public static string? GetNamespace(this ISymbol symbol)
=> symbol.ContainingNamespace?.GetFullName();
public static bool HasAttribute(this ISymbol symbol, string name,
FullNameStyle matchStyle = FullNameStyle.Metadata)
=> symbol.GetAttributes().Any(attr =>
attr.AttributeClass!.GetFullName(matchStyle) == name);
public static AttributeData? FindAttribute(this ISymbol symbol, string name,
FullNameStyle matchStyle = FullNameStyle.Metadata)
=> symbol.GetAttributes().FirstOrDefault(attr =>
attr.AttributeClass!.GetFullName(matchStyle) == name);
public static string ToStringLiteral(this string? input)
=> (input != null) ? SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal(input)).ToFullString() : "null";
}
public enum FullNameStyle
{
Full, // Namespace.Foo.Bar<Baz<Quux>>
Metadata, // Namespace.Foo+Bar`1
NoGeneric, // Namespace.Foo.Bar
}