Browse Source

Add support for 'params' arguments

tags/1.0-rc
Finite Reality RogueException 8 years ago
parent
commit
c8fc0ffa33
3 changed files with 56 additions and 7 deletions
  1. +18
    -3
      src/Discord.Net.Commands/Command.cs
  2. +5
    -1
      src/Discord.Net.Commands/CommandParameter.cs
  3. +33
    -3
      src/Discord.Net.Commands/CommandParser.cs

+ 18
- 3
src/Discord.Net.Commands/Command.cs 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();
}


+ 5
- 1
src/Discord.Net.Commands/CommandParameter.cs 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;
}



+ 33
- 3
src/Discord.Net.Commands/CommandParser.cs 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();
}
}


Loading…
Cancel
Save