Esempio n. 1
0
    public Chapter6()
    {
        ovld = new Overload();
        ovld.OvlDemo("adasd", 5); // перегрузка 2 методов
        ovld.OvlDemo(5, "asdasd");//
        Console.WriteLine("\n\n");

        OverloadConstr obj1 = new OverloadConstr("test"); //перегрузка конструктора
        OverloadConstr obj2 = new OverloadConstr(4, 3);
        OverloadConstr obj3 = new OverloadConstr(obj2);
    }
Esempio n. 2
0
		/// <summary>
		/// Emits overload call
		/// </summary>
		private void EmitCall(Overload/*!*/ overload, Label failLabel, LocalBuilder[] formals)
		{
			MethodBase overload_base = overload.Method;

			/* CHECK IS DONE IN THE EARLIER PHASE
			 * (in EmitConversion method)
			 
			if (!emitParentCtorCall && (overload_base.IsFamily || overload_base.IsFamilyOrAssembly))
			{
				// IF (!stack.AllowProtectedCall) THEN GOTO next-overload-or-error;
				stack.EmitLoad(il);
				il.Emit(OpCodes.Ldfld, Fields.PhpStack_AllowProtectedCall);
				il.Emit(OpCodes.Brfalse, failLabel);
			}*/

            //
            // LOAD <instance>
            //

            if ((emitParentCtorCall) // calling .ctor on parent
                ||(!overload_base.IsStatic && !overload_base.IsConstructor)// calling method on non-static object
                //||(overload_base.IsConstructor && overload_base.DeclaringType.IsValueType)// calling .ctor on structure (which initializes fields on existing value) (but the ClrValue does not exist yet :-))
                )
			{
                EmitLoadInstance(il, instance, overload_base.DeclaringType);
			}

            //
            // LOAD {<args>}
            //

			for (int i = 0; i < overload.Parameters.Length; i++)
			{
				if (overload.Parameters[i].ParameterType.IsByRef) il.Ldloca(formals[i]);
				else il.Ldloc(formals[i]);
			}

            //
            // CALL <method> or 
            //

            if (!overload_base.IsConstructor)
			{
                // method
                MethodInfo info = DType.MakeConstructed((MethodInfo)overload_base, constructedType);

				// CALL <method>(args);
				// TODO: il.Emit(info.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, info);
#if SILVERLIGHT
                il.Emit(info.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, info);
#else
				il.Emit(OpCodes.Call, info);
#endif

				// return value conversions:
				if (info.ReturnType != Types.Void)
				{
					il.EmitBoxing(EmitConvertToPhp(il, info.ReturnType/* scriptContext*/));
					il.Stloc(returnValue);
				}
			}
			else
			{
                // .ctor
				ConstructorInfo ctor = DType.MakeConstructed((ConstructorInfo)overload_base, constructedType);

                if (emitParentCtorCall)
				{
					// CALL <ctor>(args);
					il.Emit(OpCodes.Call, ctor);
				}
				else
				{
					// NEW <ctor>(args);
					il.Emit(OpCodes.Newobj, ctor);

                    il.EmitBoxing(EmitConvertToPhp(il, ctor.DeclaringType));    // convert any newly created object to valid PHP object
					/*if (ctor.DeclaringType.IsValueType)
					{
						// box value type:
						il.Emit(OpCodes.Box, ctor.DeclaringType);
					}

					if (!Types.DObject[0].IsAssignableFrom(ctor.DeclaringType))
					{
						// convert to ClrObject if not DObject:
						il.Emit(OpCodes.Call, Methods.ClrObject_Wrap);
					}*/

					il.Stloc(returnValue);
				}
			}

			// store ref/out parameters back to their PhpReferences shells
			int byref_counter = 0;
			for (int i = 0; i < overload.Parameters.Length; i++)
			{
				Type param_type = overload.Parameters[i].ParameterType;
				if (param_type.IsByRef)
				{
					il.Ldloc(refLocals[byref_counter++]);
					il.Ldloc(formals[i]);

                    PhpTypeCode php_type_code = EmitConvertToPhp(
						il,
						param_type.GetElementType()/*,
						scriptContext*/);

					il.EmitBoxing(php_type_code);

					il.Emit(OpCodes.Stfld, Fields.PhpReference_Value);
				}
			}

			il.Emit(OpCodes.Br, returnLabel);
		}
Esempio n. 3
0
		private static void GetOverloadValRefArgCount(Overload/*!*/ overload, out int byValCount, out int byRefCount)
		{
			int byref = 0;

			ParameterInfo[] parameters = overload.Parameters;
			for (int i = 0; i < parameters.Length; i++)
			{
				if (parameters[i].ParameterType.IsByRef) byref++;
			}

			byValCount = parameters.Length - byref;
			byRefCount = byref;
		}
Esempio n. 4
0
		private void EmitConversions(BitArray/*!*/ aliases, Overload/*!*/ overload, Label failLabel,
			LocalBuilder overloadStrictness, LocalBuilder[] formals, bool loadAllFormals)
		{
			MethodBase overload_base = overload.Method; 
			if (!emitParentCtorCall && (overload_base.IsFamily || overload_base.IsFamilyOrAssembly))
			{
				// IF (!stack.AllowProtectedCall) THEN GOTO next-overload-or-error;
				stack.EmitLoad(il);
				il.Emit(OpCodes.Ldfld, Fields.PhpStack_AllowProtectedCall);
				il.Emit(OpCodes.Brfalse, failLabel);
			}
			if (!emitParentCtorCall && !overload_base.IsStatic && !overload_base.IsConstructor)
			{
				// IF (<instance> == null) THEN GOTO next-overload-or-error;
				instance.EmitLoad(il);
				il.Emit(OpCodes.Brfalse, failLabel);
			}


			ParameterInfo[] parameters = overload.Parameters;
			int val_counter = 0, ref_counter = 0;

			bool overload_is_vararg = ((overload.Flags & ClrMethod.OverloadFlags.IsVararg) == ClrMethod.OverloadFlags.IsVararg);
			bool last_param_is_ambiguous_vararg = (overload_is_vararg && parameters.Length == aliases.Length);

			Type params_array_element_type = null;

			for (int arg_index = 0; arg_index < aliases.Length; arg_index++)
			{
				// ambiguous_vararg = true iff this is the trailing nth [ParamsArray] parameter and we've been
				// given exactly n arguments - we can accept either the array or one array element
				bool vararg = false, ambiguous_vararg = false;

				Type formal_param_type;
				if (arg_index < parameters.Length)
				{
					formal_param_type = parameters[arg_index].ParameterType;
					if (formal_param_type.IsByRef) formal_param_type = formal_param_type.GetElementType();

					// if current parameter is [params] array, set vararg to true
					if (arg_index + 1 == parameters.Length) 
					{
						ambiguous_vararg = last_param_is_ambiguous_vararg;
						vararg = overload_is_vararg;
					}
				}
				else formal_param_type = null;

				// LOAD <actual arg #arg_index>
				#region Load value or reference depending on parameter in/out settings
				PhpTypeCode php_type_code;

				if (aliases[arg_index])
				{
					if (arg_index >= parameters.Length || !parameters[arg_index].IsOut)
					{
						il.Ldloc(refLocals[ref_counter++]);
						php_type_code = PhpTypeCode.PhpReference;
					}
					else
					{
						// TODO: Completely ignoring actual arg type passed to out params - questionable
						formals[arg_index] = il.GetTemporaryLocal(formal_param_type);
						ref_counter++;
						continue;
					}
				}
				else
				{
					il.Ldloc(valLocals[val_counter++]);
					php_type_code = PhpTypeCode.Object;
				}

				#endregion

				// Switch to mode when parameters are stored in [params] array 
				// (unless we need to try conversion to array first - in case of ambigous vararg)
				if (formal_param_type != null && vararg && !ambiguous_vararg)
				{
					Debug.Assert(formal_param_type.IsArray);

					formals[arg_index] = il.GetTemporaryLocal(formal_param_type); // declare local of the vararg array type
					params_array_element_type = formal_param_type.GetElementType();
					EmitCreateParamsArray(params_array_element_type, formals[arg_index], aliases.Length - arg_index);
					formal_param_type = null;
				}

				// formal = CONVERT(stack, out success);
				bool ct_ok = EmitConvertToClr(il, php_type_code, formal_param_type ?? params_array_element_type, strictness);

				#region Store converted value in local variable or [params] array
				// Store returned value in local variable
				if (formal_param_type != null)
				{
					formals[arg_index] = il.GetTemporaryLocal(formal_param_type); // declare local of the formal param type
					il.Stloc(formals[arg_index]);
				}

				// Store returned value in [params] array
				if (formal_param_type == null)
				{
					Debug.Assert(overload_is_vararg);

					// _params[n] = formal
					LocalBuilder temp = il.GetTemporaryLocal(params_array_element_type, true);
					il.Stloc(temp);
					il.Ldloc(formals[parameters.Length - 1]);
					il.LdcI4(arg_index - parameters.Length + 1);
					il.Ldloc(temp);
					il.Stelem(params_array_element_type);
				}
				#endregion

				if (!ct_ok)
				{
					if (ambiguous_vararg)
					{
						// if the conversion to array has failed, we should try to convert it to the array element
						// this bypasses standard "strictness" handling because type can't be convertible to A and A[] at one time..
						Debug.Assert(parameters[arg_index].IsDefined(typeof(ParamArrayAttribute), false));
						EmitConversionToAmbiguousVararg(arg_index, formal_param_type, strictness, php_type_code,
							(php_type_code == PhpTypeCode.PhpReference ? refLocals[ref_counter - 1] : valLocals[val_counter - 1]), formals);
					}

					// if (strictness == Failed) goto error;
					// strictness_i += strictness
					il.Ldloc(strictness);
					il.LdcI4((int)ConversionStrictness.Failed);
					il.Emit(OpCodes.Beq, failLabel);
					
					il.Ldloc(overloadStrictness);
					il.Ldloc(strictness);
					il.Emit(OpCodes.Add);
					il.Stloc(overloadStrictness);
				}
			}

			if (loadAllFormals && parameters.Length > aliases.Length)
			{
				// one more params argument left -> add empty array
				int arg_index = aliases.Length;
				Type formal_param_type = parameters[arg_index].ParameterType;

				Debug.Assert(arg_index + 1 == parameters.Length);
				Debug.Assert(parameters[arg_index].IsDefined(typeof(ParamArrayAttribute), false));
				Debug.Assert(formal_param_type.IsArray);

				formals[arg_index] = il.GetTemporaryLocal(formal_param_type);
				EmitCreateParamsArray(formal_param_type.GetElementType(), formals[arg_index], 0);
			}
		}
Esempio n. 5
0
		/// <summary>
		/// Adds an overload by reflecting the specified real overload.
		/// Returns <see cref="DRoutine.InvalidOverloadIndex"/> and <B>null</B> in <paramref name="overload"/>
		/// if the reflection fails.
		/// </summary>
		internal int AddOverload(MethodBase/*!*/ realOverload, out Overload overload)
		{
			overload = Overload.Create(realOverload);
			if (overload == null) return DRoutine.InvalidOverloadIndex;

			int i = 0;
			int params_sum = overload.MandatoryParamCount + overload.ParamCount;
			while (i < overloads.Count && params_sum >= overloads[i].MandatoryParamCount + overloads[i].ParamCount)
			{
				// varargs (>= n params) are between (n params) and (n + 1 params)
				i++;
			}
			overloads.Insert(i, overload);

			// ClrMethod is static if at least one overload is static
			if (overload.Method.IsStatic) memberDesc.MemberAttributes |= PhpMemberAttributes.Static;

			// ClrMethod is public if at least one overload is public
			if (overload.Method.IsPublic)
			{
				memberDesc.MemberAttributes &= ~PhpMemberAttributes.VisibilityMask;
				memberDesc.MemberAttributes |= PhpMemberAttributes.Public;
			}

			// ClrMethod has a generic method desc if at least one overload is generic
			if (overload.GenericParamCount > 0 && !(memberDesc is ClrGenericMethodDesc))
			{
				memberDesc = new ClrGenericMethodDesc(memberDesc.DeclaringType, memberDesc.MemberAttributes);
			}

			return i;
		}
Esempio n. 6
0
		internal int AddOverload(MethodInfo/*!*/ realOverload, out Overload overload)
		{
			int index = AddOverload(overloads, realOverload, options);
			overload = (index >= 0) ? overloads[index] : null;
			return index;
		}
Esempio n. 7
0
        internal object HandleCommand(OpenPlayer player, string commandName, string commandOverload, dynamic commandInputJson)
        {
            Log.Debug($"HandleCommand {commandName}");
            var commands = player.Commands;

            try
            {
                Command command = null;
                if (commands.ContainsKey(commandName))
                {
                    command = commands[commandName];
                }
                else
                {
                    command = commands.Values.FirstOrDefault(cmd => cmd.Versions.Any(version => version.Aliases != null && version.Aliases.Any(s => s == commandName)));
                }

                if (command == null)
                {
                    Log.Warn($"Found no command handler for {commandName}");
                    return(null);
                }

                Overload overload = command.Versions.First().Overloads[commandOverload];

                int requiredPermission = command.Versions.First().CommandPermission;
                if (player.CommandPermission < requiredPermission)
                {
                    Log.Debug($"Insufficient permissions. Require {requiredPermission} but player had {player.CommandPermission}");
                    return(null);
                }

                MethodInfo method = overload.Method;

                List <string> strings = new List <string>();
                if (commandInputJson != null)
                {
                    foreach (ParameterInfo parameter in method.GetParameters())
                    {
                        if (typeof(OpenPlayer).IsAssignableFrom(parameter.ParameterType))
                        {
                            continue;
                        }

                        if (HasProperty(commandInputJson, parameter.Name))
                        {
                            Log.Debug($"Parameter: {commandInputJson[ToCamelCase(parameter.Name)].ToString()}");
                            strings.Add(commandInputJson[ToCamelCase(parameter.Name)].ToString());
                        }
                    }
                }

                ExecuteCommand(method, player, strings.ToArray(), out object retVal);
                return(retVal);
            }
            catch (Exception e)
            {
                Log.Error("Handle JSON command", e);
            }

            return(null);
        }
Esempio n. 8
0
 public rptReqPerDateSave(Overload v2)
 {
     InitializeComponent();
     this.ol = v2;
 }
        public async Task WithRegularScopeCreatedInsideWithForceCreateNew_ShouldBeUnrelated(Overload overload)
        {
            DbContext outerDbContext = null;
            DbContext innerDbContext = null;

            await this.Execute(overload, this.Provider, (scope, ct) =>
            {
                outerDbContext = scope.DbContext;

                var innerScope = this.Provider.CreateDbContextScope(AmbientScopeOption.ForceCreateNew);

                innerDbContext = innerScope.DbContext;

                return(Task.FromResult(true));
            });

            Assert.NotNull(outerDbContext);
            Assert.NotNull(innerDbContext);
            Assert.NotEqual(outerDbContext, innerDbContext);
        }
Esempio n. 10
0
        private CommandSet GenerateCommandSet(MethodInfo[] methods)
        {
            CommandSet commands = new CommandSet();

            foreach (MethodInfo method in methods)
            {
                CommandAttribute commandAttribute = Attribute.GetCustomAttribute(method, typeof(CommandAttribute), false) as CommandAttribute;
                if (commandAttribute == null)
                {
                    continue;
                }

                // TODO: Do we need the authorize attribute with the new permission system?
                AuthorizeAttribute authorizeAttribute = Attribute.GetCustomAttribute(method, typeof(AuthorizeAttribute), false) as AuthorizeAttribute ?? new AuthorizeAttribute();

                if (string.IsNullOrEmpty(commandAttribute.Name))
                {
                    commandAttribute.Name = method.Name;
                }

                var overload = new Overload
                {
                    Description = commandAttribute.Description ?? "Bullshit",
                    Method      = method,
                    Input       = new Input(),
                };

                string    commandName      = commandAttribute.Name.ToLowerInvariant();
                var       split            = commandName.Split(' ');
                Parameter subCommmandParam = null;
                if (split.Length > 1)
                {
                    subCommmandParam            = new Parameter();
                    subCommmandParam.Name       = "subcommand";
                    subCommmandParam.Type       = "stringenum";
                    subCommmandParam.EnumType   = "SubCommand" + commandName.Replace(" ", "-");
                    subCommmandParam.EnumValues = new[] { split[1] };
                    commandName = split[0];
                }
                if (commands.ContainsKey(commandName))
                {
                    Command command = commands[commandName];
                    command.Versions.First().Overloads.Add(commandAttribute.Overload ?? Guid.NewGuid().ToString(), overload);
                }
                else
                {
                    commands.Add(commandName, new Command
                    {
                        Name     = commandName,
                        Versions = new[]
                        {
                            new MiNET.Plugins.Version()
                            {
                                Permission        = authorizeAttribute.Permission.ToString().ToLowerInvariant(),
                                CommandPermission = authorizeAttribute.Permission,
                                ErrorMessage      = authorizeAttribute.ErrorMessage,
                                Aliases           = commandAttribute.Aliases ?? new string[0],
                                Description       = commandAttribute.Description ?? "",
                                Overloads         = new Dictionary <string, Overload>
                                {
                                    {
                                        "default", overload
                                    },
                                }
                            },
                        }
                    });
                }


                List <Parameter> inputParams = new List <Parameter>();
                if (subCommmandParam != null)
                {
                    inputParams.Add(subCommmandParam);
                }

                var  parameters   = method.GetParameters();
                bool isFirstParam = true;
                foreach (var parameter in parameters)
                {
                    if (isFirstParam && typeof(OpenPlayer).IsAssignableFrom(parameter.ParameterType))
                    {
                        continue;
                    }
                    isFirstParam = false;

                    Parameter param = new Parameter();
                    param.Name     = ToCamelCase(parameter.Name);
                    param.Type     = GetParameterType(parameter);
                    param.Optional = parameter.IsOptional;
                    if (param.Type.Equals("bool"))
                    {
                        param.Type       = "stringenum";
                        param.EnumType   = "bool";
                        param.EnumValues = new string[] { "false", "true" };
                    }
                    else if (param.Type.Equals("stringenum"))
                    {
                        if (parameter.ParameterType.IsEnum)
                        {
                            param.EnumValues = parameter.ParameterType.GetEnumNames().Select(s => s.ToLowerInvariant()).ToArray();

                            string typeName = parameter.ParameterType.Name;
                            typeName       = typeName.Replace("Enum", "");
                            typeName       = typeName.ToLowerInvariant()[0] + typeName.Substring(1);
                            param.EnumType = typeName;
                        }
                        else
                        {
                            param.EnumValues = null;

                            string typeName = parameter.ParameterType.Name;
                            typeName       = typeName.Replace("Enum", "");
                            typeName       = typeName.ToLowerInvariant()[0] + typeName.Substring(1);
                            param.EnumType = typeName;

                            if (parameter.ParameterType == typeof(ItemTypeEnum))
                            {
                                param.EnumValues = new string[] { };
                                param.EnumType   = "Item";
                            }
                            if (parameter.ParameterType == typeof(BlockTypeEnum))
                            {
                                param.EnumValues = new string[] { };
                                param.EnumType   = "Block";
                            }
                            if (parameter.ParameterType == typeof(EntityTypeEnum))
                            {
                                param.EnumValues = new string[] { };
                                param.EnumType   = "EntityType";
                            }
                            if (parameter.ParameterType == typeof(CommandNameEnum))
                            {
                                param.EnumValues = new string[] { };
                                param.EnumType   = "CommandName";
                            }
                            if (parameter.ParameterType == typeof(EnchantEnum))
                            {
                                param.EnumValues = new string[] { "enchant_test" };
                                param.EnumType   = "Enchant";
                            }
                            if (parameter.ParameterType == typeof(EffectEnum))
                            {
                                param.EnumValues = new string[] { "effect_test" };
                                param.EnumType   = "Effect";
                            }
                        }
                    }
                    inputParams.Add(param);
                }

                if (inputParams.Count == 0)
                {
                    overload.Input.Parameters = null;
                }
                else
                {
                    overload.Input.Parameters = inputParams.ToArray();
                }
            }

            return(commands);
        }
        public async Task WithinRegularScope_ShouldThrow(Overload overload)
        {
            using var scope = this.Provider.CreateDbContextScope();

            await Assert.ThrowsAsync <InvalidOperationException>(() => this.Execute(overload, this.Provider, (scope, ct) => Task.FromResult(true)));
        }
Esempio n. 12
0
        public Embed GetHelpEmbed(SocketMessage e, bool advanced)
        {
            EmbedBuilder builder = new EmbedBuilder();

            if (!commandEnabled)
            {
                builder.WithTitle("Not enabled on this server.");
                return(builder.Build());
            }

            builder.WithAuthor(Utility.GetUserName(Utility.GetServer().GetUser(Program.discordClient.CurrentUser.Id)) + " Command Help")     // lolwhat.
            .WithTitle($"Command \"{helpPrefix}{command}\"")
            .WithDescription(shortHelp);

            // This is quite similar to GetArgs and GetHelp together, and the other functions are obsolete due to this.
            MethodInfo [] methods = GetType().GetMethods().Where(x => x.Name == "Execute").ToArray();
            for (int i = 0; i < methods.Length; i++)
            {
                if (overloads.Count <= i)
                {
                    builder.AddField("Undefined overload", "Blame that lazy bastard of a dev.");
                }
                else
                {
                    MethodInfo info = methods [i];
                    Overload   ol   = overloads [i];

                    var    parameters = GetDescriptiveOverloadParameters(i);
                    string olText     = advanced ? $"{parameters.returnType} => " : helpPrefix + command;

                    olText += " (";
                    for (int j = 1; j < parameters.types.Length; j++)   // Remember to ignore first parameter, it being the SocketUserMessage.
                    {
                        Type   type = parameters.types[j];
                        string name = parameters.names [j];

                        olText += advanced ? type.Name + " " + name : name;

                        if (j != parameters.types.Length - 1)
                        {
                            olText += "; ";
                        }
                    }
                    olText += ")";

                    builder.AddField(olText, ol.description);
                }
            }

            string footer = string.Empty;

            if (isAdminOnly)
            {
                footer += " - ADMIN ONLY";
            }
            if (allowInMain)
            {
                footer += " - ALLOWED IN MAIN";
            }
            if (availableInDM && !availableOnServer)
            {
                footer += " - ONLY IN DM";
            }
            if (availableInDM && availableOnServer)
            {
                footer += " - AVAILABLE IN DM";
            }
            if (requiredPermission != Permissions.Type.Null)
            {
                footer += " - REQUIRIES PERMISSION: " + requiredPermission.ToString().ToUpper();
            }

            builder.WithColor(CSetColor.GetUserColor(Program.discordClient.CurrentUser.Id).Color);
            builder.WithFooter(footer);
            return(builder.Build());
        }
Esempio n. 13
0
        private void CheckAccessLevel()
        {
            bool accessable = true;

            if (Overload is IMethod asMethod)
            {
                if (!getter.AccessorMatches(asMethod))
                {
                    accessable = false;
                }
            }
            else if (!getter.AccessorMatches(scope, Overload.AccessLevel))
            {
                accessable = false;
            }

            if (!accessable)
            {
                parseInfo.Script.Diagnostics.Error(string.Format("'{0}' is inaccessable due to its access level.", Overload.GetLabel(false)), genericErrorRange);
            }
        }
        private void GetBestOption()
        {
            // If there are any methods with no errors, set that as the best option.
            var optionWithNoErrors = optionDiagnostics.FirstOrDefault(o => o.Value.Count == 0).Key;

            if (optionWithNoErrors != null)
            {
                Overload = optionWithNoErrors;
            }

            // Add the diagnostics of the best option.
            parseInfo.Script.Diagnostics.AddDiagnostics(optionDiagnostics[Overload].ToArray());

            // Check the access level.
            bool accessable = true;

            if (Overload is IMethod asMethod)
            {
                if (!getter.AccessorMatches(asMethod))
                {
                    accessable = false;
                }
            }
            else if (!getter.AccessorMatches(scope, Overload.AccessLevel))
            {
                accessable = false;
            }

            if (!accessable)
            {
                parseInfo.Script.Diagnostics.Error(string.Format("'{0}' is inaccessable due to its access level.", Overload.GetLabel(false)), genericErrorRange);
            }
        }
Esempio n. 15
0
        public void ParseObjectModelTest()
        {
            string commandJson = File.ReadAllText("test_commands_1.json");

            JsonConvert.DefaultSettings = () =>
            {
                var settings = new JsonSerializerSettings();
                return(settings);
            };
            var commands = JsonConvert.DeserializeObject <CommandSet>(commandJson /*, new ParameterConverter()*/);

            Assert.AreEqual(72, commands.Count);

            Assert.AreEqual("difficulty", commands.First(pair => pair.Key == "difficulty").Key);

            Command command = commands["difficulty"];

            Assert.NotNull(command);

            Version version = command.Versions[0];

            Assert.AreEqual("commands.difficulty.usage", version.Description);

            Assert.AreEqual(2, version.Overloads.Count);

            Overload overload = version.Overloads["byName"];

            Assert.NotNull(overload);

            // Input
            Input input = overload.Input;

            Assert.NotNull(input);
            Assert.NotNull(input.Parameters);
            Assert.AreEqual(1, input.Parameters.Length);

            // Input parameters
            Parameter inputParameter = input.Parameters[0];

            Assert.NotNull(inputParameter);
            Assert.AreEqual("difficulty", inputParameter.Name);
            Assert.AreEqual("stringenum", inputParameter.Type);
            //Assert.AreEqual("commandName", inputParameter.EnumType);
            Assert.IsFalse(inputParameter.Optional);

            // Output
            Output output = overload.Output;

            Assert.NotNull(output.FormatStrings);
            Assert.AreEqual(1, output.FormatStrings.Length);
            Assert.AreEqual("commands.difficulty.success", output.FormatStrings[0].Format);
            Assert.NotNull(output.Parameters);
            Assert.AreEqual(1, output.Parameters.Length);

            Parameter outputParameter = output.Parameters[0];

            Assert.AreEqual("difficulty", outputParameter.Name);
            Assert.AreEqual("string", outputParameter.Type);
            Assert.IsNullOrEmpty(outputParameter.EnumType);
            Assert.IsFalse(outputParameter.Optional);
        }