Пример #1
0
        /// <summary>
        /// Coordinates the processing of all detected switches. It gathers information necessary to invoke the build engine, and
        /// performs deeper error checking on the switches and their parameters.
        /// </summary>
        /// <returns>true, if build can be invoked</returns>
        private static bool ProcessCommandLineSwitches
        (
            CommandLineSwitches switchesFromAutoResponseFile,
            CommandLineSwitches switchesNotFromAutoResponseFile,
            ref string projectFile,
            ref string[] targets,
            ref string toolsVersion,
            ref Dictionary<string, string> globalProperties,
            ref ILogger[] loggers,
            ref LoggerVerbosity verbosity,
            ref List<DistributedLoggerRecord> distributedLoggerRecords,
            ref bool needToValidateProject,
            ref string schemaFile,
            ref int cpuCount,
            ref bool enableNodeReuse,
            ref TextWriter preprocessWriter,
            ref bool debugger,
            ref bool detailedSummary,
            bool recursing
        )
        {
            bool invokeBuild = false;

            // combine the auto-response file switches with the command line switches in a left-to-right manner, where the
            // auto-response file switches are on the left (default options), and the command line switches are on the
            // right (overriding options) so that we consume switches in the following sequence of increasing priority:
            // (1) switches from the msbuild.rsp file/s, including recursively included response files
            // (2) switches from the command line, including recursively included response file switches inserted at the point they are declared with their "@" symbol
            CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
            commandLineSwitches.Append(switchesFromAutoResponseFile);    // lowest precedence
            commandLineSwitches.Append(switchesNotFromAutoResponseFile);

            // show copyright message if nologo switch is not set
            // NOTE: we heed the nologo switch even if there are switch errors
            if (!recursing && !commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.NoLogo] && !commandLineSwitches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Preprocess))
            {
                DisplayCopyrightMessage();
            }

            // if help switch is set (regardless of switch errors), show the help message and ignore the other switches
            if (commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.Help])
            {
                ShowHelpMessage();
            }
            else if (commandLineSwitches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.NodeMode))
            {
                StartLocalNode(commandLineSwitches);
            }
            else
            {
                // if help switch is not set, and errors were found, abort (don't process the remaining switches)
                commandLineSwitches.ThrowErrors();

                // if version switch is set, just show the version and quit (ignore the other switches)
                if (commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.Version])
                {
                    ShowVersion();
                }
                else
                {
                    // figure out what project we are building
                    projectFile = ProcessProjectSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Project], commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions], Directory.GetFiles);

                    if (!recursing && !commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.NoAutoResponse])
                    {
                        // gather any switches from an msbuild.rsp that is next to the project or solution file itself
                        string projectDirectory = Path.GetDirectoryName(Path.GetFullPath(projectFile));

                        bool found = false;

                        // Don't look for more response files if it's only in the same place we already looked (next to the exe)
                        if (!String.Equals(projectDirectory, s_exePath, StringComparison.OrdinalIgnoreCase))
                        {
                            // this combines any found, with higher precedence, with the switches from the original auto response file switches
                            found = GatherAutoResponseFileSwitches(projectDirectory, switchesFromAutoResponseFile);
                        }

                        if (found)
                        {
                            // we presumably read in more switches, so start our switch processing all over again,
                            // so that we consume switches in the following sequence of increasing priority:
                            // (1) switches from the msbuild.rsp next to msbuild.exe, including recursively included response files
                            // (2) switches from this msbuild.rsp next to the project or solution <<--------- these we have just now merged with (1)
                            // (3) switches from the command line, including recursively included response file switches inserted at the point they are declared with their "@" symbol
                            return ProcessCommandLineSwitches(
                                                               switchesFromAutoResponseFile,
                                                               switchesNotFromAutoResponseFile,
                                                               ref projectFile,
                                                               ref targets,
                                                               ref toolsVersion,
                                                               ref globalProperties,
                                                               ref loggers,
                                                               ref verbosity,
                                                               ref distributedLoggerRecords,
                                                               ref needToValidateProject,
                                                               ref schemaFile,
                                                               ref cpuCount,
                                                               ref enableNodeReuse,
                                                               ref preprocessWriter,
                                                               ref debugger,
                                                               ref detailedSummary,
                                                               recursing: true
                                                             );
                        }
                    }

                    // figure out which targets we are building
                    targets = ProcessTargetSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Target]);

                    // figure out which ToolsVersion has been set on the command line
                    toolsVersion = ProcessToolsVersionSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.ToolsVersion]);

                    // figure out which properties have been set on the command line
                    globalProperties = ProcessPropertySwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Property]);

                    // figure out if there was a max cpu count provided
                    cpuCount = ProcessMaxCPUCountSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.MaxCPUCount]);

                    // figure out if we shold reuse nodes
                    enableNodeReuse = ProcessNodeReuseSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.NodeReuse]);

                    // determine what if any writer to preprocess to
                    preprocessWriter = null;
                    if (commandLineSwitches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Preprocess))
                    {
                        preprocessWriter = ProcessPreprocessSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Preprocess]);
                    }

#if FEATURE_MSBUILD_DEBUGGER
                    debugger = commandLineSwitches.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.Debugger);
#endif
                    detailedSummary = commandLineSwitches.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.DetailedSummary);

                    // figure out which loggers are going to listen to build events
                    string[][] groupedFileLoggerParameters = commandLineSwitches.GetFileLoggerParameters();

                    loggers = ProcessLoggingSwitches(
                        commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Logger],
                        commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.DistributedLogger],
                        commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Verbosity],
                        commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.NoConsoleLogger],
                        commandLineSwitches[CommandLineSwitches.ParameterlessSwitch.DistributedFileLogger],
                        commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.FileLoggerParameters], // used by DistributedFileLogger
                        commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.ConsoleLoggerParameters],
                        groupedFileLoggerParameters,
                        out distributedLoggerRecords,
                        out verbosity,
                        ref detailedSummary,
                        cpuCount
                        );

                    // If we picked up switches from the autoreponse file, let the user know. This could be a useful
                    // hint to a user that does not know that we are picking up the file automatically.
                    // Since this is going to happen often in normal use, only log it in high verbosity mode.
                    // Also, only log it to the console; logging to loggers would involve increasing the public API of
                    // the Engine, and we don't want to do that.
                    if (usingSwitchesFromAutoResponseFile && LoggerVerbosity.Diagnostic == verbosity)
                    {
                        Console.WriteLine(ResourceUtilities.FormatResourceString("PickedUpSwitchesFromAutoResponse", autoResponseFileName));
                    }

                    if (verbosity == LoggerVerbosity.Diagnostic)
                    {
                        string equivalentCommandLine = commandLineSwitches.GetEquivalentCommandLineExceptProjectFile();
                        Console.WriteLine(Path.Combine(s_exePath, s_exeName) + " " + equivalentCommandLine + " " + projectFile);
                    }

                    // figure out if the project needs to be validated against a schema
                    needToValidateProject = commandLineSwitches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Validate);
                    schemaFile = ProcessValidateSwitch(commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.Validate]);
                    invokeBuild = true;
                }
            }

            ErrorUtilities.VerifyThrow(!invokeBuild || !String.IsNullOrEmpty(projectFile), "We should have a project file if we're going to build.");

            return invokeBuild;
        }
Пример #2
0
        public void AppendParameterizedSwitchesTests1()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();

            switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true);

            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.False(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            CommandLineSwitches switchesRight = new CommandLineSwitches();

            switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:build", "build", true, true);

            Assert.False(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            switchesLeft.Append(switchesRight);

            Assert.Equal("tempproject.proj", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));

            string[] parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Project];

            Assert.NotNull(parameters);
            Assert.Equal(1, parameters.Length);
            Assert.Equal("tempproject.proj", parameters[0]);

            Assert.Equal("/t:build", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Target];

            Assert.NotNull(parameters);
            Assert.Equal(1, parameters.Length);
            Assert.Equal("build", parameters[0]);
        }
Пример #3
0
        /// <summary>
        /// Called when a switch that takes parameters is detected on the command line. This method flags errors and stores the
        /// switch parameters.
        /// </summary>
        /// <param name="commandLineSwitches"></param>
        /// <param name="parameterizedSwitch"></param>
        /// <param name="switchParameters"></param>
        /// <param name="duplicateSwitchErrorMessage"></param>
        /// <param name="multipleParametersAllowed"></param>
        /// <param name="missingParametersErrorMessage"></param>
        /// <param name="unquoteParameters"></param>
        /// <param name="unquotedCommandLineArg"></param>
        private static void GatherParameterizedCommandLineSwitch
        (
            CommandLineSwitches commandLineSwitches,
            CommandLineSwitches.ParameterizedSwitch parameterizedSwitch,
            string switchParameters,
            string duplicateSwitchErrorMessage,
            bool multipleParametersAllowed,
            string missingParametersErrorMessage,
            bool unquoteParameters,
            string unquotedCommandLineArg
        )
        {
            if (// switch must have parameters
                (switchParameters.Length > 1) ||
                // unless the parameters are optional
                (missingParametersErrorMessage == null))
            {
                // check if switch is duplicated, and if that's allowed
                if (!commandLineSwitches.IsParameterizedSwitchSet(parameterizedSwitch) ||
                    (duplicateSwitchErrorMessage == null))
                {
                    // skip the parameter indicator (if any)
                    if (switchParameters.Length > 0)
                    {
                        switchParameters = switchParameters.Substring(1);
                    }

                    // save the parameters after unquoting and splitting them if necessary
                    if (!commandLineSwitches.SetParameterizedSwitch(parameterizedSwitch, unquotedCommandLineArg, switchParameters, multipleParametersAllowed, unquoteParameters))
                    {
                        // if parsing revealed there were no real parameters, flag an error, unless the parameters are optional
                        if (missingParametersErrorMessage != null)
                        {
                            commandLineSwitches.SetSwitchError(missingParametersErrorMessage, unquotedCommandLineArg);
                        }
                    }
                }
                else
                {
                    commandLineSwitches.SetSwitchError(duplicateSwitchErrorMessage, unquotedCommandLineArg);
                }
            }
            else
            {
                commandLineSwitches.SetSwitchError(missingParametersErrorMessage, unquotedCommandLineArg);
            }
        }
Пример #4
0
        public void SetParameterizedSwitchTests2()
        {
            CommandLineSwitches switches = new CommandLineSwitches();

            // we haven't set this switch yet
            Assert.Null(switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.False(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.Target];

            Assert.NotNull(parameters);
            Assert.Equal(0, parameters.Length);

            // fake/missing parameters -- this is bogus because the /target switch allows multiple parameters but we're turning
            // that off here just for testing purposes
            Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"", "\"", false, true));

            // switch has been set
            Assert.Equal("/t:\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Target];

            // but no parameters
            Assert.NotNull(parameters);
            Assert.Equal(0, parameters.Length);

            // more fake/missing parameters
            Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:A,\"\";B", "A,\"\";B", true, true));

            Assert.Equal("/t:\" /t:A,\"\";B", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Target];

            // now we have some parameters
            Assert.NotNull(parameters);
            Assert.Equal(2, parameters.Length);
            Assert.Equal("A", parameters[0]);
            Assert.Equal("B", parameters[1]);
        }
Пример #5
0
        public void SetParameterizedSwitchTests3()
        {
            CommandLineSwitches switches = new CommandLineSwitches();

            // we haven't set this switch yet
            Assert.Null(switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
            Assert.False(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));

            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.Logger];

            Assert.NotNull(parameters);
            Assert.Equal(0, parameters.Length);

            // don't unquote fake/missing parameters
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/l:\"", "\"", false, false));

            Assert.Equal("/l:\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));

            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Logger];

            Assert.NotNull(parameters);
            Assert.Equal(1, parameters.Length);
            Assert.Equal("\"", parameters[0]);

            // don't unquote multiple fake/missing parameters -- this is bogus because the /logger switch does not take multiple
            // parameters, but for testing purposes this is fine
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/LOGGER:\"\",asm;\"p,a;r\"", "\"\",asm;\"p,a;r\"", true, false));

            Assert.Equal("/l:\" /LOGGER:\"\",asm;\"p,a;r\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));

            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Logger];

            Assert.NotNull(parameters);
            Assert.Equal(4, parameters.Length);
            Assert.Equal("\"", parameters[0]);
            Assert.Equal("\"\"", parameters[1]);
            Assert.Equal("asm", parameters[2]);
            Assert.Equal("\"p,a;r\"", parameters[3]);
        }
Пример #6
0
        public void SetParameterizedSwitchTests1()
        {
            CommandLineSwitches switches = new CommandLineSwitches();

            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true));

            Assert.Equal("/v:q", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Verbosity));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Verbosity));

            string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.Verbosity];

            Assert.NotNull(parameters);
            Assert.Equal(1, parameters.Length);
            Assert.Equal("q", parameters[0]);

            // set it again -- this is bogus, because the /verbosity switch doesn't allow multiple parameters, but for the
            // purposes of testing the SetParameterizedSwitch() method, it doesn't matter
            Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/verbosity:\"diag\";minimal", "\"diag\";minimal", true, true));

            Assert.Equal("/v:q /verbosity:\"diag\";minimal", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Verbosity));
            Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Verbosity));

            parameters = switches[CommandLineSwitches.ParameterizedSwitch.Verbosity];

            Assert.NotNull(parameters);
            Assert.Equal(3, parameters.Length);
            Assert.Equal("q", parameters[0]);
            Assert.Equal("diag", parameters[1]);
            Assert.Equal("minimal", parameters[2]);
        }
Пример #7
0
        public void AppendParameterizedSwitchesTests3()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();

            switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true);

            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));

            CommandLineSwitches switchesRight = new CommandLineSwitches();

            switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "Rhubarb.proj", "Rhubarb.proj", false, true);

            Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));

            switchesLeft.Append(switchesRight);

            Assert.Equal("tempproject.proj", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Project));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));

            string[] parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Project];

            Assert.NotNull(parameters);
            Assert.Equal(1, parameters.Length);
            Assert.Equal("tempproject.proj", parameters[0]);

            Assert.True(switchesLeft.HaveErrors());

            VerifySwitchError(switchesLeft, "Rhubarb.proj");
        }
Пример #8
0
        public void AppendParameterizedSwitchesTests2()
        {
            CommandLineSwitches switchesLeft = new CommandLineSwitches();

            switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/target:Clean", "Clean", true, true);

            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            CommandLineSwitches switchesRight = new CommandLineSwitches();

            switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"RESOURCES\";build", "\"RESOURCES\";build", true, true);

            Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            switchesLeft.Append(switchesRight);

            Assert.Equal("/t:\"RESOURCES\";build", switchesLeft.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
            Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));

            string[] parameters = switchesLeft[CommandLineSwitches.ParameterizedSwitch.Target];

            Assert.NotNull(parameters);
            Assert.Equal(3, parameters.Length);
            Assert.Equal("Clean", parameters[0]);
            Assert.Equal("RESOURCES", parameters[1]);
            Assert.Equal("build", parameters[2]);
        }
Пример #9
0
        /// <summary>
        /// Appends the given collection of command-line switches to this one.
        /// </summary>
        /// <remarks>
        /// Command-line switches have left-to-right precedence i.e. switches on the right override switches on the left. As a
        /// result, this "append" operation is also performed in a left-to-right manner -- the switches being appended to are
        /// considered to be on the "left", and the switches being appended are on the "right".
        /// </remarks>
        /// <param name="switchesToAppend"></param>
        internal void Append(CommandLineSwitches switchesToAppend)
        {
            // if this collection doesn't already have an error registered, but the collection being appended does
            if (!HaveErrors() && switchesToAppend.HaveErrors())
            {
                // register the error from the given collection
                // NOTE: we always store the first error found (parsing left-to-right), and since this collection is considered to
                // be on the "left" of the collection being appended, the error flagged in this collection takes priority over the
                // error in the collection being appended
                _errorMessage      = switchesToAppend._errorMessage;
                _badCommandLineArg = switchesToAppend._badCommandLineArg;
                _innerException    = switchesToAppend._innerException;
                _isParameterError  = switchesToAppend._isParameterError;
            }

            // NOTE: we might run into some duplicate switch errors below, but if we've already registered the error from the
            // collection being appended, all the duplicate switch errors will be ignored; this is fine because we really have no
            // way of telling which error would occur first in the left-to-right order without keeping track of a lot more error
            // information -- so we play it safe, and register the guaranteed error

            // append the parameterless switches with left-to-right precedence, flagging duplicate switches as necessary
            for (int i = 0; i < (int)ParameterlessSwitch.NumberOfParameterlessSwitches; i++)
            {
                if (switchesToAppend.IsParameterlessSwitchSet((ParameterlessSwitch)i))
                {
                    if (!IsParameterlessSwitchSet((ParameterlessSwitch)i) ||
                        (s_parameterlessSwitchesMap[i].duplicateSwitchErrorMessage == null))
                    {
                        _parameterlessSwitches[i].commandLineArg = switchesToAppend._parameterlessSwitches[i].commandLineArg;
                    }
                    else
                    {
                        SetSwitchError(s_parameterlessSwitchesMap[i].duplicateSwitchErrorMessage,
                                       switchesToAppend.GetParameterlessSwitchCommandLineArg((ParameterlessSwitch)i));
                    }
                }
            }

            // append the parameterized switches with left-to-right precedence, flagging duplicate switches as necessary
            for (int j = 0; j < (int)ParameterizedSwitch.NumberOfParameterizedSwitches; j++)
            {
                if (switchesToAppend.IsParameterizedSwitchSet((ParameterizedSwitch)j))
                {
                    if (!IsParameterizedSwitchSet((ParameterizedSwitch)j) ||
                        (s_parameterizedSwitchesMap[j].duplicateSwitchErrorMessage == null))
                    {
                        if (_parameterizedSwitches[j].commandLineArg == null)
                        {
                            _parameterizedSwitches[j].parameters = new ArrayList();
                        }

                        _parameterizedSwitches[j].commandLineArg = switchesToAppend._parameterizedSwitches[j].commandLineArg;
                        _parameterizedSwitches[j].parameters.AddRange(switchesToAppend._parameterizedSwitches[j].parameters);
                    }
                    else
                    {
                        SetSwitchError(s_parameterizedSwitchesMap[j].duplicateSwitchErrorMessage,
                                       switchesToAppend.GetParameterizedSwitchCommandLineArg((ParameterizedSwitch)j));
                    }
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Appends the given collection of command-line switches to this one.
        /// </summary>
        /// <remarks>
        /// Command-line switches have left-to-right precedence i.e. switches on the right override switches on the left. As a
        /// result, this "append" operation is also performed in a left-to-right manner -- the switches being appended to are
        /// considered to be on the "left", and the switches being appended are on the "right".
        /// </remarks>
        /// <param name="switchesToAppend"></param>
        internal void Append(CommandLineSwitches switchesToAppend)
        {
            // if this collection doesn't already have an error registered, but the collection being appended does
            if (!HaveErrors() && switchesToAppend.HaveErrors())
            {
                // register the error from the given collection
                // NOTE: we always store the first error found (parsing left-to-right), and since this collection is considered to
                // be on the "left" of the collection being appended, the error flagged in this collection takes priority over the
                // error in the collection being appended
                _errorMessage = switchesToAppend._errorMessage;
                _badCommandLineArg = switchesToAppend._badCommandLineArg;
                _innerException = switchesToAppend._innerException;
                _isParameterError = switchesToAppend._isParameterError;
            }

            // NOTE: we might run into some duplicate switch errors below, but if we've already registered the error from the
            // collection being appended, all the duplicate switch errors will be ignored; this is fine because we really have no
            // way of telling which error would occur first in the left-to-right order without keeping track of a lot more error
            // information -- so we play it safe, and register the guaranteed error

            // append the parameterless switches with left-to-right precedence, flagging duplicate switches as necessary
            for (int i = 0; i < (int)ParameterlessSwitch.NumberOfParameterlessSwitches; i++)
            {
                if (switchesToAppend.IsParameterlessSwitchSet((ParameterlessSwitch)i))
                {
                    if (!IsParameterlessSwitchSet((ParameterlessSwitch)i) ||
                        (s_parameterlessSwitchesMap[i].duplicateSwitchErrorMessage == null))
                    {
                        _parameterlessSwitches[i].commandLineArg = switchesToAppend._parameterlessSwitches[i].commandLineArg;
                    }
                    else
                    {
                        SetSwitchError(s_parameterlessSwitchesMap[i].duplicateSwitchErrorMessage,
                            switchesToAppend.GetParameterlessSwitchCommandLineArg((ParameterlessSwitch)i));
                    }
                }
            }

            // append the parameterized switches with left-to-right precedence, flagging duplicate switches as necessary
            for (int j = 0; j < (int)ParameterizedSwitch.NumberOfParameterizedSwitches; j++)
            {
                if (switchesToAppend.IsParameterizedSwitchSet((ParameterizedSwitch)j))
                {
                    if (!IsParameterizedSwitchSet((ParameterizedSwitch)j) ||
                        (s_parameterizedSwitchesMap[j].duplicateSwitchErrorMessage == null))
                    {
                        if (_parameterizedSwitches[j].commandLineArg == null)
                        {
                            _parameterizedSwitches[j].parameters = new ArrayList();
                        }

                        _parameterizedSwitches[j].commandLineArg = switchesToAppend._parameterizedSwitches[j].commandLineArg;
                        _parameterizedSwitches[j].parameters.AddRange(switchesToAppend._parameterizedSwitches[j].parameters);
                    }
                    else
                    {
                        SetSwitchError(s_parameterizedSwitchesMap[j].duplicateSwitchErrorMessage,
                            switchesToAppend.GetParameterizedSwitchCommandLineArg((ParameterizedSwitch)j));
                    }
                }
            }
        }