diff --git a/src/ConsoleAppFramework/Command.cs b/src/ConsoleAppFramework/Command.cs index 9a9a585..00344de 100644 --- a/src/ConsoleAppFramework/Command.cs +++ b/src/ConsoleAppFramework/Command.cs @@ -273,7 +273,7 @@ string Core(ITypeSymbol type, bool nullable) { if (elementType.AllInterfaces.Any(x => x.EqualsUnconstructedGenericType(parsable))) { - return $"if ({incrementIndex}!TrySplitParse(commandArgs[i], {outArgVar})) {{ ThrowArgumentParseFailed(\"{argumentName}\", commandArgs[i]); }}{elseExpr}"; + return $"if ({incrementIndex}!TrySplitParse(commandArgs[i], arg{argCount})) {{ ThrowArgumentParseFailed(\"{argumentName}\", commandArgs[i]); }}{elseExpr}"; } } break; diff --git a/src/ConsoleAppFramework/ConsoleAppBaseCode.cs b/src/ConsoleAppFramework/ConsoleAppBaseCode.cs index fd0f373..d2f1018 100644 --- a/src/ConsoleAppFramework/ConsoleAppBaseCode.cs +++ b/src/ConsoleAppFramework/ConsoleAppBaseCode.cs @@ -18,6 +18,7 @@ namespace ConsoleAppFramework; using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; """; @@ -37,6 +38,7 @@ namespace ConsoleAppFramework; using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; #if !USE_EXTERNAL_CONSOLEAPP_ABSTRACTIONS @@ -296,28 +298,29 @@ static bool TryParseParamsArray(ReadOnlySpan args, ref T[] result, re return true; } - static bool TrySplitParse(ReadOnlySpan s, out T[] result) + static bool TrySplitParse(ReadOnlySpan s, List result) where T : ISpanParsable { + T[] array = default(T[]); if (s.StartsWith("[")) { try { - result = System.Text.Json.JsonSerializer.Deserialize(s, JsonSerializerOptions)!; + array = System.Text.Json.JsonSerializer.Deserialize(s, JsonSerializerOptions)!; + result.AddRange(array); return true; } catch { - result = default!; return false; } } var count = s.Count(',') + 1; - result = new T[count]; + array = new T[count]; var source = s; - var destination = result.AsSpan(); + var destination = array.AsSpan(); Span ranges = stackalloc Range[Math.Min(count, 128)]; while (true) @@ -349,6 +352,8 @@ static bool TrySplitParse(ReadOnlySpan s, out T[] result) } } + result.AddRange(array); + return true; } diff --git a/src/ConsoleAppFramework/Emitter.cs b/src/ConsoleAppFramework/Emitter.cs index 7481bf2..f1cbf85 100644 --- a/src/ConsoleAppFramework/Emitter.cs +++ b/src/ConsoleAppFramework/Emitter.cs @@ -159,10 +159,18 @@ public void EmitRun(SourceBuilder sb, CommandWithId commandWithId, bool isRunAsy var parameter = command.Parameters[i]; if (parameter.IsParsable) { - var defaultValue = parameter.IsParams ? $"({parameter.ToTypeDisplayString()})[]" + if (parameter.Type.TypeKind == TypeKind.Array && !parameter.IsParams) + { + sb.AppendLine($"var arg{i} = new List<{((IArrayTypeSymbol)parameter.Type.TypeSymbol).ElementType.ToFullyQualifiedFormatDisplayString()}>();"); + } + else + { + var defaultValue = parameter.IsParams ? $"({parameter.ToTypeDisplayString()})[]" : parameter.HasDefaultValue ? parameter.DefaultValueToString() : $"default({parameter.Type.ToFullyQualifiedFormatDisplayString()})"; - sb.AppendLine($"var arg{i} = {defaultValue};"); + sb.AppendLine($"var arg{i} = {defaultValue};"); + } + if (parameter.RequireCheckArgumentParsed) { sb.AppendLine($"var arg{i}Parsed = false;"); @@ -348,7 +356,13 @@ public void EmitRun(SourceBuilder sb, CommandWithId commandWithId, bool isRunAsy // invoke for sync/async, void/int sb.AppendLine(); - var methodArguments = string.Join(", ", command.Parameters.Select((x, i) => $"arg{i}!")); + var methodArguments = string.Join(", ", command.Parameters.Select((x, i) => + { + if (x.IsParsable && x.Type.TypeKind == TypeKind.Array && !x.IsParams) + return $"arg{i}.ToArray()"; + else + return $"arg{i}!"; + })); string invokeCommand; if (command.CommandMethodInfo == null) { diff --git a/tests/ConsoleAppFramework.GeneratorTests/ArrayParseTest.cs b/tests/ConsoleAppFramework.GeneratorTests/ArrayParseTest.cs index 45ecb2c..57da833 100644 --- a/tests/ConsoleAppFramework.GeneratorTests/ArrayParseTest.cs +++ b/tests/ConsoleAppFramework.GeneratorTests/ArrayParseTest.cs @@ -48,6 +48,18 @@ public async Task ParseArray() await verifier.Execute(code, args: $"--ix {largeIntArray} --sx a,b,c,d,e", expected: $"[{expectedIntArray}][a, b, c, d, e]"); } + [Test] + public async Task RepeatArguments() + { + var code = """ +ConsoleApp.Run(args, (int[] number) => +{ + Console.Write("[" + string.Join(", ", number) + "]"); +}); +"""; + await verifier.Execute(code, args: "--number 1 --number 2 --number 3 --number 4 --number 5", expected: "[1, 2, 3, 4, 5]"); + } + [Test] public async Task JsonArray() {