2 // ConsoleLogger.cs: Outputs to the console
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Runtime.InteropServices;
30 using System.Collections;
31 using System.Collections.Generic;
34 using System.Security;
36 using Microsoft.Build.Framework;
38 #if MICROSOFT_BUILD_DLL
39 namespace Microsoft.Build.Logging
41 namespace Microsoft.Build.BuildEngine
44 public class ConsoleLogger : ILogger {
47 LoggerVerbosity verbosity;
48 WriteHandler writeHandler;
49 bool skipProjectStartedText;
50 ConsoleColor errorColor, warningColor, eventColor, messageColor, highMessageColor;
52 ColorResetter colorReset;
53 IEventSource eventSource;
54 bool no_message_color, use_colors;
55 ConsoleLoggerParameter config = new ConsoleLoggerParameter ();
57 public ConsoleLogger ()
58 : this (LoggerVerbosity.Normal, null, null, null)
62 public ConsoleLogger (LoggerVerbosity verbosity)
63 : this (verbosity, null, null, null)
67 public ConsoleLogger (LoggerVerbosity verbosity,
70 ColorResetter colorReset)
72 this.verbosity = verbosity;
74 this.writeHandler += new WriteHandler (WriteHandlerFunction);
76 this.writeHandler += write;
77 this.skipProjectStartedText = false;
78 this.colorSet = colorSet;
79 this.colorReset = colorReset;
82 errorColor = ConsoleColor.DarkRed;
83 warningColor = ConsoleColor.DarkYellow;
84 eventColor = ConsoleColor.DarkCyan;
85 messageColor = ConsoleColor.DarkGray;
86 highMessageColor = ConsoleColor.White;
88 // if message color is not set via the env var,
89 // then don't use any color for it.
90 no_message_color = true;
93 if (colorSet == null || colorReset == null)
97 string config = Environment.GetEnvironmentVariable ("XBUILD_COLORS");
103 if (config == "disable")
107 string [] pairs = config.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
108 foreach (string pair in pairs) {
109 string [] parts = pair.Split (new char[] {'='}, StringSplitOptions.RemoveEmptyEntries);
110 if (parts.Length != 2)
113 if (parts [0] == "errors")
114 TryParseConsoleColor (parts [1], ref errorColor);
115 else if (parts [0] == "warnings")
116 TryParseConsoleColor (parts [1], ref warningColor);
117 else if (parts [0] == "events")
118 TryParseConsoleColor (parts [1], ref eventColor);
119 else if (parts [0] == "messages") {
120 if (TryParseConsoleColor (parts [1], ref messageColor)) {
121 highMessageColor = GetBrightColorFor (messageColor);
122 no_message_color = false;
128 private void WriteHandlerFunction (string message)
130 Console.WriteLine (message);
133 bool TryParseConsoleColor (string color_str, ref ConsoleColor color)
135 switch (color_str.ToLowerInvariant ()) {
136 case "black": color = ConsoleColor.Black; break;
138 case "blue": color = ConsoleColor.DarkBlue; break;
139 case "green": color = ConsoleColor.DarkGreen; break;
140 case "cyan": color = ConsoleColor.DarkCyan; break;
141 case "red": color = ConsoleColor.DarkRed; break;
142 case "magenta": color = ConsoleColor.DarkMagenta; break;
143 case "yellow": color = ConsoleColor.DarkYellow; break;
144 case "grey": color = ConsoleColor.DarkGray; break;
146 case "brightgrey": color = ConsoleColor.Gray; break;
147 case "brightblue": color = ConsoleColor.Blue; break;
148 case "brightgreen": color = ConsoleColor.Green; break;
149 case "brightcyan": color = ConsoleColor.Cyan; break;
150 case "brightred": color = ConsoleColor.Red; break;
151 case "brightmagenta": color = ConsoleColor.Magenta; break;
152 case "brightyellow": color = ConsoleColor.Yellow; break;
155 case "brightwhite": color = ConsoleColor.White; break;
156 default: return false;
162 ConsoleColor GetBrightColorFor (ConsoleColor color)
165 case ConsoleColor.DarkBlue: return ConsoleColor.Blue;
166 case ConsoleColor.DarkGreen: return ConsoleColor.Green;
167 case ConsoleColor.DarkCyan: return ConsoleColor.Cyan;
168 case ConsoleColor.DarkRed: return ConsoleColor.Red;
169 case ConsoleColor.DarkMagenta: return ConsoleColor.Magenta;
170 case ConsoleColor.DarkYellow: return ConsoleColor.Yellow;
171 case ConsoleColor.DarkGray: return ConsoleColor.Gray;
172 case ConsoleColor.Gray: return ConsoleColor.White;
174 default: return color;
178 class ConsoleLoggerParameter
180 public ConsoleLoggerParameter ()
184 public bool PerformanceSummary { get; set; }
185 public bool ShowSummary { get; set; }
186 public bool NoItemAndPropertyList { get; set; }
189 public void ApplyParameter (string parameterName,
190 string parameterValue)
192 switch (parameterName) {
193 case "PerformanceSummary":
194 config.PerformanceSummary = true;
197 config.ShowSummary = true;
200 config.ShowSummary = false;
202 case "NoItemAndPropertyList":
203 config.NoItemAndPropertyList = true;
206 if (parameterName.StartsWith ("Verbosity="))
207 ParseVerbosity (parameterName);
212 void ParseVerbosity (string s)
215 if (!TrySplitKeyValuePair (s, out key, out value))
216 throw new LoggerException ("Unknown Verbosity, should be set as 'Verbosity=<verbosity>'");
221 Verbosity = LoggerVerbosity.Quiet;
225 Verbosity = LoggerVerbosity.Minimal;
229 Verbosity = LoggerVerbosity.Normal;
233 Verbosity = LoggerVerbosity.Detailed;
237 Verbosity = LoggerVerbosity.Diagnostic;
240 throw new LoggerException (String.Format ("Unknown verbosity - '{0}'", s));
244 bool TrySplitKeyValuePair (string pair, out string key, out string value)
247 string[] parts = pair.Split ('=');
248 if (parts.Length != 2)
256 public virtual void Initialize (IEventSource eventSource)
258 this.eventSource = eventSource;
260 eventSource.BuildStarted += BuildStartedHandler;
261 eventSource.BuildFinished += BuildFinishedHandler;
263 eventSource.ProjectStarted += PushEvent;
264 eventSource.ProjectFinished += PopEvent;
266 eventSource.TargetStarted += PushEvent;
267 eventSource.TargetFinished += PopEvent;
269 eventSource.TaskStarted += PushEvent;
270 eventSource.TaskFinished += PopEvent;
272 eventSource.MessageRaised += MessageHandler;
273 eventSource.WarningRaised += WarningHandler;
274 eventSource.ErrorRaised += ErrorHandler;
276 if (!String.IsNullOrEmpty (parameters))
280 Dictionary<object,BuildRecord> build_records = new Dictionary<object, BuildRecord> ();
282 object dummy_key = new object ();
284 BuildRecord GetBuildRecord (object sender)
287 // FIXME: our Microsoft.Build.Engine shouldn't give different "sender" object for each event
288 // during the same build run. But it actually does.
289 // It is problematic for parallel build because it is impossible to determine right "ongoing build"
290 // record for the event without correct sender object.
291 // Hence we expect sender as a valid object only if it is IBuildEngine4 -
292 // only Microsoft.Build.Internal.BuildEngine4 implements it so far.
293 // (Used IBuildEngine3 because it needs to build for NET_4_0).
295 var key = sender as IBuildEngine3 ?? dummy_key;
299 if (!build_records.TryGetValue (key, out r)) {
300 r = new BuildRecord (this);
301 build_records.Add (key, r);
306 public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
308 GetBuildRecord (sender).BuildStartedHandler (sender, args);
311 public void BuildFinishedHandler (object sender, BuildFinishedEventArgs args)
313 GetBuildRecord (sender).BuildFinishedHandler (args);
314 build_records.Remove (sender);
317 void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
319 GetBuildRecord (sender).PushEvent (sender, args);
321 void PopEvent<T> (object sender, T args) where T: BuildStatusEventArgs
323 GetBuildRecord (sender).PopEvent (args);
325 public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args)
327 GetBuildRecord (sender).ProjectStartedHandler (args);
329 public void ProjectFinishedHandler (object sender, ProjectFinishedEventArgs args)
331 GetBuildRecord (sender).ProjectFinishedHandler (args);
333 public void TargetStartedHandler (object sender, TargetStartedEventArgs args)
335 GetBuildRecord (sender).TargetStartedHandler (args);
337 public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args)
339 GetBuildRecord (sender).TargetFinishedHandler (args);
341 public void TaskStartedHandler (object sender, TaskStartedEventArgs args)
343 GetBuildRecord (sender).TaskStartedHandler (args);
345 public void TaskFinishedHandler (object sender, TaskFinishedEventArgs args)
347 GetBuildRecord (sender).TaskFinishedHandler (args);
349 public void MessageHandler (object sender, BuildMessageEventArgs args)
351 GetBuildRecord (sender).MessageHandler (args);
353 public void WarningHandler (object sender, BuildWarningEventArgs args)
355 GetBuildRecord (sender).WarningHandler (args);
357 public void ErrorHandler (object sender, BuildErrorEventArgs args)
359 GetBuildRecord (sender).ErrorHandler (args);
363 public void CustomEventHandler (object sender, CustomBuildEventArgs args)
365 build_records [sender].CustomHandler (args);
368 void SetColor (ConsoleColor color)
380 private void ParseParameters ()
382 string[] splittedParameters = parameters.Split (';');
383 foreach (string s in splittedParameters )
384 ApplyParameter (s, null);
387 public virtual void Shutdown ()
389 if (eventSource == null)
392 eventSource.BuildStarted -= BuildStartedHandler;
393 eventSource.BuildFinished -= BuildFinishedHandler;
395 eventSource.ProjectStarted -= PushEvent;
396 eventSource.ProjectFinished -= PopEvent;
398 eventSource.TargetStarted -= PushEvent;
399 eventSource.TargetFinished -= PopEvent;
401 eventSource.TaskStarted -= PushEvent;
402 eventSource.TaskFinished -= PopEvent;
404 eventSource.MessageRaised -= MessageHandler;
405 eventSource.WarningRaised -= WarningHandler;
406 eventSource.ErrorRaised -= ErrorHandler;
409 public string Parameters {
415 throw new ArgumentNullException ();
421 public bool ShowSummary {
422 get { return config.ShowSummary; }
423 set { config.ShowSummary = value; }
426 public bool SkipProjectStartedText {
427 get { return skipProjectStartedText; }
428 set { skipProjectStartedText = value; }
431 public LoggerVerbosity Verbosity {
432 get { return verbosity; }
433 set { verbosity = value; }
436 protected WriteHandler WriteHandler {
437 get { return writeHandler; }
438 set { writeHandler = value; }
443 readonly ConsoleLogger parent;
445 readonly List<BuildEvent> events;
446 readonly Dictionary<string, List<string>> errorsTable;
447 readonly Dictionary<string, List<string>> warningsTable;
448 readonly SortedDictionary<string, PerfInfo> targetPerfTable, tasksPerfTable;
449 List<string> errors, warnings;
456 string current_events_string;
458 ConsoleColor eventColor {
459 get { return parent.eventColor; }
461 LoggerVerbosity verbosity {
462 get { return parent.Verbosity; }
465 public BuildRecord (ConsoleLogger parent)
467 this.parent = parent;
471 this.warningCount = 0;
472 errors = new List<string> ();
473 warnings = new List<string> ();
474 events = new List<BuildEvent> ();
475 errorsTable = new Dictionary<string, List<string>> ();
476 warningsTable = new Dictionary<string, List<string>> ();
477 targetPerfTable = new SortedDictionary<string, PerfInfo> ();
478 tasksPerfTable = new SortedDictionary<string, PerfInfo> ();
481 internal void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
483 BuildEvent be = new BuildEvent {
486 StartHandlerHasExecuted = false,
487 ConsoleLogger = this.parent
491 current_events_string = null;
494 void PopEvent<T> (object sender, T finished_args) where T: BuildStatusEventArgs
496 PopEvent (finished_args);
499 internal void PopEvent<T> (T finished_args) where T: BuildStatusEventArgs
501 if (events.Count == 0)
502 throw new InvalidOperationException ("INTERNAL ERROR: Trying to pop from an empty events stack");
504 BuildEvent be = events [events.Count - 1];
505 if (parent.config.PerformanceSummary || verbosity == LoggerVerbosity.Diagnostic) {
506 var args = be.EventArgs;
507 TargetStartedEventArgs tgt_args = args as TargetStartedEventArgs;
508 if (tgt_args != null) {
509 AddPerfInfo (tgt_args.TargetName, args.Timestamp, targetPerfTable);
511 TaskStartedEventArgs tsk_args = args as TaskStartedEventArgs;
512 if (tsk_args != null)
513 AddPerfInfo (tsk_args.TaskName, args.Timestamp, tasksPerfTable);
517 be.ExecuteFinishedHandler (finished_args);
518 events.RemoveAt (events.Count - 1);
519 current_events_string = null;
522 public void ResetBuildState ()
526 errorsTable.Clear ();
527 warningsTable.Clear ();
528 targetPerfTable.Clear ();
529 tasksPerfTable.Clear ();
536 projectFailed = false;
539 void AddPerfInfo (string name, DateTime start, IDictionary<string, PerfInfo> perf_table)
542 if (!perf_table.TryGetValue (name, out pi)) {
543 pi = new PerfInfo ();
544 perf_table [name] = pi;
547 pi.Time += DateTime.Now - start;
551 public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
553 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
554 WriteLine (String.Empty);
555 WriteLine (String.Format ("Build started {0}.", args.Timestamp));
556 WriteLine ("__________________________________________________");
558 buildStart = args.Timestamp;
560 PushEvent (sender, args);
563 public void BuildFinishedHandler (BuildFinishedEventArgs args)
565 BuildFinishedHandlerActual (args);
570 void BuildFinishedHandlerActual (BuildFinishedEventArgs args)
572 if (!IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
577 TimeSpan timeElapsed = args.Timestamp - buildStart;
578 if (parent.config.PerformanceSummary || verbosity == LoggerVerbosity.Diagnostic)
579 DumpPerformanceSummary ();
581 if (args.Succeeded == true && !projectFailed) {
582 WriteLine ("Build succeeded.");
584 WriteLine ("Build FAILED.");
586 if (warnings.Count > 0) {
587 WriteLine (Environment.NewLine + "Warnings:");
588 SetColor (parent.warningColor);
590 WriteLine (String.Empty);
591 foreach (KeyValuePair<string, List<string>> pair in warningsTable) {
592 if (!String.IsNullOrEmpty (pair.Key))
593 WriteLine (pair.Key);
595 string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
596 foreach (string msg in pair.Value)
597 WriteLine (String.Format ("{0}{1}", indent_str, msg));
599 WriteLine (String.Empty);
605 if (errors.Count > 0) {
606 WriteLine ("Errors:");
607 SetColor (parent.errorColor);
609 WriteLine (String.Empty);
610 foreach (KeyValuePair<string, List<string>> pair in errorsTable) {
611 if (!String.IsNullOrEmpty (pair.Key))
612 WriteLine (pair.Key);
614 string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
615 foreach (string msg in pair.Value)
616 WriteLine (String.Format ("{0}{1}", indent_str, msg));
618 WriteLine (String.Empty);
623 if (parent.ShowSummary == true){
624 WriteLine (String.Format ("\t {0} Warning(s)", warningCount));
625 WriteLine (String.Format ("\t {0} Error(s)", errorCount));
626 WriteLine (String.Empty);
627 WriteLine (String.Format ("Time Elapsed {0}", timeElapsed));
633 public void ProjectStartedHandler (ProjectStartedEventArgs args)
635 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
636 SetColor (eventColor);
637 WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile,
638 String.IsNullOrEmpty (args.TargetNames) ? "default" : args.TargetNames));
640 DumpProperties (args.Properties);
641 DumpItems (args.Items);
645 public void ProjectFinishedHandler (ProjectFinishedEventArgs args)
647 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
650 SetColor (eventColor);
651 WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile,
652 args.Succeeded ? String.Empty : "-- FAILED"));
654 WriteLine (String.Empty);
657 // no project has failed yet, so update the flag
658 projectFailed = !args.Succeeded;
661 public void TargetStartedHandler (TargetStartedEventArgs args)
663 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
665 SetColor (eventColor);
666 WriteLine (String.Empty);
667 WriteLine (String.Format ("Target {0}:",args.TargetName));
672 public void TargetFinishedHandler (TargetFinishedEventArgs args)
674 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
675 (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
676 SetColor (eventColor);
677 WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}",
678 args.TargetName, args.ProjectFile,
679 args.Succeeded ? String.Empty : "-- FAILED"));
681 WriteLine (String.Empty);
686 public void TaskStartedHandler (TaskStartedEventArgs args)
688 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
689 SetColor (eventColor);
690 WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
696 public void TaskFinishedHandler (TaskFinishedEventArgs args)
699 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
700 (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
701 SetColor (eventColor);
703 WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
705 WriteLine (String.Format ("Task \"{0}\" execution -- FAILED", args.TaskName));
710 public void MessageHandler (BuildMessageEventArgs args)
712 if (IsMessageOk (args)) {
713 if (parent.no_message_color) {
714 ExecutePendingEventHandlers ();
715 WriteLine (args.Message);
717 ExecutePendingEventHandlers ();
718 SetColor (args.Importance == MessageImportance.High ? parent.highMessageColor : parent.messageColor);
719 WriteLine (args.Message);
725 public void WarningHandler (BuildWarningEventArgs args)
727 string msg = FormatWarningEvent (args);
728 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
729 ExecutePendingEventHandlers ();
730 SetColor (parent.warningColor);
731 WriteLineWithoutIndent (msg);
736 List<string> list = null;
737 if (!warningsTable.TryGetValue (EventsAsString, out list))
738 warningsTable [EventsAsString] = list = new List<string> ();
744 public void ErrorHandler (BuildErrorEventArgs args)
746 string msg = FormatErrorEvent (args);
747 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
748 ExecutePendingEventHandlers ();
749 SetColor (parent.errorColor);
750 WriteLineWithoutIndent (msg);
755 List<string> list = null;
756 if (!errorsTable.TryGetValue (EventsAsString, out list))
757 errorsTable [EventsAsString] = list = new List<string> ();
762 public void CustomHandler (CustomBuildEventArgs args)
766 private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
768 if (v == LoggerVerbosity.Diagnostic) {
769 return LoggerVerbosity.Diagnostic <= verbosity;
770 } else if (v == LoggerVerbosity.Detailed) {
771 return LoggerVerbosity.Detailed <= verbosity;
772 } else if (v == LoggerVerbosity.Normal) {
773 return LoggerVerbosity.Normal <= verbosity;
774 } else if (v == LoggerVerbosity.Minimal) {
775 return LoggerVerbosity.Minimal <= verbosity;
776 } else if (v == LoggerVerbosity.Quiet) {
782 void DumpItems (IEnumerable items)
784 if (parent.config.NoItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic) || items == null)
787 SetColor (eventColor);
788 WriteLine (String.Empty);
789 WriteLine ("Initial Items:");
794 var items_table = new SortedDictionary<string, List<ITaskItem>> ();
795 foreach (DictionaryEntry de in items) {
796 string key = (string)de.Key;
797 if (!items_table.ContainsKey (key))
798 items_table [key] = new List<ITaskItem> ();
800 items_table [key].Add ((ITaskItem) de.Value);
803 foreach (string name in items_table.Keys) {
806 foreach (ITaskItem item in items_table [name])
807 WriteLine (item.ItemSpec);
812 string EventsAsString {
814 if (current_events_string == null)
815 current_events_string = EventsToString ();
816 return current_events_string;
820 private bool IsMessageOk (BuildMessageEventArgs bsea)
822 if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
824 } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
826 } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
832 void DumpProperties (IEnumerable properties)
834 if (parent.config.NoItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic))
837 SetColor (eventColor);
838 WriteLine (String.Empty);
839 WriteLine ("Initial Properties:");
842 if (properties == null)
845 var dict = new SortedDictionary<string, string> ();
846 foreach (DictionaryEntry de in properties)
847 dict [(string)de.Key] = (string)de.Value;
849 foreach (KeyValuePair<string, string> pair in dict)
850 WriteLine (String.Format ("{0} = {1}", pair.Key, pair.Value));
853 private void WriteLine (string message)
856 StringBuilder sb = new StringBuilder ();
857 for (int i = 0; i < indent; i++)
860 string indent_str = sb.ToString ();
862 foreach (string line in message.Split (new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries))
863 parent.writeHandler (indent_str + line);
865 parent.writeHandler (message);
869 void ExecutePendingEventHandlers ()
871 foreach (var be in events)
872 be.ExecuteStartedHandler ();
875 string EventsToString ()
877 StringBuilder sb = new StringBuilder ();
879 string last_imported_target_file = String.Empty;
880 for (int i = 0; i < events.Count; i ++) {
881 var args = events [i].EventArgs;
882 ProjectStartedEventArgs pargs = args as ProjectStartedEventArgs;
884 sb.AppendFormat ("{0} ({1}) ->\n", pargs.ProjectFile,
885 String.IsNullOrEmpty (pargs.TargetNames) ?
888 last_imported_target_file = String.Empty;
892 TargetStartedEventArgs targs = args as TargetStartedEventArgs;
894 if (targs.TargetFile != targs.ProjectFile && targs.TargetFile != last_imported_target_file)
895 // target from an imported file,
896 // and it hasn't been mentioned as yet
897 sb.AppendFormat ("{0} ", targs.TargetFile);
899 last_imported_target_file = targs.TargetFile;
900 sb.AppendFormat ("({0} target) ->\n", targs.TargetName);
904 return sb.ToString ();
907 void DumpPerformanceSummary ()
909 SetColor (eventColor);
910 WriteLine ("Target perfomance summary:");
913 foreach (var pi in targetPerfTable.OrderBy (pair => pair.Value.Time))
914 WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
916 WriteLine (String.Empty);
918 SetColor (eventColor);
919 WriteLine ("Tasks perfomance summary:");
922 foreach (var pi in tasksPerfTable.OrderBy (pair => pair.Value.Time))
923 WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
925 WriteLine (String.Empty);
928 private string FormatErrorEvent (BuildErrorEventArgs args)
930 // For some reason we get an 1-char empty string as Subcategory somtimes.
931 string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
932 string subcat = subprefix == "" ? "" : args.Subcategory;
934 if (args.LineNumber != 0){
935 if (args.ColumnNumber != 0 && !InEmacs)
936 return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
937 args.File, args.LineNumber, args.ColumnNumber,
938 subprefix, subcat, args.Code, args.Message);
940 return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
941 args.File, args.LineNumber,
942 subprefix, subcat, args.Code, args.Message);
944 return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
949 static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
951 private string FormatWarningEvent (BuildWarningEventArgs args)
953 // For some reason we get an 1-char empty string as Subcategory somtimes.
954 string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
955 string subcat = subprefix == "" ? "" : args.Subcategory;
957 // FIXME: show more complicated args
958 if (args.LineNumber != 0){
960 if (args.ColumnNumber != 0 && !InEmacs) {
961 return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
962 args.File, args.LineNumber, args.ColumnNumber,
963 subprefix, subcat, args.Code, args.Message);
965 return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
966 args.File, args.LineNumber,
967 subprefix, subcat, args.Code, args.Message);
969 return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
974 void SetColor (ConsoleColor color)
976 if (parent.use_colors)
977 parent.colorSet (color);
982 if (parent.use_colors)
983 parent.colorReset ();
986 private void WriteLineWithoutIndent (string message)
988 parent.writeHandler (message);
994 public object Sender;
995 public BuildStatusEventArgs EventArgs;
996 public bool StartHandlerHasExecuted;
997 public ConsoleLogger ConsoleLogger;
999 public void ExecuteStartedHandler ()
1001 if (StartHandlerHasExecuted)
1004 if (EventArgs is ProjectStartedEventArgs)
1005 ConsoleLogger.ProjectStartedHandler (Sender, (ProjectStartedEventArgs)EventArgs);
1006 else if (EventArgs is TargetStartedEventArgs)
1007 ConsoleLogger.TargetStartedHandler (Sender, (TargetStartedEventArgs)EventArgs);
1008 else if (EventArgs is TaskStartedEventArgs)
1009 ConsoleLogger.TaskStartedHandler (Sender, (TaskStartedEventArgs)EventArgs);
1010 else if (!(EventArgs is BuildStartedEventArgs))
1011 throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
1013 StartHandlerHasExecuted = true;
1016 public void ExecuteFinishedHandler (BuildStatusEventArgs finished_args)
1018 if (!StartHandlerHasExecuted)
1021 if (EventArgs is ProjectStartedEventArgs)
1022 ConsoleLogger.ProjectFinishedHandler (Sender, finished_args as ProjectFinishedEventArgs);
1023 else if (EventArgs is TargetStartedEventArgs)
1024 ConsoleLogger.TargetFinishedHandler (Sender, finished_args as TargetFinishedEventArgs);
1025 else if (EventArgs is TaskStartedEventArgs)
1026 ConsoleLogger.TaskFinishedHandler (Sender, finished_args as TaskFinishedEventArgs);
1027 else if (!(EventArgs is BuildStartedEventArgs))
1028 throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
1033 public TimeSpan Time;
1034 public int NumberOfCalls;