Files
RobustToolbox/Robust.Roslyn.Shared/TypeSymbolHelper.cs
34ce2ba534 serv5 (#6496)
* Add source generator for DataDefinition validation

* Add source generator for reading

* Add source generator for writing

* Include prototypes and other meansdatadefinition types

* Target ISerializationGenerated in data definitions

* Murder

* Use array, struct, enum methods

* Source generate get field definitions

* serv5

* Fix and pray

* Fix release compile

* Tayrtahn review

* a

* Generator bugfix

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
2026-07-08 22:18:35 +10:00

114 lines
3.5 KiB
C#

using Microsoft.CodeAnalysis;
namespace Robust.Roslyn.Shared;
#nullable enable
public static class TypeSymbolHelper
{
public static bool ShittyTypeMatch(ITypeSymbol type, string attributeMetadataName)
{
// Doing it like this only allocates when the type actually matches, which is good enough for me right now.
if (!attributeMetadataName.EndsWith(type.Name))
return false;
return type.ToDisplayString() == attributeMetadataName;
}
public static bool ImplementsInterface(ITypeSymbol type, string interfaceTypeName)
{
foreach (var interfaceType in type.AllInterfaces)
{
if (ShittyTypeMatch(interfaceType, interfaceTypeName))
return true;
}
return false;
}
public static bool ImplementsInterface(ITypeSymbol type, INamedTypeSymbol interfaceType)
{
foreach (var @interface in type.AllInterfaces)
{
if (SymbolEqualityComparer.Default.Equals(@interface, interfaceType))
return true;
}
return false;
}
/// <summary>
/// Gets all Members of a symbol, including those that are inherited.
/// We need this because sometimes Components have abstract parents with autonetworked datafields.
/// </summary>
public static IEnumerable<ISymbol> GetAllMembersIncludingInherited(INamedTypeSymbol type)
{
var current = type;
while (current != null)
{
foreach (var member in current.GetMembers())
{
yield return member;
}
current = current.BaseType;
}
}
/// <summary>
/// If <paramref name="type"/> is a Nullable{T}, returns the <see cref="ITypeSymbol"/> of the underlying type.
/// Otherwise, returns <paramref name="type"/>.
/// </summary>
// Modified from https://www.meziantou.net/working-with-types-in-a-roslyn-analyzer.htm
public static ITypeSymbol GetNullableUnderlyingTypeOrSelf(ITypeSymbol type)
{
if (type is INamedTypeSymbol namedType && namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T)
{
return namedType.TypeArguments[0];
}
return type;
}
/// <summary>
/// Enumerates all base types of the given <paramref name="type"/>.
/// </summary>
public static IEnumerable<ITypeSymbol> GetBaseTypes(ITypeSymbol type)
{
var baseType = type.BaseType;
while (baseType != null)
{
yield return baseType;
baseType = baseType.BaseType;
}
}
/// <summary>
/// Checks if the given <paramref name="type"/> inherits from <paramref name="other"/>.
/// </summary>
/// <returns>True if <paramref name="type"/> inherits from <paramref name="other"/>, otherwise false.</returns>
public static bool Inherits(ITypeSymbol type, ITypeSymbol other)
{
foreach (var baseType in GetBaseTypes(type))
{
if (SymbolEqualityComparer.Default.Equals(baseType, other))
return true;
}
return false;
}
/// <summary>
/// Checks if the given <paramref name="type"/> inherits from a type with the given metadata name.
/// </summary>
public static bool Inherits(ITypeSymbol type, string otherTypeName)
{
foreach (var baseType in GetBaseTypes(type))
{
if (ShittyTypeMatch(baseType, otherTypeName))
return true;
}
return false;
}
}