TeamCity.MSBuild.Logger/MessageWriter.cs (273 lines of code) (raw):

namespace TeamCity.MSBuild.Logger { using Microsoft.Build.Framework; using System; using System.Collections.Generic; using System.Text; using JetBrains.Annotations; // ReSharper disable once ClassNeverInstantiated.Global internal class MessageWriter: IMessageWriter { [NotNull] private readonly IStringService _stringService; [NotNull] private readonly IEventFormatter _eventFormatter; [NotNull] private readonly ILogFormatter _logFormatter; [NotNull] private readonly IBuildEventManager _buildEventManager; private static readonly string[] NewLines = { "\r\n", "\n" }; [NotNull] private readonly ILoggerContext _context; [NotNull] private readonly ILogWriter _logWriter; public MessageWriter( [NotNull] ILoggerContext context, [NotNull] ILogWriter logWriter, [NotNull] IBuildEventManager buildEventManager, [NotNull] ILogFormatter logFormatter, [NotNull] IEventFormatter eventFormatter, [NotNull] IStringService stringService) { _stringService = stringService ?? throw new ArgumentNullException(nameof(stringService)); _eventFormatter = eventFormatter ?? throw new ArgumentNullException(nameof(eventFormatter)); _logFormatter = logFormatter ?? throw new ArgumentNullException(nameof(logFormatter)); _buildEventManager = buildEventManager ?? throw new ArgumentNullException(nameof(buildEventManager)); _context = context ?? throw new ArgumentNullException(nameof(context)); _logWriter = logWriter ?? throw new ArgumentNullException(nameof(logWriter)); } public void WriteLinePrefix(BuildEventContext e, DateTime eventTimeStamp, bool isMessagePrefix) { WriteLinePrefix(_context.GetFullProjectKey(e).ToString(_context.Verbosity), eventTimeStamp, isMessagePrefix); } public void WriteMessageAligned(string message, bool prefixAlreadyWritten, int prefixAdjustment = 0) { var adjustedPrefixWidth = _context.PrefixWidth + prefixAdjustment; var strArray = SplitStringOnNewLines(message); for (var index = 0; index < strArray.Length; ++index) { var nonNullMessage = strArray[index]; var num = _context.Parameters.BufferWidth - 1; if ((num > adjustedPrefixWidth) & (nonNullMessage.Length + adjustedPrefixWidth > num) && _context.Parameters.AlignMessages) { var str = nonNullMessage.Replace("\t", " "); var startIndex = 0; var length1 = str.Length; while (startIndex < length1) { var length2 = length1 - startIndex < num - adjustedPrefixWidth ? length1 - startIndex : num - adjustedPrefixWidth; WriteBasedOnPrefix(str.Substring(startIndex, length2), prefixAlreadyWritten && startIndex == 0 && index == 0, adjustedPrefixWidth); startIndex += length2; } } else { WriteBasedOnPrefix(nonNullMessage, prefixAlreadyWritten, adjustedPrefixWidth); } } } public void PrintMessage(BuildMessageEventArgs e, bool lightenText) { var message = e.File == null ? e.Message ?? string.Empty : _eventFormatter.FormatEventMessage(e, false, _context.Parameters.ShowProjectFile); var prefixAdjustment = 0; if (e.BuildEventContext.TaskId != -1 && e.File == null) { prefixAdjustment = 2; } if (lightenText) { _logWriter.SetColor(Color.Details); } PrintTargetNamePerMessage(e, lightenText); if ((_context.IsVerbosityAtLeast(LoggerVerbosity.Diagnostic) || (_context.Parameters.ShowEventId ?? false)) && e.BuildEventContext.TaskId != -1) { var prefixAlreadyWritten = WriteTargetMessagePrefix(e, e.BuildEventContext, e.Timestamp); WriteMessageAligned(_stringService.FormatResourceString("TaskMessageWithId", message, e.BuildEventContext.TaskId), prefixAlreadyWritten, prefixAdjustment); } else if (_context.Parameters.ShowTimeStamp || _context.IsVerbosityAtLeast(LoggerVerbosity.Detailed)) { var prefixAlreadyWritten = WriteTargetMessagePrefix(e, e.BuildEventContext, e.Timestamp); WriteMessageAligned(message, prefixAlreadyWritten, prefixAdjustment); } else { WriteMessageAligned(message, false, prefixAdjustment); } if (!lightenText) { return; } _logWriter.ResetColor(); } public void WriteNewLine() { _logWriter.Write(System.Environment.NewLine); } public bool WriteTargetMessagePrefix(BuildEventArgs e, BuildEventContext context, DateTime timeStamp) { var flag = true; var fullProjectKey = _context.GetFullProjectKey(e.BuildEventContext); if (!_context.LastProjectFullKey.Equals(fullProjectKey)) { WriteLinePrefix(context, timeStamp, false); _context.LastProjectFullKey = fullProjectKey; } else { flag = false; } return flag; } public void DisplayCounters(IDictionary<string, IPerformanceCounter> counters) { var sortedCounters = new List<IPerformanceCounter>(counters.Values); sortedCounters.Sort(DescendingByElapsedTime.Shared); var hasReenteredScope = false; foreach (var performanceCounter in sortedCounters) { if (performanceCounter.ReenteredScope) { hasReenteredScope = true; } performanceCounter.PrintCounterMessage(); } if (!hasReenteredScope) { return; } WriteLinePrettyFromResource(4, "PerformanceReentrancyNote"); } public void WriteLinePrettyFromResource(string resourceString, params object[] args) { if (resourceString == null) throw new ArgumentNullException(nameof(resourceString)); if (args == null) throw new ArgumentNullException(nameof(args)); WriteLinePrettyFromResource(_context.IsVerbosityAtLeast(LoggerVerbosity.Normal) ? _context.CurrentIndentLevel : 0, resourceString, args); } public void WriteLinePrettyFromResource(int indentLevel, string resourceString, params object[] args) { if (resourceString == null) throw new ArgumentNullException(nameof(resourceString)); if (args == null) throw new ArgumentNullException(nameof(args)); var formattedString = _stringService.FormatResourceString(resourceString, args); WriteLinePretty(indentLevel, formattedString); } public void WriteLinePretty(string formattedString) { if (formattedString == null) throw new ArgumentNullException(nameof(formattedString)); WriteLinePretty(_context.IsVerbosityAtLeast(LoggerVerbosity.Normal) ? _context.CurrentIndentLevel : 0, formattedString); } public void WriteLinePretty(int indentLevel, string formattedString) { if (formattedString == null) throw new ArgumentNullException(nameof(formattedString)); indentLevel = indentLevel > 0 ? indentLevel : 0; _logWriter.Write(IndentString(formattedString, indentLevel * 2)); } private void WriteBasedOnPrefix(string nonNullMessage, bool prefixAlreadyWritten, int adjustedPrefixWidth) { if (prefixAlreadyWritten) { _logWriter.Write(nonNullMessage + System.Environment.NewLine); } else { _logWriter.Write(IndentString(nonNullMessage, adjustedPrefixWidth)); } } private static string[] SplitStringOnNewLines([NotNull] string str) { if (str == null) throw new ArgumentNullException(nameof(str)); return str.Split(NewLines, StringSplitOptions.None); } private void WritePretty([NotNull] string formattedString) { if (formattedString == null) throw new ArgumentNullException(nameof(formattedString)); WritePretty(_context.IsVerbosityAtLeast(LoggerVerbosity.Normal) ? _context.CurrentIndentLevel : 0, formattedString); } private void WritePretty(int indentLevel, [NotNull] string formattedString) { if (formattedString == null) throw new ArgumentNullException(nameof(formattedString)); var stringBuilder = new StringBuilder(); stringBuilder.Append(' ', indentLevel * 2).Append(formattedString); _logWriter.Write(stringBuilder.ToString()); } private static string IndentString([CanBeNull] string str, int indent) { if (str == null) { str = string.Empty; } var lines = SplitStringOnNewLines(str); var stringBuilder = new StringBuilder(lines.Length * indent + lines.Length * System.Environment.NewLine.Length + str.Length); foreach (var line in lines) { stringBuilder.Append(' ', indent).Append(line); stringBuilder.AppendLine(); } return stringBuilder.ToString(); } private void PrintTargetNamePerMessage(BuildEventArgs e, bool lightenText) { if (!_context.IsVerbosityAtLeast(LoggerVerbosity.Normal)) { return; } var buildEventContext = e.BuildEventContext; var flag1 = false; var str = string.Empty; var flag2 = ComparerContextNodeIdTargetId.Shared.Equals(buildEventContext, _context.LastDisplayedBuildEventContext == default ? null : _context.LastDisplayedBuildEventContext); TargetStartedEventMinimumFields eventMinimumFields = null; if (!flag2) { eventMinimumFields = _buildEventManager.GetTargetStartedEvent(buildEventContext); if (eventMinimumFields != null) { str = eventMinimumFields.TargetName; flag1 = true; } } if (!flag1) { return; } var prefixAlreadyWritten = WriteTargetMessagePrefix(e, eventMinimumFields.TargetBuildEventContext, eventMinimumFields.TimeStamp); _logWriter.SetColor(Color.BuildStage); if (_context.IsVerbosityAtLeast(LoggerVerbosity.Diagnostic) || (_context.Parameters.ShowEventId ?? false)) { WriteMessageAligned(_stringService.FormatResourceString("TargetMessageWithId", str, e.BuildEventContext.TargetId), prefixAlreadyWritten); } else { WriteMessageAligned(str + ":", prefixAlreadyWritten); } if (lightenText) { _logWriter.SetColor(Color.Details); } else { _logWriter.ResetColor(); } } public void WriteLinePrefix(string key, DateTime eventTimeStamp, bool isMessagePrefix) { if (_context.NumberOfProcessors == 1) { return; } _logWriter.SetColor(Color.BuildStage); var str = string.Empty; if (_context.Parameters.ShowTimeStamp || _context.IsVerbosityAtLeast(LoggerVerbosity.Diagnostic)) { str = _logFormatter.FormatLogTimeStamp(eventTimeStamp); } string formattedString; if (!isMessagePrefix || _context.IsVerbosityAtLeast(LoggerVerbosity.Detailed)) { formattedString = _stringService.FormatResourceString("BuildEventContext", str, key) + ">"; } else { formattedString = _stringService.FormatResourceString("BuildEventContext", str, string.Empty) + " "; } WritePretty(formattedString); _logWriter.ResetColor(); if (_context.PrefixWidth != 0) { return; } _context.PrefixWidth = formattedString.Length; } } }