Files
AdamuSw/src/Persistence/SourceGenerator/ModelGeneratorHelper.cs
2026-07-14 19:00:35 +03:00

167 lines
6.0 KiB
C#

// <copyright file="ModelGeneratorHelper.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.SourceGenerator;
using System.Reflection;
using MUnique.OpenMU.DataModel;
/// <summary>
/// Helper class containing shared functionality for model generators.
/// </summary>
internal static class ModelGeneratorHelper
{
private static IList<Type> _customTypes;
/// <summary>
/// Gets a header template for a generated file.
/// </summary>
public static string FileHeaderTemplate => @"// <copyright file=""{0}.Generated.cs"" company=""MUnique"">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All";
/// <summary>
/// Gets the namespace of the configuration classes.
/// </summary>
public static string ConfigurationNamespace => "MUnique.OpenMU.DataModel.Configuration";
/// <summary>
/// Gets the types which need to be customized for persistence.
/// </summary>
public static IEnumerable<Type> CustomTypes => _customTypes ??= GetCustomTypes();
/// <summary>
/// Determines whether the given type is a configuration type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns><c>true</c> if the given type is a configuration type; otherwise, <c>false</c>.</returns>
public static bool IsConfigurationType(Type type)
{
if (type.Namespace != null
&& type.Namespace.StartsWith(ConfigurationNamespace, StringComparison.InvariantCulture))
{
return true;
}
if (type.BaseType is { Namespace: { } }
&& type.BaseType.Namespace.StartsWith(ConfigurationNamespace, StringComparison.InvariantCulture))
{
return true;
}
if (type.Name.Contains("Definition", StringComparison.InvariantCulture))
{
return true;
}
if (type.Name is "AttributeRelationship" or "PlugInConfiguration" or "ConstValueAttribute")
{
return true;
}
return false;
}
/// <summary>
/// Gets the parameter definitions for a method or constructor.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <returns>The string of the parameter definitions.</returns>
public static string GetParameterDefinitions(ICollection<ParameterInfo> parameters)
{
var result = new StringBuilder();
foreach (var p in parameters)
{
result.Append(p.ParameterType.GetCSharpFullName())
.Append(" ")
.Append(p.Name);
if (parameters.Count > p.Position + 1)
{
result.Append(", ");
}
}
return result.ToString();
}
/// <summary>
/// Gets the parameters used to call a method.
/// </summary>
/// <param name="parameters">The parameter infos.</param>
/// <returns>The parameters used to call a method.</returns>
public static string GetParameters(ICollection<ParameterInfo> parameters)
{
var result = new StringBuilder();
foreach (var p in parameters)
{
result.Append(p.Name);
if (parameters.Count > p.Position + 1)
{
result.Append(", ");
}
}
return result.ToString();
}
/// <summary>
/// Overrides the <see cref="ICloneable{T}"/> implementation, so that the correct class instance
/// is created and the id is assigned.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="className">Name of the class.</param>
/// <returns>The implementation for <see cref="ICloneable{T}"/>.</returns>
public static string OverrideClonable(Type type, string className)
{
return $$"""
/// <inheritdoc />
public override {{type.Namespace}}.{{className}} Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new {{className}}();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf({{type.Namespace}}.{{className}} other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
""";
}
/// <summary>
/// Determines the types which require customization.
/// </summary>
/// <returns>The types that require customization.</returns>
private static List<Type> GetCustomTypes()
{
var result = new List<Type>();
var loadedTypes = typeof(DataModel.Attributes.PowerUpDefinition).Assembly.GetTypes()
.Where(type => type.IsClass && type.IsPublic)
.Where(type => !type.IsSealed && !type.IsAbstract && type.GetConstructor([]) != null).ToList();
result.AddRange(loadedTypes);
result.Add(typeof(MUnique.OpenMU.AttributeSystem.AttributeDefinition));
result.Add(typeof(MUnique.OpenMU.AttributeSystem.StatAttribute));
result.Add(typeof(MUnique.OpenMU.AttributeSystem.ConstValueAttribute));
result.Add(typeof(MUnique.OpenMU.AttributeSystem.AttributeRelationship));
result.Add(typeof(MUnique.OpenMU.Interfaces.LetterHeader));
result.Add(typeof(MUnique.OpenMU.Interfaces.Friend));
result.Add(typeof(MUnique.OpenMU.PlugIns.PlugInConfiguration));
return result;
}
}