|
1 | 1 | using Microsoft.CodeAnalysis; |
2 | 2 | using Microsoft.CodeAnalysis.CSharp; |
3 | 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; |
| 4 | +using System.Text; |
4 | 5 |
|
5 | 6 | // 这坨写得太史了 |
6 | 7 |
|
@@ -289,7 +290,7 @@ var errors |
289 | 290 | property?.Name ?? subClass.Name, |
290 | 291 | property?.ContainingType?.ToDisplayString() ?? subClass.ContainingType?.ToDisplayString())); |
291 | 292 | } |
292 | | - if(fallbackType is not null) |
| 293 | + if (fallbackType is not null) |
293 | 294 | { |
294 | 295 | var property = fallbackType.GetMembers().FirstOrDefault(m => m.Kind == SymbolKind.Property && m.Name == enumPropertyName); |
295 | 296 | if (property is IPropertySymbol propSymbol) |
@@ -322,7 +323,7 @@ var errors |
322 | 323 | } |
323 | 324 | typesToGenerate.Add(new() |
324 | 325 | { |
325 | | - ClassType = classGen.RootType, |
| 326 | + RootClassType = classGen.RootType, |
326 | 327 | ClassTypeEnum = enumType, |
327 | 328 | FallbackClassType = fallbackType, |
328 | 329 | FallbackClassTypeEnum = fallbackEnumMember, |
@@ -537,6 +538,7 @@ static IEnumerable<INamedTypeSymbol> GetAllTypes(INamespaceSymbol namespaceSymbo |
537 | 538 | GenerateEventTypeRegistry(context, registryInfo.Combine(context.CompilationProvider).Combine(EventTypeRegistryInfo), errors); |
538 | 539 | GenerateEnumConverter(context, registryInfo); |
539 | 540 | GenerateOtherFiles(context, registryInfo); |
| 541 | + GenerateUpgrater(context, registryInfo.Combine(EventTypeRegistryInfo)); |
540 | 542 |
|
541 | 543 | } |
542 | 544 | private const string CoreNs = "Global"; |
@@ -625,6 +627,90 @@ public static void SerializeMainEntry<T>(T mainEntry, Stream stream, RhythmBase. |
625 | 627 | context.AddSource($"FileMainEntryConverter.{registryId}.g.cs", src); |
626 | 628 | }); |
627 | 629 | } |
| 630 | + private static void GenerateUpgrater(IncrementalGeneratorInitializationContext cxt, IncrementalValueProvider<(string? Left, EventTypeRegistryGenerationInfo[] Right)> incrementalValueProvider) |
| 631 | + { |
| 632 | + cxt.RegisterSourceOutput(incrementalValueProvider, (source, value) => |
| 633 | + { |
| 634 | + (string? registryId, EventTypeRegistryGenerationInfo[]? gens) = value; |
| 635 | + if (string.IsNullOrEmpty(registryId)) |
| 636 | + return; |
| 637 | + bool multiple = gens?.Length > 1; |
| 638 | + StringBuilder sb = new(); |
| 639 | + sb.AppendLine($"namespace RhythmBase.{registryId}.Converters;"); |
| 640 | + foreach (var info in gens ?? []) |
| 641 | + { |
| 642 | + string mtpName = multiple ? $"{info.RootClassType.Name}" : ""; |
| 643 | + string src = $$""" |
| 644 | + /// <summary> |
| 645 | + /// A JSON converter for <see cref="{{info.RootClassType.ToDisplayString()}}"/> that uses metadata-aware serializer options. |
| 646 | + /// </summary> |
| 647 | + internal abstract class BackwardCompatible{{mtpName}}MetadataJsonConverter : RhythmBase.Global.Converters.MetadataJsonConverter<{{info.RootClassType.ToDisplayString()}}> |
| 648 | + { |
| 649 | + protected class Upgrater |
| 650 | + { |
| 651 | + internal int MaxVersion { get; init; } |
| 652 | + internal required Action<{{info.RootClassType.ToDisplayString()}}> UpgrateFunc { get; init; } |
| 653 | + internal required {{info.ClassTypeEnum.ToDisplayString()}} Type { get; init; } |
| 654 | + } |
| 655 | + private readonly List<Upgrater> _upgraters = []; |
| 656 | + private readonly EnumCollection<{{info.ClassTypeEnum.ToDisplayString()}}> _typeHasUpgrater = []; |
| 657 | + private int _maxVersion; |
| 658 | + /// <summary> |
| 659 | + /// The maximum version that this converter can upgrade. |
| 660 | + /// </summary> |
| 661 | + internal int MaxVersion => _maxVersion; |
| 662 | + /// <summary> |
| 663 | + /// The types of events that this converter can upgrade. |
| 664 | + /// </summary> |
| 665 | + internal EnumCollection<{{info.ClassTypeEnum.ToDisplayString()}}> TypeHasUpgrater => _typeHasUpgrater; |
| 666 | + /// <summary> |
| 667 | + /// Registers an upgrader for a specific event type and version. |
| 668 | + /// </summary> |
| 669 | + /// <typeparam name="T">The type of the event to upgrade.</typeparam> |
| 670 | + /// <param name="version"> |
| 671 | + /// The version for which to register the upgrader. |
| 672 | + /// Versions <b>equal to or lower than</b> this will be affected by this upgrader. |
| 673 | + /// </param> |
| 674 | + /// <param name="upgrateAction">The action to perform when upgrading the event.</param> |
| 675 | + protected void Register<T>(int version, Action<{{info.RootClassType.ToDisplayString()}}> upgrateAction) where T : {{info.RootClassType.ToDisplayString()}}, new() |
| 676 | + { |
| 677 | + var type = EventTypeRegistry.ToEnum{{(multiple ? info.ClassTypeEnum.Name : "")}}<T>(); |
| 678 | + _maxVersion = int.Max(_maxVersion, version); |
| 679 | + _typeHasUpgrater.Add(type); |
| 680 | + _upgraters.Add(new Upgrater() |
| 681 | + { |
| 682 | + MaxVersion = version, |
| 683 | + Type = type, |
| 684 | + UpgrateFunc = upgrateAction |
| 685 | + }); |
| 686 | + } |
| 687 | + /// <summary> |
| 688 | + /// Upgrades the specified event to the latest version if an upgrader is registered for its type and version. |
| 689 | + /// </summary> |
| 690 | + /// <param name="version">The version of the event to upgrade.</param> |
| 691 | + /// <param name="type">The type of the event to upgrade.</param> |
| 692 | + /// <returns>An enumerable of upgraders that can upgrade the event.</returns> |
| 693 | + protected IEnumerable<Upgrater> GetUpgraters(int version, {{info.ClassTypeEnum.ToDisplayString()}} type) |
| 694 | + { |
| 695 | + foreach (Upgrater upgrater in _upgraters) |
| 696 | + if (upgrater.Type == type && upgrater.MaxVersion >= version) |
| 697 | + yield return upgrater; |
| 698 | + } |
| 699 | + internal BackwardCompatible{{mtpName}}MetadataJsonConverter() |
| 700 | + { |
| 701 | + InitializeUpgraters(); |
| 702 | + } |
| 703 | + /// <summary> |
| 704 | + /// Initializes the upgraders for this converter. This method is called once when the converter is first used. |
| 705 | + /// </summary> |
| 706 | + protected abstract void InitializeUpgraters(); |
| 707 | + } |
| 708 | + """; |
| 709 | + sb.AppendLine(src); |
| 710 | + } |
| 711 | + source.AddSource($"Upgrader.{registryId}.g.cs", sb.ToString()); |
| 712 | + }); |
| 713 | + } |
628 | 714 |
|
629 | 715 | private static ClassGenCvtrInfo GetClassGenCvtrInfo(Compilation compilation, INamedTypeSymbol? enumType, string enumPropertyName, INamedTypeSymbol? symbol) |
630 | 716 | { |
|
0 commit comments