private void Init()
        {
            var ast = CommandLineHelper.ParseCommandLine(GetCommandLine());

            CommandLineHelper.Check(ast, _rulesGetter());
            _parsedCmdLine = ast;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Check command line semantics.
 /// </summary>
 public static void Check(CmdLineNode commandLine, CmdLineRules rules)
 {
     CommandLineChecker.Check(commandLine, rules);
 }
        /// <summary>
        /// Check command line semantics.
        /// </summary>
        public static void Check(CmdLineNode commandLine, CmdLineRules rules)
        {
            // Check rules consistency
            var cmds = new HashSet <string>();

            foreach (var command in rules.Commands)
            {
                if (!cmds.Add(command.Name))
                {
                    throw new CommandLineCheckException($"Duplicate commands \'{command.Name}\'");
                }
            }
            var cmdOpts = LazyDictionary.Create <string, HashSet <string> >(cn => new HashSet <string>(), false);

            foreach (var cmdOpt in
                     rules
                     .Options
                     .SelectMany(
                         opt =>
                         !opt.DependOnCommands.Any()
                                                                ? new[] { new { Cmd = "", Opt = opt.Name } }
                                                                : opt.DependOnCommands.Select(cn => new { Cmd = cn, Opt = opt.Name })))
            {
                if (!cmdOpts[cmdOpt.Cmd].Add(cmdOpt.Opt))
                {
                    throw new CommandLineCheckException(
                              "Duplicate option {0}{1}"
                              .FormatWith(
                                  cmdOpt.Opt,
                                  cmdOpt.Cmd == ""
                                                                        ? ""
                                                                        : " in command {0}".FormatWith(cmdOpt.Cmd)));
                }
            }

            // Check command quantity
            var cmdCount = commandLine.Commands.Length;

            switch (rules.CommandQuantifier)
            {
            case CommandQuantifier.ZeroOrOne:
                if (cmdCount > 1)
                {
                    throw new CommandLineCheckException("Maximum one command is allowed.");
                }
                break;

            case CommandQuantifier.ZeroOrMultiple:
                // Any combination allowed
                break;

            case CommandQuantifier.One:
                if (cmdCount > 1)
                {
                    throw new CommandLineCheckException("Maximum one command is allowed.");
                }
                if (cmdCount == 0)
                {
                    throw new CommandLineCheckException("Required command not specified.");
                }
                break;

            case CommandQuantifier.OneOrMultiple:
                if (cmdCount == 0)
                {
                    throw new CommandLineCheckException("Required command(s) not specified.");
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            // Check for unknown commands
            var cmdRules = rules.Commands.ToDictionary(cr => cr.Name);
            var unkCmds  =
                commandLine
                .Commands
                .Where(cmd => !cmdRules.ContainsKey(cmd.Text))
                .ToArray();

            if (unkCmds.Length > 0)
            {
                throw new CommandLineCheckException(
                          "Unknown commands :{0}".FormatWith(unkCmds.Select(cmd => "'" + cmd.Text + "'").Join(", ")));
            }

            // Check for unknown options
            var optRules = rules.Options.ToDictionary(cr => cr.Name);
            var unkOpts  =
                commandLine
                .Options
                .Where(opt => !optRules.ContainsKey(opt.Text))
                .ToArray();

            if (unkOpts.Length > 0)
            {
                throw new CommandLineCheckException(
                          "Unknown options :{0}".FormatWith(unkOpts.Select(opt => "'" + opt.Text + "'").Join(", ")));
            }

            // Option values check
            foreach (var option in commandLine.Options)
            {
                var rule = optRules[option.Text];
                if (rule.Type != option.Type)
                {
                    switch (rule.Type)
                    {
                    case OptionType.Valueless:
                        throw new CommandLineCheckException("Option '{0}' cannot have value".FormatWith(rule.Name));

                    case OptionType.Bool:
                        throw new CommandLineCheckException("'+' or '-' must be specified for option '{0}'".FormatWith(rule.Name));

                    case OptionType.Value:
                        throw new CommandLineCheckException("Value must be specified for option '{0}'".FormatWith(rule.Name));

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }

            // Options presence check
            var specCmds = new HashSet <string>(commandLine.Commands.Select(cmd => cmd.Text));
            var specOpts = new HashSet <string>(commandLine.Options.Select(opt => opt.Text));

            foreach (var optRule in rules.Options)
            {
                var existed      = specOpts.Contains(optRule.Name);
                var dependent    = optRule.DependOnCommands.Any();
                var hasMasterCmd = dependent && optRule.DependOnCommands.Any(specCmds.Contains);
                if (existed && dependent && !hasMasterCmd)
                {
                    throw new CommandLineCheckException(
                              "{0} command(s) must be specified for use {1} option."
                              .FormatWith(optRule.DependOnCommands.Select(c => c).Join(", "), optRule.Name));
                }

                if (!existed && optRule.Required && (!dependent || hasMasterCmd))
                {
                    throw new CommandLineCheckException("Required option '{0}' absent.".FormatWith(optRule.Name));
                }
            }
        }