New tests.
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / ConsoleLogger.cs
1 //
2 // ConsoleLogger.cs: Outputs to the console
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 // 
7 // (C) 2005 Marek Sieradzki
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27
28 #if NET_2_0
29
30 using System;
31 using System.Runtime.InteropServices;
32 using System.Collections.Generic;
33 using System.IO;
34 using System.Security;
35 using Microsoft.Build.Framework;
36
37 namespace Microsoft.Build.BuildEngine {
38         public class ConsoleLogger : ILogger {
39         
40                 string          parameters;
41                 int             indent;
42                 LoggerVerbosity verbosity;
43                 WriteHandler    writeHandler;
44                 int             errorCount;
45                 int             warningCount;
46                 DateTime                buildStart;
47                 bool            performanceSummary;
48                 bool            showSummary;
49                 bool            skipProjectStartedText;
50                 List<string> errors, warnings;
51                 
52                 public ConsoleLogger ()
53                         : this (LoggerVerbosity.Normal, null, null, null)
54                 {
55                 }
56
57                 public ConsoleLogger (LoggerVerbosity verbosity)
58                         : this (LoggerVerbosity.Normal, null, null, null)
59                 {
60                 }
61                 
62                 // FIXME: what about colorSet and colorReset?
63                 public ConsoleLogger (LoggerVerbosity verbosity,
64                                       WriteHandler write,
65                                       ColorSetter colorSet,
66                                       ColorResetter colorReset)
67                 {
68                         this.verbosity = verbosity;
69                         this.indent = 0;
70                         this.errorCount = 0;
71                         this.warningCount = 0;
72                         if (write == null)
73                                 this.writeHandler += new WriteHandler (WriteHandlerFunction);
74                         else
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> ();
81                 }
82                 
83                 public void ApplyParameter (string parameterName,
84                                             string parameterValue)
85                 {
86                         // FIXME: what we should do here? in msbuild it isn't
87                         // changing "parameters" property
88                 }
89
90                 public virtual void Initialize (IEventSource eventSource)
91                 {
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);
103                 }
104                 
105                 public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
106                 {
107                         WriteLine (String.Empty);
108                         WriteLine (String.Format ("Build started {0}.", args.Timestamp));
109                         WriteLine ("__________________________________________________");
110                         buildStart = args.Timestamp;
111                 }
112                 
113                 public void BuildFinishedHandler (object sender, BuildFinishedEventArgs args)
114                 {
115                         if (args.Succeeded == true) {
116                                 WriteLine ("Build succeeded.");
117                         } else {
118                                 WriteLine ("Build failed.");
119                         }
120                         if (performanceSummary == true) {
121                         }
122
123                         if (errors.Count > 0) {
124                                 WriteLine ("Errors:");
125                                 foreach (string error in errors)
126                                         WriteLine (error);
127                         }
128
129                         if (warnings.Count > 0) {
130                                 WriteLine ("Warnings:");
131                                 foreach (string warning in warnings)
132                                         WriteLine (warning);
133                         }
134
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));
141                         } 
142                 }
143
144                 public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args)
145                 {
146                         WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile, args.TargetNames));
147                         WriteLine (String.Empty);
148                 }
149                 
150                 public void ProjectFinishedHandler (object sender, ProjectFinishedEventArgs args)
151                 {
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);
156                         }
157                 }
158                 
159                 public void TargetStartedHandler (object sender, TargetStartedEventArgs args)
160                 {
161                         WriteLine (String.Format ("Target {0}:",args.TargetName));
162                         indent++;
163                 }
164                 
165                 public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args)
166                 {
167                         indent--;
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"));
172                         if (!args.Succeeded)
173                                 errorCount++;
174                         WriteLine (String.Empty);
175                 }
176                 
177                 public void TaskStartedHandler (object sender, TaskStartedEventArgs args)
178                 {
179                         if (this.verbosity == LoggerVerbosity.Diagnostic)
180                                 WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
181                         indent++;
182                 }
183                 
184                 public void TaskFinishedHandler (object sender, TaskFinishedEventArgs args)
185                 {
186                         indent--;
187                         if (this.verbosity == LoggerVerbosity.Diagnostic) {
188                                 if (args.Succeeded)
189                                         WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
190                                 else {
191                                         WriteLine (String.Format ("Task \"{0}\" execution failed", args.TaskName));
192                                         errorCount++;
193                                 }
194                         }
195                 }
196                 
197                 public void MessageHandler (object sender, BuildMessageEventArgs args)
198                 {
199                         if (IsMessageOk (args)) {
200                                 WriteLine (args.Message);
201                         }
202                 }
203                 
204                 public void WarningHandler (object sender, BuildWarningEventArgs args)
205                 {
206                         string msg = FormatWarningEvent (args);
207                         if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))
208                                 WriteLineWithoutIndent (msg);
209                         warnings.Add (msg);
210                         warningCount++;
211                 }
212                 
213                 public void ErrorHandler (object sender, BuildErrorEventArgs args)
214                 {
215                         string msg = FormatErrorEvent (args);
216                         if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) 
217                                 WriteLineWithoutIndent (msg);
218                         errors.Add (msg);
219                         errorCount++;
220                 }
221                 
222                 [MonoTODO]
223                 public void CustomEventHandler (object sender, CustomBuildEventArgs args)
224                 {
225                 }
226                 
227                 private void WriteLine (string message)
228                 {
229                         for (int i = 0; i < indent; i++)
230                                 Console.Write ('\t');
231                         writeHandler (message);
232                 }
233                 
234                 private void WriteLineWithoutIndent (string message)
235                 {
236                         writeHandler (message);
237                 }
238                 
239                 private void WriteHandlerFunction (string message)
240                 {
241                         Console.WriteLine (message);
242                 }
243                 
244                 private void ParseParameters ()
245                 {
246                         string[] splittedParameters = parameters.Split (';');
247                         foreach (string s in splittedParameters ) {
248                                 switch (s) {
249                                 case "PerformanceSummary":
250                                         this.performanceSummary = true;
251                                         break;
252                                 case "NoSummary":
253                                         this.showSummary = false;
254                                         break;
255                                 default:
256                                         throw new ArgumentException ("Invalid parameter.");
257                                 }
258                         }
259                 }
260                 
261                 public virtual void Shutdown ()
262                 {
263                 }
264
265                 static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
266                 
267                 private string FormatErrorEvent (BuildErrorEventArgs args)
268                 {
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;
272                                 
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);
278
279                                 return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
280                                                       args.File, args.LineNumber,
281                                                       subprefix, subcat, args.Code, args.Message);
282                         } else {
283                                 return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
284                                         args.Message);
285                         }
286                 }
287
288                 private string FormatWarningEvent (BuildWarningEventArgs args)
289                 {
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;
293
294                         // FIXME: show more complicated args
295                         if (args.LineNumber != 0){
296
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);
301                                 }
302                                 return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
303                                                       args.File, args.LineNumber,
304                                                       subprefix, subcat, args.Code, args.Message);
305                         } else {
306                                 return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
307                                         args.Message);
308                         }
309                 }
310                 
311                 private bool IsMessageOk (BuildMessageEventArgs bsea)
312                 {
313                         if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
314                                 return true;
315                         } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
316                                 return true;
317                         } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
318                                 return true;
319                         } else
320                                 return false;
321                 }
322                 
323                 private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
324                 {
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) {
334                                         return true;
335                                 } else
336                                         return false;
337                 }
338
339                 public string Parameters {
340                         get {
341                                 return parameters;
342                         }
343                         set {
344                                 if (value == null)
345                                         throw new ArgumentNullException ();
346                                 parameters = value;
347                                 if (parameters != String.Empty)
348                                         ParseParameters ();
349                         }
350                 }
351                 
352                 public bool ShowSummary {
353                         get { return showSummary; }
354                         set { showSummary = value; }
355                 }
356                 
357                 public bool SkipProjectStartedText {
358                         get { return skipProjectStartedText; }
359                         set { skipProjectStartedText = value; }
360                 }
361
362                 public LoggerVerbosity Verbosity {
363                         get { return verbosity; }
364                         set { verbosity = value; }
365                 }
366
367                 protected WriteHandler WriteHandler {
368                         get { return writeHandler; }
369                         set { writeHandler = value; }
370                 }
371         }
372 }
373
374 #endif