Add support for 'params' arguments

This commit is contained in:
Finite Reality
2016-07-30 21:37:55 +01:00
committed by RogueException
parent 724dbf0abf
commit c8fc0ffa33
3 changed files with 56 additions and 7 deletions

View File

@@ -71,6 +71,7 @@ namespace Discord.Commands
{
var parameter = parameters[i];
var type = parameter.ParameterType;
Type underlyingType = null;
if (i == 0)
{
@@ -80,10 +81,24 @@ namespace Discord.Commands
continue;
}
var typeInfo = type.GetTypeInfo();
var reader = Module.Service.GetTypeReader(type);
if (reader == null && typeInfo.IsEnum)
// TODO: is there a better way of detecting 'params'?
bool isParams = type.IsArray && i == parameters.Length - 1;
if (isParams)
{
underlyingType = type.GetElementType();
reader = Module.Service.GetTypeReader(underlyingType);
}
else
{
underlyingType = type;
}
var underlyingTypeInfo = underlyingType.GetTypeInfo();
var typeInfo = type.GetTypeInfo();
if (reader == null && underlyingTypeInfo.IsEnum)
{
reader = EnumTypeReader.GetReader(type);
Module.Service.AddTypeReader(type, reader);
@@ -101,7 +116,7 @@ namespace Discord.Commands
bool isOptional = parameter.IsOptional;
object defaultValue = parameter.HasDefaultValue ? parameter.DefaultValue : null;
paramBuilder.Add(new CommandParameter(name, description, type, reader, isOptional, isRemainder, defaultValue));
paramBuilder.Add(new CommandParameter(name, description, type, underlyingType, reader, isOptional, isRemainder, isParams, defaultValue));
}
return paramBuilder.ToImmutable();
}

View File

@@ -15,17 +15,21 @@ namespace Discord.Commands
public string Description { get; }
public bool IsOptional { get; }
public bool IsRemainder { get; }
public bool IsParams { get; }
public Type Type { get; }
public Type UnderlyingType { get; }
internal object DefaultValue { get; }
public CommandParameter(string name, string description, Type type, TypeReader reader, bool isOptional, bool isRemainder, object defaultValue)
public CommandParameter(string name, string description, Type type, Type underlyingType, TypeReader reader, bool isOptional, bool isRemainder, bool isParams, object defaultValue)
{
Name = name;
Description = description;
Type = type;
UnderlyingType = underlyingType;
_reader = reader;
IsOptional = isOptional;
IsRemainder = isRemainder;
IsParams = isParams;
DefaultValue = defaultValue;
}

View File

@@ -1,6 +1,9 @@
using System.Collections.Immutable;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System;
namespace Discord.Commands
{
@@ -20,6 +23,7 @@ namespace Discord.Commands
int endPos = input.Length;
var curPart = ParserPart.None;
int lastArgEndPos = int.MinValue;
IList<object> paramsList = null; // TODO: could we use a better type?
var argList = ImmutableArray.CreateBuilder<object>();
bool isEscaping = false;
char c;
@@ -70,6 +74,10 @@ namespace Discord.Commands
argBuilder.Append(c);
continue;
}
if (curParam != null && curParam.IsParams)
{
paramsList = new List<object>();
}
if (c == '\"')
{
curPart = ParserPart.QuotedParameter;
@@ -110,10 +118,32 @@ namespace Discord.Commands
var typeReaderResult = await curParam.Parse(context, argString).ConfigureAwait(false);
if (!typeReaderResult.IsSuccess)
return ParseResult.FromError(typeReaderResult);
argList.Add(typeReaderResult.Value);
curParam = null;
curPart = ParserPart.None;
if (curParam.IsParams)
{
paramsList.Add(typeReaderResult.Value);
if (curPos == endPos)
{
// TODO: can this logic be improved?
object[] _params = paramsList.ToArray();
Array realParams = Array.CreateInstance(curParam.UnderlyingType, _params.Length);
for (int i = 0; i < _params.Length; i++)
realParams.SetValue(Convert.ChangeType(_params[i], curParam.UnderlyingType), i);
argList.Add(realParams);
curParam = null;
curPart = ParserPart.None;
}
}
else
{
argList.Add(typeReaderResult.Value);
curParam = null;
curPart = ParserPart.None;
}
argBuilder.Clear();
}
}