Example #1
0
 /// <summary>
 /// Generates a new parser that uses the given registry, args, metadata, context, and ID to run
 /// </summary>
 /// <param name="registry">Registry from which the parser will obtain <see cref="IObjectConverter"/>s</param>
 /// <param name="input">The original input string</param>
 /// <param name="additionalArgs">Any additional arguments to be added to the end of the argument list</param>
 /// <param name="metadata">CommandMetadata containing information used to parse and execute</param>
 /// <param name="exeData"><see cref="CommandExecutorData"/> containing the data required for execution</param>
 /// <param name="ctx">Context object passed to the executed command, and an <see cref="IObjectConverter"/>s that are used</param>
 /// <param name="callback">Reference to a method used as a callback when processing completes</param>
 public Parser(CommandRegistry registry,
               string input,
               IEnumerable <object> additionalArgs,
               CommandMetadata metadata,
               CommandExecutorData exeData,
               IContextObject ctx,
               InputResultDelegate callback)
     : base(registry, input, additionalArgs, metadata, exeData, ctx, callback)
 {
 }
        /// <summary>
        /// Ensures the given parameters follow the parameter rules
        /// </summary>
        /// <exception cref="CommandParsingException">Thrown if a parameter does not follow command parameter rules</exception>
        public void CheckParameterStructure(CommandExecutorData executor, IEnumerable<ParameterInfo> parameters)
        {
            bool optionalFound = false;
            bool unknownLengthFound = false;
            requiredArgumentCount = 0;
            Dictionary<ParameterInfo, CommandParameterAttribute> paramData = new Dictionary<ParameterInfo, CommandParameterAttribute>();

            foreach (ParameterInfo param in parameters)
            {
                CommandParameterAttribute attr = param.GetCustomAttribute<CommandParameterAttribute>();

                if (attr == null)
                {
                    attr = new CommandParameterAttribute(param.IsOptional);
                }

                paramData.Add(param, attr);

                if (optionalFound && !attr.Optional)
                {
                    throw new CommandParsingException(
                        ParserFailReason.InvalidParameter,
                        $"Parameter '{param.Name}' is required, but follows an optional parameter."
                    );
                }

                if (unknownLengthFound)
                {
                    throw new CommandParsingException(
                        ParserFailReason.InvalidParameter,
                        $"Parameter '{param.Name}' follows an unknown-length parameter."
                    );
                }

                if (attr.Optional)
                {
                    optionalFound = true;
                }
                if (attr.Repetitions < 1)
                {
                    unknownLengthFound = true;
                    requiredArgumentCount = -1;
                }
                if (!attr.Optional)
                {
                    requiredArgumentCount += attr.Repetitions;
                }
            }

            executor.ParameterData = paramData;
        }
Example #3
0
 /// <summary>
 /// Generates a new parser that uses the given registry, args, metadata, context, and ID to run
 /// </summary>
 /// <param name="registry">Registry from which the parser will obtain <see cref="IObjectConverter"/>s</param>
 /// <param name="input">The original input string</param>
 /// <param name="additionalArgs">Enumerable of objects to be parsed</param>
 /// <param name="metadata">CommandMetadata containing information used to parse and execute</param>
 /// <param name="exeData"><see cref="CommandExecutorData"/> containing the data required for execution</param>
 /// <param name="ctx">Context object passed to the executed command, and an <see cref="IObjectConverter"/>s that are used</param>
 /// <param name="callback">Reference to a method to be invoked when parsing completes</param>
 public AbstractParser(CommandRegistry registry,
                       string input,
                       IEnumerable <object> additionalArgs,
                       CommandMetadata metadata,
                       CommandExecutorData exeData,
                       IContextObject ctx,
                       InputResultDelegate callback)
 {
     Registry       = registry;
     Input          = input;
     AdditionalArgs = additionalArgs;
     Metadata       = metadata;
     ExecutorData   = exeData;
     Context        = ctx;
     Callback       = callback;
 }
        /// <summary>
        /// Ensures the executing method follows the command executor method rules
        /// </summary>
        /// <exception cref="CommandParsingException">Thrown if the executor does not follow command executor method rules</exception>
        public ParameterInfo[] VerifyMethodStructure(CommandExecutorData data)
        {
            MethodInfo mInfo = data.ExecutingMethod;
            if (!data.AsyncExecution)
            {
                if (mInfo.ReturnType != typeof(object))
                {
                    throw new CommandParsingException(
                        ParserFailReason.MalformedExecutor,
                        $"Executor method '{mInfo.Name}' of command '{_type.Name}' does not return '{nameof(Object)}'."
                    );
                }
            }
            else
            {
                if (mInfo.ReturnType != typeof(Task<object>))
                {
                    throw new CommandParsingException(
                           ParserFailReason.MalformedExecutor,
                           $"Executor method '{mInfo.Name}' of command '{_type.Name}' does not return '{nameof(Task<object>)}'."
                       );
                }
            }

            ParameterInfo[] parameters = mInfo.GetParameters();
            Exception inner = null;

            if (parameters.Length < 1)
            {
                inner = new Exception("Method defines no parameters, but requires at least one.");
            }
            else if (!typeof(IContextObject).GetTypeInfo().IsAssignableFrom(parameters[0].ParameterType))
            {
                inner = new InvalidCastException($"Parameter '{parameters[0].Name}' of type '{parameters[0].ParameterType.Name}' must be castable to type '{nameof(IContextObject)}'.");
            }

            if (inner != null)
            {
                throw new CommandParsingException(
                    ParserFailReason.MalformedExecutor,
                    $"Executor method '{mInfo.Name}' of command '{_type.Name}' does not meet the required parameter rulings.",
                    inner
                );
            }

            return parameters;
        }
Example #5
0
        /// <summary>
        /// Attempts to switch to a subcommand instead of the main executor
        /// </summary>
        protected override void AttemptSwitchToSubcommand()
        {
            if (!ExecutorData.HasSubcommands || Input.Length == 0)
            {
                return;
            }

            CommandExecutorData subcommand = ExecutorData.Subcommands.FirstOrDefault(
                sub => sub.ExecutorAttribute.CommandMatcher.Matches(Input)
                );

            if (subcommand != null)
            {
                ExecutorData = subcommand;
                //Remove the subcommand name
                Input = subcommand.ExecutorAttribute.CommandMatcher.RemoveMatchedString(Input);
            }
        }