From bf73798c743ccc5a04dcb0d89ffeea81791cd552 Mon Sep 17 00:00:00 2001 From: Tim Potze Date: Sun, 31 May 2026 22:25:14 +0200 Subject: [PATCH] Add CommandParameterAttribute --- .../Attributes/CommandParameterAttribute.cs | 36 +++++++++++++++++++ .../Core/CommandScanner.cs | 10 ++++-- .../Core/CommandScannerTests.cs | 21 +++++++++++ .../Systems/TestConsoleCommandsSystem.cs | 24 ++++++++++++- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 src/SampSharp.OpenMp.Entities.Commands/Attributes/CommandParameterAttribute.cs diff --git a/src/SampSharp.OpenMp.Entities.Commands/Attributes/CommandParameterAttribute.cs b/src/SampSharp.OpenMp.Entities.Commands/Attributes/CommandParameterAttribute.cs new file mode 100644 index 00000000..2767ea4e --- /dev/null +++ b/src/SampSharp.OpenMp.Entities.Commands/Attributes/CommandParameterAttribute.cs @@ -0,0 +1,36 @@ +namespace SampSharp.Entities.SAMP.Commands; + +/// +/// Specifies metadata for a command parameter, such as its display name and optional parser type. +/// +[AttributeUsage(AttributeTargets.Parameter)] +public class CommandParameterAttribute : Attribute +{ + /// + /// Initializes a new instance of the class. + /// + public CommandParameterAttribute() + { + } + + /// + /// Initializes a new instance of the class with a name and optional parser type. + /// + /// The display name of the command parameter or to use the default name. + /// The type used to parse the parameter value, or to use the default parser. + public CommandParameterAttribute(string? name, Type? parserType = null) + { + Name = name; + ParserType = parserType; + } + + /// + /// Gets or sets the display name of the command parameter. + /// + public string? Name { get; set; } + + /// + /// Gets or sets the type used to parse the command parameter. + /// + public Type? ParserType { get; set; } +} \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities.Commands/Core/CommandScanner.cs b/src/SampSharp.OpenMp.Entities.Commands/Core/CommandScanner.cs index 66949e1c..37b49c9d 100644 --- a/src/SampSharp.OpenMp.Entities.Commands/Core/CommandScanner.cs +++ b/src/SampSharp.OpenMp.Entities.Commands/Core/CommandScanner.cs @@ -348,10 +348,16 @@ private static bool TryCollectParameters(ParameterInfo[] parameters, int prefixP { var param = parameters[i]; - var paramName = param.Name ?? $"param{i}"; + var paramAtribute = param.GetCustomAttribute(); + + var paramName = paramAtribute?.Name ?? param.Name ?? $"param{i}"; // Try to get a parser for this parameter - var parser = parserFactory.CreateParser(parameters, i); + var parserInstance = paramAtribute?.ParserType is not null + ? Activator.CreateInstance(paramAtribute.ParserType) + : null; + + var parser = parserInstance as ICommandParameterParser ?? parserFactory.CreateParser(parameters, i); if (parser == null) { diff --git a/test/SampSharp.OpenMp.Entities.Commands.Tests/Core/CommandScannerTests.cs b/test/SampSharp.OpenMp.Entities.Commands.Tests/Core/CommandScannerTests.cs index 67fecb80..41c335b2 100644 --- a/test/SampSharp.OpenMp.Entities.Commands.Tests/Core/CommandScannerTests.cs +++ b/test/SampSharp.OpenMp.Entities.Commands.Tests/Core/CommandScannerTests.cs @@ -159,6 +159,12 @@ private class CommandWithSuffixSystem : ISystem public void HelpCommand(Player player) { } } + private class CommandWithCustomNameSystem : ISystem + { + [PlayerCommand] + public void MessageCommand(Player player, [CommandParameter("custom")]string text) { } + } + private class InvalidReturnTypeSystem : ISystem { // int is not a valid return type for player commands @@ -259,6 +265,21 @@ public void ScanPlayerCommands_StripsSuffixFromMethodName() FindByName(registry, "help").ShouldNotBeNull(); } + [Fact] + public void ScanPlayerCommands_ProvidesCustomName() + { + var registry = CreateCommandRegistry(); + var scanner = CreateScanner(typeof(CommandWithCustomNameSystem)); + + scanner.ScanPlayerCommands(registry, CreateParserFactory()); + + FindByName(registry, "message") + .ShouldNotBeNull() + .ParsedParameters[0] + .Name + .ShouldBe("custom"); + } + [Fact] public void ScanPlayerCommands_ExtractsParsedParameters() { diff --git a/test/TestMode.OpenMp.Entities/Systems/TestConsoleCommandsSystem.cs b/test/TestMode.OpenMp.Entities/Systems/TestConsoleCommandsSystem.cs index 27856d08..a4552aee 100644 --- a/test/TestMode.OpenMp.Entities/Systems/TestConsoleCommandsSystem.cs +++ b/test/TestMode.OpenMp.Entities/Systems/TestConsoleCommandsSystem.cs @@ -43,4 +43,26 @@ public void AddCommand(int a, int b) { Console.WriteLine($"{a} + {b} = {a + b}"); } -} \ No newline at end of file + + [ConsoleCommand(Name = "double_number")] + public void DoubleValueCommand([CommandParameter("value", typeof(DoubleIntParser))] int v) + { + Console.WriteLine(v); + } + + private class DoubleIntParser : ICommandParameterParser + { + private readonly IntParser _inner = new(); + + public bool TryParse(IServiceProvider services, ref StringSpan inputText, out object? result) + { + if (_inner.TryParse(services, ref inputText, out result) && result is int num) + { + result = num * 2; + return true; + } + + return false; + } + } +}