using GFramework.Godot.SourceGenerators.Behavior; using GFramework.Godot.SourceGenerators.Tests.Core; namespace GFramework.Godot.SourceGenerators.Tests.Behavior; [TestFixture] public class AutoUiPageGeneratorTests { [Test] public async Task Generates_Ui_Page_Behavior_Boilerplate() { const string source = """ using System; using GFramework.Godot.SourceGenerators.Abstractions; using Godot; namespace GFramework.Godot.SourceGenerators.Abstractions { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class AutoUiPageAttribute : Attribute { public AutoUiPageAttribute(string key, string layerName) { } } } namespace Godot { public class Node { } public class CanvasItem : Node { } public class Control : CanvasItem { } } namespace GFramework.Game.Abstractions.Enums { public enum UiLayer { Page, Overlay, Modal } } namespace GFramework.Game.Abstractions.UI { public interface IUiPageBehavior { } } namespace GFramework.Godot.UI { using GFramework.Game.Abstractions.Enums; using GFramework.Game.Abstractions.UI; using Godot; public static class UiPageBehaviorFactory { public static IUiPageBehavior Create(T owner, string key, UiLayer layer) where T : CanvasItem { return null!; } } } namespace TestApp { [AutoUiPage("MainMenu", "Page")] public partial class MainMenu : Control { } } """; const string expected = """ // #nullable enable namespace TestApp; partial class MainMenu { private global::GFramework.Game.Abstractions.UI.IUiPageBehavior? __autoUiPageBehavior_Generated; public static string UiKeyStr => "MainMenu"; public global::GFramework.Game.Abstractions.UI.IUiPageBehavior GetPage() { return __autoUiPageBehavior_Generated ??= global::GFramework.Godot.UI.UiPageBehaviorFactory.Create(this, UiKeyStr, global::GFramework.Game.Abstractions.Enums.UiLayer.Page); } } """; await GeneratorTest.RunAsync( source, ("TestApp_MainMenu.AutoUiPage.g.cs", expected)); } [Test] public async Task Reports_Diagnostic_When_AutoUiPage_Attribute_Arguments_Are_Invalid() { const string source = """ using System; using GFramework.Godot.SourceGenerators.Abstractions; using Godot; namespace GFramework.Godot.SourceGenerators.Abstractions { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class AutoUiPageAttribute : Attribute { public AutoUiPageAttribute(string key) { } } } namespace Godot { public class Node { } public class CanvasItem : Node { } public class Control : CanvasItem { } } namespace GFramework.Game.Abstractions.Enums { public enum UiLayer { Page } } namespace GFramework.Game.Abstractions.UI { public interface IUiPageBehavior { } } namespace GFramework.Godot.UI { using GFramework.Game.Abstractions.Enums; using GFramework.Game.Abstractions.UI; using Godot; public static class UiPageBehaviorFactory { public static IUiPageBehavior Create(T owner, string key, UiLayer layer) where T : CanvasItem { return null!; } } } namespace TestApp { [{|#0:AutoUiPage("MainMenu")|}] public partial class MainMenu : Control { } } """; var test = new CSharpSourceGeneratorTest { TestState = { Sources = { source } }, DisabledDiagnostics = { "GF_Common_Trace_001" }, TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck }; test.ExpectedDiagnostics.Add(new DiagnosticResult("GF_AutoBehavior_004", DiagnosticSeverity.Error) .WithLocation(0) .WithArguments( "AutoUiPageAttribute", "MainMenu", "a string key argument and a string UiLayer name argument")); await test.RunAsync(); } [Test] public async Task Generates_Type_Constraints_For_ClassNullable_NotNull_And_Unmanaged() { const string source = """ #nullable enable using System; using GFramework.Godot.SourceGenerators.Abstractions; using Godot; namespace GFramework.Godot.SourceGenerators.Abstractions { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public sealed class AutoUiPageAttribute : Attribute { public AutoUiPageAttribute(string key, string layerName) { } } } namespace Godot { public class Node { } public class CanvasItem : Node { } public class Control : CanvasItem { } } namespace GFramework.Game.Abstractions.Enums { public enum UiLayer { Page } } namespace GFramework.Game.Abstractions.UI { public interface IUiPageBehavior { } } namespace GFramework.Godot.UI { using GFramework.Game.Abstractions.Enums; using GFramework.Game.Abstractions.UI; using Godot; public static class UiPageBehaviorFactory { public static IUiPageBehavior Create(T owner, string key, UiLayer layer) where T : CanvasItem { return null!; } } } namespace TestApp { [AutoUiPage("MainMenu", "Page")] public partial class MainMenu : Control where TReference : class? where TNotNull : notnull where TUnmanaged : unmanaged { } } """; const string expected = """ // #nullable enable namespace TestApp; partial class MainMenu where TReference : class? where TNotNull : notnull where TUnmanaged : unmanaged { private global::GFramework.Game.Abstractions.UI.IUiPageBehavior? __autoUiPageBehavior_Generated; public static string UiKeyStr => "MainMenu"; public global::GFramework.Game.Abstractions.UI.IUiPageBehavior GetPage() { return __autoUiPageBehavior_Generated ??= global::GFramework.Godot.UI.UiPageBehaviorFactory.Create(this, UiKeyStr, global::GFramework.Game.Abstractions.Enums.UiLayer.Page); } } """; await GeneratorTest.RunAsync( source, ("TestApp_MainMenu.AutoUiPage.g.cs", expected)); } }