File: Logging\SimpleErrorLogger.cs
Web Access
Project: ..\..\..\src\Build\Microsoft.Build.csproj (Microsoft.Build)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging.TerminalLogger;
using Microsoft.Build.Shared;
 
namespace Microsoft.Build.Logging.SimpleErrorLogger
{
    /// <summary>
    /// This logger ignores all message-level output, writing errors and warnings to
    /// standard error, colored red and yellow respectively.
    ///
    /// It is currently used only when the user requests information about specific
    /// properties, items, or target results. In that case, we write the desired output
    /// to standard out, but we do not want it polluted with any other kinds of information.
    /// Users still might want diagnostic information if something goes wrong, so still
    /// output that as necessary.
    /// </summary>
    public sealed class SimpleErrorLogger : INodeLogger
    {
        private readonly bool acceptAnsiColorCodes;
        private readonly uint? originalConsoleMode;
        public SimpleErrorLogger()
        {
            (acceptAnsiColorCodes, _, originalConsoleMode) = NativeMethods.QueryIsScreenAndTryEnableAnsiColorCodes(NativeMethods.StreamHandleType.StdErr);
        }
 
        public bool HasLoggedErrors { get; private set; } = false;
 
        public LoggerVerbosity Verbosity
        {
            get => LoggerVerbosity.Minimal;
            set { }
        }
 
        public string? Parameters
        {
            get => string.Empty;
            set { }
        }
 
        public void Initialize(IEventSource eventSource, int nodeCount)
        {
            eventSource.ErrorRaised += HandleErrorEvent;
            eventSource.WarningRaised += HandleWarningEvent;
 
            // This needs to happen so binary loggers can get evaluation properties and items
            if (eventSource is IEventSource4 eventSource4)
            {
                eventSource4.IncludeEvaluationPropertiesAndItems();
            }
        }
 
        private void HandleErrorEvent(object sender, BuildErrorEventArgs e)
        {
            HasLoggedErrors = true;
            LogWithColor(EventArgsFormatting.FormatEventMessage(e, showProjectFile: true),
                TerminalColor.Red);
        }
 
        private void HandleWarningEvent(object sender, BuildWarningEventArgs e)
        {
            LogWithColor(EventArgsFormatting.FormatEventMessage(e, showProjectFile: true),
                TerminalColor.Yellow);
        }
 
        private void LogWithColor(string message, TerminalColor color)
        {
            if (acceptAnsiColorCodes)
            {
                Console.Error.WriteLine(AnsiCodes.Colorize(message, color));
            }
            else
            {
                Console.Error.WriteLine(message);
            }
        }
 
        public void Initialize(IEventSource eventSource)
        {
            Initialize(eventSource, 1);
        }
 
        public void Shutdown()
        {
            NativeMethods.RestoreConsoleMode(originalConsoleMode, NativeMethods.StreamHandleType.StdErr);
        }
    }
}