PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs

https://bitbucket.org/danipen/mono
C# | 904 lines | 735 code | 132 blank | 37 comment | 176 complexity | fbd0e50b3d185477300d57e585d8446b MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  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. using System;
  28. using System.Runtime.InteropServices;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using System.IO;
  32. using System.Linq;
  33. using System.Security;
  34. using System.Text;
  35. using Microsoft.Build.Framework;
  36. namespace Microsoft.Build.BuildEngine {
  37. public class ConsoleLogger : ILogger {
  38. string parameters;
  39. int indent;
  40. LoggerVerbosity verbosity;
  41. WriteHandler writeHandler;
  42. int errorCount;
  43. int warningCount;
  44. DateTime buildStart;
  45. bool performanceSummary;
  46. bool showSummary;
  47. bool skipProjectStartedText;
  48. List<string> errors, warnings;
  49. bool projectFailed;
  50. ConsoleColor errorColor, warningColor, eventColor, messageColor, highMessageColor;
  51. ColorSetter colorSet;
  52. ColorResetter colorReset;
  53. IEventSource eventSource;
  54. bool no_message_color, use_colors;
  55. bool noItemAndPropertyList;
  56. List<BuildEvent> events;
  57. Dictionary<string, List<string>> errorsTable;
  58. Dictionary<string, List<string>> warningsTable;
  59. SortedDictionary<string, PerfInfo> targetPerfTable, tasksPerfTable;
  60. string current_events_string;
  61. public ConsoleLogger ()
  62. : this (LoggerVerbosity.Normal, null, null, null)
  63. {
  64. }
  65. public ConsoleLogger (LoggerVerbosity verbosity)
  66. : this (LoggerVerbosity.Normal, null, null, null)
  67. {
  68. }
  69. public ConsoleLogger (LoggerVerbosity verbosity,
  70. WriteHandler write,
  71. ColorSetter colorSet,
  72. ColorResetter colorReset)
  73. {
  74. this.verbosity = verbosity;
  75. this.indent = 0;
  76. this.errorCount = 0;
  77. this.warningCount = 0;
  78. if (write == null)
  79. this.writeHandler += new WriteHandler (WriteHandlerFunction);
  80. else
  81. this.writeHandler += write;
  82. this.performanceSummary = false;
  83. this.showSummary = true;
  84. this.skipProjectStartedText = false;
  85. errors = new List<string> ();
  86. warnings = new List<string> ();
  87. this.colorSet = colorSet;
  88. this.colorReset = colorReset;
  89. events = new List<BuildEvent> ();
  90. errorsTable = new Dictionary<string, List<string>> ();
  91. warningsTable = new Dictionary<string, List<string>> ();
  92. targetPerfTable = new SortedDictionary<string, PerfInfo> ();
  93. tasksPerfTable = new SortedDictionary<string, PerfInfo> ();
  94. //defaults
  95. errorColor = ConsoleColor.DarkRed;
  96. warningColor = ConsoleColor.DarkYellow;
  97. eventColor = ConsoleColor.DarkCyan;
  98. messageColor = ConsoleColor.DarkGray;
  99. highMessageColor = ConsoleColor.White;
  100. // if message color is not set via the env var,
  101. // then don't use any color for it.
  102. no_message_color = true;
  103. use_colors = false;
  104. if (colorSet == null || colorReset == null)
  105. return;
  106. // color support
  107. string config = Environment.GetEnvironmentVariable ("XBUILD_COLORS");
  108. if (config == null) {
  109. use_colors = true;
  110. return;
  111. }
  112. if (config == "disable")
  113. return;
  114. use_colors = true;
  115. string [] pairs = config.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
  116. foreach (string pair in pairs) {
  117. string [] parts = pair.Split (new char[] {'='}, StringSplitOptions.RemoveEmptyEntries);
  118. if (parts.Length != 2)
  119. continue;
  120. if (parts [0] == "errors")
  121. TryParseConsoleColor (parts [1], ref errorColor);
  122. else if (parts [0] == "warnings")
  123. TryParseConsoleColor (parts [1], ref warningColor);
  124. else if (parts [0] == "events")
  125. TryParseConsoleColor (parts [1], ref eventColor);
  126. else if (parts [0] == "messages") {
  127. if (TryParseConsoleColor (parts [1], ref messageColor)) {
  128. highMessageColor = GetBrightColorFor (messageColor);
  129. no_message_color = false;
  130. }
  131. }
  132. }
  133. }
  134. bool TryParseConsoleColor (string color_str, ref ConsoleColor color)
  135. {
  136. switch (color_str.ToLowerInvariant ()) {
  137. 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;
  145. case "brightgrey": color = ConsoleColor.Gray; break;
  146. case "brightblue": color = ConsoleColor.Blue; break;
  147. case "brightgreen": color = ConsoleColor.Green; break;
  148. case "brightcyan": color = ConsoleColor.Cyan; break;
  149. case "brightred": color = ConsoleColor.Red; break;
  150. case "brightmagenta": color = ConsoleColor.Magenta; break;
  151. case "brightyellow": color = ConsoleColor.Yellow; break;
  152. case "white":
  153. case "brightwhite": color = ConsoleColor.White; break;
  154. default: return false;
  155. }
  156. return true;
  157. }
  158. ConsoleColor GetBrightColorFor (ConsoleColor color)
  159. {
  160. switch (color) {
  161. case ConsoleColor.DarkBlue: return ConsoleColor.Blue;
  162. case ConsoleColor.DarkGreen: return ConsoleColor.Green;
  163. case ConsoleColor.DarkCyan: return ConsoleColor.Cyan;
  164. case ConsoleColor.DarkRed: return ConsoleColor.Red;
  165. case ConsoleColor.DarkMagenta: return ConsoleColor.Magenta;
  166. case ConsoleColor.DarkYellow: return ConsoleColor.Yellow;
  167. case ConsoleColor.DarkGray: return ConsoleColor.Gray;
  168. case ConsoleColor.Gray: return ConsoleColor.White;
  169. default: return color;
  170. }
  171. }
  172. public void ApplyParameter (string parameterName,
  173. string parameterValue)
  174. {
  175. switch (parameterName) {
  176. case "PerformanceSummary":
  177. this.performanceSummary = true;
  178. break;
  179. case "Summary":
  180. this.showSummary = true;
  181. break;
  182. case "NoSummary":
  183. this.showSummary = false;
  184. break;
  185. case "NoItemAndPropertyList":
  186. this.noItemAndPropertyList = true;
  187. break;
  188. default:
  189. if (parameterName.StartsWith ("Verbosity="))
  190. ParseVerbosity (parameterName);
  191. break;
  192. }
  193. }
  194. void ParseVerbosity (string s)
  195. {
  196. string key, value;
  197. if (!TrySplitKeyValuePair (s, out key, out value))
  198. throw new LoggerException ("Unknown Verbosity, should be set as 'Verbosity=<verbosity>'");
  199. switch (value) {
  200. case "q":
  201. case "quiet":
  202. Verbosity = LoggerVerbosity.Quiet;
  203. break;
  204. case "m":
  205. case "minimal":
  206. Verbosity = LoggerVerbosity.Minimal;
  207. break;
  208. case "n":
  209. case "normal":
  210. Verbosity = LoggerVerbosity.Normal;
  211. break;
  212. case "d":
  213. case "detailed":
  214. Verbosity = LoggerVerbosity.Detailed;
  215. break;
  216. case "diag":
  217. case "diagnostic":
  218. Verbosity = LoggerVerbosity.Diagnostic;
  219. break;
  220. default:
  221. throw new LoggerException (String.Format ("Unknown verbosity - '{0}'", s));
  222. }
  223. }
  224. bool TrySplitKeyValuePair (string pair, out string key, out string value)
  225. {
  226. key = value = null;
  227. string[] parts = pair.Split ('=');
  228. if (parts.Length != 2)
  229. return false;
  230. key = parts [0];
  231. value = parts [1];
  232. return true;
  233. }
  234. public virtual void Initialize (IEventSource eventSource)
  235. {
  236. this.eventSource = eventSource;
  237. eventSource.BuildStarted += BuildStartedHandler;
  238. eventSource.BuildFinished += BuildFinishedHandler;
  239. eventSource.ProjectStarted += PushEvent;
  240. eventSource.ProjectFinished += PopEvent;
  241. eventSource.TargetStarted += PushEvent;
  242. eventSource.TargetFinished += PopEvent;
  243. eventSource.TaskStarted += PushEvent;
  244. eventSource.TaskFinished += PopEvent;
  245. eventSource.MessageRaised += MessageHandler;
  246. eventSource.WarningRaised += WarningHandler;
  247. eventSource.ErrorRaised += ErrorHandler;
  248. if (!String.IsNullOrEmpty (parameters))
  249. ParseParameters ();
  250. }
  251. public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
  252. {
  253. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
  254. WriteLine (String.Empty);
  255. WriteLine (String.Format ("Build started {0}.", args.Timestamp));
  256. WriteLine ("__________________________________________________");
  257. }
  258. buildStart = args.Timestamp;
  259. PushEvent (args);
  260. }
  261. public void BuildFinishedHandler (object sender, BuildFinishedEventArgs args)
  262. {
  263. BuildFinishedHandlerActual (args);
  264. // Reset
  265. events.Clear ();
  266. errorsTable.Clear ();
  267. warningsTable.Clear ();
  268. targetPerfTable.Clear ();
  269. tasksPerfTable.Clear ();
  270. errors.Clear ();
  271. warnings.Clear ();
  272. indent = 0;
  273. errorCount = 0;
  274. warningCount = 0;
  275. projectFailed = false;
  276. }
  277. void BuildFinishedHandlerActual (BuildFinishedEventArgs args)
  278. {
  279. if (!IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
  280. PopEvent (args);
  281. return;
  282. }
  283. TimeSpan timeElapsed = args.Timestamp - buildStart;
  284. if (performanceSummary || verbosity == LoggerVerbosity.Diagnostic)
  285. DumpPerformanceSummary ();
  286. if (args.Succeeded == true && !projectFailed) {
  287. WriteLine ("Build succeeded.");
  288. } else {
  289. WriteLine ("Build FAILED.");
  290. }
  291. if (warnings.Count > 0) {
  292. WriteLine (Environment.NewLine + "Warnings:");
  293. SetColor (warningColor);
  294. WriteLine (String.Empty);
  295. foreach (KeyValuePair<string, List<string>> pair in warningsTable) {
  296. if (!String.IsNullOrEmpty (pair.Key))
  297. WriteLine (pair.Key);
  298. string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
  299. foreach (string msg in pair.Value)
  300. WriteLine (String.Format ("{0}{1}", indent_str, msg));
  301. WriteLine (String.Empty);
  302. }
  303. ResetColor ();
  304. }
  305. if (errors.Count > 0) {
  306. WriteLine ("Errors:");
  307. SetColor (errorColor);
  308. WriteLine (String.Empty);
  309. foreach (KeyValuePair<string, List<string>> pair in errorsTable) {
  310. if (!String.IsNullOrEmpty (pair.Key))
  311. WriteLine (pair.Key);
  312. string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
  313. foreach (string msg in pair.Value)
  314. WriteLine (String.Format ("{0}{1}", indent_str, msg));
  315. WriteLine (String.Empty);
  316. }
  317. ResetColor ();
  318. }
  319. if (showSummary == true){
  320. WriteLine (String.Format ("\t {0} Warning(s)", warningCount));
  321. WriteLine (String.Format ("\t {0} Error(s)", errorCount));
  322. WriteLine (String.Empty);
  323. WriteLine (String.Format ("Time Elapsed {0}", timeElapsed));
  324. }
  325. PopEvent (args);
  326. }
  327. public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args)
  328. {
  329. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
  330. SetColor (eventColor);
  331. WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile,
  332. String.IsNullOrEmpty (args.TargetNames) ? "default" : args.TargetNames));
  333. ResetColor ();
  334. DumpProperties (args.Properties);
  335. DumpItems (args.Items);
  336. }
  337. }
  338. public void ProjectFinishedHandler (object sender, ProjectFinishedEventArgs args)
  339. {
  340. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
  341. if (indent == 1)
  342. indent --;
  343. SetColor (eventColor);
  344. WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile,
  345. args.Succeeded ? String.Empty : "-- FAILED"));
  346. ResetColor ();
  347. WriteLine (String.Empty);
  348. }
  349. if (!projectFailed)
  350. // no project has failed yet, so update the flag
  351. projectFailed = !args.Succeeded;
  352. }
  353. public void TargetStartedHandler (object sender, TargetStartedEventArgs args)
  354. {
  355. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
  356. indent++;
  357. SetColor (eventColor);
  358. WriteLine (String.Empty);
  359. WriteLine (String.Format ("Target {0}:",args.TargetName));
  360. ResetColor ();
  361. }
  362. }
  363. public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args)
  364. {
  365. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
  366. (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
  367. SetColor (eventColor);
  368. WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}",
  369. args.TargetName, args.ProjectFile,
  370. args.Succeeded ? String.Empty : "-- FAILED"));
  371. ResetColor ();
  372. WriteLine (String.Empty);
  373. }
  374. indent--;
  375. }
  376. public void TaskStartedHandler (object sender, TaskStartedEventArgs args)
  377. {
  378. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
  379. SetColor (eventColor);
  380. WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
  381. ResetColor ();
  382. }
  383. indent++;
  384. }
  385. public void TaskFinishedHandler (object sender, TaskFinishedEventArgs args)
  386. {
  387. indent--;
  388. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
  389. (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
  390. SetColor (eventColor);
  391. if (args.Succeeded)
  392. WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
  393. else
  394. WriteLine (String.Format ("Task \"{0}\" execution -- FAILED", args.TaskName));
  395. ResetColor ();
  396. }
  397. }
  398. public void MessageHandler (object sender, BuildMessageEventArgs args)
  399. {
  400. if (IsMessageOk (args)) {
  401. if (no_message_color) {
  402. ExecutePendingEventHandlers ();
  403. WriteLine (args.Message);
  404. } else {
  405. ExecutePendingEventHandlers ();
  406. SetColor (args.Importance == MessageImportance.High ? highMessageColor : messageColor);
  407. WriteLine (args.Message);
  408. ResetColor ();
  409. }
  410. }
  411. }
  412. public void WarningHandler (object sender, BuildWarningEventArgs args)
  413. {
  414. string msg = FormatWarningEvent (args);
  415. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
  416. ExecutePendingEventHandlers ();
  417. SetColor (warningColor);
  418. WriteLineWithoutIndent (msg);
  419. ResetColor ();
  420. }
  421. warnings.Add (msg);
  422. List<string> list = null;
  423. if (!warningsTable.TryGetValue (EventsAsString, out list))
  424. warningsTable [EventsAsString] = list = new List<string> ();
  425. list.Add (msg);
  426. warningCount++;
  427. }
  428. public void ErrorHandler (object sender, BuildErrorEventArgs args)
  429. {
  430. string msg = FormatErrorEvent (args);
  431. if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
  432. ExecutePendingEventHandlers ();
  433. SetColor (errorColor);
  434. WriteLineWithoutIndent (msg);
  435. ResetColor ();
  436. }
  437. errors.Add (msg);
  438. List<string> list = null;
  439. if (!errorsTable.TryGetValue (EventsAsString, out list))
  440. errorsTable [EventsAsString] = list = new List<string> ();
  441. list.Add (msg);
  442. errorCount++;
  443. }
  444. [MonoTODO]
  445. public void CustomEventHandler (object sender, CustomBuildEventArgs args)
  446. {
  447. }
  448. private void WriteLine (string message)
  449. {
  450. if (indent > 0) {
  451. StringBuilder sb = new StringBuilder ();
  452. for (int i = 0; i < indent; i++)
  453. sb.Append ('\t');
  454. string indent_str = sb.ToString ();
  455. foreach (string line in message.Split (new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries))
  456. writeHandler (indent_str + line);
  457. } else {
  458. writeHandler (message);
  459. }
  460. }
  461. void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
  462. {
  463. PushEvent (args);
  464. }
  465. void PushEvent<T> (T args) where T: BuildStatusEventArgs
  466. {
  467. BuildEvent be = new BuildEvent {
  468. EventArgs = args,
  469. StartHandlerHasExecuted = false,
  470. ConsoleLogger = this
  471. };
  472. events.Add (be);
  473. current_events_string = null;
  474. }
  475. void PopEvent<T> (object sender, T finished_args) where T: BuildStatusEventArgs
  476. {
  477. PopEvent (finished_args);
  478. }
  479. void PopEvent<T> (T finished_args) where T: BuildStatusEventArgs
  480. {
  481. if (events.Count == 0)
  482. throw new InvalidOperationException ("INTERNAL ERROR: Trying to pop from an empty events stack");
  483. BuildEvent be = events [events.Count - 1];
  484. if (performanceSummary || verbosity == LoggerVerbosity.Diagnostic) {
  485. var args = be.EventArgs;
  486. TargetStartedEventArgs tgt_args = args as TargetStartedEventArgs;
  487. if (tgt_args != null) {
  488. AddPerfInfo (tgt_args.TargetName, args.Timestamp, targetPerfTable);
  489. } else {
  490. TaskStartedEventArgs tsk_args = args as TaskStartedEventArgs;
  491. if (tsk_args != null)
  492. AddPerfInfo (tsk_args.TaskName, args.Timestamp, tasksPerfTable);
  493. }
  494. }
  495. be.ExecuteFinishedHandler (finished_args);
  496. events.RemoveAt (events.Count - 1);
  497. current_events_string = null;
  498. }
  499. void ExecutePendingEventHandlers ()
  500. {
  501. foreach (var be in events)
  502. be.ExecuteStartedHandler ();
  503. }
  504. string EventsToString ()
  505. {
  506. StringBuilder sb = new StringBuilder ();
  507. string last_imported_target_file = String.Empty;
  508. for (int i = 0; i < events.Count; i ++) {
  509. var args = events [i].EventArgs;
  510. ProjectStartedEventArgs pargs = args as ProjectStartedEventArgs;
  511. if (pargs != null) {
  512. sb.AppendFormat ("{0} ({1}) ->\n", pargs.ProjectFile,
  513. String.IsNullOrEmpty (pargs.TargetNames) ?
  514. "default targets" :
  515. pargs.TargetNames);
  516. last_imported_target_file = String.Empty;
  517. continue;
  518. }
  519. TargetStartedEventArgs targs = args as TargetStartedEventArgs;
  520. if (targs != null) {
  521. if (targs.TargetFile != targs.ProjectFile && targs.TargetFile != last_imported_target_file)
  522. // target from an imported file,
  523. // and it hasn't been mentioned as yet
  524. sb.AppendFormat ("{0} ", targs.TargetFile);
  525. last_imported_target_file = targs.TargetFile;
  526. sb.AppendFormat ("({0} target) ->\n", targs.TargetName);
  527. }
  528. }
  529. return sb.ToString ();
  530. }
  531. void AddPerfInfo (string name, DateTime start, IDictionary<string, PerfInfo> perf_table)
  532. {
  533. PerfInfo pi;
  534. if (!perf_table.TryGetValue (name, out pi)) {
  535. pi = new PerfInfo ();
  536. perf_table [name] = pi;
  537. }
  538. pi.Time += DateTime.Now - start;
  539. pi.NumberOfCalls ++;
  540. }
  541. void DumpPerformanceSummary ()
  542. {
  543. SetColor (eventColor);
  544. WriteLine ("Target perfomance summary:");
  545. ResetColor ();
  546. foreach (var pi in targetPerfTable.OrderBy (pair => pair.Value.Time))
  547. WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
  548. WriteLine (String.Empty);
  549. SetColor (eventColor);
  550. WriteLine ("Tasks perfomance summary:");
  551. ResetColor ();
  552. foreach (var pi in tasksPerfTable.OrderBy (pair => pair.Value.Time))
  553. WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
  554. WriteLine (String.Empty);
  555. }
  556. private void WriteLineWithoutIndent (string message)
  557. {
  558. writeHandler (message);
  559. }
  560. private void WriteHandlerFunction (string message)
  561. {
  562. Console.WriteLine (message);
  563. }
  564. void SetColor (ConsoleColor color)
  565. {
  566. if (use_colors)
  567. colorSet (color);
  568. }
  569. void ResetColor ()
  570. {
  571. if (use_colors)
  572. colorReset ();
  573. }
  574. private void ParseParameters ()
  575. {
  576. string[] splittedParameters = parameters.Split (';');
  577. foreach (string s in splittedParameters )
  578. ApplyParameter (s, null);
  579. }
  580. public virtual void Shutdown ()
  581. {
  582. if (eventSource == null)
  583. return;
  584. eventSource.BuildStarted -= BuildStartedHandler;
  585. eventSource.BuildFinished -= BuildFinishedHandler;
  586. eventSource.ProjectStarted -= PushEvent;
  587. eventSource.ProjectFinished -= PopEvent;
  588. eventSource.TargetStarted -= PushEvent;
  589. eventSource.TargetFinished -= PopEvent;
  590. eventSource.TaskStarted -= PushEvent;
  591. eventSource.TaskFinished -= PopEvent;
  592. eventSource.MessageRaised -= MessageHandler;
  593. eventSource.WarningRaised -= WarningHandler;
  594. eventSource.ErrorRaised -= ErrorHandler;
  595. }
  596. static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
  597. private string FormatErrorEvent (BuildErrorEventArgs args)
  598. {
  599. // For some reason we get an 1-char empty string as Subcategory somtimes.
  600. string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
  601. string subcat = subprefix == "" ? "" : args.Subcategory;
  602. if (args.LineNumber != 0){
  603. if (args.ColumnNumber != 0 && !InEmacs)
  604. return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
  605. args.File, args.LineNumber, args.ColumnNumber,
  606. subprefix, subcat, args.Code, args.Message);
  607. return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
  608. args.File, args.LineNumber,
  609. subprefix, subcat, args.Code, args.Message);
  610. } else {
  611. return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
  612. args.Message);
  613. }
  614. }
  615. private string FormatWarningEvent (BuildWarningEventArgs args)
  616. {
  617. // For some reason we get an 1-char empty string as Subcategory somtimes.
  618. string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
  619. string subcat = subprefix == "" ? "" : args.Subcategory;
  620. // FIXME: show more complicated args
  621. if (args.LineNumber != 0){
  622. if (args.ColumnNumber != 0 && !InEmacs) {
  623. return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
  624. args.File, args.LineNumber, args.ColumnNumber,
  625. subprefix, subcat, args.Code, args.Message);
  626. }
  627. return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
  628. args.File, args.LineNumber,
  629. subprefix, subcat, args.Code, args.Message);
  630. } else {
  631. return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
  632. args.Message);
  633. }
  634. }
  635. private bool IsMessageOk (BuildMessageEventArgs bsea)
  636. {
  637. if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
  638. return true;
  639. } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
  640. return true;
  641. } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
  642. return true;
  643. } else
  644. return false;
  645. }
  646. private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
  647. {
  648. if (v == LoggerVerbosity.Diagnostic) {
  649. return LoggerVerbosity.Diagnostic <= verbosity;
  650. } else if (v == LoggerVerbosity.Detailed) {
  651. return LoggerVerbosity.Detailed <= verbosity;
  652. } else if (v == LoggerVerbosity.Normal) {
  653. return LoggerVerbosity.Normal <= verbosity;
  654. } else if (v == LoggerVerbosity.Minimal) {
  655. return LoggerVerbosity.Minimal <= verbosity;
  656. } else if (v == LoggerVerbosity.Quiet) {
  657. return true;
  658. } else
  659. return false;
  660. }
  661. void DumpProperties (IEnumerable properties)
  662. {
  663. if (noItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic))
  664. return;
  665. SetColor (eventColor);
  666. WriteLine (String.Empty);
  667. WriteLine ("Initial Properties:");
  668. ResetColor ();
  669. if (properties == null)
  670. return;
  671. var dict = new SortedDictionary<string, string> ();
  672. foreach (DictionaryEntry de in properties)
  673. dict [(string)de.Key] = (string)de.Value;
  674. foreach (KeyValuePair<string, string> pair in dict)
  675. WriteLine (String.Format ("{0} = {1}", pair.Key, pair.Value));
  676. }
  677. void DumpItems (IEnumerable items)
  678. {
  679. if (noItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic) || items == null)
  680. return;
  681. SetColor (eventColor);
  682. WriteLine (String.Empty);
  683. WriteLine ("Initial Items:");
  684. ResetColor ();
  685. if (items == null)
  686. return;
  687. var items_table = new SortedDictionary<string, List<ITaskItem>> ();
  688. foreach (DictionaryEntry de in items) {
  689. string key = (string)de.Key;
  690. if (!items_table.ContainsKey (key))
  691. items_table [key] = new List<ITaskItem> ();
  692. items_table [key].Add ((ITaskItem) de.Value);
  693. }
  694. foreach (string name in items_table.Keys) {
  695. WriteLine (name);
  696. indent ++;
  697. foreach (ITaskItem item in items_table [name])
  698. WriteLine (item.ItemSpec);
  699. indent--;
  700. }
  701. }
  702. public string Parameters {
  703. get {
  704. return parameters;
  705. }
  706. set {
  707. if (value == null)
  708. throw new ArgumentNullException ();
  709. parameters = value;
  710. }
  711. }
  712. string EventsAsString {
  713. get {
  714. if (current_events_string == null)
  715. current_events_string = EventsToString ();
  716. return current_events_string;
  717. }
  718. }
  719. public bool ShowSummary {
  720. get { return showSummary; }
  721. set { showSummary = value; }
  722. }
  723. public bool SkipProjectStartedText {
  724. get { return skipProjectStartedText; }
  725. set { skipProjectStartedText = value; }
  726. }
  727. public LoggerVerbosity Verbosity {
  728. get { return verbosity; }
  729. set { verbosity = value; }
  730. }
  731. protected WriteHandler WriteHandler {
  732. get { return writeHandler; }
  733. set { writeHandler = value; }
  734. }
  735. }
  736. class BuildEvent {
  737. public BuildStatusEventArgs EventArgs;
  738. public bool StartHandlerHasExecuted;
  739. public ConsoleLogger ConsoleLogger;
  740. public void ExecuteStartedHandler ()
  741. {
  742. if (StartHandlerHasExecuted)
  743. return;
  744. if (EventArgs is ProjectStartedEventArgs)
  745. ConsoleLogger.ProjectStartedHandler (null, (ProjectStartedEventArgs)EventArgs);
  746. else if (EventArgs is TargetStartedEventArgs)
  747. ConsoleLogger.TargetStartedHandler (null, (TargetStartedEventArgs)EventArgs);
  748. else if (EventArgs is TaskStartedEventArgs)
  749. ConsoleLogger.TaskStartedHandler (null, (TaskStartedEventArgs)EventArgs);
  750. else if (!(EventArgs is BuildStartedEventArgs))
  751. throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
  752. StartHandlerHasExecuted = true;
  753. }
  754. public void ExecuteFinishedHandler (BuildStatusEventArgs finished_args)
  755. {
  756. if (!StartHandlerHasExecuted)
  757. return;
  758. if (EventArgs is ProjectStartedEventArgs)
  759. ConsoleLogger.ProjectFinishedHandler (null, finished_args as ProjectFinishedEventArgs);
  760. else if (EventArgs is TargetStartedEventArgs)
  761. ConsoleLogger.TargetFinishedHandler (null, finished_args as TargetFinishedEventArgs);
  762. else if (EventArgs is TaskStartedEventArgs)
  763. ConsoleLogger.TaskFinishedHandler (null, finished_args as TaskFinishedEventArgs);
  764. else if (!(EventArgs is BuildStartedEventArgs))
  765. throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
  766. }
  767. }
  768. class PerfInfo {
  769. public TimeSpan Time;
  770. public int NumberOfCalls;
  771. }
  772. }