Skip to content

Commit

Permalink
Implement /NoWarn switch
Browse files Browse the repository at this point in the history
Warnings are logged as low importance messages instead.  This way they can still be seen with more verbosity but are essentially suppressed.

Closes dotnet#68
  • Loading branch information
jeffkl committed Nov 29, 2016
1 parent 7633e84 commit d3a76fe
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 15 deletions.
1 change: 1 addition & 0 deletions ref/net46/Microsoft.Build/Microsoft.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@ public BuildParameters(Microsoft.Build.Evaluation.ProjectCollection projectColle
public System.Globalization.CultureInfo UICulture { get { throw null; } set { } }
public bool UseSynchronousLogging { get { throw null; } set { } }
public System.Collections.Generic.ISet<string> WarningsAsErrors { get { throw null; } set { } }
public System.Collections.Generic.ISet<string> WarningsAsMessages { get { throw null; } set { } }
public Microsoft.Build.Execution.BuildParameters Clone() { throw null; }
public Microsoft.Build.Evaluation.Toolset GetToolset(string toolsVersion) { throw null; }
}
Expand Down
5 changes: 3 additions & 2 deletions src/XMakeBuildEngine/BackEnd/BuildManager/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ public void BeginBuild(BuildParameters parameters)
}

// Set up the logging service.
ILoggingService loggingService = CreateLoggingService(_buildParameters.Loggers, _buildParameters.ForwardingLoggers, _buildParameters.WarningsAsErrors);
ILoggingService loggingService = CreateLoggingService(_buildParameters.Loggers, _buildParameters.ForwardingLoggers, _buildParameters.WarningsAsErrors, _buildParameters.WarningsAsMessages);

_nodeManager.RegisterPacketHandler(NodePacketType.LogMessage, LogMessagePacket.FactoryForDeserialization, loggingService as INodePacketHandler);
try
Expand Down Expand Up @@ -1736,7 +1736,7 @@ private void OnProjectStarted(object sender, ProjectStartedEventArgs e)
/// <summary>
/// Creates a logging service around the specified set of loggers.
/// </summary>
private ILoggingService CreateLoggingService(IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> forwardingLoggers, ISet<string> warningsAsErrors)
private ILoggingService CreateLoggingService(IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> forwardingLoggers, ISet<string> warningsAsErrors, ISet<string> warningsAsMessages)
{
int cpuCount = _buildParameters.MaxNodeCount;

Expand Down Expand Up @@ -1764,6 +1764,7 @@ private ILoggingService CreateLoggingService(IEnumerable<ILogger> loggers, IEnum
loggingService.OnProjectStarted += _projectStartedEventHandler;
loggingService.OnProjectFinished += _projectFinishedEventHandler;
loggingService.WarningsAsErrors = warningsAsErrors;
loggingService.WarningsAsMessages = warningsAsMessages;

try
{
Expand Down
15 changes: 15 additions & 0 deletions src/XMakeBuildEngine/BackEnd/BuildManager/BuildParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ public class BuildParameters : INodePacketTranslatable
/// </summary>
private ISet<string> _warningsAsErrors = null;

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
private ISet<string> _warningsAsMessages = null;

/// <summary>
/// The location of the toolset definitions.
/// </summary>
Expand Down Expand Up @@ -326,6 +331,7 @@ private BuildParameters(BuildParameters other)
_logTaskInputs = other._logTaskInputs;
_logInitialPropertiesAndItems = other._logInitialPropertiesAndItems;
_warningsAsErrors = other._warningsAsErrors == null ? null : new HashSet<string>(other._warningsAsErrors, StringComparer.OrdinalIgnoreCase);
_warningsAsMessages = other._warningsAsMessages == null ? null : new HashSet<string>(other._warningsAsMessages, StringComparer.OrdinalIgnoreCase);
}

#if FEATURE_THREAD_PRIORITY
Expand Down Expand Up @@ -598,6 +604,15 @@ public ISet<string> WarningsAsErrors
set { _warningsAsErrors = value; }
}

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
public ISet<string> WarningsAsMessages
{
get { return _warningsAsMessages; }
set { _warningsAsMessages = value; }
}

/// <summary>
/// Locations to search for toolsets.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ public ISet<string> WarningsAsErrors
set;
}

/// <summary>
/// This property is ignored by this event sink and relies on the receiver to treat warnings as low importance messages.
/// </summary>
public ISet<string> WarningsAsMessages
{
get;
set;
}


/// <summary>
/// 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.
/// </summary>
Expand Down
37 changes: 35 additions & 2 deletions src/XMakeBuildEngine/BackEnd/Components/Logging/EventSourceSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ public ISet<string> WarningsAsErrors
set;
}

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
public ISet<string> WarningsAsMessages
{
get;
set;
}

/// <summary>
/// A list of build submission IDs that have logged errors. If an error is logged outside of a submission, the submission ID is <see cref="BuildEventContext.InvalidSubmissionId"/>.
/// </summary>
Expand Down Expand Up @@ -224,9 +233,33 @@ public void Consume(BuildEventArgs 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)))
if (WarningsAsMessages != null && WarningsAsMessages.Contains(warningEvent.Code))
{
// Treat this warning as a message with low importance if its in the list
BuildMessageEventArgs errorEvent = new BuildMessageEventArgs(
warningEvent.Subcategory,
warningEvent.Code,
warningEvent.File,
warningEvent.LineNumber,
warningEvent.ColumnNumber,
warningEvent.EndLineNumber,
warningEvent.EndColumnNumber,
warningEvent.Message,
warningEvent.HelpKeyword,
warningEvent.SenderName,
MessageImportance.Low,
warningEvent.Timestamp)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
};

this.RaiseMessageEvent(null, errorEvent);

}
else if (WarningsAsErrors != null && (WarningsAsErrors.Count == 0 || WarningsAsErrors.Contains(warningEvent.Code)))
{
// Treat this warning as an error if an empty set of warnings was specified or this code was specified
BuildErrorEventArgs errorEvent = new BuildErrorEventArgs(
warningEvent.Subcategory,
warningEvent.Code,
Expand Down
18 changes: 18 additions & 0 deletions src/XMakeBuildEngine/BackEnd/Components/Logging/ILoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ ISet<string> WarningsAsErrors
get;
set;
}

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
ISet<string> WarningsAsMessages
{
get;
set;
}
#endregion

/// <summary>
Expand Down Expand Up @@ -472,6 +481,15 @@ ISet<string> WarningsAsErrors
set;
}

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
ISet<string> WarningsAsMessages
{
get;
set;
}

/// <summary>
/// A list of build submissions that have logged errors.
/// </summary>
Expand Down
20 changes: 18 additions & 2 deletions src/XMakeBuildEngine/BackEnd/Components/Logging/LoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ internal partial class LoggingService : ILoggingService, INodePacketHandler, IBu
/// </summary>
private ISet<string> _warningsAsErrors = null;

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
private ISet<string> _warningsAsMessages = null;

#endregion

#endregion
Expand Down Expand Up @@ -459,6 +464,15 @@ public ISet<string> WarningsAsErrors
set { _warningsAsErrors = value; }
}

/// <summary>
/// A list of warnings to treat as low importance messages.
/// </summary>
public ISet<string> WarningsAsMessages
{
get { return _warningsAsMessages; }
set { _warningsAsMessages = value; }
}

/// <summary>
/// Determines if the specified submission has logged an errors.
/// </summary>
Expand Down Expand Up @@ -819,7 +833,8 @@ public bool RegisterDistributedLogger(ILogger centralLogger, LoggerDescription f
// create an eventSourceSink which the central logger will register with to receive the events from the forwarding logger
EventSourceSink eventSourceSink = new EventSourceSink
{
WarningsAsErrors = WarningsAsErrors == null ? null : new HashSet<string>(WarningsAsErrors, StringComparer.OrdinalIgnoreCase)
WarningsAsErrors = WarningsAsErrors == null ? null : new HashSet<string>(WarningsAsErrors, StringComparer.OrdinalIgnoreCase),
WarningsAsMessages = WarningsAsMessages == null ? null : new HashSet<string>(WarningsAsMessages, StringComparer.OrdinalIgnoreCase),
};

// If the logger is already in the list it should not be registered again.
Expand Down Expand Up @@ -1135,7 +1150,8 @@ private void CreateFilterEventSource()
_filterEventSource = new EventSourceSink
{
Name = "Sink for Distributed/Filter loggers",
WarningsAsErrors = WarningsAsErrors == null ? null : new HashSet<string>(WarningsAsErrors, StringComparer.OrdinalIgnoreCase)
WarningsAsErrors = WarningsAsErrors == null ? null : new HashSet<string>(WarningsAsErrors, StringComparer.OrdinalIgnoreCase),
WarningsAsMessages = WarningsAsMessages == null ? null : new HashSet<string>(WarningsAsMessages, StringComparer.OrdinalIgnoreCase),
};
}
}
Expand Down
69 changes: 69 additions & 0 deletions src/XMakeBuildEngine/UnitTests/BackEnd/EventSourceSink_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,75 @@ public void TreatWarningsAsErrorWhenAllSpecified()
Assert.IsType<BuildErrorEventArgs>(eventHandlerHelper.RaisedEvent);
}

/// <summary>
/// Verifies that a warning is logged as a low importance message when it's warning code is specified.
/// </summary>
[Fact]
public void TreatWarningsAsMessagesWhenSpecified()
{
BuildWarningEventArgs expectedBuildEvent = RaiseEventHelper.Warning;

EventSourceSink eventSourceSink = new EventSourceSink()
{
WarningsAsMessages = new HashSet<string>
{
"FOO",
expectedBuildEvent.Code,
"BAR",
},
};

RaiseEventHelper raiseEventHelper = new RaiseEventHelper(eventSourceSink);
EventHandlerHelper eventHandlerHelper = new EventHandlerHelper(eventSourceSink, null);

raiseEventHelper.RaiseBuildEvent(RaiseEventHelper.Warning);

Assert.IsType<BuildMessageEventArgs>(eventHandlerHelper.RaisedEvent);

BuildMessageEventArgs actualBuildEvent = (BuildMessageEventArgs)eventHandlerHelper.RaisedEvent;

Assert.Equal(expectedBuildEvent.BuildEventContext, actualBuildEvent.BuildEventContext);
Assert.Equal(expectedBuildEvent.Code, actualBuildEvent.Code);
Assert.Equal(expectedBuildEvent.ColumnNumber, actualBuildEvent.ColumnNumber);
Assert.Equal(expectedBuildEvent.EndColumnNumber, actualBuildEvent.EndColumnNumber);
Assert.Equal(expectedBuildEvent.EndLineNumber, actualBuildEvent.EndLineNumber);
Assert.Equal(expectedBuildEvent.File, actualBuildEvent.File);
Assert.Equal(expectedBuildEvent.HelpKeyword, actualBuildEvent.HelpKeyword);
Assert.Equal(MessageImportance.Low, actualBuildEvent.Importance);
Assert.Equal(expectedBuildEvent.LineNumber, actualBuildEvent.LineNumber);
Assert.Equal(expectedBuildEvent.Message, actualBuildEvent.Message);
Assert.Equal(expectedBuildEvent.ProjectFile, actualBuildEvent.ProjectFile);
Assert.Equal(expectedBuildEvent.SenderName, actualBuildEvent.SenderName);
Assert.Equal(expectedBuildEvent.Subcategory, actualBuildEvent.Subcategory);
Assert.Equal(expectedBuildEvent.ThreadId, actualBuildEvent.ThreadId);
Assert.Equal(expectedBuildEvent.Timestamp, actualBuildEvent.Timestamp);
}

/// <summary>
/// Verifies that a warning is not treated as a low importance message when other warning codes are specified.
/// </summary>
[Fact]
public void NotTreatWarningsAsMessagesWhenNotSpecified()
{
BuildWarningEventArgs expectedBuildEvent = RaiseEventHelper.Warning;

EventSourceSink eventSourceSink = new EventSourceSink()
{
WarningsAsMessages = new HashSet<string>
{
"123",
"ABC",
},
};

RaiseEventHelper raiseEventHelper = new RaiseEventHelper(eventSourceSink);
EventHandlerHelper eventHandlerHelper = new EventHandlerHelper(eventSourceSink, null);

raiseEventHelper.RaiseBuildEvent(RaiseEventHelper.Warning);

Assert.Equal(expectedBuildEvent, eventHandlerHelper.RaisedEvent);
}

#region TestsThrowingLoggingExceptions

/// <summary>
Expand Down
8 changes: 8 additions & 0 deletions src/XMakeBuildEngine/UnitTests/BackEnd/MockLoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ public ISet<string> WarningsAsErrors
set;
}

/// <summary>
/// List of warnings to treat as low importance messages.
/// </summary>
public ISet<string> WarningsAsMessages
{
get;
set;
}

/// <summary>
/// Is the logging service on a remote node, this is used to determine if properties need to be serialized
Expand Down
2 changes: 2 additions & 0 deletions src/XMakeCommandLine/CommandLineSwitches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ internal enum ParameterizedSwitch
ServerToClientPipeHandle,
#endif
WarningsAsErrors,
WarningsAsMessages,
NumberOfParameterizedSwitches
}

Expand Down Expand Up @@ -281,6 +282,7 @@ bool emptyParametersAllowed
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 ),
new ParameterizedSwitchInfo( new string[] { "warnasmessage", "nowarn" }, ParameterizedSwitch.WarningsAsMessages, null, true, "MissingWarnAsMessageParameterError", true, false ),
};

/// <summary>
Expand Down
25 changes: 24 additions & 1 deletion src/XMakeCommandLine/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,22 @@ Copyright (C) Microsoft Corporation. All rights reserved.
build will fail.
</value>
<comment>
LOCALIZATION: "warnaserror" should not be localized.
LOCALIZATION: "/warnaserror" and "/err" should not be localized.
LOCALIZATION: None of the lines should be longer than a standard width console window, eg 80 chars.
</comment>
</data>
<data name="HelpMessage_29_WarnAsMessageSwitch" UESanitized="false" Visibility="Public">
<value> /warnasmessage[:code[;code2]]
List of warning codes to treats as low importance
messages. Use a semicolon or a comma to separate
multiple warning codes.
(Short form: /nowarn[:c;[c2]])

Example:
/warnasmessage:MSB3026
</value>
<comment>
LOCALIZATION: "/warnasmessage" and "/nowarn" should not be localized.
LOCALIZATION: None of the lines should be longer than a standard width console window, eg 80 chars.
</comment>
</data>
Expand Down Expand Up @@ -975,6 +990,14 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<value>{0} ({1},{2})</value>
<comment>A file location to be embedded in a string.</comment>
</data>
<data name="MissingWarnAsMessageParameterError" UESanitized="true" Visibility="Public">
<value>MSBUILD : error MSB1050: Specify one or more warning codes to treat as low importance messages when using the /warnasmessage switch.</value>
<comment>
{StrBegin="MSBUILD : error MSB1050: "}
UE: This happens if the user does something like "msbuild.exe /warnasmessage:" without any codes.
LOCALIZATION: The prefix "MSBUILD : error MSBxxxx:" should not be localized.
</comment>
</data>

<!--
The command line message bucket is: MSB1001 - MSB1999
Expand Down
Loading

0 comments on commit d3a76fe

Please sign in to comment.