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.
31 using System.Runtime.InteropServices;
32 using System.Collections.Generic;
34 using System.Security;
35 using Microsoft.Build.Framework;
37 namespace Microsoft.Build.BuildEngine {
38 public class ConsoleLogger : ILogger {
42 LoggerVerbosity verbosity;
43 WriteHandler writeHandler;
47 bool performanceSummary;
49 bool skipProjectStartedText;
50 List<string> errors, warnings;
52 public ConsoleLogger ()
53 : this (LoggerVerbosity.Normal, null, null, null)
57 public ConsoleLogger (LoggerVerbosity verbosity)
58 : this (LoggerVerbosity.Normal, null, null, null)
62 // FIXME: what about colorSet and colorReset?
63 public ConsoleLogger (LoggerVerbosity verbosity,
66 ColorResetter colorReset)
68 this.verbosity = verbosity;
71 this.warningCount = 0;
73 this.writeHandler += new WriteHandler (WriteHandlerFunction);
75 this.writeHandler += write;
76 this.performanceSummary = false;
77 this.showSummary = true;
78 this.skipProjectStartedText = false;
79 errors = new List<string> ();
80 warnings = new List<string> ();
83 public void ApplyParameter (string parameterName,
84 string parameterValue)
86 // FIXME: what we should do here? in msbuild it isn't
87 // changing "parameters" property
90 public virtual void Initialize (IEventSource eventSource)
92 eventSource.BuildStarted += new BuildStartedEventHandler (BuildStartedHandler);
93 eventSource.BuildFinished += new BuildFinishedEventHandler (BuildFinishedHandler);
94 eventSource.ProjectStarted += new ProjectStartedEventHandler (ProjectStartedHandler);
95 eventSource.ProjectFinished += new ProjectFinishedEventHandler (ProjectFinishedHandler);
96 eventSource.TargetStarted += new TargetStartedEventHandler (TargetStartedHandler);
97 eventSource.TargetFinished += new TargetFinishedEventHandler (TargetFinishedHandler);
98 eventSource.TaskStarted += new TaskStartedEventHandler (TaskStartedHandler);
99 eventSource.TaskFinished += new TaskFinishedEventHandler (TaskFinishedHandler);
100 eventSource.MessageRaised += new BuildMessageEventHandler (MessageHandler);
101 eventSource.WarningRaised += new BuildWarningEventHandler (WarningHandler);
102 eventSource.ErrorRaised += new BuildErrorEventHandler (ErrorHandler);
105 public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
107 WriteLine (String.Empty);
108 WriteLine (String.Format ("Build started {0}.", args.Timestamp));
109 WriteLine ("__________________________________________________");
110 buildStart = args.Timestamp;
113 public void BuildFinishedHandler (object sender, BuildFinishedEventArgs args)
115 if (args.Succeeded == true) {
116 WriteLine ("Build succeeded.");
118 WriteLine ("Build failed.");
120 if (performanceSummary == true) {
123 if (errors.Count > 0) {
124 WriteLine ("Errors:");
125 foreach (string error in errors)
129 if (warnings.Count > 0) {
130 WriteLine ("Warnings:");
131 foreach (string warning in warnings)
135 if (showSummary == true){
136 TimeSpan timeElapsed = args.Timestamp - buildStart;
137 WriteLine (String.Format ("\t {0} Warning(s)", warningCount));
138 WriteLine (String.Format ("\t {0} Error(s)", errorCount));
139 WriteLine (String.Empty);
140 WriteLine (String.Format ("Time Elapsed {0}", timeElapsed));
144 public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args)
146 WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile, args.TargetNames));
147 WriteLine (String.Empty);
150 public void ProjectFinishedHandler (object sender, ProjectFinishedEventArgs args)
152 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
153 WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile,
154 args.Succeeded ? String.Empty : "-- FAILED"));
155 WriteLine (String.Empty);
159 public void TargetStartedHandler (object sender, TargetStartedEventArgs args)
161 WriteLine (String.Format ("Target {0}:",args.TargetName));
165 public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args)
168 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic))
169 WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}",
170 args.TargetName, args.ProjectFile,
171 args.Succeeded ? String.Empty : "-- FAILED"));
174 WriteLine (String.Empty);
177 public void TaskStartedHandler (object sender, TaskStartedEventArgs args)
179 if (this.verbosity == LoggerVerbosity.Diagnostic)
180 WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
184 public void TaskFinishedHandler (object sender, TaskFinishedEventArgs args)
187 if (this.verbosity == LoggerVerbosity.Diagnostic) {
189 WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
191 WriteLine (String.Format ("Task \"{0}\" execution failed", args.TaskName));
197 public void MessageHandler (object sender, BuildMessageEventArgs args)
199 if (IsMessageOk (args)) {
200 WriteLine (args.Message);
204 public void WarningHandler (object sender, BuildWarningEventArgs args)
206 string msg = FormatWarningEvent (args);
207 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))
208 WriteLineWithoutIndent (msg);
213 public void ErrorHandler (object sender, BuildErrorEventArgs args)
215 string msg = FormatErrorEvent (args);
216 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal))
217 WriteLineWithoutIndent (msg);
223 public void CustomEventHandler (object sender, CustomBuildEventArgs args)
227 private void WriteLine (string message)
229 for (int i = 0; i < indent; i++)
230 Console.Write ('\t');
231 writeHandler (message);
234 private void WriteLineWithoutIndent (string message)
236 writeHandler (message);
239 private void WriteHandlerFunction (string message)
241 Console.WriteLine (message);
244 private void ParseParameters ()
246 string[] splittedParameters = parameters.Split (';');
247 foreach (string s in splittedParameters ) {
249 case "PerformanceSummary":
250 this.performanceSummary = true;
253 this.showSummary = false;
256 throw new ArgumentException ("Invalid parameter.");
261 public virtual void Shutdown ()
265 static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
267 private string FormatErrorEvent (BuildErrorEventArgs args)
269 // For some reason we get an 1-char empty string as Subcategory somtimes.
270 string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
271 string subcat = subprefix == "" ? "" : args.Subcategory;
273 if (args.LineNumber != 0){
274 if (args.ColumnNumber != 0 && !InEmacs)
275 return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
276 args.File, args.LineNumber, args.ColumnNumber,
277 subprefix, subcat, args.Code, args.Message);
279 return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
280 args.File, args.LineNumber,
281 subprefix, subcat, args.Code, args.Message);
283 return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
288 private string FormatWarningEvent (BuildWarningEventArgs args)
290 // For some reason we get an 1-char empty string as Subcategory somtimes.
291 string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
292 string subcat = subprefix == "" ? "" : args.Subcategory;
294 // FIXME: show more complicated args
295 if (args.LineNumber != 0){
297 if (args.ColumnNumber != 0 && !InEmacs) {
298 return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
299 args.File, args.LineNumber, args.ColumnNumber,
300 subprefix, subcat, args.Code, args.Message);
302 return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
303 args.File, args.LineNumber,
304 subprefix, subcat, args.Code, args.Message);
306 return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
311 private bool IsMessageOk (BuildMessageEventArgs bsea)
313 if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
315 } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
317 } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
323 private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
325 if (v == LoggerVerbosity.Diagnostic) {
326 return LoggerVerbosity.Diagnostic <= verbosity;
327 } else if (v == LoggerVerbosity.Detailed) {
328 return LoggerVerbosity.Detailed <= verbosity;
329 } else if (v == LoggerVerbosity.Normal) {
330 return LoggerVerbosity.Normal <= verbosity;
331 } else if (v == LoggerVerbosity.Minimal) {
332 return LoggerVerbosity.Minimal <= verbosity;
333 } else if (v == LoggerVerbosity.Quiet) {
339 public string Parameters {
345 throw new ArgumentNullException ();
347 if (parameters != String.Empty)
352 public bool ShowSummary {
353 get { return showSummary; }
354 set { showSummary = value; }
357 public bool SkipProjectStartedText {
358 get { return skipProjectStartedText; }
359 set { skipProjectStartedText = value; }
362 public LoggerVerbosity Verbosity {
363 get { return verbosity; }
364 set { verbosity = value; }
367 protected WriteHandler WriteHandler {
368 get { return writeHandler; }
369 set { writeHandler = value; }