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 parameter = parameters[i];
var type = parameter.ParameterType; var type = parameter.ParameterType;
Type underlyingType = null;


if (i == 0) if (i == 0)
{ {
@@ -80,10 +81,24 @@ namespace Discord.Commands
continue; continue;
} }


var typeInfo = type.GetTypeInfo();
var reader = Module.Service.GetTypeReader(type); 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); reader = EnumTypeReader.GetReader(type);
Module.Service.AddTypeReader(type, reader); Module.Service.AddTypeReader(type, reader);
@@ -101,7 +116,7 @@ namespace Discord.Commands
bool isOptional = parameter.IsOptional; bool isOptional = parameter.IsOptional;
object defaultValue = parameter.HasDefaultValue ? parameter.DefaultValue : null; 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(); 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 string Description { get; }
public bool IsOptional { get; } public bool IsOptional { get; }
public bool IsRemainder { get; } public bool IsRemainder { get; }
public bool IsParams { get; }
public Type Type { get; } public Type Type { get; }
public Type UnderlyingType { get; }
internal object DefaultValue { 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; Name = name;
Description = description; Description = description;
Type = type; Type = type;
UnderlyingType = underlyingType;
_reader = reader; _reader = reader;
IsOptional = isOptional; IsOptional = isOptional;
IsRemainder = isRemainder; IsRemainder = isRemainder;
IsParams = isParams;
DefaultValue = defaultValue; DefaultValue = defaultValue;
} }




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

@@ -1,6 +1,9 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System;


namespace Discord.Commands namespace Discord.Commands
{ {
@@ -20,6 +23,7 @@ namespace Discord.Commands
int endPos = input.Length; int endPos = input.Length;
var curPart = ParserPart.None; var curPart = ParserPart.None;
int lastArgEndPos = int.MinValue; int lastArgEndPos = int.MinValue;
IList<object> paramsList = null; // TODO: could we use a better type?
var argList = ImmutableArray.CreateBuilder<object>(); var argList = ImmutableArray.CreateBuilder<object>();
bool isEscaping = false; bool isEscaping = false;
char c; char c;
@@ -70,6 +74,10 @@ namespace Discord.Commands
argBuilder.Append(c); argBuilder.Append(c);
continue; continue;
} }
if (curParam != null && curParam.IsParams)
{
paramsList = new List<object>();
}
if (c == '\"') if (c == '\"')
{ {
curPart = ParserPart.QuotedParameter; curPart = ParserPart.QuotedParameter;
@@ -110,10 +118,32 @@ namespace Discord.Commands
var typeReaderResult = await curParam.Parse(context, argString).ConfigureAwait(false); var typeReaderResult = await curParam.Parse(context, argString).ConfigureAwait(false);
if (!typeReaderResult.IsSuccess) if (!typeReaderResult.IsSuccess)
return ParseResult.FromError(typeReaderResult); 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(); argBuilder.Clear();
} }
} }


Loading…
Cancel
Save