mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Co-authored-by: Paul <ritter.paul1+git@googlemail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
288 lines
9.9 KiB
C#
288 lines
9.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
using XamlX.TypeSystem;
|
|
|
|
namespace Robust.Client.NameGenerator
|
|
{
|
|
/// <summary>
|
|
/// Taken from https://github.com/AvaloniaUI/Avalonia.NameGenerator/blob/ecc9677a23de5cbc90af07ccac14e31c0da41d6a/src/Avalonia.NameGenerator/Infrastructure/RoslynTypeSystem.cs
|
|
/// </summary>
|
|
public class RoslynTypeSystem : IXamlTypeSystem
|
|
{
|
|
private readonly List<IXamlAssembly> _assemblies = new List<IXamlAssembly>();
|
|
|
|
public RoslynTypeSystem(CSharpCompilation compilation)
|
|
{
|
|
_assemblies.Add(new RoslynAssembly(compilation.Assembly));
|
|
|
|
var assemblySymbols = compilation
|
|
.References
|
|
.Select(compilation.GetAssemblyOrModuleSymbol)
|
|
.OfType<IAssemblySymbol>()
|
|
.Select(assembly => new RoslynAssembly(assembly))
|
|
.ToList();
|
|
|
|
_assemblies.AddRange(assemblySymbols);
|
|
}
|
|
|
|
public IReadOnlyList<IXamlAssembly> Assemblies => _assemblies;
|
|
|
|
public IXamlAssembly FindAssembly(string substring) => _assemblies[0];
|
|
|
|
public IXamlType FindType(string name)
|
|
{
|
|
foreach (var assembly in _assemblies)
|
|
{
|
|
var type = assembly.FindType(name);
|
|
if (type != null)
|
|
return type;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public IXamlType FindType(string name, string assembly)
|
|
{
|
|
foreach (var assemblyInstance in _assemblies)
|
|
{
|
|
var type = assemblyInstance.FindType(name);
|
|
if (type != null)
|
|
return type;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class RoslynAssembly : IXamlAssembly
|
|
{
|
|
private readonly IAssemblySymbol _symbol;
|
|
|
|
public RoslynAssembly(IAssemblySymbol symbol) => _symbol = symbol;
|
|
|
|
public bool Equals(IXamlAssembly other) =>
|
|
other is RoslynAssembly roslynAssembly &&
|
|
SymbolEqualityComparer.Default.Equals(_symbol, roslynAssembly._symbol);
|
|
|
|
public string Name => _symbol.Name;
|
|
|
|
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes =>
|
|
_symbol.GetAttributes()
|
|
.Select(data => new RoslynAttribute(data, this))
|
|
.ToList();
|
|
|
|
public IXamlType FindType(string fullName)
|
|
{
|
|
var type = _symbol.GetTypeByMetadataName(fullName);
|
|
return type is null ? null : new RoslynType(type, this);
|
|
}
|
|
}
|
|
|
|
public class RoslynAttribute : IXamlCustomAttribute
|
|
{
|
|
private readonly AttributeData _data;
|
|
private readonly RoslynAssembly _assembly;
|
|
|
|
public RoslynAttribute(AttributeData data, RoslynAssembly assembly)
|
|
{
|
|
_data = data;
|
|
_assembly = assembly;
|
|
}
|
|
|
|
public bool Equals(IXamlCustomAttribute other) =>
|
|
other is RoslynAttribute attribute &&
|
|
_data == attribute._data;
|
|
|
|
public IXamlType Type => new RoslynType(_data.AttributeClass, _assembly);
|
|
|
|
public List<object> Parameters =>
|
|
_data.ConstructorArguments
|
|
.Select(argument => argument.Value)
|
|
.ToList();
|
|
|
|
public Dictionary<string, object> Properties =>
|
|
_data.NamedArguments.ToDictionary(
|
|
pair => pair.Key,
|
|
pair => pair.Value.Value);
|
|
}
|
|
|
|
public class RoslynType : IXamlType
|
|
{
|
|
private static readonly SymbolDisplayFormat SymbolDisplayFormat = new SymbolDisplayFormat(
|
|
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
|
|
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters |
|
|
SymbolDisplayGenericsOptions.IncludeTypeConstraints |
|
|
SymbolDisplayGenericsOptions.IncludeVariance);
|
|
|
|
private readonly RoslynAssembly _assembly;
|
|
private readonly INamedTypeSymbol _symbol;
|
|
|
|
public RoslynType(INamedTypeSymbol symbol, RoslynAssembly assembly)
|
|
{
|
|
_symbol = symbol;
|
|
_assembly = assembly;
|
|
}
|
|
|
|
public bool Equals(IXamlType other) =>
|
|
other is RoslynType roslynType &&
|
|
SymbolEqualityComparer.Default.Equals(_symbol, roslynType._symbol);
|
|
|
|
public object Id => _symbol;
|
|
|
|
public string Name => _symbol.Name;
|
|
|
|
public string Namespace => _symbol.ContainingNamespace.ToDisplayString(SymbolDisplayFormat);
|
|
|
|
public string FullName => $"{Namespace}.{Name}";
|
|
|
|
public IXamlAssembly Assembly => _assembly;
|
|
|
|
public IReadOnlyList<IXamlProperty> Properties =>
|
|
_symbol.GetMembers()
|
|
.Where(member => member.Kind == SymbolKind.Property)
|
|
.OfType<IPropertySymbol>()
|
|
.Select(property => new RoslynProperty(property, _assembly))
|
|
.ToList();
|
|
|
|
public IReadOnlyList<IXamlEventInfo> Events { get; } = new List<IXamlEventInfo>();
|
|
|
|
public IReadOnlyList<IXamlField> Fields { get; } = new List<IXamlField>();
|
|
|
|
public IReadOnlyList<IXamlMethod> Methods { get; } = new List<IXamlMethod>();
|
|
|
|
public IReadOnlyList<IXamlConstructor> Constructors =>
|
|
_symbol.Constructors
|
|
.Select(method => new RoslynConstructor(method, _assembly))
|
|
.ToList();
|
|
|
|
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes { get; } = new List<IXamlCustomAttribute>();
|
|
|
|
public IReadOnlyList<IXamlType> GenericArguments { get; } = new List<IXamlType>();
|
|
|
|
public bool IsAssignableFrom(IXamlType type) => type == this;
|
|
|
|
public IXamlType MakeGenericType(IReadOnlyList<IXamlType> typeArguments) => this;
|
|
|
|
public IXamlType GenericTypeDefinition => this;
|
|
|
|
public bool IsArray => false;
|
|
|
|
public IXamlType ArrayElementType { get; } = null;
|
|
|
|
public IXamlType MakeArrayType(int dimensions) => null;
|
|
|
|
public IXamlType BaseType => _symbol.BaseType == null ? null : new RoslynType(_symbol.BaseType, _assembly);
|
|
|
|
public bool IsValueType { get; } = false;
|
|
|
|
public bool IsEnum { get; } = false;
|
|
|
|
public IReadOnlyList<IXamlType> Interfaces =>
|
|
_symbol.AllInterfaces
|
|
.Select(abstraction => new RoslynType(abstraction, _assembly))
|
|
.ToList();
|
|
|
|
public bool IsInterface => _symbol.IsAbstract;
|
|
|
|
public IXamlType GetEnumUnderlyingType() => null;
|
|
|
|
public IReadOnlyList<IXamlType> GenericParameters { get; } = new List<IXamlType>();
|
|
}
|
|
|
|
public class RoslynConstructor : IXamlConstructor
|
|
{
|
|
private readonly IMethodSymbol _symbol;
|
|
private readonly RoslynAssembly _assembly;
|
|
|
|
public RoslynConstructor(IMethodSymbol symbol, RoslynAssembly assembly)
|
|
{
|
|
_symbol = symbol;
|
|
_assembly = assembly;
|
|
}
|
|
|
|
public bool Equals(IXamlConstructor other) =>
|
|
other is RoslynConstructor roslynConstructor &&
|
|
SymbolEqualityComparer.Default.Equals(_symbol, roslynConstructor._symbol);
|
|
|
|
public bool IsPublic => true;
|
|
|
|
public bool IsStatic => false;
|
|
|
|
public IReadOnlyList<IXamlType> Parameters =>
|
|
_symbol.Parameters
|
|
.Select(parameter => parameter.Type)
|
|
.OfType<INamedTypeSymbol>()
|
|
.Select(type => new RoslynType(type, _assembly))
|
|
.ToList();
|
|
}
|
|
|
|
public class RoslynProperty : IXamlProperty
|
|
{
|
|
private readonly IPropertySymbol _symbol;
|
|
private readonly RoslynAssembly _assembly;
|
|
|
|
public RoslynProperty(IPropertySymbol symbol, RoslynAssembly assembly)
|
|
{
|
|
_symbol = symbol;
|
|
_assembly = assembly;
|
|
}
|
|
|
|
public bool Equals(IXamlProperty other) =>
|
|
other is RoslynProperty roslynProperty &&
|
|
SymbolEqualityComparer.Default.Equals(_symbol, roslynProperty._symbol);
|
|
|
|
public string Name => _symbol.Name;
|
|
|
|
public IXamlType PropertyType =>
|
|
_symbol.Type is INamedTypeSymbol namedTypeSymbol
|
|
? new RoslynType(namedTypeSymbol, _assembly)
|
|
: null;
|
|
|
|
public IXamlMethod Getter => _symbol.GetMethod == null ? null : new RoslynMethod(_symbol.GetMethod, _assembly);
|
|
|
|
public IXamlMethod Setter => _symbol.SetMethod == null ? null : new RoslynMethod(_symbol.SetMethod, _assembly);
|
|
|
|
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes { get; } = new List<IXamlCustomAttribute>();
|
|
|
|
public IReadOnlyList<IXamlType> IndexerParameters { get; } = new List<IXamlType>();
|
|
}
|
|
|
|
public class RoslynMethod : IXamlMethod
|
|
{
|
|
private readonly IMethodSymbol _symbol;
|
|
private readonly RoslynAssembly _assembly;
|
|
|
|
public RoslynMethod(IMethodSymbol symbol, RoslynAssembly assembly)
|
|
{
|
|
_symbol = symbol;
|
|
_assembly = assembly;
|
|
}
|
|
|
|
public bool Equals(IXamlMethod other) =>
|
|
other is RoslynMethod roslynMethod &&
|
|
SymbolEqualityComparer.Default.Equals(roslynMethod._symbol, _symbol);
|
|
|
|
public string Name => _symbol.Name;
|
|
|
|
public bool IsPublic => true;
|
|
|
|
public bool IsStatic => false;
|
|
|
|
public IXamlType ReturnType => new RoslynType((INamedTypeSymbol) _symbol.ReturnType, _assembly);
|
|
|
|
public IReadOnlyList<IXamlType> Parameters =>
|
|
_symbol.Parameters.Select(parameter => parameter.Type)
|
|
.OfType<INamedTypeSymbol>()
|
|
.Select(type => new RoslynType(type, _assembly))
|
|
.ToList();
|
|
|
|
public IXamlType DeclaringType => new RoslynType((INamedTypeSymbol)_symbol.ReceiverType, _assembly);
|
|
|
|
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments) => null;
|
|
|
|
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes { get; } = new List<IXamlCustomAttribute>();
|
|
}
|
|
}
|