File: BackEnd\Components\Logging\BuildEventArgTransportSink.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.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
 
#nullable disable
 
namespace Microsoft.Build.BackEnd.Logging
{
    /// <summary>
    /// Delegate to a method which will transport the packet accross the wire.
    /// </summary>
    /// <param name="packetToSend">A node packet to send accross the wire</param>
    internal delegate void SendDataDelegate(INodePacket packetToSend);
 
    /// <summary>
    /// This class will consume the BuildEventArgs forwarded by the EventRedirectorToSink class.
    /// The sink will then create a packet and then pass this along to the transport layer to be
    /// sent back to the build manager.
    /// </summary>
    internal class BuildEventArgTransportSink : IBuildEventSink
    {
        #region Data
        /// <summary>
        /// Delegate to a method which accepts a INodePacket and send the packet to where it needs to go
        /// </summary>
        private SendDataDelegate _sendDataDelegate;
        #endregion
 
        #region Constructor
 
        /// <summary>
        /// Create the sink which will consume a buildEventArg
        /// Create a INodePacket and send it to the transport component
        /// </summary>
        /// <param name="sendData">A delegate which takes an INodePacket and sends the packet to where it needs to go</param>
        /// <exception cref="InternalErrorException">Send data delegate is null</exception>
        internal BuildEventArgTransportSink(SendDataDelegate sendData)
        {
            ErrorUtilities.VerifyThrow(sendData != null, "sendData delegate is null");
            _sendDataDelegate = sendData;
        }
 
        #endregion
 
        #region Properties
        /// <summary>
        /// Provide a friendly name for the sink to make it easier to differentiate during
        /// debugging and display
        /// </summary>
        public string Name
        {
            get;
            set;
        }
 
        /// <summary>
        /// Has the sink logged the BuildStartedEvent. This is important to know because we only want to log the build started event once
        /// </summary>
        public bool HaveLoggedBuildStartedEvent
        {
            get;
            set;
        }
 
        /// <summary>
        /// Has the sink logged the BuildFinishedEvent. This is important to know because we only want to log the build finished event once
        /// </summary>
        public bool HaveLoggedBuildFinishedEvent
        {
            get;
            set;
        }
 
        /// <summary>
        /// This property is ignored by this event sink and relies on the receiver to treat warnings as errors.
        /// </summary>
        public ISet<string> WarningsAsErrors
        {
            get;
            set;
        }
 
        /// <summary>
        /// This property is ignored by this event sink and relies on the receiver to treat warnings as errors.
        /// </summary>
        public IDictionary<int, ISet<string>> WarningsAsErrorsByProject
        {
            get;
            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 treat warnings as low importance messages.
        /// </summary>
        public IDictionary<int, ISet<string>> WarningsAsMessagesByProject
        {
            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>
        public ISet<int> BuildSubmissionIdsThatHaveLoggedErrors { get; } = null;
        #endregion
        #region IBuildEventSink Methods
 
        /// <summary>
        /// This method should not be used since we need the sinkID
        /// </summary>
        public void Consume(BuildEventArgs buildEvent)
        {
            ErrorUtilities.ThrowInternalError("Do not use this method for the transport sink");
        }
 
        /// <summary>
        /// Consumes the buildEventArg and creates a logMessagePacket
        /// </summary>
        /// <param name="buildEvent">Build event to package into a INodePacket</param>
        /// <param name="sinkId">The sink identifier.</param>
        /// <exception cref="InternalErrorException">buildEvent is null</exception>
        public void Consume(BuildEventArgs buildEvent, int sinkId)
        {
            ErrorUtilities.VerifyThrow(buildEvent != null, "buildEvent is null");
            if (buildEvent is BuildStartedEventArgs)
            {
                HaveLoggedBuildStartedEvent = true;
                return;
            }
            else if (buildEvent is BuildFinishedEventArgs)
            {
                HaveLoggedBuildFinishedEvent = true;
                return;
            }
 
            LogMessagePacket logPacket = new LogMessagePacket(new KeyValuePair<int, BuildEventArgs>(sinkId, buildEvent));
            _sendDataDelegate(logPacket);
        }
 
        /// <summary>
        /// Dispose of any resources the sink is holding onto.
        /// </summary>
        public void ShutDown()
        {
            _sendDataDelegate = null;
        }
        #endregion
    }
}