diff --git a/dir.props b/dir.props
index 407c0c2ffda..35cbb91755d 100644
--- a/dir.props
+++ b/dir.props
@@ -308,6 +308,8 @@
$(DefineConstants);FEATURE_REGISTRYHIVE_DYNDATA
$(DefineConstants);FEATURE_RESGEN
$(DefineConstants);FEATURE_RESOURCE_EXPOSURE
+
+ $(DefineConstants);FEATURE_RESOURCEMANAGER_GETRESOURCESET
$(DefineConstants);FEATURE_RESX_RESOURCE_READER
$(DefineConstants);FEATURE_RTLMOVEMEMORY
$(DefineConstants);FEATURE_RUN_EXE_IN_TESTS
diff --git a/ref/net46/Microsoft.Build/Microsoft.Build.cs b/ref/net46/Microsoft.Build/Microsoft.Build.cs
index 13424e130a9..a5b7e11a2ea 100644
--- a/ref/net46/Microsoft.Build/Microsoft.Build.cs
+++ b/ref/net46/Microsoft.Build/Microsoft.Build.cs
@@ -940,6 +940,7 @@ public BuildParameters(Microsoft.Build.Evaluation.ProjectCollection projectColle
public System.Collections.Generic.ICollection Toolsets { get { throw null; } }
public System.Globalization.CultureInfo UICulture { get { throw null; } set { } }
public bool UseSynchronousLogging { get { throw null; } set { } }
+ public System.Collections.Generic.ISet WarningsAsErrors { get { throw null; } set { } }
public Microsoft.Build.Execution.BuildParameters Clone() { throw null; }
public Microsoft.Build.Evaluation.Toolset GetToolset(string toolsVersion) { throw null; }
}
diff --git a/src/XMakeBuildEngine/BackEnd/BuildManager/BuildManager.cs b/src/XMakeBuildEngine/BackEnd/BuildManager/BuildManager.cs
index 9f3d793288e..92872a5e736 100644
--- a/src/XMakeBuildEngine/BackEnd/BuildManager/BuildManager.cs
+++ b/src/XMakeBuildEngine/BackEnd/BuildManager/BuildManager.cs
@@ -424,7 +424,7 @@ public void BeginBuild(BuildParameters parameters)
}
// Set up the logging service.
- ILoggingService loggingService = CreateLoggingService(_buildParameters.Loggers, _buildParameters.ForwardingLoggers);
+ ILoggingService loggingService = CreateLoggingService(_buildParameters.Loggers, _buildParameters.ForwardingLoggers, _buildParameters.WarningsAsErrors);
_nodeManager.RegisterPacketHandler(NodePacketType.LogMessage, LogMessagePacket.FactoryForDeserialization, loggingService as INodePacketHandler);
try
@@ -575,7 +575,11 @@ public BuildSubmission PendBuildRequest(BuildRequestData requestData)
public BuildResult BuildRequest(BuildRequestData requestData)
{
BuildSubmission submission = PendBuildRequest(requestData);
- return submission.Execute();
+ BuildResult result = submission.Execute();
+
+ SetOverallResultIfWarningsAsErrors(result);
+
+ return result;
}
///
@@ -621,6 +625,12 @@ public void EndBuild()
if (loggingService != null)
{
+ // Override the build success if the user specified /warnaserror and any errors were logged outside of a build submission.
+ if (_overallBuildSuccess && loggingService.HasBuildSubmissionLoggedErrors(BuildEventContext.InvalidSubmissionId))
+ {
+ _overallBuildSuccess = false;
+ }
+
loggingService.LogBuildFinished(_overallBuildSuccess);
}
@@ -1578,6 +1588,9 @@ private void ReportResultsToSubmission(BuildResult result)
if (_buildSubmissions.ContainsKey(result.SubmissionId))
{
BuildSubmission submission = _buildSubmissions[result.SubmissionId];
+
+ SetOverallResultIfWarningsAsErrors(result);
+
submission.CompleteResults(result);
// If the request failed because we caught an exception from the loggers, we can assume we will receive no more logging messages for
@@ -1723,7 +1736,7 @@ private void OnProjectStarted(object sender, ProjectStartedEventArgs e)
///
/// Creates a logging service around the specified set of loggers.
///
- private ILoggingService CreateLoggingService(IEnumerable loggers, IEnumerable forwardingLoggers)
+ private ILoggingService CreateLoggingService(IEnumerable loggers, IEnumerable forwardingLoggers, ISet warningsAsErrors)
{
int cpuCount = _buildParameters.MaxNodeCount;
@@ -1750,6 +1763,7 @@ private ILoggingService CreateLoggingService(IEnumerable loggers, IEnum
loggingService.OnLoggingThreadException += _loggingThreadExceptionEventHandler;
loggingService.OnProjectStarted += _projectStartedEventHandler;
loggingService.OnProjectFinished += _projectFinishedEventHandler;
+ loggingService.WarningsAsErrors = warningsAsErrors;
try
{
@@ -1820,6 +1834,23 @@ private I ExpectPacketType(INodePacket packet, NodePacketType expectedType) w
return castPacket;
}
+ ///
+ /// Sets the overall result of a build only if the user had specified /warnaserror and there were any errors.
+ /// This ensures the old behavior stays intact where builds could succeed even if a failure was logged.
+ ///
+ private void SetOverallResultIfWarningsAsErrors(BuildResult result)
+ {
+ if (result.OverallResult == BuildResultCode.Success)
+ {
+ ILoggingService loggingService = ((IBuildComponentHost)this).LoggingService;
+
+ if (loggingService.HasBuildSubmissionLoggedErrors(result.SubmissionId))
+ {
+ result.SetOverallResult(overallResult: false);
+ }
+ }
+ }
+
///
/// Shutdown the logging service
///
diff --git a/src/XMakeBuildEngine/BackEnd/BuildManager/BuildParameters.cs b/src/XMakeBuildEngine/BackEnd/BuildManager/BuildParameters.cs
index 3249229a840..34459823cfc 100644
--- a/src/XMakeBuildEngine/BackEnd/BuildManager/BuildParameters.cs
+++ b/src/XMakeBuildEngine/BackEnd/BuildManager/BuildParameters.cs
@@ -200,6 +200,11 @@ public class BuildParameters : INodePacketTranslatable
///
private bool _onlyLogCriticalEvents = false;
+ ///
+ /// A list of warnings to treat as errors.
+ ///
+ private ISet _warningsAsErrors = null;
+
///
/// The location of the toolset definitions.
///
@@ -320,6 +325,7 @@ private BuildParameters(BuildParameters other)
_disableInProcNode = other._disableInProcNode;
_logTaskInputs = other._logTaskInputs;
_logInitialPropertiesAndItems = other._logInitialPropertiesAndItems;
+ _warningsAsErrors = other._warningsAsErrors == null ? null : new HashSet(other._warningsAsErrors, StringComparer.OrdinalIgnoreCase);
}
#if FEATURE_THREAD_PRIORITY
@@ -583,6 +589,15 @@ public bool OnlyLogCriticalEvents
set { _onlyLogCriticalEvents = value; }
}
+ ///
+ /// A list of warnings to treat as errors. To treat all warnings as errors, set this to an empty .
+ ///
+ public ISet WarningsAsErrors
+ {
+ get { return _warningsAsErrors; }
+ set { _warningsAsErrors = value; }
+ }
+
///
/// Locations to search for toolsets.
///
diff --git a/src/XMakeBuildEngine/BackEnd/Components/Logging/BuildEventArgTransportSink.cs b/src/XMakeBuildEngine/BackEnd/Components/Logging/BuildEventArgTransportSink.cs
index 2305a0e6c55..bce7890e6de 100644
--- a/src/XMakeBuildEngine/BackEnd/Components/Logging/BuildEventArgTransportSink.cs
+++ b/src/XMakeBuildEngine/BackEnd/Components/Logging/BuildEventArgTransportSink.cs
@@ -81,6 +81,19 @@ public bool HaveLoggedBuildFinishedEvent
set;
}
+ ///
+ /// This property is ignored by this event sink and relies on the receiver to treat warnings as errors.
+ ///
+ public ISet WarningsAsErrors
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// This property is ignored by this event sink and relies on the receiver to keep track of whether or not any errors have been logged.
+ ///
+ public ISet BuildSubmissionIdsThatHaveLoggedErrors { get; } = null;
#endregion
#region IBuildEventSink Methods
diff --git a/src/XMakeBuildEngine/BackEnd/Components/Logging/EventSourceSink.cs b/src/XMakeBuildEngine/BackEnd/Components/Logging/EventSourceSink.cs
index 7b11f16d6d1..c023231b9bf 100644
--- a/src/XMakeBuildEngine/BackEnd/Components/Logging/EventSourceSink.cs
+++ b/src/XMakeBuildEngine/BackEnd/Components/Logging/EventSourceSink.cs
@@ -5,6 +5,7 @@
//-----------------------------------------------------------------------
using System;
+using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
@@ -129,6 +130,24 @@ public bool HaveLoggedBuildFinishedEvent
get;
set;
}
+
+ ///
+ /// A list of warnings to treat as errors. If null, nothing is treated as an error. If an empty set, all warnings are treated as errors.
+ ///
+ public ISet WarningsAsErrors
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// A list of build submission IDs that have logged errors. If an error is logged outside of a submission, the submission ID is .
+ ///
+ public ISet BuildSubmissionIdsThatHaveLoggedErrors
+ {
+ get;
+ } = new HashSet();
+
#endregion
#region Methods
@@ -203,7 +222,34 @@ public void Consume(BuildEventArgs buildEvent)
}
else if (buildEvent is BuildWarningEventArgs)
{
- this.RaiseWarningEvent(null, (BuildWarningEventArgs)buildEvent);
+ BuildWarningEventArgs warningEvent = (BuildWarningEventArgs) buildEvent;
+
+ // Treat this warning as an error if an empty set of warnings was specified or this code was specified
+ if (WarningsAsErrors != null && (WarningsAsErrors.Count == 0 || WarningsAsErrors.Contains(warningEvent.Code)))
+ {
+ BuildErrorEventArgs errorEvent = new BuildErrorEventArgs(
+ warningEvent.Subcategory,
+ warningEvent.Code,
+ warningEvent.File,
+ warningEvent.LineNumber,
+ warningEvent.ColumnNumber,
+ warningEvent.EndLineNumber,
+ warningEvent.EndColumnNumber,
+ warningEvent.Message,
+ warningEvent.HelpKeyword,
+ warningEvent.SenderName,
+ warningEvent.Timestamp)
+ {
+ BuildEventContext = warningEvent.BuildEventContext,
+ ProjectFile = warningEvent.ProjectFile,
+ };
+
+ this.RaiseErrorEvent(null, errorEvent);
+ }
+ else
+ {
+ this.RaiseWarningEvent(null, warningEvent);
+ }
}
else if (buildEvent is BuildErrorEventArgs)
{
@@ -308,6 +354,9 @@ private void RaiseMessageEvent(object sender, BuildMessageEventArgs buildEvent)
/// ExceptionHandling.IsCriticalException exceptions will not be wrapped
private void RaiseErrorEvent(object sender, BuildErrorEventArgs buildEvent)
{
+ // Keep track of build submissions that have logged errors. If there is no build context, add BuildEventContext.InvalidSubmissionId.
+ BuildSubmissionIdsThatHaveLoggedErrors.Add(buildEvent?.BuildEventContext?.SubmissionId ?? BuildEventContext.InvalidSubmissionId);
+
if (ErrorRaised != null)
{
try
diff --git a/src/XMakeBuildEngine/BackEnd/Components/Logging/ILoggingService.cs b/src/XMakeBuildEngine/BackEnd/Components/Logging/ILoggingService.cs
index 6aab65dfc10..9e4f0c1e068 100644
--- a/src/XMakeBuildEngine/BackEnd/Components/Logging/ILoggingService.cs
+++ b/src/XMakeBuildEngine/BackEnd/Components/Logging/ILoggingService.cs
@@ -153,8 +153,24 @@ bool RunningOnRemoteNode
get;
set;
}
+
+ ///
+ /// Set of warnings to treat as errors. An empty non-null set will treat all warnings as errors.
+ ///
+ ISet WarningsAsErrors
+ {
+ get;
+ set;
+ }
#endregion
+ ///
+ /// Determines if the specified submission has logged an errors.
+ ///
+ /// The ID of the build submission. A value of "0" means that an error was logged outside of any build submission.
+ /// true
if the build submission logged an errors, otherwise false
.
+ bool HasBuildSubmissionLoggedErrors(int submissionId);
+
#region Register
///
@@ -447,6 +463,20 @@ bool HaveLoggedBuildFinishedEvent
set;
}
+ ///
+ /// A list of warnings to treat as errors. If null, nothing is treated as an error. If an empty set, all warnings are treated as errors.
+ ///
+ ISet WarningsAsErrors
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// A list of build submissions that have logged errors.
+ ///
+ ISet BuildSubmissionIdsThatHaveLoggedErrors { get; }
+
#endregion
///
/// Entry point for a sink to consume an event.
@@ -461,7 +491,7 @@ bool HaveLoggedBuildFinishedEvent
void Consume(BuildEventArgs buildEvent);
///
- /// Shutsdown the sink and any resources it may be holding
+ /// Shuts down the sink and any resources it may be holding
///
void ShutDown();
}
diff --git a/src/XMakeBuildEngine/BackEnd/Components/Logging/LoggingService.cs b/src/XMakeBuildEngine/BackEnd/Components/Logging/LoggingService.cs
index 55d343b4f2f..0d0c55e08fd 100644
--- a/src/XMakeBuildEngine/BackEnd/Components/Logging/LoggingService.cs
+++ b/src/XMakeBuildEngine/BackEnd/Components/Logging/LoggingService.cs
@@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
@@ -218,6 +219,11 @@ internal partial class LoggingService : ILoggingService, INodePacketHandler, IBu
///
private LoggerMode _logMode = NativeMethodsShared.IsMono ? LoggerMode.Synchronous : LoggerMode.Asynchronous;
+ ///
+ /// A list of warnings to treat as errors.
+ ///
+ private ISet _warningsAsErrors = null;
+
#endregion
#endregion
@@ -444,6 +450,33 @@ public LoggerMode LoggingMode
}
}
+ ///
+ /// Get of warnings to treat as errors. An empty non-null set will treat all warnings as errors.
+ ///
+ public ISet WarningsAsErrors
+ {
+ get { return _warningsAsErrors; }
+ set { _warningsAsErrors = value; }
+ }
+
+ ///
+ /// Determines if the specified submission has logged an errors.
+ ///
+ /// The ID of the build submission. A value of "0" means that an error was logged outside of any build submission.
+ /// true
if the build submission logged an errors, otherwise false
.
+ public bool HasBuildSubmissionLoggedErrors(int submissionId)
+ {
+ // Warnings as errors are not tracked if the user did not specify to do so
+ if (WarningsAsErrors == null)
+ {
+ return false;
+ }
+
+ // Determine if any of the event sinks have logged an error with this submission ID
+ return (_filterEventSource != null && _filterEventSource.BuildSubmissionIdsThatHaveLoggedErrors.Contains(submissionId))
+ || (_eventSinkDictionary != null && _eventSinkDictionary.Values.Any(i => i.BuildSubmissionIdsThatHaveLoggedErrors.Contains(submissionId)));
+ }
+
///
/// Return whether or not the LoggingQueue has any events left in it
///
@@ -784,7 +817,10 @@ public bool RegisterDistributedLogger(ILogger centralLogger, LoggerDescription f
IForwardingLogger localForwardingLogger = null;
// create an eventSourceSink which the central logger will register with to receive the events from the forwarding logger
- EventSourceSink eventSourceSink = new EventSourceSink();
+ EventSourceSink eventSourceSink = new EventSourceSink
+ {
+ WarningsAsErrors = WarningsAsErrors == null ? null : new HashSet(WarningsAsErrors, StringComparer.OrdinalIgnoreCase)
+ };
// If the logger is already in the list it should not be registered again.
if (_iloggerList.Contains(centralLogger))
@@ -1096,8 +1132,11 @@ private void CreateFilterEventSource()
{
if (_filterEventSource == null)
{
- _filterEventSource = new EventSourceSink();
- _filterEventSource.Name = "Sink for Distributed/Filter loggers";
+ _filterEventSource = new EventSourceSink
+ {
+ Name = "Sink for Distributed/Filter loggers",
+ WarningsAsErrors = WarningsAsErrors == null ? null : new HashSet(WarningsAsErrors, StringComparer.OrdinalIgnoreCase)
+ };
}
}
diff --git a/src/XMakeBuildEngine/BackEnd/Shared/BuildResult.cs b/src/XMakeBuildEngine/BackEnd/Shared/BuildResult.cs
index a6fa40adb9f..318b4cd6011 100644
--- a/src/XMakeBuildEngine/BackEnd/Shared/BuildResult.cs
+++ b/src/XMakeBuildEngine/BackEnd/Shared/BuildResult.cs
@@ -639,6 +639,15 @@ internal BuildResult Clone()
return result;
}
+ ///
+ /// Sets the overall result.
+ ///
+ /// true
if the result is success, otherwise false
.
+ internal void SetOverallResult(bool overallResult)
+ {
+ _baseOverallResult = false;
+ }
+
///
/// Creates the target result dictionary.
///
diff --git a/src/XMakeBuildEngine/UnitTests/BackEnd/BuildManager_Tests.cs b/src/XMakeBuildEngine/UnitTests/BackEnd/BuildManager_Tests.cs
index d37f27e5d6d..2dc1be36d1d 100644
--- a/src/XMakeBuildEngine/UnitTests/BackEnd/BuildManager_Tests.cs
+++ b/src/XMakeBuildEngine/UnitTests/BackEnd/BuildManager_Tests.cs
@@ -3594,6 +3594,101 @@ public void Regress265010()
}
}
+ ///
+ /// Verifies that all warnings are treated as errors and that the overall build result is a failure.
+ ///
+ [Fact]
+ public void WarningsAreTreatedAsErrorsAll()
+ {
+ string contents = ObjectModelHelpers.CleanupFileContents(@"
+
+
+
+
+
+
+");
+ _parameters.WarningsAsErrors = new HashSet();
+
+ Project project = CreateProject(contents, ObjectModelHelpers.MSBuildDefaultToolsVersion, _projectCollection, true);
+ ProjectInstance instance = _buildManager.GetProjectInstanceForBuild(project);
+ _buildManager.BeginBuild(_parameters);
+ BuildResult result1 = _buildManager.BuildRequest(new BuildRequestData(instance, new string[] { "target1" }));
+ _buildManager.EndBuild();
+
+ Assert.Equal(0, _logger.WarningCount);
+ Assert.Equal(2, _logger.ErrorCount);
+
+ Assert.Equal(BuildResultCode.Failure, result1.OverallResult);
+ Assert.True(result1.HasResultsForTarget("target1"));
+ }
+
+ ///
+ /// Verifies that only the specified warnings are treated as errors and that the overall build result is a failure.
+ ///
+ [Fact]
+ public void WarningsAreTreatedAsErrorsSpecific()
+ {
+ string contents = ObjectModelHelpers.CleanupFileContents(@"
+
+
+
+
+
+
+
+");
+ _parameters.WarningsAsErrors = new HashSet { "ABC123" };
+
+ Project project = CreateProject(contents, ObjectModelHelpers.MSBuildDefaultToolsVersion, _projectCollection, true);
+ ProjectInstance instance = _buildManager.GetProjectInstanceForBuild(project);
+ _buildManager.BeginBuild(_parameters);
+ BuildResult result1 = _buildManager.BuildRequest(new BuildRequestData(instance, new string[] { "target1" }));
+ _buildManager.EndBuild();
+
+ Assert.Equal(2, _logger.WarningCount);
+ Assert.Equal(1, _logger.ErrorCount);
+
+ Assert.Equal(BuildResultCode.Failure, result1.OverallResult);
+ Assert.True(result1.HasResultsForTarget("target1"));
+ }
+
+ ///
+ /// Verifies that when building targets which emit warnings, they still show as succeeding but the overall build result is a failure.
+ ///
+ [Fact]
+ public void WarningsAreTreatedAsErrorsButTargetsStillSucceed()
+ {
+ string contents = ObjectModelHelpers.CleanupFileContents(@"
+
+
+
+
+
+
+
+
+");
+ _parameters.WarningsAsErrors = new HashSet { "ABC123" };
+
+ Project project = CreateProject(contents, ObjectModelHelpers.MSBuildDefaultToolsVersion, _projectCollection, true);
+ ProjectInstance instance = _buildManager.GetProjectInstanceForBuild(project);
+ _buildManager.BeginBuild(_parameters);
+ BuildResult buildResult = _buildManager.BuildRequest(new BuildRequestData(instance, new string[] { "target1", "target2" }));
+ _buildManager.EndBuild();
+
+ Assert.Equal(0, _logger.WarningCount);
+ Assert.Equal(1, _logger.ErrorCount);
+
+ Assert.Equal(BuildResultCode.Failure, buildResult.OverallResult);
+ Assert.True(buildResult.HasResultsForTarget("target1"));
+ Assert.True(buildResult.HasResultsForTarget("target2"));
+ // The two targets should still show as success because they don't know their warning was changed to an error
+ // Logging a warning as an error does not change execution, only the final result of the build
+ Assert.Equal(TargetResultCode.Success, buildResult.ResultsByTarget["target1"].ResultCode);
+ Assert.Equal(TargetResultCode.Success, buildResult.ResultsByTarget["target2"].ResultCode);
+ }
+
///
/// Helper for cache tests. Builds a project and verifies the right cache files are created.
///
diff --git a/src/XMakeBuildEngine/UnitTests/BackEnd/EventSourceSink_Tests.cs b/src/XMakeBuildEngine/UnitTests/BackEnd/EventSourceSink_Tests.cs
index 553eecaa7af..58ad2633ffc 100644
--- a/src/XMakeBuildEngine/UnitTests/BackEnd/EventSourceSink_Tests.cs
+++ b/src/XMakeBuildEngine/UnitTests/BackEnd/EventSourceSink_Tests.cs
@@ -83,6 +83,93 @@ public void ConsumeEventsGoodEventsNoHandlers()
eventHelper.RaiseBuildEvent(RaiseEventHelper.GenericStatusEvent);
}
+ ///
+ /// Verifies that a warning is logged as an error when it's warning code specified.
+ ///
+ [Fact]
+ public void TreatWarningsAsErrorWhenSpecified()
+ {
+ BuildWarningEventArgs expectedBuildEvent = RaiseEventHelper.Warning;
+
+ EventSourceSink eventSourceSink = new EventSourceSink()
+ {
+ WarningsAsErrors = new HashSet
+ {
+ "123",
+ expectedBuildEvent.Code,
+ "ABC",
+ },
+ };
+
+ RaiseEventHelper raiseEventHelper = new RaiseEventHelper(eventSourceSink);
+ EventHandlerHelper eventHandlerHelper = new EventHandlerHelper(eventSourceSink, null);
+
+ raiseEventHelper.RaiseBuildEvent(RaiseEventHelper.Warning);
+
+ Assert.IsType(eventHandlerHelper.RaisedEvent);
+
+ BuildErrorEventArgs actualBuildEvent = (BuildErrorEventArgs) eventHandlerHelper.RaisedEvent;
+
+ Assert.Equal(expectedBuildEvent.Code, actualBuildEvent.Code);
+ Assert.Equal(expectedBuildEvent.File, actualBuildEvent.File);
+ Assert.Equal(expectedBuildEvent.ProjectFile, actualBuildEvent.ProjectFile);
+ Assert.Equal(expectedBuildEvent.Subcategory, actualBuildEvent.Subcategory);
+ Assert.Equal(expectedBuildEvent.HelpKeyword, actualBuildEvent.HelpKeyword);
+ Assert.Equal(expectedBuildEvent.Message, actualBuildEvent.Message);
+ Assert.Equal(expectedBuildEvent.SenderName, actualBuildEvent.SenderName);
+ Assert.Equal(expectedBuildEvent.ColumnNumber, actualBuildEvent.ColumnNumber);
+ Assert.Equal(expectedBuildEvent.EndColumnNumber, actualBuildEvent.EndColumnNumber);
+ Assert.Equal(expectedBuildEvent.EndLineNumber, actualBuildEvent.EndLineNumber);
+ Assert.Equal(expectedBuildEvent.LineNumber, actualBuildEvent.LineNumber);
+ Assert.Equal(expectedBuildEvent.BuildEventContext, actualBuildEvent.BuildEventContext);
+ Assert.Equal(expectedBuildEvent.ThreadId, actualBuildEvent.ThreadId);
+ Assert.Equal(expectedBuildEvent.Timestamp, actualBuildEvent.Timestamp);
+ }
+
+ ///
+ /// Verifies that a warning is not treated as an error when other warning codes are specified.
+ ///
+ [Fact]
+ public void NotTreatWarningsAsErrorWhenNotSpecified()
+ {
+ BuildWarningEventArgs expectedBuildEvent = RaiseEventHelper.Warning;
+
+ EventSourceSink eventSourceSink = new EventSourceSink()
+ {
+ WarningsAsErrors = new HashSet
+ {
+ "123",
+ "ABC",
+ },
+ };
+
+ RaiseEventHelper raiseEventHelper = new RaiseEventHelper(eventSourceSink);
+ EventHandlerHelper eventHandlerHelper = new EventHandlerHelper(eventSourceSink, null);
+
+ raiseEventHelper.RaiseBuildEvent(RaiseEventHelper.Warning);
+
+ Assert.Equal(expectedBuildEvent, eventHandlerHelper.RaisedEvent);
+ }
+
+ ///
+ /// Verifies that a warning is not treated as an error when other warning codes are specified.
+ ///
+ [Fact]
+ public void TreatWarningsAsErrorWhenAllSpecified()
+ {
+ EventSourceSink eventSourceSink = new EventSourceSink()
+ {
+ WarningsAsErrors = new HashSet(),
+ };
+
+ RaiseEventHelper raiseEventHelper = new RaiseEventHelper(eventSourceSink);
+ EventHandlerHelper eventHandlerHelper = new EventHandlerHelper(eventSourceSink, null);
+
+ raiseEventHelper.RaiseBuildEvent(RaiseEventHelper.Warning);
+
+ Assert.IsType(eventHandlerHelper.RaisedEvent);
+ }
+
#region TestsThrowingLoggingExceptions
///
diff --git a/src/XMakeBuildEngine/UnitTests/BackEnd/MockLoggingService.cs b/src/XMakeBuildEngine/UnitTests/BackEnd/MockLoggingService.cs
index 7ec91aa0fa6..c3559fac92b 100644
--- a/src/XMakeBuildEngine/UnitTests/BackEnd/MockLoggingService.cs
+++ b/src/XMakeBuildEngine/UnitTests/BackEnd/MockLoggingService.cs
@@ -147,6 +147,16 @@ public string[] PropertiesToSerialize
set;
}
+ ///
+ /// List of warnings to treat as errors.
+ ///
+ public ISet WarningsAsErrors
+ {
+ get;
+ set;
+ }
+
+
///
/// Is the logging service on a remote node, this is used to determine if properties need to be serialized
///
@@ -475,6 +485,11 @@ public void LogTelemetry(BuildEventContext buildEventContext, string eventName,
{
}
+ public bool HasBuildSubmissionLoggedErrors(int submissionId)
+ {
+ return false;
+ }
+
#endregion
}
}
diff --git a/src/XMakeCommandLine/CommandLineSwitches.cs b/src/XMakeCommandLine/CommandLineSwitches.cs
index 8dba43b5e11..be2786a7d77 100644
--- a/src/XMakeCommandLine/CommandLineSwitches.cs
+++ b/src/XMakeCommandLine/CommandLineSwitches.cs
@@ -102,6 +102,7 @@ internal enum ParameterizedSwitch
ClientToServerPipeHandle,
ServerToClientPipeHandle,
#endif
+ WarningsAsErrors,
NumberOfParameterizedSwitches
}
@@ -171,7 +172,8 @@ internal ParameterizedSwitchInfo
string duplicateSwitchErrorMessage,
bool multipleParametersAllowed,
string missingParametersErrorMessage,
- bool unquoteParameters
+ bool unquoteParameters,
+ bool emptyParametersAllowed
)
{
this.switchNames = switchNames;
@@ -180,6 +182,7 @@ bool unquoteParameters
this.missingParametersErrorMessage = missingParametersErrorMessage;
this.unquoteParameters = unquoteParameters;
this.parameterizedSwitch = parameterizedSwitch;
+ this.emptyParametersAllowed = emptyParametersAllowed;
}
// names of the switch (without leading switch indicator)
@@ -198,6 +201,8 @@ bool unquoteParameters
internal bool unquoteParameters;
// the switch id
internal ParameterizedSwitch parameterizedSwitch;
+ // indicates if empty parameters are allowed and if so an empty string will be added to the list of parameter values
+ internal bool emptyParametersAllowed;
}
@@ -240,41 +245,42 @@ bool unquoteParameters
// WARNING: keep this map in the same order as the ParameterizedSwitch enumeration
private static readonly ParameterizedSwitchInfo[] s_parameterizedSwitchesMap =
{
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Switch Names Switch Id Duplicate Switch Error Multi Params? Missing Parameters Error Unquote?
- //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- new ParameterizedSwitchInfo( new string[] { null }, ParameterizedSwitch.Project, "DuplicateProjectSwitchError", false, null, true ),
- new ParameterizedSwitchInfo( new string[] { "target", "t"}, ParameterizedSwitch.Target, null, true, "MissingTargetError", true ),
- new ParameterizedSwitchInfo( new string[] { "property", "p" }, ParameterizedSwitch.Property, null, true, "MissingPropertyError", true ),
- new ParameterizedSwitchInfo( new string[] { "logger", "l" }, ParameterizedSwitch.Logger, null, false, "MissingLoggerError", false ),
- new ParameterizedSwitchInfo( new string[] { "distributedlogger", "dl" }, ParameterizedSwitch.DistributedLogger, null, false, "MissingLoggerError", false ),
- new ParameterizedSwitchInfo( new string[] { "verbosity", "v" }, ParameterizedSwitch.Verbosity, null, false, "MissingVerbosityError", true ),
+ //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ // Switch Names Switch Id Duplicate Switch Error Multi Params? Missing Parameters Error Unquote? Empty?
+ //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ new ParameterizedSwitchInfo( new string[] { null }, ParameterizedSwitch.Project, "DuplicateProjectSwitchError", false, null, true, false ),
+ new ParameterizedSwitchInfo( new string[] { "target", "t"}, ParameterizedSwitch.Target, null, true, "MissingTargetError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "property", "p" }, ParameterizedSwitch.Property, null, true, "MissingPropertyError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "logger", "l" }, ParameterizedSwitch.Logger, null, false, "MissingLoggerError", false, false ),
+ new ParameterizedSwitchInfo( new string[] { "distributedlogger", "dl" }, ParameterizedSwitch.DistributedLogger, null, false, "MissingLoggerError", false, false ),
+ new ParameterizedSwitchInfo( new string[] { "verbosity", "v" }, ParameterizedSwitch.Verbosity, null, false, "MissingVerbosityError", true, false ),
#if FEATURE_XML_SCHEMA_VALIDATION
- new ParameterizedSwitchInfo( new string[] { "validate", "val" }, ParameterizedSwitch.Validate, null, false, null, true ),
+ new ParameterizedSwitchInfo( new string[] { "validate", "val" }, ParameterizedSwitch.Validate, null, false, null, true, false ),
#endif
- new ParameterizedSwitchInfo( new string[] { "consoleloggerparameters", "clp" }, ParameterizedSwitch.ConsoleLoggerParameters, null, false, "MissingConsoleLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "nodemode", "nmode" }, ParameterizedSwitch.NodeMode, null, false, null, false ),
- new ParameterizedSwitchInfo( new string[] { "maxcpucount", "m" }, ParameterizedSwitch.MaxCPUCount, null, false, "MissingMaxCPUCountError", true ),
- new ParameterizedSwitchInfo( new string[] { "ignoreprojectextensions", "ignore" }, ParameterizedSwitch.IgnoreProjectExtensions, null, true, "MissingIgnoreProjectExtensionsError", true ),
- new ParameterizedSwitchInfo( new string[] { "toolsversion","tv" }, ParameterizedSwitch.ToolsVersion, null, false, "MissingToolsVersionError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters", "flp" }, ParameterizedSwitch.FileLoggerParameters, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters1", "flp1" }, ParameterizedSwitch.FileLoggerParameters1, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters2", "flp2" }, ParameterizedSwitch.FileLoggerParameters2, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters3", "flp3" }, ParameterizedSwitch.FileLoggerParameters3, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters4", "flp4" }, ParameterizedSwitch.FileLoggerParameters4, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters5", "flp5" }, ParameterizedSwitch.FileLoggerParameters5, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters6", "flp6" }, ParameterizedSwitch.FileLoggerParameters6, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters7", "flp7" }, ParameterizedSwitch.FileLoggerParameters7, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters8", "flp8" }, ParameterizedSwitch.FileLoggerParameters8, null, false, "MissingFileLoggerParameterError", true ),
- new ParameterizedSwitchInfo( new string[] { "fileloggerparameters9", "flp9" }, ParameterizedSwitch.FileLoggerParameters9, null, false, "MissingFileLoggerParameterError", true ),
+ new ParameterizedSwitchInfo( new string[] { "consoleloggerparameters", "clp" }, ParameterizedSwitch.ConsoleLoggerParameters, null, false, "MissingConsoleLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "nodemode", "nmode" }, ParameterizedSwitch.NodeMode, null, false, null, false, false ),
+ new ParameterizedSwitchInfo( new string[] { "maxcpucount", "m" }, ParameterizedSwitch.MaxCPUCount, null, false, "MissingMaxCPUCountError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "ignoreprojectextensions", "ignore" }, ParameterizedSwitch.IgnoreProjectExtensions, null, true, "MissingIgnoreProjectExtensionsError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "toolsversion","tv" }, ParameterizedSwitch.ToolsVersion, null, false, "MissingToolsVersionError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters", "flp" }, ParameterizedSwitch.FileLoggerParameters, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters1", "flp1" }, ParameterizedSwitch.FileLoggerParameters1, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters2", "flp2" }, ParameterizedSwitch.FileLoggerParameters2, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters3", "flp3" }, ParameterizedSwitch.FileLoggerParameters3, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters4", "flp4" }, ParameterizedSwitch.FileLoggerParameters4, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters5", "flp5" }, ParameterizedSwitch.FileLoggerParameters5, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters6", "flp6" }, ParameterizedSwitch.FileLoggerParameters6, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters7", "flp7" }, ParameterizedSwitch.FileLoggerParameters7, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters8", "flp8" }, ParameterizedSwitch.FileLoggerParameters8, null, false, "MissingFileLoggerParameterError", true, false ),
+ new ParameterizedSwitchInfo( new string[] { "fileloggerparameters9", "flp9" }, ParameterizedSwitch.FileLoggerParameters9, null, false, "MissingFileLoggerParameterError", true, false ),
#if FEATURE_NODE_REUSE
- new ParameterizedSwitchInfo( new string[] { "nodereuse", "nr" }, ParameterizedSwitch.NodeReuse, null, false, "MissingNodeReuseParameterError", true ),
+ new ParameterizedSwitchInfo( new string[] { "nodereuse", "nr" }, ParameterizedSwitch.NodeReuse, null, false, "MissingNodeReuseParameterError", true, false ),
#endif
- new ParameterizedSwitchInfo( new string[] { "preprocess", "pp" }, ParameterizedSwitch.Preprocess, null, false, null, true ),
+ new ParameterizedSwitchInfo( new string[] { "preprocess", "pp" }, ParameterizedSwitch.Preprocess, null, false, null, true, false ),
#if !FEATURE_NAMED_PIPES_FULL_DUPLEX
- new ParameterizedSwitchInfo( new string[] { "clientToServerPipeHandle", "c2s" }, ParameterizedSwitch.ClientToServerPipeHandle, null, false, null, true ),
- new ParameterizedSwitchInfo( new string[] { "serverToClientPipeHandle", "s2c" }, ParameterizedSwitch.ServerToClientPipeHandle, null, false, null, true )
+ new ParameterizedSwitchInfo( new string[] { "clientToServerPipeHandle", "c2s" }, ParameterizedSwitch.ClientToServerPipeHandle, null, false, null, true, false ),
+ new ParameterizedSwitchInfo( new string[] { "serverToClientPipeHandle", "s2c" }, ParameterizedSwitch.ServerToClientPipeHandle, null, false, null, true, false ),
#endif
+ new ParameterizedSwitchInfo( new string[] { "warnaserror", "err" }, ParameterizedSwitch.WarningsAsErrors, null, true, null, true, true ),
};
///
@@ -343,7 +349,8 @@ internal static bool IsParameterizedSwitch
out string duplicateSwitchErrorMessage,
out bool multipleParametersAllowed,
out string missingParametersErrorMessage,
- out bool unquoteParameters
+ out bool unquoteParameters,
+ out bool emptyParametersAllowed
)
{
parameterizedSwitch = ParameterizedSwitch.Invalid;
@@ -351,6 +358,7 @@ out bool unquoteParameters
multipleParametersAllowed = false;
missingParametersErrorMessage = null;
unquoteParameters = false;
+ emptyParametersAllowed = false;
foreach (ParameterizedSwitchInfo switchInfo in s_parameterizedSwitchesMap)
{
@@ -363,6 +371,7 @@ out bool unquoteParameters
multipleParametersAllowed = switchInfo.multipleParametersAllowed;
missingParametersErrorMessage = switchInfo.missingParametersErrorMessage;
unquoteParameters = switchInfo.unquoteParameters;
+ emptyParametersAllowed = switchInfo.emptyParametersAllowed;
break;
}
}
@@ -454,7 +463,8 @@ internal bool SetParameterizedSwitch
string commandLineArg,
string switchParameters,
bool multipleParametersAllowed,
- bool unquoteParameters
+ bool unquoteParameters,
+ bool emptyParametersAllowed
)
{
bool parametersStored = false;
@@ -481,12 +491,22 @@ bool unquoteParameters
// check if the switch has multiple parameters
if (multipleParametersAllowed)
{
- // store all the switch parameters
- int emptyParameters;
- _parameterizedSwitches[(int)parameterizedSwitch].parameters.AddRange(QuotingUtilities.SplitUnquoted(switchParameters, int.MaxValue, false /* discard empty parameters */, unquoteParameters, out emptyParameters, s_parameterSeparators));
+ if (String.Empty.Equals(switchParameters) && emptyParametersAllowed)
+ {
+ // Store a null parameter if its allowed
+ _parameterizedSwitches[(int) parameterizedSwitch].parameters.Add(null);
+ parametersStored = true;
+ }
+ else
+ {
+ // store all the switch parameters
+ int emptyParameters;
+ _parameterizedSwitches[(int)parameterizedSwitch].parameters.AddRange(QuotingUtilities.SplitUnquoted(switchParameters, int.MaxValue, false /* discard empty parameters */, unquoteParameters, out emptyParameters, s_parameterSeparators));
- // check if they were all stored successfully i.e. they were all non-empty (after removing quoting, if requested)
- parametersStored = (emptyParameters == 0);
+ // check if they were all stored successfully i.e. they were all non-empty (after removing quoting, if requested)
+ parametersStored = (emptyParameters == 0);
+ }
+
}
else
{
diff --git a/src/XMakeCommandLine/Resources/Strings.resx b/src/XMakeCommandLine/Resources/Strings.resx
index a4740198870..18bbfd134f7 100644
--- a/src/XMakeCommandLine/Resources/Strings.resx
+++ b/src/XMakeCommandLine/Resources/Strings.resx
@@ -586,6 +586,25 @@ Copyright (C) Microsoft Corporation. All rights reserved.
MSBuild XML and any tasks and loggers it uses.
+
+ /warnaserror[:code[;code2]]
+ List of warning codes to treats as errors. Use a semicolon
+ or a comma to separate multiple warning codes. To treat all
+ warnings as errors use the switch with no values.
+ (Short form: /err[:c;[c2]])
+
+ Example:
+ /warnaserror:MSB4130
+
+ When a warning is treated as an error the target will
+ continue to execute as if it was a warning but the overall
+ build will fail.
+
+
+ LOCALIZATION: "warnaserror" should not be localized.
+ LOCALIZATION: None of the lines should be longer than a standard width console window, eg 80 chars.
+
+
MSBUILD : Configuration error MSB1043: The application could not start. {0}
diff --git a/src/XMakeCommandLine/UnitTests/CommandLineSwitches_Tests.cs b/src/XMakeCommandLine/UnitTests/CommandLineSwitches_Tests.cs
index a138a7d9531..60bc3af5ee2 100644
--- a/src/XMakeCommandLine/UnitTests/CommandLineSwitches_Tests.cs
+++ b/src/XMakeCommandLine/UnitTests/CommandLineSwitches_Tests.cs
@@ -4,8 +4,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
-
+using System.Linq;
+using System.Resources;
using Microsoft.Build.CommandLine;
using Microsoft.Build.Construction;
using Microsoft.Build.Framework;
@@ -36,8 +38,9 @@ public void BogusSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.False(CommandLineSwitches.IsParameterizedSwitch("bogus", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.False(CommandLineSwitches.IsParameterizedSwitch("bogus", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Invalid, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -250,29 +253,30 @@ public void FileLoggerParametersIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("flp", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("flp", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.FileLoggerParameters, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("FLP", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("FLP", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.FileLoggerParameters, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("fileLoggerParameters", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("fileLoggerParameters", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.FileLoggerParameters, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("FILELOGGERPARAMETERS", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("FILELOGGERPARAMETERS", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.FileLoggerParameters, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -289,29 +293,30 @@ public void NodeReuseParametersIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("nr", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("nr", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.NodeReuse, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("NR", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("NR", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.NodeReuse, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("nodereuse", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("nodereuse", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.NodeReuse, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("NodeReuse", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("NodeReuse", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.NodeReuse, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -328,8 +333,9 @@ public void ProjectSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch(null, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch(null, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Project, parameterizedSwitch);
Assert.NotNull(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -337,7 +343,7 @@ public void ProjectSwitchIdentificationTests()
Assert.True(unquoteParameters);
// for the virtual project switch, we match on null, not empty string
- Assert.False(CommandLineSwitches.IsParameterizedSwitch(String.Empty, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.False(CommandLineSwitches.IsParameterizedSwitch(String.Empty, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Invalid, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -353,36 +359,37 @@ public void IgnoreProjectExtensionsSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("ignoreprojectextensions", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("ignoreprojectextensions", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("IgnoreProjectExtensions", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("IgnoreProjectExtensions", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("IGNOREPROJECTEXTENSIONS", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("IGNOREPROJECTEXTENSIONS", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("ignore", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("ignore", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("IGNORE", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("IGNORE", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.IgnoreProjectExtensions, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
@@ -398,36 +405,37 @@ public void TargetSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("target", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("target", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Target, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("TARGET", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("TARGET", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Target, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("Target", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("Target", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Target, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("t", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("t", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Target, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("T", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("T", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Target, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
@@ -443,36 +451,37 @@ public void PropertySwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("property", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("property", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Property, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("PROPERTY", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("PROPERTY", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Property, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("Property", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("Property", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Property, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("p", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("p", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Property, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("P", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("P", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Property, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.True(multipleParametersAllowed);
@@ -488,36 +497,37 @@ public void LoggerSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("logger", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("logger", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Logger, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.False(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("LOGGER", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("LOGGER", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Logger, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.False(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("Logger", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("Logger", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Logger, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.False(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("l", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("l", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Logger, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.False(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("L", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("L", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Logger, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -533,36 +543,37 @@ public void VerbositySwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("verbosity", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("verbosity", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Verbosity, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("VERBOSITY", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("VERBOSITY", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Verbosity, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("Verbosity", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("Verbosity", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Verbosity, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("v", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("v", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Verbosity, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("V", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("V", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Verbosity, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -608,29 +619,30 @@ public void MaxCPUCountSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("m", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("m", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.MaxCPUCount, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("M", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("M", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.MaxCPUCount, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("maxcpucount", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("maxcpucount", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.MaxCPUCount, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.NotNull(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("MAXCPUCOUNT", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("MAXCPUCOUNT", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.MaxCPUCount, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -647,43 +659,44 @@ public void ValidateSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("validate", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("validate", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Validate, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.Null(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("VALIDATE", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("VALIDATE", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Validate, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.Null(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("Validate", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("Validate", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Validate, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.Null(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("val", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("val", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Validate, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.Null(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("VAL", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("VAL", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Validate, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.Null(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("Val", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("Val", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Validate, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -700,15 +713,16 @@ public void PreprocessSwitchIdentificationTests()
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool emptyParametersAllowed;
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("preprocess", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("preprocess", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Preprocess, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
Assert.Null(missingParametersErrorMessage);
Assert.True(unquoteParameters);
- Assert.True(CommandLineSwitches.IsParameterizedSwitch("pp", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters));
+ Assert.True(CommandLineSwitches.IsParameterizedSwitch("pp", out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out emptyParametersAllowed));
Assert.Equal(CommandLineSwitches.ParameterizedSwitch.Preprocess, parameterizedSwitch);
Assert.Null(duplicateSwitchErrorMessage);
Assert.False(multipleParametersAllowed);
@@ -745,7 +759,7 @@ public void SetParameterizedSwitchTests1()
{
CommandLineSwitches switches = new CommandLineSwitches();
- Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true));
+ Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true, false));
Assert.Equal("/v:q", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Verbosity));
Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Verbosity));
@@ -758,7 +772,7 @@ public void SetParameterizedSwitchTests1()
// 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.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/verbosity:\"diag\";minimal", "\"diag\";minimal", true, true, false));
Assert.Equal("/v:q /verbosity:\"diag\";minimal", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Verbosity));
Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Verbosity));
@@ -788,7 +802,7 @@ public void SetParameterizedSwitchTests2()
// 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));
+ Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"", "\"", false, true, false));
// switch has been set
Assert.Equal("/t:\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
@@ -801,7 +815,7 @@ public void SetParameterizedSwitchTests2()
Assert.Equal(0, parameters.Length);
// more fake/missing parameters
- Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:A,\"\";B", "A,\"\";B", true, true));
+ Assert.False(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:A,\"\";B", "A,\"\";B", true, true, false));
Assert.Equal("/t:\" /t:A,\"\";B", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Target));
Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
@@ -830,7 +844,7 @@ public void SetParameterizedSwitchTests3()
Assert.Equal(0, parameters.Length);
// don't unquote fake/missing parameters
- Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/l:\"", "\"", false, false));
+ Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/l:\"", "\"", false, false, false));
Assert.Equal("/l:\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));
@@ -843,7 +857,7 @@ public void SetParameterizedSwitchTests3()
// 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.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Logger, "/LOGGER:\"\",asm;\"p,a;r\"", "\"\",asm;\"p,a;r\"", true, false, false));
Assert.Equal("/l:\" /LOGGER:\"\",asm;\"p,a;r\"", switches.GetParameterizedSwitchCommandLineArg(CommandLineSwitches.ParameterizedSwitch.Logger));
Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Logger));
@@ -858,6 +872,24 @@ public void SetParameterizedSwitchTests3()
Assert.Equal("\"p,a;r\"", parameters[3]);
}
+ [Fact]
+ public void SetParameterizedSwitchTestsAllowEmpty()
+ {
+ CommandLineSwitches switches = new CommandLineSwitches();
+
+ Assert.True(switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors, "/warnaserror", "", multipleParametersAllowed: true, unquoteParameters: false, emptyParametersAllowed: true));
+
+ Assert.True(switches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors));
+
+ string[] parameters = switches[CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors];
+
+ Assert.NotNull(parameters);
+
+ Assert.True(parameters.Length > 0);
+
+ Assert.Null(parameters.Last());
+ }
+
[Fact]
public void AppendErrorTests1()
{
@@ -970,14 +1002,14 @@ public void AppendParameterizedSwitchesTests1()
{
CommandLineSwitches switchesLeft = new CommandLineSwitches();
- switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true);
+ switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true, false);
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);
+ switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:build", "build", true, true, false);
Assert.False(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
@@ -1008,13 +1040,13 @@ public void AppendParameterizedSwitchesTests2()
{
CommandLineSwitches switchesLeft = new CommandLineSwitches();
- switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/target:Clean", "Clean", true, true);
+ switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/target:Clean", "Clean", true, true, false);
Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
CommandLineSwitches switchesRight = new CommandLineSwitches();
- switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"RESOURCES\";build", "\"RESOURCES\";build", true, true);
+ switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Target, "/t:\"RESOURCES\";build", "\"RESOURCES\";build", true, true, false);
Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Target));
@@ -1037,13 +1069,13 @@ public void AppendParameterizedSwitchesTests3()
{
CommandLineSwitches switchesLeft = new CommandLineSwitches();
- switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true);
+ switchesLeft.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "tempproject.proj", "tempproject.proj", false, true, false);
Assert.True(switchesLeft.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
CommandLineSwitches switchesRight = new CommandLineSwitches();
- switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "Rhubarb.proj", "Rhubarb.proj", false, true);
+ switchesRight.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Project, "Rhubarb.proj", "Rhubarb.proj", false, true, false);
Assert.True(switchesRight.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.Project));
@@ -1090,7 +1122,8 @@ public void InvalidToolsVersionErrors()
true,
new StringWriter(),
false,
- false);
+ false,
+ warningsAsErrors: null);
}
finally
{
@@ -1105,7 +1138,7 @@ public void TestHaveAnySwitchesBeenSet()
// Check if method works with parameterized switch
CommandLineSwitches switches = new CommandLineSwitches();
Assert.False(switches.HaveAnySwitchesBeenSet());
- switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true);
+ switches.SetParameterizedSwitch(CommandLineSwitches.ParameterizedSwitch.Verbosity, "/v:q", "q", false, true, false);
Assert.True(switches.HaveAnySwitchesBeenSet());
// Check if method works with parameterless switches
@@ -1152,6 +1185,173 @@ public void ExtractAnyLoggerParameterPickLast()
Assert.Equal("v=q", result);
}
+ ///
+ /// Verifies that when the /warnaserror switch is not specified, the set of warnings is null.
+ ///
+ [Fact]
+ public void ProcessWarnAsErrorSwitchNotSpecified()
+ {
+ CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
+
+ MSBuildApp.GatherCommandLineSwitches(new ArrayList(new[] { "" }), commandLineSwitches);
+
+ Assert.Null(MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches));
+ }
+
+ ///
+ /// Verifies that the /warnaserror switch is parsed properly when codes are specified.
+ ///
+ [Fact]
+ public void ProcessWarnAsErrorSwitchWithCodes()
+ {
+ ISet expectedWarningsAsErors = new HashSet(StringComparer.OrdinalIgnoreCase) { "a", "B", "c", "D", "e" };
+
+ CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
+
+ MSBuildApp.GatherCommandLineSwitches(new ArrayList(new[]
+ {
+ "\"/warnaserror: a,B ; c \"", // Leading, trailing, leading and trailing whitespace
+ "/warnaserror:A,b,C", // Repeats of different case
+ "\"/warnaserror:, ,,\"", // Empty items
+ "/err:D,d;E,e", // A different source with new items and uses the short form
+ "/warnaserror:a", // A different source with a single duplicate
+ "/warnaserror:a,b", // A different source with multiple duplicates
+ }), commandLineSwitches);
+
+ ISet actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
+
+ Assert.NotNull(actualWarningsAsErrors);
+
+ Assert.Equal(expectedWarningsAsErors, actualWarningsAsErrors, StringComparer.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Verifies that an empty /warnaserror switch clears the list of codes.
+ ///
+ [Fact]
+ public void ProcessWarnAsErrorSwitchEmptySwitchClearsSet()
+ {
+ CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
+
+ MSBuildApp.GatherCommandLineSwitches(new ArrayList(new[]
+ {
+ "/warnaserror:a;b;c",
+ "/warnaserror",
+ }), commandLineSwitches);
+
+ ISet actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
+
+ Assert.NotNull(actualWarningsAsErrors);
+
+ Assert.Equal(0, actualWarningsAsErrors.Count);
+ }
+
+ ///
+ /// Verifies that when values are specified after an empty /warnaserror switch that they are added to the cleared list.
+ ///
+ [Fact]
+ public void ProcessWarnAsErrorSwitchValuesAfterEmptyAddOn()
+ {
+ ISet expectedWarningsAsErors = new HashSet(StringComparer.OrdinalIgnoreCase) { "e", "f", "g" };
+
+ CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
+
+ MSBuildApp.GatherCommandLineSwitches(new ArrayList(new[]
+ {
+ "/warnaserror:a;b;c",
+ "/warnaserror",
+ "/warnaserror:e;f;g",
+ }), commandLineSwitches);
+
+ ISet actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
+
+ Assert.NotNull(actualWarningsAsErrors);
+
+ Assert.Equal(expectedWarningsAsErors, actualWarningsAsErrors, StringComparer.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Verifies that the /warnaserror switch is parsed properly when no codes are specified.
+ ///
+ [Fact]
+ public void ProcessWarnAsErrorSwitchEmpty()
+ {
+ CommandLineSwitches commandLineSwitches = new CommandLineSwitches();
+
+ MSBuildApp.GatherCommandLineSwitches(new ArrayList(new [] { "/warnaserror" }), commandLineSwitches);
+
+ ISet actualWarningsAsErrors = MSBuildApp.ProcessWarnAsErrorSwitch(commandLineSwitches);
+
+ Assert.NotNull(actualWarningsAsErrors);
+
+ Assert.Equal(0, actualWarningsAsErrors.Count);
+ }
+
+#if FEATURE_RESOURCEMANAGER_GETRESOURCESET
+ ///
+ /// Verifies that help messages are correctly formed with the right width and leading spaces.
+ ///
+ [Fact]
+ public void HelpMessagesAreValid()
+ {
+ ResourceManager resourceManager = new ResourceManager("MSBuild.Strings", typeof(AssemblyResources).Assembly);
+
+ const string switchLeadingSpaces = " ";
+ const string otherLineLeadingSpaces = " ";
+ const string examplesLeadingSpaces = " ";
+
+ foreach (KeyValuePair item in resourceManager.GetResourceSet(CultureInfo.CurrentUICulture, createIfNotExists: true, tryParents: true)
+ .Cast().Where(i => i.Key is string && ((string)i.Key).StartsWith("HelpMessage_"))
+ .Select(i => new KeyValuePair((string)i.Key, (string)i.Value)))
+ {
+ string[] helpMessageLines = item.Value.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
+
+ for (int i = 0; i < helpMessageLines.Length; i++)
+ {
+ // All lines should be 80 characters or less
+ Assert.True(helpMessageLines[i].Length <= 80, $"Line {i + 1} of '{item.Key}' should be no longer than 80 characters.");
+
+ if (i == 0)
+ {
+ if (helpMessageLines[i].Trim().StartsWith("/") || helpMessageLines[i].Trim().StartsWith("@"))
+ {
+ // If the first line in a switch it needs a certain amount of leading spaces
+ Assert.True(helpMessageLines[i].StartsWith(switchLeadingSpaces), $"Line {i + 1} of '{item.Key}' should start with '{switchLeadingSpaces}'.");
+ }
+ else
+ {
+ // Otherwise it should have no leading spaces because it's a section
+ Assert.False(helpMessageLines[i].StartsWith(" "), $"Line {i + 1} of '{item.Key}' should not have any leading spaces.");
+ }
+ }
+ else
+ {
+ // Ignore empty lines
+ if (!String.IsNullOrWhiteSpace(helpMessageLines[i]))
+ {
+
+ if (item.Key.Contains("Examples"))
+ {
+ // Examples require a certain number of leading spaces
+ Assert.True(helpMessageLines[i].StartsWith(examplesLeadingSpaces), $"Line {i + 1} of '{item.Key}' should start with '{examplesLeadingSpaces}'.");
+ }
+ else if (helpMessageLines[i].Trim().StartsWith("/") || helpMessageLines[i].Trim().StartsWith("@"))
+ {
+ // Switches require a certain number of leading spaces
+ Assert.True(helpMessageLines[i].StartsWith(switchLeadingSpaces), $"Line {i + 1} of '{item.Key}' should start with '{switchLeadingSpaces}'.");
+ }
+ else
+ {
+ // All other lines require a certain number of leading spaces
+ Assert.True(helpMessageLines[i].StartsWith(otherLineLeadingSpaces), $"Line {i + 1} of '{item.Key}' should start with '{otherLineLeadingSpaces}'.");
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
///
/// Verifies that a switch collection has an error registered for the given command line arg.
///
diff --git a/src/XMakeCommandLine/XMake.cs b/src/XMakeCommandLine/XMake.cs
index c9b1d04bb37..69d26aa88ff 100644
--- a/src/XMakeCommandLine/XMake.cs
+++ b/src/XMakeCommandLine/XMake.cs
@@ -11,6 +11,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
@@ -546,6 +547,7 @@ string [] commandLine
TextWriter preprocessWriter = null;
bool debugger = false;
bool detailedSummary = false;
+ ISet warningsAsErrors = null;
CommandLineSwitches switchesFromAutoResponseFile;
CommandLineSwitches switchesNotFromAutoResponseFile;
@@ -572,6 +574,7 @@ string [] commandLine
ref preprocessWriter,
ref debugger,
ref detailedSummary,
+ ref warningsAsErrors,
recursing: false
))
{
@@ -600,7 +603,7 @@ string [] commandLine
#if FEATURE_XML_SCHEMA_VALIDATION
needToValidateProject, schemaFile,
#endif
- cpuCount, enableNodeReuse, preprocessWriter, debugger, detailedSummary))
+ cpuCount, enableNodeReuse, preprocessWriter, debugger, detailedSummary, warningsAsErrors))
{
exitType = ExitType.BuildError;
}
@@ -891,7 +894,8 @@ internal static bool BuildProject
bool enableNodeReuse,
TextWriter preprocessWriter,
bool debugger,
- bool detailedSummary
+ bool detailedSummary,
+ ISet warningsAsErrors
)
{
if (String.Equals(Path.GetExtension(projectFile), ".vcproj", StringComparison.OrdinalIgnoreCase) ||
@@ -1055,6 +1059,7 @@ bool detailedSummary
parameters.ToolsetDefinitionLocations = Microsoft.Build.Evaluation.ToolsetDefinitionLocations.ConfigurationFile | Microsoft.Build.Evaluation.ToolsetDefinitionLocations.Registry;
parameters.DetailedSummary = detailedSummary;
parameters.LogTaskInputs = logTaskInputs;
+ parameters.WarningsAsErrors = warningsAsErrors;
if (!String.IsNullOrEmpty(toolsVersion))
{
@@ -1424,6 +1429,7 @@ internal static void GatherCommandLineSwitches(ArrayList commandLineArgs, Comman
bool multipleParametersAllowed;
string missingParametersErrorMessage;
bool unquoteParameters;
+ bool allowEmptyParameters;
// Special case: for the switch "/m" or "/maxCpuCount" we wish to pretend we saw "/m:"
// This allows a subsequent /m:n on the command line to override it.
@@ -1444,9 +1450,9 @@ internal static void GatherCommandLineSwitches(ArrayList commandLineArgs, Comman
{
GatherParameterlessCommandLineSwitch(commandLineSwitches, parameterlessSwitch, switchParameters, duplicateSwitchErrorMessage, unquotedCommandLineArg);
}
- else if (CommandLineSwitches.IsParameterizedSwitch(switchName, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters))
+ else if (CommandLineSwitches.IsParameterizedSwitch(switchName, out parameterizedSwitch, out duplicateSwitchErrorMessage, out multipleParametersAllowed, out missingParametersErrorMessage, out unquoteParameters, out allowEmptyParameters))
{
- GatherParameterizedCommandLineSwitch(commandLineSwitches, parameterizedSwitch, switchParameters, duplicateSwitchErrorMessage, multipleParametersAllowed, missingParametersErrorMessage, unquoteParameters, unquotedCommandLineArg);
+ GatherParameterizedCommandLineSwitch(commandLineSwitches, parameterizedSwitch, switchParameters, duplicateSwitchErrorMessage, multipleParametersAllowed, missingParametersErrorMessage, unquoteParameters, unquotedCommandLineArg, allowEmptyParameters);
}
else
{
@@ -1677,7 +1683,8 @@ private static void GatherParameterizedCommandLineSwitch
bool multipleParametersAllowed,
string missingParametersErrorMessage,
bool unquoteParameters,
- string unquotedCommandLineArg
+ string unquotedCommandLineArg,
+ bool allowEmptyParameters
)
{
if (// switch must have parameters
@@ -1696,7 +1703,7 @@ string unquotedCommandLineArg
}
// save the parameters after unquoting and splitting them if necessary
- if (!commandLineSwitches.SetParameterizedSwitch(parameterizedSwitch, unquotedCommandLineArg, switchParameters, multipleParametersAllowed, unquoteParameters))
+ if (!commandLineSwitches.SetParameterizedSwitch(parameterizedSwitch, unquotedCommandLineArg, switchParameters, multipleParametersAllowed, unquoteParameters, allowEmptyParameters))
{
// if parsing revealed there were no real parameters, flag an error, unless the parameters are optional
if (missingParametersErrorMessage != null)
@@ -1786,6 +1793,7 @@ private static bool ProcessCommandLineSwitches
ref TextWriter preprocessWriter,
ref bool debugger,
ref bool detailedSummary,
+ ref ISet warningsAsErrors,
bool recursing
)
{
@@ -1889,6 +1897,7 @@ bool recursing
ref preprocessWriter,
ref debugger,
ref detailedSummary,
+ ref warningsAsErrors,
recursing: true
);
}
@@ -1923,6 +1932,8 @@ bool recursing
#endif
detailedSummary = commandLineSwitches.IsParameterlessSwitchSet(CommandLineSwitches.ParameterlessSwitch.DetailedSummary);
+ warningsAsErrors = ProcessWarnAsErrorSwitch(commandLineSwitches);
+
// figure out which loggers are going to listen to build events
string[][] groupedFileLoggerParameters = commandLineSwitches.GetFileLoggerParameters();
@@ -2030,6 +2041,37 @@ internal static TextWriter ProcessPreprocessSwitch(string[] parameters)
return writer;
}
+ internal static ISet ProcessWarnAsErrorSwitch(CommandLineSwitches commandLineSwitches)
+ {
+ // TODO: Parse an environment variable as well?
+
+ if (!commandLineSwitches.IsParameterizedSwitchSet(CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors))
+ {
+ return null;
+ }
+
+ string[] parameters = commandLineSwitches[CommandLineSwitches.ParameterizedSwitch.WarningsAsErrors];
+
+ ISet warningsAsErrors = new HashSet(StringComparer.OrdinalIgnoreCase);
+
+ foreach (string code in parameters
+ .SelectMany(parameter => parameter?.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[] { null }))
+ {
+ if (code == null)
+ {
+ // An empty /warnaserror is added as "null". In this case, the list is cleared
+ // so that all warnings are treated errors
+ warningsAsErrors.Clear();
+ }
+ else if(!String.IsNullOrWhiteSpace(code))
+ {
+ warningsAsErrors.Add(code.Trim());
+ }
+ }
+
+ return warningsAsErrors;
+ }
+
///
/// Uses the input from thinNodeMode switch to start a local node server
///
@@ -3137,6 +3179,7 @@ private static void ShowHelpMessage()
Console.WriteLine(AssemblyResources.GetString("HelpMessage_18_DistributedLoggerSwitch"));
Console.WriteLine(AssemblyResources.GetString("HelpMessage_21_DistributedFileLoggerSwitch"));
Console.WriteLine(AssemblyResources.GetString("HelpMessage_11_LoggerSwitch"));
+ Console.WriteLine(AssemblyResources.GetString("HelpMessage_28_WarnAsErrorSwitch"));
#if FEATURE_XML_SCHEMA_VALIDATION
Console.WriteLine(AssemblyResources.GetString("HelpMessage_15_ValidateSwitch"));
#endif