From 80f316e906ff0ccb995f4f9942d65e16601794b2 Mon Sep 17 00:00:00 2001 From: Ben Villalobos <4691428+BenVillalobos@users.noreply.github.com> Date: Wed, 31 Mar 2021 09:57:18 -0700 Subject: [PATCH] Properly Consider WarningsAsMessages In TaskLoggingHelper's `HasLoggedErrors` (#6308) Fixes #6306 Context #6174 didn't properly account for warningsaserrors and warningsasmessages together. This PR makes each taskhost aware of both WarningsAsMessages and WarningsAsErrors when telling tasks whether or not an error should be treated as a warning. Changes Made LoggingService and TaskLoggingContext expose a GetWarningsAsMessages to each taskhost for them to store. No changes to IBE8 API Taskhosts first check if a warning would be treated as a message when telling tasks whether or not a warning should be treated as a warning. --- .../BackEnd/MockLoggingService.cs | 7 +- .../BackEnd/TaskHostConfiguration_Tests.cs | 117 +++++++++++++---- .../WarningsAsMessagesAndErrors_Tests.cs | 119 ++++-------------- .../Components/Logging/ILoggingService.cs | 12 +- .../Components/Logging/LoggingService.cs | 49 ++++---- .../Components/Logging/TaskLoggingContext.cs | 7 +- .../Components/RequestBuilder/TaskHost.cs | 25 +++- .../Instance/TaskFactories/TaskHostTask.cs | 3 +- src/MSBuild/OutOfProcTaskHostNode.cs | 11 +- src/Shared/TaskHostConfiguration.cs | 28 ++++- 10 files changed, 224 insertions(+), 154 deletions(-) diff --git a/src/Build.UnitTests/BackEnd/MockLoggingService.cs b/src/Build.UnitTests/BackEnd/MockLoggingService.cs index cfd53b89220..5409a6f3822 100644 --- a/src/Build.UnitTests/BackEnd/MockLoggingService.cs +++ b/src/Build.UnitTests/BackEnd/MockLoggingService.cs @@ -557,7 +557,12 @@ public bool HasBuildSubmissionLoggedErrors(int submissionId) return false; } - public ICollection GetWarningsToBeLoggedAsErrorsByProject(BuildEventContext context) + public ICollection GetWarningsAsErrors(BuildEventContext context) + { + throw new NotImplementedException(); + } + + public ICollection GetWarningsAsMessages(BuildEventContext context) { throw new NotImplementedException(); } diff --git a/src/Build.UnitTests/BackEnd/TaskHostConfiguration_Tests.cs b/src/Build.UnitTests/BackEnd/TaskHostConfiguration_Tests.cs index d892c47a917..144f30bea1a 100644 --- a/src/Build.UnitTests/BackEnd/TaskHostConfiguration_Tests.cs +++ b/src/Build.UnitTests/BackEnd/TaskHostConfiguration_Tests.cs @@ -57,7 +57,8 @@ public void ConstructorWithNullName() taskLocation: @"c:\my tasks\mytask.dll", taskParameters: null, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); } ); } @@ -90,7 +91,8 @@ public void ConstructorWithEmptyName() taskLocation: @"c:\my tasks\mytask.dll", taskParameters: null, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); } ); } @@ -123,7 +125,8 @@ public void ConstructorWithNullLocation() taskLocation: null, taskParameters: null, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); } ); } @@ -158,7 +161,8 @@ public void ConstructorWithEmptyLocation() taskLocation: String.Empty, taskParameters: null, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); } ); } @@ -191,26 +195,32 @@ public void TestValidConstructors() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: null, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); TaskHostConfiguration config2 = new TaskHostConfiguration( - 1, - Directory.GetCurrentDirectory(), - null, - Thread.CurrentThread.CurrentCulture, - Thread.CurrentThread.CurrentUICulture, + nodeId: 1, + startupDirectory: Directory.GetCurrentDirectory(), + buildProcessEnvironment: null, + culture: Thread.CurrentThread.CurrentCulture, + uiCulture: Thread.CurrentThread.CurrentUICulture, +#if FEATURE_APPDOMAIN + appDomainSetup: #if FEATURE_APPDOMAIN null, +#endif + lineNumberOfTask: #endif 1, - 1, - @"c:\my project\myproj.proj", - _continueOnErrorDefault, - "TaskName", - @"c:\MyTasks\MyTask.dll", - null, - null, - null); + columnNumberOfTask: 1, + projectFileOfTask: @"c:\my project\myproj.proj", + continueOnError: _continueOnErrorDefault, + taskName: "TaskName", + taskLocation: @"c:\MyTasks\MyTask.dll", + taskParameters: null, + globalParameters: null, + warningsAsErrors: null, + warningsAsMessages: null); IDictionary parameters = new Dictionary(); TaskHostConfiguration config3 = new TaskHostConfiguration( @@ -234,7 +244,8 @@ public void TestValidConstructors() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: parameters, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); IDictionary parameters2 = new Dictionary(); parameters2.Add("Text", "Hello!"); @@ -263,7 +274,8 @@ public void TestValidConstructors() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: parameters2, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); HashSet WarningsAsErrors = new HashSet(); WarningsAsErrors.Add("MSB1234"); @@ -292,7 +304,8 @@ public void TestValidConstructors() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: parameters2, globalParameters: null, - warningsAsErrors: WarningsAsErrors); + warningsAsErrors: WarningsAsErrors, + warningsAsMessages: null); } /// @@ -328,7 +341,8 @@ public void TestTranslationWithNullDictionary() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: null, globalParameters: expectedGlobalProperties, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); @@ -371,7 +385,8 @@ public void TestTranslationWithEmptyDictionary() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: new Dictionary(), globalParameters: new Dictionary(), - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); @@ -419,7 +434,8 @@ public void TestTranslationWithValueTypesInDictionary() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: parameters, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); @@ -465,7 +481,8 @@ public void TestTranslationWithITaskItemInDictionary() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: parameters, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); @@ -510,7 +527,8 @@ public void TestTranslationWithITaskItemArrayInDictionary() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: parameters, globalParameters: null, - warningsAsErrors: null); + warningsAsErrors: null, + warningsAsMessages: null); ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); @@ -562,7 +580,8 @@ public void TestTranslationWithWarningsAsErrors() taskLocation: @"c:\MyTasks\MyTask.dll", taskParameters: null, globalParameters: null, - warningsAsErrors: WarningsAsErrors); + warningsAsErrors: WarningsAsErrors, + warningsAsMessages: null); ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); @@ -578,6 +597,50 @@ public void TestTranslationWithWarningsAsErrors() } + /// + /// Test serialization / deserialization when the parameter dictionary contains warningsasmessages + /// + [Fact] + public void TestTranslationWithWarningsAsMessages() + { + HashSet WarningsAsMessages = new HashSet(); + WarningsAsMessages.Add("MSB1234"); + WarningsAsMessages.Add("MSB1235"); + WarningsAsMessages.Add("MSB1236"); + WarningsAsMessages.Add("MSB1237"); + TaskHostConfiguration config = new TaskHostConfiguration( + nodeId: 1, + startupDirectory: Directory.GetCurrentDirectory(), + buildProcessEnvironment: null, + culture: Thread.CurrentThread.CurrentCulture, + uiCulture: Thread.CurrentThread.CurrentUICulture, +#if FEATURE_APPDOMAIN + appDomainSetup: +#if FEATURE_APPDOMAIN + null, +#endif + lineNumberOfTask: +#endif + 1, + columnNumberOfTask: 1, + projectFileOfTask: @"c:\my project\myproj.proj", + continueOnError: _continueOnErrorDefault, + taskName: "TaskName", + taskLocation: @"c:\MyTasks\MyTask.dll", + taskParameters: null, + globalParameters: null, + warningsAsErrors: null, + warningsAsMessages: WarningsAsMessages); + + ((ITranslatable)config).Translate(TranslationHelpers.GetWriteTranslator()); + INodePacket packet = TaskHostConfiguration.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); + + TaskHostConfiguration deserializedConfig = packet as TaskHostConfiguration; + + Assert.NotNull(deserializedConfig.WarningsAsMessages); + config.WarningsAsMessages.SequenceEqual(deserializedConfig.WarningsAsMessages, StringComparer.Ordinal).ShouldBeTrue(); + } + /// /// Helper methods for testing the task host-related packets. /// diff --git a/src/Build.UnitTests/WarningsAsMessagesAndErrors_Tests.cs b/src/Build.UnitTests/WarningsAsMessagesAndErrors_Tests.cs index e2973629106..15344781043 100644 --- a/src/Build.UnitTests/WarningsAsMessagesAndErrors_Tests.cs +++ b/src/Build.UnitTests/WarningsAsMessagesAndErrors_Tests.cs @@ -272,11 +272,16 @@ private string GetTestProject(bool? treatAllWarningsAsErrors = null, string warn "; } - /// - /// We have a unique task host per bucket. Show that in these scenarios the build will stop if one sees an error. - /// - [Fact] - public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldStopAndFail_BatchedBuild() + [Theory] + + [InlineData("MSB1235", "MSB1234", "MSB1234", "MSB1234", false)] // Log MSB1234, treat as error via MSBuildWarningsAsErrors + [InlineData("MSB1235", "", "MSB1234", "MSB1234", true)] // Log MSB1234, expect MSB1234 as error via MSBuildTreatWarningsAsErrors + [InlineData("MSB1234", "MSB1234", "MSB1234", "MSB4181", true)]// Log MSB1234, MSBuildWarningsAsMessages takes priority + public void WarningsAsErrorsAndMessages_Tests(string WarningsAsMessages, + string WarningsAsErrors, + string WarningToLog, + string LogShouldContain, + bool allWarningsAreErrors = false) { using (TestEnvironment env = TestEnvironment.Create(_output)) { @@ -285,22 +290,12 @@ public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldStopAndFai - MSB1234 + {allWarningsAreErrors} + {WarningsAsMessages} + {WarningsAsErrors} - - - true - true - MSB1234 - - - true - true - MSB1235 - - - + "); @@ -310,8 +305,7 @@ public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldStopAndFai logger.WarningCount.ShouldBe(0); logger.ErrorCount.ShouldBe(1); - // The build should STOP when a task logs an error, make sure ReturnFailureWithoutLoggingErrorTask doesn't run. - logger.AssertLogDoesntContain("MSB4181"); + logger.AssertLogContains(LogShouldContain); } } @@ -319,7 +313,7 @@ public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldStopAndFai /// Item1 and Item2 log warnings and continue, item 3 logs a warn-> error and prevents item 4 from running in the batched build. /// [Fact] - public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldStopOnceItLogsWarningAsErrorAndFail_BatchedBuild() + public void TaskLogsWarningAsError_BatchedBuild() { using (TestEnvironment env = TestEnvironment.Create(_output)) { @@ -368,40 +362,15 @@ public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldStopOnceIt } } - [Fact] - public void TaskReturnsHasLoggedErrorAndLogsWarningAsError_BuildShouldFinishAndFail() - { - using (TestEnvironment env = TestEnvironment.Create(_output)) - { - TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@" - - - - - MSB1234 - - - - - - "); - - MockLogger logger = proj.BuildProjectExpectFailure(); - - logger.WarningCount.ShouldBe(0); - logger.ErrorCount.ShouldBe(1); - - // The build should STOP when a task logs an error, make sure ReturnFailureWithoutLoggingErrorTask doesn't run. - logger.AssertLogDoesntContain("MSB4181"); - } - } - /// - /// MSBuild behavior as of 16.10: As long as a task returns true, the build will continue despite logging a warning as error. - /// This tests MSBuildWarningsAsErrors + /// Task logs MSB1234 as a warning and returns true. + /// Test behavior with MSBuildWarningsAsErrors & MSBuildTreatWarningsAsErrors + /// Both builds should continue despite logging errors. /// - [Fact] - public void TaskReturnsTrueButLogsWarningAsError_BuildShouldFinishAndFail() + [Theory] + [InlineData("MSB1234", false, 1, 1)] + [InlineData("MSB0000", true, 0, 2)] + public void TaskReturnsTrue_Tests(string warningsAsErrors, bool treatAllWarningsAsErrors, int warningCountShouldBe, int errorCountShouldBe) { using (TestEnvironment env = TestEnvironment.Create(_output)) { @@ -409,9 +378,9 @@ public void TaskReturnsTrueButLogsWarningAsError_BuildShouldFinishAndFail() - - MSB1234 + {treatAllWarningsAsErrors} + {warningsAsErrors} @@ -421,48 +390,14 @@ public void TaskReturnsTrueButLogsWarningAsError_BuildShouldFinishAndFail() MockLogger logger = proj.BuildProjectExpectFailure(); - logger.WarningCount.ShouldBe(1); - logger.ErrorCount.ShouldBe(1); + logger.WarningCount.ShouldBe(warningCountShouldBe); + logger.ErrorCount.ShouldBe(errorCountShouldBe); // The build will continue so we should see the warning MSB1235 logger.AssertLogContains("MSB1235"); } } - - /// - /// MSBuild behavior as of 16.10: As long as a task returns true, the build will continue despite logging warning as error. - /// This test specifically tests the MSBuildTreatWarningsAsErrors flag as opposed to MSBuildWarningsAsErrors - /// - [Fact] - public void TaskReturnsTrueButLogsWarning_TreatWarningsAsErrors_BuildShouldFinishAndFail() - { - using (TestEnvironment env = TestEnvironment.Create(_output)) - { - TransientTestProjectWithFiles proj = env.CreateTestProjectWithFiles($@" - - - - - - true - - - - - - "); - - MockLogger logger = proj.BuildProjectExpectFailure(); - - logger.WarningCount.ShouldBe(0); - logger.ErrorCount.ShouldBe(2); - - // The build will continue so we should see the error MSB1235 - logger.AssertLogContains("MSB1235"); - } - } - [Fact] public void TaskReturnsFailureButDoesNotLogError_ShouldCauseBuildFailure() { diff --git a/src/Build/BackEnd/Components/Logging/ILoggingService.cs b/src/Build/BackEnd/Components/Logging/ILoggingService.cs index e8257651162..eebb06bea2a 100644 --- a/src/Build/BackEnd/Components/Logging/ILoggingService.cs +++ b/src/Build/BackEnd/Components/Logging/ILoggingService.cs @@ -221,11 +221,17 @@ bool IncludeTaskInputs /// /// Returns a hashset of warnings to be logged as errors for the specified project instance ID. - /// Note that WarningsAsMessages takes priority over WarningsAsErrors and are excluded from the set. /// /// The build context through which warnings will be logged as errors. - /// A Hashset containing warning codes that should be treated as warnings that will not be treated as messages. - ICollection GetWarningsToBeLoggedAsErrorsByProject(BuildEventContext context); + /// A Hashset containing warning codes that should be treated as errors. + ICollection GetWarningsAsErrors(BuildEventContext context); + + /// + /// Returns a hashset of warnings to be logged as messages for the specified project instance ID. + /// + /// The build context through which warnings will be logged as errors. + /// A Hashset containing warning codes that should be treated as messages. + ICollection GetWarningsAsMessages(BuildEventContext context); #region Register diff --git a/src/Build/BackEnd/Components/Logging/LoggingService.cs b/src/Build/BackEnd/Components/Logging/LoggingService.cs index 89d9008f90d..c86ac786792 100644 --- a/src/Build/BackEnd/Components/Logging/LoggingService.cs +++ b/src/Build/BackEnd/Components/Logging/LoggingService.cs @@ -521,43 +521,46 @@ public bool HasBuildSubmissionLoggedErrors(int submissionId) /// /// Returns a hashset of warnings to be logged as errors for the specified build context. - /// Note that WarningsAsMessages takes priority over WarningsAsErrors and are excluded from the set. - /// - /// If all warnings to be treated as errors should also be treated as messages, return null. - /// This is to avoid all warnings being treated as errors. /// /// The build context through which warnings will be logged as errors. /// - /// An empty set if all warnings should be treated as errors. - /// A set containing warning codes to be logged as errors. - /// Null if no warnings should be treated as errors. /// - public ICollection GetWarningsToBeLoggedAsErrorsByProject(BuildEventContext context) + public ICollection GetWarningsAsErrors(BuildEventContext context) { - if (_warningsAsErrorsByProject == null) - { - return null; - } - int key = GetWarningsAsErrorOrMessageKey(context); - if (!_warningsAsErrorsByProject.TryGetValue(key, out ISet warningsAsErrorsExcludingMessages)) + if (_warningsAsErrorsByProject != null && _warningsAsErrorsByProject.TryGetValue(key, out ISet warningsAsErrors)) { - return null; - } + if (WarningsAsErrors != null) + { + warningsAsErrors.UnionWith(WarningsAsErrors); + } - if (_warningsAsMessagesByProject != null) + return warningsAsErrors; + } + else { - warningsAsErrorsExcludingMessages.ExceptWith(_warningsAsMessagesByProject[key]); + return WarningsAsErrors; + } + } - // A non-null empty set means all warnings are errors. Avoid this. - if (warningsAsErrorsExcludingMessages.Count == 0) + public ICollection GetWarningsAsMessages(BuildEventContext context) + { + int key = GetWarningsAsErrorOrMessageKey(context); + + if (_warningsAsMessagesByProject != null && _warningsAsMessagesByProject.TryGetValue(key, out ISet warningsAsMessages)) + { + if (WarningsAsMessages != null) { - warningsAsErrorsExcludingMessages = null; + warningsAsMessages.UnionWith(WarningsAsMessages); } - } - return warningsAsErrorsExcludingMessages; + return warningsAsMessages; + } + else + { + return WarningsAsMessages; + } } public void AddWarningsAsErrors(BuildEventContext buildEventContext, ISet codes) diff --git a/src/Build/BackEnd/Components/Logging/TaskLoggingContext.cs b/src/Build/BackEnd/Components/Logging/TaskLoggingContext.cs index 2f4758b2196..6dc62c389ce 100644 --- a/src/Build/BackEnd/Components/Logging/TaskLoggingContext.cs +++ b/src/Build/BackEnd/Components/Logging/TaskLoggingContext.cs @@ -148,7 +148,12 @@ internal void LogTaskWarningFromException(Exception exception, BuildEventFileInf internal ICollection GetWarningsAsErrors() { - return LoggingService.GetWarningsToBeLoggedAsErrorsByProject(BuildEventContext); + return LoggingService.GetWarningsAsErrors(BuildEventContext); + } + + internal ICollection GetWarningsAsMessages() + { + return LoggingService.GetWarningsAsMessages(BuildEventContext); } } } diff --git a/src/Build/BackEnd/Components/RequestBuilder/TaskHost.cs b/src/Build/BackEnd/Components/RequestBuilder/TaskHost.cs index 88b32c65d1e..9222e6e9baf 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/TaskHost.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/TaskHost.cs @@ -704,14 +704,35 @@ private ICollection WarningsAsErrors } } + private ICollection _warningsAsMessages; + + /// + /// Contains all warnings that should be logged as errors. + /// Non-null empty set when all warnings should be treated as errors. + /// + private ICollection WarningsAsMessages + { + get + { + // Test compatibility + if (_taskLoggingContext == null) + { + return null; + } + + return _warningsAsMessages ??= _taskLoggingContext.GetWarningsAsMessages(); + } + } + /// /// Determines if the given warning should be treated as an error. /// /// - /// True if WarningsAsErrors is an empty set or contains the given warning code. + /// True if the warning should not be treated as a message and WarningsAsErrors is an empty set or contains the given warning code. public bool ShouldTreatWarningAsError(string warningCode) { - if (WarningsAsErrors == null) + // Warnings as messages overrides warnings as errors. + if (WarningsAsErrors == null || WarningsAsMessages?.Contains(warningCode) == true) { return false; } diff --git a/src/Build/Instance/TaskFactories/TaskHostTask.cs b/src/Build/Instance/TaskFactories/TaskHostTask.cs index 5c7da148de3..c080e9338e3 100644 --- a/src/Build/Instance/TaskFactories/TaskHostTask.cs +++ b/src/Build/Instance/TaskFactories/TaskHostTask.cs @@ -270,7 +270,8 @@ public bool Execute() AssemblyUtilities.GetAssemblyLocation(_taskType.Type.GetTypeInfo().Assembly), _setParameters, new Dictionary(_buildComponentHost.BuildParameters.GlobalProperties), - _taskLoggingContext.GetWarningsAsErrors() + _taskLoggingContext.GetWarningsAsErrors(), + _taskLoggingContext.GetWarningsAsMessages() ); diff --git a/src/MSBuild/OutOfProcTaskHostNode.cs b/src/MSBuild/OutOfProcTaskHostNode.cs index fa626e3b70d..34adcd7cb25 100644 --- a/src/MSBuild/OutOfProcTaskHostNode.cs +++ b/src/MSBuild/OutOfProcTaskHostNode.cs @@ -275,9 +275,17 @@ public bool IsRunningMultipleNodes /// private ICollection WarningsAsErrors { get; set; } + private ICollection WarningsAsMessages { get; set; } + public bool ShouldTreatWarningAsError(string warningCode) { - return WarningsAsErrors != null && (WarningsAsErrors.Count == 0 || WarningsAsErrors.Contains(warningCode)); + // Warnings as messages overrides warnings as errors. + if (WarningsAsErrors == null || WarningsAsMessages?.Contains(warningCode) == true) + { + return false; + } + + return WarningsAsErrors.Count == 0 || WarningsAsErrors.Contains(warningCode); } #endregion @@ -824,6 +832,7 @@ private void RunTask(object state) _updateEnvironment = !taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostDoNotUpdateEnvironment", "1", StringComparison.OrdinalIgnoreCase); _updateEnvironmentAndLog = taskConfiguration.BuildProcessEnvironment.ContainsValueAndIsEqual("MSBuildTaskHostUpdateEnvironmentAndLog", "1", StringComparison.OrdinalIgnoreCase); WarningsAsErrors = taskConfiguration.WarningsAsErrors; + WarningsAsMessages = taskConfiguration.WarningsAsMessages; try { // Change to the startup directory diff --git a/src/Shared/TaskHostConfiguration.cs b/src/Shared/TaskHostConfiguration.cs index 367e2845823..1bcae1d7574 100644 --- a/src/Shared/TaskHostConfiguration.cs +++ b/src/Shared/TaskHostConfiguration.cs @@ -87,6 +87,8 @@ internal class TaskHostConfiguration : INodePacket private ICollection _warningsAsErrors; + private ICollection _warningsAsMessages; + #if FEATURE_APPDOMAIN /// /// Constructor @@ -105,7 +107,8 @@ internal class TaskHostConfiguration : INodePacket /// Location of the assembly the task is to be loaded from. /// Parameters to apply to the task. /// global properties for the current project. - /// Warning codes to be thrown as errors for the current project. + /// Warning codes to be treated as errors for the current project. + /// Warning codes to be treated as messages for the current project. #else /// /// Constructor @@ -124,6 +127,7 @@ internal class TaskHostConfiguration : INodePacket /// Parameters to apply to the task. /// global properties for the current project. /// Warning codes to be logged as errors for the current project. + /// Warning codes to be treated as messages for the current project. #endif public TaskHostConfiguration ( @@ -143,7 +147,8 @@ public TaskHostConfiguration string taskLocation, IDictionary taskParameters, Dictionary globalParameters, - ICollection warningsAsErrors + ICollection warningsAsErrors, + ICollection warningsAsMessages ) { ErrorUtilities.VerifyThrowInternalLength(taskName, nameof(taskName)); @@ -174,6 +179,7 @@ ICollection warningsAsErrors _taskName = taskName; _taskLocation = taskLocation; _warningsAsErrors = warningsAsErrors; + _warningsAsMessages = warningsAsMessages; if (taskParameters != null) { @@ -357,6 +363,15 @@ public ICollection WarningsAsErrors } } + public ICollection WarningsAsMessages + { + [DebuggerStepThrough] + get + { + return _warningsAsMessages; + } + } + /// /// Translates the packet to/from binary form. /// @@ -382,7 +397,14 @@ public void Translate(ITranslator translator) translator.Translate(collection: ref _warningsAsErrors, objectTranslator: (ITranslator t, ref string s) => t.Translate(ref s), #if CLR2COMPATIBILITY - collectionFactory: count => new HashSet()); + collectionFactory: count => new HashSet(StringComparer.OrdinalIgnoreCase)); +#else + collectionFactory: count => new HashSet(count, StringComparer.OrdinalIgnoreCase)); +#endif + translator.Translate(collection: ref _warningsAsMessages, + objectTranslator: (ITranslator t, ref string s) => t.Translate(ref s), +#if CLR2COMPATIBILITY + collectionFactory: count => new HashSet(StringComparer.OrdinalIgnoreCase)); #else collectionFactory: count => new HashSet(count, StringComparer.OrdinalIgnoreCase)); #endif