Browse Source

feature: Provide ParameterInfo with error ParseResult (#1355)

Currently, when handling parsing errors, there is no way to know what
parameter caused the error. This change makes the CommandParser create
the parsing error with the current parameter info when ParseAsync()
fails. It is then available through the ErrorParameter of the
ParseResult.
tags/2.2.0
Adam Gauthier Christopher F 5 years ago
parent
commit
3755a027b3
2 changed files with 28 additions and 14 deletions
  1. +6
    -6
      src/Discord.Net.Commands/CommandParser.cs
  2. +22
    -8
      src/Discord.Net.Commands/Results/ParseResult.cs

+ 6
- 6
src/Discord.Net.Commands/CommandParser.cs View File

@@ -103,7 +103,7 @@ namespace Discord.Commands
argBuilder.Append(c);
continue;
}
if (IsOpenQuote(aliasMap, c))
{
curPart = ParserPart.QuotedParameter;
@@ -136,7 +136,7 @@ namespace Discord.Commands
else
argBuilder.Append(c);
}
if (argString != null)
{
if (curParam == null)
@@ -149,7 +149,7 @@ namespace Discord.Commands

var typeReaderResult = await curParam.ParseAsync(context, argString, services).ConfigureAwait(false);
if (!typeReaderResult.IsSuccess && typeReaderResult.Error != CommandError.MultipleMatches)
return ParseResult.FromError(typeReaderResult);
return ParseResult.FromError(typeReaderResult, curParam);

if (curParam.IsMultiple)
{
@@ -172,7 +172,7 @@ namespace Discord.Commands
{
var typeReaderResult = await curParam.ParseAsync(context, argBuilder.ToString(), services).ConfigureAwait(false);
if (!typeReaderResult.IsSuccess)
return ParseResult.FromError(typeReaderResult);
return ParseResult.FromError(typeReaderResult, curParam);
argList.Add(typeReaderResult);
}

@@ -180,7 +180,7 @@ namespace Discord.Commands
return ParseResult.FromError(CommandError.ParseFailed, "Input text may not end on an incomplete escape.");
if (curPart == ParserPart.QuotedParameter)
return ParseResult.FromError(CommandError.ParseFailed, "A quoted parameter is incomplete.");
//Add missing optionals
for (int i = argList.Count; i < command.Parameters.Count; i++)
{
@@ -191,7 +191,7 @@ namespace Discord.Commands
return ParseResult.FromError(CommandError.BadArgCount, "The input text has too few parameters.");
argList.Add(TypeReaderResult.FromSuccess(param.DefaultValue));
}
return ParseResult.FromSuccess(argList.ToImmutable(), paramList.ToImmutable());
}
}


+ 22
- 8
src/Discord.Net.Commands/Results/ParseResult.cs View File

@@ -18,30 +18,40 @@ namespace Discord.Commands
/// <inheritdoc/>
public string ErrorReason { get; }

/// <summary>
/// Provides information about the parameter that caused the parsing error.
/// </summary>
/// <returns>
/// A <see cref="ParameterInfo" /> indicating the parameter info of the error that may have occurred during parsing;
/// <c>null</c> if the parsing was successful or the parsing error is not specific to a single parameter.
/// </returns>
public ParameterInfo ErrorParameter { get; }

/// <inheritdoc/>
public bool IsSuccess => !Error.HasValue;

private ParseResult(IReadOnlyList<TypeReaderResult> argValues, IReadOnlyList<TypeReaderResult> paramValues, CommandError? error, string errorReason)
private ParseResult(IReadOnlyList<TypeReaderResult> argValues, IReadOnlyList<TypeReaderResult> paramValues, CommandError? error, string errorReason, ParameterInfo errorParamInfo)
{
ArgValues = argValues;
ParamValues = paramValues;
Error = error;
ErrorReason = errorReason;
ErrorParameter = errorParamInfo;
}
public static ParseResult FromSuccess(IReadOnlyList<TypeReaderResult> argValues, IReadOnlyList<TypeReaderResult> paramValues)
{
for (int i = 0; i < argValues.Count; i++)
{
if (argValues[i].Values.Count > 1)
return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found.");
return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found.", null);
}
for (int i = 0; i < paramValues.Count; i++)
{
if (paramValues[i].Values.Count > 1)
return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found.");
return new ParseResult(argValues, paramValues, CommandError.MultipleMatches, "Multiple matches found.", null);
}
return new ParseResult(argValues, paramValues, null, null);
return new ParseResult(argValues, paramValues, null, null, null);
}
public static ParseResult FromSuccess(IReadOnlyList<TypeReaderValue> argValues, IReadOnlyList<TypeReaderValue> paramValues)
{
@@ -55,15 +65,19 @@ namespace Discord.Commands
for (int i = 0; i < paramValues.Count; i++)
paramList[i] = TypeReaderResult.FromSuccess(paramValues[i]);
}
return new ParseResult(argList, paramList, null, null);
return new ParseResult(argList, paramList, null, null, null);
}

public static ParseResult FromError(CommandError error, string reason)
=> new ParseResult(null, null, error, reason);
=> new ParseResult(null, null, error, reason, null);
public static ParseResult FromError(CommandError error, string reason, ParameterInfo parameterInfo)
=> new ParseResult(null, null, error, reason, parameterInfo);
public static ParseResult FromError(Exception ex)
=> FromError(CommandError.Exception, ex.Message);
public static ParseResult FromError(IResult result)
=> new ParseResult(null, null, result.Error, result.ErrorReason);
=> new ParseResult(null, null, result.Error, result.ErrorReason, null);
public static ParseResult FromError(IResult result, ParameterInfo parameterInfo)
=> new ParseResult(null, null, result.Error, result.ErrorReason, parameterInfo);

public override string ToString() => IsSuccess ? "Success" : $"{Error}: {ErrorReason}";
private string DebuggerDisplay => IsSuccess ? $"Success ({ArgValues.Count}{(ParamValues.Count > 0 ? $" +{ParamValues.Count} Values" : "")})" : $"{Error}: {ErrorReason}";


Loading…
Cancel
Save