Пример #1
0
 public void Add(CommandSpecification comSpec)
 {
     if (_syntaxes.TryGetValue(comSpec.Name, out var lst))
     {
         lst.Add(new CommandSyntax(comSpec));
     }
     else
     {
         _syntaxes.Add(comSpec.Name, new List <CommandSyntax> {
             new CommandSyntax(comSpec)
         });
     }
 }
Пример #2
0
 public ParseError(
     string description,
     int position,
     int index,
     CommandSpecification commandSpecification,
     IList <CommandParameterSpecification> commandParameterSpecifications
     )
 {
     Description                    = description;
     Position                       = position;
     Index                          = index;
     CommandSpecification           = commandSpecification;
     CommandParameterSpecifications = new ReadOnlyCollection <CommandParameterSpecification>(commandParameterSpecifications);
 }
Пример #3
0
 public void Remove(CommandSpecification comSpec)
 {
     if (_syntaxes.TryGetValue(comSpec.Name, out var lst))
     {
         var sytx = lst.Where(x => x.CommandSpecification == comSpec).FirstOrDefault();
         if (sytx != null)
         {
             lst.Remove(sytx);
             if (lst.Count == 0)
             {
                 _syntaxes.Remove(comSpec.Name);
             }
         }
     }
 }
Пример #4
0
 public bool UnregisterCommand(CommandSpecification comSpec)
 {
     if (_commands.TryGetValue(comSpec.Name, out var cmdLst))
     {
         var r = cmdLst.Remove(comSpec);
         if (r)
         {
             _syntaxAnalyzer.Remove(comSpec);
         }
         if (cmdLst.Count == 0)
         {
             _commands.Remove(comSpec.Name);
         }
         return(r);
     }
     return(false);
 }
Пример #5
0
        void PrintCommandHelp(
            CommandEvaluationContext context,
            CommandSpecification com,
            bool shortView       = false,
            bool list            = false,
            int maxcnamelength   = -1,
            int maxcmdtypelength = -1,
            int maxmodlength     = -1,
            bool singleout       = false)
        {
#pragma warning disable IDE0071                  // Simplifier l’interpolation
#pragma warning disable IDE0071WithoutSuggestion // Simplifier l’interpolation
            if (maxcnamelength == -1)
            {
                maxcnamelength = com.Name.Length + 1;
            }
            if (maxcmdtypelength == -1)
            {
                maxcmdtypelength = com.DeclaringTypeShortName.Length + 1;
            }
            var col = singleout? "": "".PadRight(maxcnamelength, ' ');
            var f   = GetCmd(EchoDirectives.f + "", DefaultForeground.ToString().ToLower());
            if (list)
            {
                if (!shortView)
                {
                    context.Out.Echoln($"{Darkcyan}{com.ModuleName.PadRight(maxmodlength, ' ')}   {com.DeclaringTypeShortName.PadRight(maxcmdtypelength, ' ')}{Tab}{ColorSettings.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{Tab}{f}{com.Description}{ColorSettings.Default}");
                }
                else
                {
                    context.Out.Echoln($"{ColorSettings.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{f}{Tab}{com.Description}{ColorSettings.Default}");
                }
            }
            else
            {
                if (singleout)
                {
                    context.Out.Echoln(com.Description);
                    if (com.ParametersCount > 0)
                    {
                        context.Out.Echo($"{Br}{col}{ColorSettings.Label}syntax: {f}{com.ToColorizedString()}{(!shortView ? Br : "")}");
                    }
                    context.Out.Echoln(GetPrintableDocText(com.LongDescription, list, shortView, 0));
                }
                else
                {
                    context.Out.Echoln($"{com.Name.PadRight(maxcnamelength, ' ')}{com.Description}");
                    if (com.ParametersCount > 0)
                    {
                        context.Out.Echo($"{Br}{col}{ColorSettings.Label}syntax: {f}{com.ToColorizedString()}{(!shortView ? Br : "")}");
                    }
                    context.Out.Echo(GetPrintableDocText(com.LongDescription, list, shortView, maxcnamelength));
                }
            }

            if (!list)
            {
                if (com.ParametersCount > 0)
                {
                    if (!shortView)
                    {
                        var mpl = com.ParametersSpecifications.Values.Select(x => x.Dump(false).Length).Max() + TabLength;
                        foreach (var p in com.ParametersSpecifications.Values)
                        {
                            var ptype  = (!p.IsOption && p.HasValue) ? $"of type: {Darkyellow}{p.ParameterInfo.ParameterType.Name}{f}" : "";
                            var pdef   = (p.HasValue && p.IsOptional && p.HasDefaultValue && p.DefaultValue != null && (!p.IsOption || p.ParameterValueTypeName != typeof(bool).Name)) ? ((ptype != ""?". ":"") + $"default value: {Darkyellow}{DumpAsText(p.DefaultValue)}{f}") : "";
                            var supdef = $"{ptype}{pdef}";
                            context.Out.Echoln($"{col}{Tab}{p.ToColorizedString(false)}{"".PadRight(mpl - p.Dump(false).Length, ' ')}{p.Description}");
                            if (!string.IsNullOrWhiteSpace(supdef))
                            {
                                context.Out.Echoln($"{col}{Tab}{" ".PadRight(mpl)}{supdef}");
                            }
                        }

                        if (string.IsNullOrWhiteSpace(com.Documentation))
                        {
                            context.Out.Echoln();
                        }
                        context.Out.Echo(GetPrintableDocText(com.Documentation, list, shortView, singleout ? 0 : maxcnamelength));
                    }
                    else
                    {
                        context.Out.Echoln(GetPrintableDocText(com.Documentation, list, shortView, singleout ? 0 : maxcnamelength));
                    }
                }
                if (!shortView)
                {
                    context.Out.Echoln($"{col}{ColorSettings.Label}type  : {ColorSettings.DarkLabel}{com.DeclaringTypeShortName}");
                    context.Out.Echoln($"{col}{ColorSettings.Label}module: {ColorSettings.DarkLabel}{com.ModuleName}{ColorSettings.Default}");
                }
            }
#pragma warning restore IDE0071WithoutSuggestion // Simplifier l’interpolation
#pragma warning restore IDE0071                  // Simplifier l’interpolation
        }
Пример #6
0
        public int RegisterCommandClass(
            CommandEvaluationContext context,
            Type type,
            bool registerAsModule
            )
        {
            if (type.GetInterface(typeof(ICommandsDeclaringType).FullName) == null)
            {
                throw new Exception($"the type '{type.FullName}' must implements interface '{typeof(ICommandsDeclaringType).FullName}' to be registered as a command class");
            }

            var dtNamespaceAttr = type.GetCustomAttribute <CommandsNamespaceAttribute>();
            var dtNamespace     = (dtNamespaceAttr == null) ? "" : CheckAndNormalizeCommandNamespace(dtNamespaceAttr.Segments);

            var    comsCount = 0;
            object instance  = Activator.CreateInstance(type, new object[] { });
            var    methods   = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            if (registerAsModule && _modules.ContainsKey(type.FullName))
            {
                context.Errorln($"a module with same name than the commands declaring type '{type.FullName}' is already registered");
                return(0);
            }

            foreach (var method in methods)
            {
                var cmd = method.GetCustomAttribute <CommandAttribute>();
                if (cmd != null)
                {
                    if (!method.ReturnType.HasInterface(typeof(ICommandResult)))
                    {
                        context.Errorln($"class={type.FullName} method={method.Name} wrong return type. should be of type '{typeof(ICommandResult).FullName}', but is of type: {method.ReturnType.FullName}");
                    }
                    else
                    {
                        // ⏺ build the command specification from the method meta-data

                        var cmdNamespaceAttr  = method.GetCustomAttribute <CommandNamespaceAttribute>();
                        var cmdNamespace      = cmdNamespaceAttr == null ? dtNamespace : CheckAndNormalizeCommandNamespace(cmdNamespaceAttr.Segments);
                        var cmdAliasesAttrLst = method.GetCustomAttributes <CommandAliasAttribute>();
                        var cmdAliases        = cmdAliasesAttrLst?.Select(x => (x.AliasName, x.AliasText)).ToList();
                        if (cmdAliases.Count == 0)
                        {
                            cmdAliases = null;                        // convention
                        }
                        #region init from method parameters attributes

                        var  paramspecs  = new List <CommandParameterSpecification>();
                        bool syntaxError = false;
                        var  pindex      = 0;
                        foreach (var parameter in method.GetParameters())
                        {
                            if (pindex == 0)
                            {
                                // manadatory: param 0 is CommandEvaluationContext
                                if (parameter.ParameterType != typeof(CommandEvaluationContext))
                                {
                                    context.Errorln($"class={type.FullName} method={method.Name} parameter 0 ('{parameter.Name}') should be of type '{typeof(CommandEvaluationContext).FullName}', but is of type: {parameter.ParameterType.FullName}");
                                    syntaxError = true;
                                    break;
                                }
                            }
                            else
                            {
                                CommandParameterSpecification pspec = null;
                                object defval = null;
                                if (!parameter.HasDefaultValue && parameter.ParameterType.IsValueType)
                                {
                                    defval = Activator.CreateInstance(parameter.ParameterType);
                                }

                                // param
                                var paramAttr = parameter.GetCustomAttribute <ParameterAttribute>();
                                if (paramAttr != null)
                                {
                                    // TODO: validate command specification (eg. indexs validity)
                                    pspec = new CommandParameterSpecification(
                                        parameter.Name,
                                        paramAttr.Description,
                                        paramAttr.IsOptional,
                                        paramAttr.Index,
                                        null,
                                        null,
                                        true,
                                        parameter.HasDefaultValue,
                                        paramAttr.HasDefaultValue ?
                                        paramAttr.DefaultValue
                                            : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval),
                                        parameter);
                                }

                                // option
                                var optAttr = parameter.GetCustomAttribute <OptionAttribute>();
                                if (optAttr != null)
                                {
                                    var reqParamAttr = parameter.GetCustomAttribute <OptionRequireParameterAttribute>();
                                    try
                                    {
                                        pspec = new CommandParameterSpecification(
                                            parameter.Name,
                                            optAttr.Description,
                                            optAttr.IsOptional,
                                            -1,
                                            optAttr.OptionName /*?? parameter.Name*/,
                                            optAttr.OptionLongName,
                                            optAttr.HasValue,
                                            parameter.HasDefaultValue,
                                            optAttr.HasDefaultValue ?
                                            optAttr.DefaultValue
                                                : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval),
                                            parameter,
                                            reqParamAttr?.RequiredParameterName);
                                    }
                                    catch (Exception ex)
                                    {
                                        context.Errorln(ex.Message);
                                    }
                                }

                                if (pspec == null)
                                {
                                    syntaxError = true;
                                    context.Errorln($"invalid parameter: class={type.FullName} method={method.Name} name={parameter.Name}");
                                }
                                else
                                {
                                    paramspecs.Add(pspec);
                                }
                            }
                            pindex++;
                        }

                        #endregion

                        if (!syntaxError)
                        {
                            var cmdNameAttr = method.GetCustomAttribute <CommandNameAttribute>();

                            var cmdName = CheckAndNormalizeCommandName(
                                (cmdNameAttr != null && cmdNameAttr.Name != null) ?
                                cmdNameAttr.Name
                                        : (cmd.Name ?? method.Name));

                            bool registered = true;
                            CommandSpecification cmdspec = null;

                            try
                            {
                                cmdspec = new CommandSpecification(
                                    cmdNamespace,
                                    cmdName,
                                    cmd.Description,
                                    cmd.LongDescription,
                                    cmd.Documentation,
                                    method,
                                    instance,
                                    cmdAliases,
                                    paramspecs);
                            } catch (Exception ex)
                            {
                                context.Errorln($"error in command '{cmdName}' specification: {ex.Message}");
                            }

                            if (cmdspec != null)
                            {
                                if (_commands.TryGetValue(cmdspec.Name, out var cmdlst))
                                {
                                    if (cmdlst.Select(x => x.MethodInfo.DeclaringType == type).Any())
                                    {
                                        context.Errorln($"command already registered: '{cmdspec.Name}' in type '{cmdspec.DeclaringTypeFullName}'");
                                        registered = false;
                                    }
                                    else
                                    {
                                        cmdlst.Add(cmdspec);
                                    }
                                }
                                else
                                {
                                    _commands.Add(cmdspec.Name, new List <CommandSpecification> {
                                        cmdspec
                                    });
                                }


                                if (registered)
                                {
                                    _syntaxAnalyzer.Add(cmdspec);
                                    comsCount++;
                                    // register command Aliases
                                    if (cmdspec.Aliases != null)
                                    {
                                        foreach (var alias in cmdspec.Aliases)
                                        {
                                            context.CommandLineProcessor.CommandsAlias.AddOrReplaceAlias(
                                                context,
                                                alias.name,
                                                alias.text
                                                );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (registerAsModule)
            {
                if (comsCount == 0)
                {
                    context.Errorln($"no commands found in type '{type.FullName}'");
                }
                else
                {
                    var descAttr    = type.GetCustomAttribute <CommandsAttribute>();
                    var description = descAttr != null ? descAttr.Description : "";
                    _modules.Add(
                        type.FullName,      // key not from assembly but from type
                        new ModuleSpecification(
                            type.FullName,
                            ModuleUtil.DeclaringTypeShortName(type),
                            description,
                            type.Assembly,
                            new ModuleInfo(
                                1,
                                comsCount
                                ),
                            type
                            ));
                }
            }
            return(comsCount);
        }
        void _PrintCommandHelp(
            CommandEvaluationContext context,
            CommandSpecification com,
            bool shortView       = false,
            bool verboseView     = false,
            bool list            = false,
            int maxnslength      = -1,
            int maxcnamelength   = -1,
            int maxcmdtypelength = -1,
            int maxmodlength     = -1,
            bool singleout       = false
            )
        {
#pragma warning disable IDE0071                  // Simplifier l’interpolation
#pragma warning disable IDE0071WithoutSuggestion // Simplifier l’interpolation
            if (maxcnamelength == -1)
            {
                maxcnamelength = com.Name.Length + 1;
            }
            if (maxnslength == -1)
            {
                maxnslength = com.Namespace.Length + 1;
            }
            if (maxcmdtypelength == -1)
            {
                maxcmdtypelength = com.DeclaringTypeShortName.Length + 1;
            }
            var col = singleout ? "" : "".PadRight(maxcnamelength, ' ');
            var f   = GetCmd(EchoDirectives.f + "", context.CommandLineProcessor.Console.DefaultForeground.ToString().ToLower());
            if (list)
            {
                if (!shortView)
                {
                    context.Out.Echoln($"{Darkcyan}{com.ModuleName.PadRight(maxmodlength, ' ')}   {com.DeclaringTypeShortName.PadRight(maxcmdtypelength, ' ')}   {com.Namespace.PadRight(maxnslength, ' ')}{Tab}{context.ShellEnv.Colors.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{Tab}{f}{com.Description}{context.ShellEnv.Colors.Default}");
                }
                else
                {
                    context.Out.Echoln($"{context.ShellEnv.Colors.Highlight}{com.Name.PadRight(maxcnamelength, ' ')}{f}{Tab}{com.Description}{context.ShellEnv.Colors.Default}");
                }
            }
            else
            {
                bool hasrtt   = com.ReturnType != null;
                bool hasalias = com.Aliases != null;
                if (singleout)
                {
                    context.Out.Echoln(com.Description);
                    context.Out.Echo($"{Br}{col}{context.ShellEnv.Colors.Label}syntax: {f}{com.ToColorizedString(context.ShellEnv.Colors)}", hasrtt | hasalias);
                    if (hasrtt)
                    {
                        context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}returns: {context.ShellEnv.Colors.TypeName}{com.ReturnType.UnmangledName()}");
                    }
                    if (hasalias)
                    {
                        context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}aliases: {context.ShellEnv.Colors.TypeName}{string.Join(",", com.Aliases.Select(x => x.name))}");
                    }
                    context.Out.Echo(!shortView ? Br : "");
                    if (!string.IsNullOrWhiteSpace(com.LongDescription))
                    {
                        context.Out.Echoln(_GetPrintableDocText(com.LongDescription, list, shortView, 0));
                    }
                }
                else
                {
                    context.Out.Echoln($"{com.Name.PadRight(maxcnamelength, ' ')}{com.Description}");
                    context.Out.Echoln($"{Br}{col}{context.ShellEnv.Colors.Label}syntax: {f}{com.ToColorizedString(context.ShellEnv.Colors)}");
                    if (hasrtt)
                    {
                        context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}returns: {context.ShellEnv.Colors.TypeName}{com.ReturnType.UnmangledName()}");
                    }
                    if (hasalias)
                    {
                        context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}aliases: {context.ShellEnv.Colors.TypeName}{string.Join(",", com.Aliases.Select(x => x.name))}");
                    }
                    context.Out.Echo(!shortView ? Br : "");
                    if (!string.IsNullOrWhiteSpace(com.LongDescription))
                    {
                        context.Out.Echo(_GetPrintableDocText(com.LongDescription + "(br)", list, shortView, maxcnamelength));
                    }
                }
            }

            if (!list)
            {
                if (com.ParametersCount > 0)
                {
                    if (!shortView)
                    {
                        var mpl = (com.ParametersCount > 0 ? com.ParametersSpecifications.Values.Select(x => x.Dump(false).Length).Max() : 0) + context.CommandLineProcessor.Console.TabLength;
                        foreach (var p in com.ParametersSpecifications.Values)
                        {
                            var ptype = (!p.IsOption && p.HasValue) ? $"of type: {context.ShellEnv.Colors.TypeName}{p.ParameterInfo.ParameterType.UnmangledName()}{f}" : "";
                            var pdef  = (p.HasValue && p.IsOptional && p.HasDefaultValue && p.DefaultValue != null &&
                                         (!p.IsOption || p.ParameterValueTypeName != typeof(bool).Name)) ?
                                        ((ptype != "" ? ". " : "") + $"default value: {context.ShellEnv.Colors.OptionValue}{EchoPrimitives.DumpAsText(context, p.DefaultValue)}{f}")
                                        : "";

                            var pleftCol = "".PadRight(mpl - p.Dump(false).Length, ' ');
                            var leftCol  = "".PadRight(mpl, ' ');

                            if (p.ParameterInfo.ParameterType.IsEnum)
                            {
                                pdef += $"(br){col}{Tab}{leftCol}possibles values: {context.ShellEnv.Colors.OptionValue}{string.Join(CommandLineSyntax.ParameterTypeListValuesSeparator, Enum.GetNames(p.ParameterInfo.ParameterType))}(rdc)";
                            }

                            var supdef = $"{ptype}{pdef}";
                            // method 'Echo if has' else to string
                            context.Out.Echoln($"{col}{Tab}{p.ToColorizedString(context.ShellEnv.Colors, false)}{pleftCol}{p.Description}");
                            if (!string.IsNullOrWhiteSpace(supdef))
                            {
                                context.Out.Echoln($"{col}{Tab}{" ".PadRight(mpl)}{supdef}");
                            }
                        }

                        //if (string.IsNullOrWhiteSpace(com.Documentation)) context.Out.Echoln();
                        if (!string.IsNullOrWhiteSpace(com.Documentation))
                        {
                            context.Out.Echo(_GetPrintableDocText("(br)" + com.Documentation, list, shortView, singleout ? 0 : maxcnamelength));
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrWhiteSpace(com.Documentation))
                        {
                            context.Out.Echoln(_GetPrintableDocText("(br)" + com.Documentation, list, shortView, singleout ? 0 : maxcnamelength));
                        }
                    }
                }
                if (verboseView)
                {
                    if (com.ParametersCount > 0)
                    {
                        context.Out.Echoln("");
                    }
                    context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}namespace       : {context.ShellEnv.Colors.HalfDarkLabel}{com.Namespace}");
                    context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}declaring type  : {context.ShellEnv.Colors.HalfDarkLabel}{com.DeclaringTypeShortName}");
                    context.Out.Echoln($"{col}{context.ShellEnv.Colors.Label}module          : {context.ShellEnv.Colors.HalfDarkLabel}{com.ModuleName}{context.ShellEnv.Colors.Default}");
                }
            }
#pragma warning restore IDE0071WithoutSuggestion // Simplifier l’interpolation
#pragma warning restore IDE0071                  // Simplifier l’interpolation
        }
        int RegisterCommandsClass(CommandEvaluationContext context, Type type, bool registerAsModule)
        {
            if (type.GetInterface(typeof(ICommandsDeclaringType).FullName) == null)
            {
                throw new Exception($"the type '{type.FullName}' must implements interface '{typeof(ICommandsDeclaringType).FullName}' to be registered as a command class");
            }
            var    comsCount = 0;
            object instance  = Activator.CreateInstance(type, new object[] { });
            var    methods   = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            if (registerAsModule && _modules.ContainsKey(type.FullName))
            {
                Errorln($"a module with same name than commands type '{type.FullName}' is already registered");
                return(0);
            }
            foreach (var method in methods)
            {
                var cmd = method.GetCustomAttribute <CommandAttribute>();
                if (cmd != null)
                {
                    if (!method.ReturnType.HasInterface(typeof(ICommandResult)))
                    {
                        Errorln($"class={type.FullName} method={method.Name} wrong return type. should be of type '{typeof(ICommandResult).FullName}', but is of type: {method.ReturnType.FullName}");
                    }
                    else
                    {
                        var  paramspecs  = new List <CommandParameterSpecification>();
                        bool syntaxError = false;
                        var  pindex      = 0;
                        foreach (var parameter in method.GetParameters())
                        {
                            if (pindex == 0)
                            {
                                // manadatory: param 0 is CommandEvaluationContext
                                if (parameter.ParameterType != typeof(CommandEvaluationContext))
                                {
                                    Errorln($"class={type.FullName} method={method.Name} parameter 0 ('{parameter.Name}') should be of type '{typeof(CommandEvaluationContext).FullName}', but is of type: {parameter.ParameterType.FullName}");
                                    syntaxError = true;
                                    break;
                                }
                            }
                            else
                            {
                                CommandParameterSpecification pspec = null;
                                var    paramAttr = parameter.GetCustomAttribute <ParameterAttribute>();
                                object defval    = null;
                                if (!parameter.HasDefaultValue && parameter.ParameterType.IsValueType)
                                {
                                    defval = Activator.CreateInstance(parameter.ParameterType);
                                }

                                if (paramAttr != null)
                                {
                                    // TODO: validate command specification (eg. indexs validity)
                                    pspec = new CommandParameterSpecification(
                                        parameter.Name,
                                        paramAttr.Description,
                                        paramAttr.IsOptional,
                                        paramAttr.Index,
                                        null,
                                        true,
                                        parameter.HasDefaultValue,
                                        (parameter.HasDefaultValue) ? parameter.DefaultValue : defval,
                                        parameter);
                                }
                                var optAttr = parameter.GetCustomAttribute <OptionAttribute>();
                                if (optAttr != null)
                                {
                                    var reqParamAttr = parameter.GetCustomAttribute <OptionRequireParameterAttribute>();
                                    try
                                    {
                                        pspec = new CommandParameterSpecification(
                                            parameter.Name,
                                            optAttr.Description,
                                            optAttr.IsOptional,
                                            -1,
                                            optAttr.OptionName ?? parameter.Name,
                                            optAttr.HasValue,
                                            parameter.HasDefaultValue,
                                            (parameter.HasDefaultValue) ? parameter.DefaultValue : defval,
                                            parameter,
                                            reqParamAttr?.RequiredParameterName);
                                    }
                                    catch (Exception ex)
                                    {
                                        Errorln(ex.Message);
                                    }
                                }
                                if (pspec == null)
                                {
                                    syntaxError = true;
                                    Errorln($"invalid parameter: class={type.FullName} method={method.Name} name={parameter.Name}");
                                }
                                else
                                {
                                    paramspecs.Add(pspec);
                                }
                            }
                            pindex++;
                        }

                        if (!syntaxError)
                        {
                            var cmdNameAttr = method.GetCustomAttribute <CommandNameAttribute>();

                            var cmdName = (cmdNameAttr != null && cmdNameAttr.Name != null) ? cmdNameAttr.Name
                                : (cmd.Name ?? method.Name.ToLower());

                            var cmdspec = new CommandSpecification(
                                cmdName,
                                cmd.Description,
                                cmd.LongDescription,
                                cmd.Documentation,
                                method,
                                instance,
                                paramspecs);

                            bool registered = true;
                            if (_commands.TryGetValue(cmdspec.Name, out var cmdlst))
                            {
                                if (cmdlst.Select(x => x.MethodInfo.DeclaringType == type).Any())
                                {
                                    Errorln($"command already registered: '{cmdspec.Name}' in type '{cmdspec.DeclaringTypeFullName}'");
                                    registered = false;
                                }
                                else
                                {
                                    cmdlst.Add(cmdspec);
                                }
                            }
                            else
                            {
                                _commands.Add(cmdspec.Name, new List <CommandSpecification> {
                                    cmdspec
                                });
                            }

                            if (registered)
                            {
                                _syntaxAnalyzer.Add(cmdspec);
                                comsCount++;
                            }
                        }
                    }
                }
            }
            if (registerAsModule)
            {
                if (comsCount == 0)
                {
                    Errorln($"no commands found in type '{type.FullName}'");
                }
                else
                {
                    var descAttr    = type.GetCustomAttribute <CommandsAttribute>();
                    var description = descAttr != null ? descAttr.Description : "";
                    _modules.Add(type.FullName, new CommandsModule(CommandsModule.DeclaringTypeShortName(type), description, type.Assembly, 1, comsCount, type));
                }
            }
            return(comsCount);
        }