Skip to content

Commit

Permalink
Add checks for positional arguments (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrey-zherikov authored Sep 12, 2023
1 parent 6c7083a commit 38d217b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
2 changes: 1 addition & 1 deletion source/argparse/internal/argumentuda.d
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ if(!is(TYPE == void))
}
else static if(isStaticArray!T)
{
enum min = 1;
enum min = T.length;
enum max = T.length;
}
else static if(isArray!T || isAssociativeArray!T)
Expand Down
26 changes: 25 additions & 1 deletion source/argparse/internal/command.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import argparse.param;
import argparse.result;
import argparse.api.argument: TrailingArguments, NamedArgument, NumberOfValues;
import argparse.api.command: isDefaultCommand, RemoveDefaultAttribute, SubCommandsUDA = SubCommands;
import argparse.internal.arguments: Arguments;
import argparse.internal.arguments: Arguments, ArgumentInfo;
import argparse.internal.commandinfo;
import argparse.internal.argumentuda: ArgumentUDA, getArgumentUDA, getMemberArgumentUDA;
import argparse.internal.help: HelpArgumentUDA;
Expand Down Expand Up @@ -263,6 +263,30 @@ package(argparse) Command createCommand(Config config, COMMAND_TYPE, CommandInfo
{
import std.algorithm: map;
import std.array: array;
import std.meta: Filter, staticMap, staticSort;


enum hasArgumentUDA(alias sym) = hasUDA!(__traits(getMember, COMMAND_TYPE, sym), ArgumentUDA);
enum getArgumentInfo(alias sym) = getMemberArgumentUDA!(config, COMMAND_TYPE, sym, void).info;//getUDAs!(__traits(getMember, COMMAND_TYPE, sym), ArgumentUDA)[0].info;

enum positional(ArgumentInfo info) = info.positional;

enum cmp(ArgumentInfo info1, ArgumentInfo info2) = info1.position.get - info2.position.get;

enum positionalArgs = staticSort!(cmp, Filter!(positional, staticMap!(getArgumentInfo, Filter!(hasArgumentUDA, iterateArguments!COMMAND_TYPE))));

static foreach(int i, info; positionalArgs)
{{
enum int pos = info.position.get;

static if(i < pos)
static assert(false, "Positional argument with index "~i.stringof~" is missed in "~COMMAND_TYPE.stringof);
else static if(i > pos)
static assert(false, "Positional argument with index "~pos.stringof~" is duplicated in "~COMMAND_TYPE.stringof);

static if(pos < positionalArgs.length - 1)
static assert(info.minValuesCount.get == info.maxValuesCount.get, "Positional argument with index "~pos.stringof~" in "~COMMAND_TYPE.stringof~" has variable number of values.");
}}

Command res;

Expand Down
7 changes: 7 additions & 0 deletions source/argparse/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ unittest
@(PositionalArgument(2)) int b;
}
static assert(!__traits(compiles, { T4 t; enum c = createCommand!(Config.init)(t); }));

struct T5
{
@(PositionalArgument(0)) int[] a;
@(PositionalArgument(1)) int b;
}
static assert(!__traits(compiles, { T5 t; enum c = createCommand!(Config.init)(t); }));
}

unittest
Expand Down

0 comments on commit 38d217b

Please sign in to comment.