From dd5d1c3496a09ecc46d6d57ed2a33e74760cf6db Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 28 Jun 2022 18:34:41 +0700 Subject: [PATCH] Change remainder param to allow options first --- sources/Commands/CommandParser.uc | 34 ++++++++++++++------------ sources/Commands/Tests/TEST_Command.uc | 10 ++++---- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/sources/Commands/CommandParser.uc b/sources/Commands/CommandParser.uc index d35d6c2..7bb4877 100644 --- a/sources/Commands/CommandParser.uc +++ b/sources/Commands/CommandParser.uc @@ -400,23 +400,29 @@ private final function bool ParseSingleValue( AssociativeArray parsedParameters, Command.Parameter expectedParameter) { - // First we try `CPT_Remainder` parameter, since it is a special case that - // consumes all further input - if (expectedParameter.type == CPT_Remainder) { - return ParseRemainderValue(parsedParameters, expectedParameter); - } // Before parsing any other value we need to check if user has // specified any options instead. // However this might lead to errors if we are already parsing // necessary parameters of another option: // we must handle such situation and report an error. - if ( currentTargetIsOption && currentTarget != CPT_ExtraParameter - && TryParsingOptions()) + if (currentTargetIsOption) { - DeclareError(CET_NoRequiredParamForOption, targetOption.longName); - return false; + // There is no problem is option's parameter is remainder + if (expectedParameter.type == CPT_Remainder) { + return ParseRemainderValue(parsedParameters, expectedParameter); + } + if (currentTarget != CPT_ExtraParameter && TryParsingOptions()) + { + DeclareError(CET_NoRequiredParamForOption, targetOption.longName); + return false; + } } while (TryParsingOptions()); + // First we try `CPT_Remainder` parameter, since it is a special case that + // consumes all further input + if (expectedParameter.type == CPT_Remainder) { + return ParseRemainderValue(parsedParameters, expectedParameter); + } // Propagate errors after parsing options if (nextResult.parsingError != CET_None) { return false; @@ -567,15 +573,13 @@ private final function bool ParseRemainderValue( AssociativeArray parsedParameters, Command.Parameter expectedParameter) { - local string textValue; - // TODO: use parsing methods into `Text` - // (needs some work for reading formatting `string`s from `Text` objects) - commandParser.Skip().MUntilS(textValue); + local MutableText value; + + commandParser.Skip().MUntil(value); if (!commandParser.Ok()) { return false; } - RecordParameter(parsedParameters, expectedParameter, - _.text.FromString(textValue)); + RecordParameter(parsedParameters, expectedParameter, value.IntoText()); return true; } diff --git a/sources/Commands/Tests/TEST_Command.uc b/sources/Commands/Tests/TEST_Command.uc index 243dc8d..341a863 100644 --- a/sources/Commands/Tests/TEST_Command.uc +++ b/sources/Commands/Tests/TEST_Command.uc @@ -395,24 +395,24 @@ protected static function SubTest_MockBQ2() protected static function SubTest_MockBQ3Remainder() { - local Command.CallData result; + local Command.CallData result; local DynamicArray subArray; local AssociativeArray options, subObject; Issue("Cannot parse command queries with `CPT_Remainder` type parameters."); result = class'MockCommandB'.static.GetInstance() .ParseInputWith(PRS(default.queryBSuccess3), none); - TEST_ExpectTrue(result.Parameters.GetLength() == 1); - subArray = DynamicArray(result.Parameters.GetItem(P("list"))); + TEST_ExpectTrue(result.parameters.GetLength() == 1); + subArray = DynamicArray(result.parameters.GetItem(P("list"))); TEST_ExpectTrue(FloatBox(subArray.GetItem(0)).Get() == 3); TEST_ExpectTrue(FloatBox(subArray.GetItem(1)).Get() == -76); - options = result.Options; + options = result.options; TEST_ExpectTrue(options.GetLength() == 1); TEST_ExpectTrue(options.HasKey(P("remainder"))); subObject = AssociativeArray(options.GetItem(P("remainder"))); TEST_ExpectTrue( Text(subObject.GetItem(P("everything"))).ToString() == "--type \"value\" -va 8 -sV --forced -T \"\" 32"); } -// [1, 2, 3, 6] + defaultproperties { caseName = "Command"