@@ -71,7 +71,6 @@ namespace Discord.Commands | |||
{ | |||
var parameter = parameters[i]; | |||
var type = parameter.ParameterType; | |||
Type underlyingType = null; | |||
if (i == 0) | |||
{ | |||
@@ -81,20 +80,18 @@ namespace Discord.Commands | |||
continue; | |||
} | |||
// TODO: is there a better way of detecting 'params'? | |||
bool isParams = type.IsArray && i == parameters.Length - 1; | |||
if (isParams) | |||
underlyingType = type.GetElementType(); | |||
else | |||
underlyingType = type; | |||
//Detect 'params' | |||
bool isMultiple = parameter.GetCustomAttribute<ParamArrayAttribute>() != null; | |||
if (isMultiple) | |||
type = type.GetElementType(); | |||
var reader = Module.Service.GetTypeReader(underlyingType); | |||
var underlyingTypeInfo = underlyingType.GetTypeInfo(); | |||
var reader = Module.Service.GetTypeReader(type); | |||
var typeInfo = type.GetTypeInfo(); | |||
if (reader == null && underlyingTypeInfo.IsEnum) | |||
//Detect enums | |||
if (reader == null && typeInfo.IsEnum) | |||
{ | |||
reader = EnumTypeReader.GetReader(underlyingType); | |||
reader = EnumTypeReader.GetReader(type); | |||
Module.Service.AddTypeReader(type, reader); | |||
} | |||
@@ -110,7 +107,7 @@ namespace Discord.Commands | |||
bool isOptional = parameter.IsOptional; | |||
object defaultValue = parameter.HasDefaultValue ? parameter.DefaultValue : null; | |||
paramBuilder.Add(new CommandParameter(name, description, type, underlyingType, reader, isOptional, isRemainder, isParams, defaultValue)); | |||
paramBuilder.Add(new CommandParameter(name, description, type, reader, isOptional, isRemainder, isMultiple, defaultValue)); | |||
} | |||
return paramBuilder.ToImmutable(); | |||
} | |||
@@ -118,8 +115,7 @@ namespace Discord.Commands | |||
{ | |||
if (methodInfo.ReturnType != typeof(Task)) | |||
throw new InvalidOperationException("Commands must return a non-generic Task."); | |||
//TODO: Temporary reflection hack. Lets build an actual expression tree here. | |||
return (msg, args) => | |||
{ | |||
object[] newArgs = new object[args.Count + 1]; | |||
@@ -1,11 +1,9 @@ | |||
using System; | |||
using System.Diagnostics; | |||
using System.Reflection; | |||
using System.Threading.Tasks; | |||
namespace Discord.Commands | |||
{ | |||
//TODO: Add support for Multiple | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class CommandParameter | |||
{ | |||
@@ -15,21 +13,19 @@ namespace Discord.Commands | |||
public string Description { get; } | |||
public bool IsOptional { get; } | |||
public bool IsRemainder { get; } | |||
public bool IsParams { get; } | |||
public bool IsMultiple { get; } | |||
public Type Type { get; } | |||
public Type UnderlyingType { get; } | |||
internal object DefaultValue { get; } | |||
public CommandParameter(string name, string description, Type type, Type underlyingType, TypeReader reader, bool isOptional, bool isRemainder, bool isParams, object defaultValue) | |||
public CommandParameter(string name, string description, Type type, TypeReader reader, bool isOptional, bool isRemainder, bool isMultiple, object defaultValue) | |||
{ | |||
Name = name; | |||
Description = description; | |||
Type = type; | |||
UnderlyingType = underlyingType; | |||
_reader = reader; | |||
IsOptional = isOptional; | |||
IsRemainder = isRemainder; | |||
IsParams = isParams; | |||
IsMultiple = isMultiple; | |||
DefaultValue = defaultValue; | |||
} | |||
@@ -23,8 +23,8 @@ 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>(); | |||
List<object> paramsList = null; // TODO: could we use a better type? | |||
bool isEscaping = false; | |||
char c; | |||
@@ -74,10 +74,6 @@ namespace Discord.Commands | |||
argBuilder.Append(c); | |||
continue; | |||
} | |||
if (curParam != null && curParam.IsParams) | |||
{ | |||
paramsList = new List<object>(); | |||
} | |||
if (c == '\"') | |||
{ | |||
curPart = ParserPart.QuotedParameter; | |||
@@ -119,17 +115,17 @@ namespace Discord.Commands | |||
if (!typeReaderResult.IsSuccess) | |||
return ParseResult.FromError(typeReaderResult); | |||
if (curParam.IsParams) | |||
if (curParam.IsMultiple) | |||
{ | |||
if (paramsList == null) | |||
paramsList = new List<object>(); | |||
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); | |||
Array realParams = Array.CreateInstance(curParam.Type, paramsList.Count); | |||
for (int i = 0; i < paramsList.Count; i++) | |||
realParams.SetValue(Convert.ChangeType(paramsList[i], curParam.Type), i); | |||
argList.Add(realParams); | |||