PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/mcs/report.cs

https://bitbucket.org/danipen/mono
C# | 1116 lines | 824 code | 195 blank | 97 comment | 117 complexity | e29e61e969b238596bb4370c1c5fd6f3 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. // report.cs: report errors and warnings.
  3. //
  4. // Author: Miguel de Icaza (miguel@ximian.com)
  5. // Marek Safar (marek.safar@gmail.com)
  6. //
  7. // Copyright 2001 Ximian, Inc. (http://www.ximian.com)
  8. // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  9. //
  10. using System;
  11. using System.IO;
  12. using System.Text;
  13. using System.Collections.Generic;
  14. using System.Diagnostics;
  15. namespace Mono.CSharp {
  16. //
  17. // Errors and warnings manager
  18. //
  19. public class Report
  20. {
  21. public const int RuntimeErrorId = 10000;
  22. Dictionary<int, WarningRegions> warning_regions_table;
  23. ReportPrinter printer;
  24. int reporting_disabled;
  25. readonly CompilerSettings settings;
  26. /// <summary>
  27. /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
  28. /// </summary>
  29. List<string> extra_information = new List<string> ();
  30. //
  31. // IF YOU ADD A NEW WARNING YOU HAVE TO ADD ITS ID HERE
  32. //
  33. public static readonly int[] AllWarnings = new int[] {
  34. 28, 67, 78,
  35. 105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197,
  36. 219, 251, 252, 253, 278, 282,
  37. 402, 414, 419, 420, 429, 436, 437, 440, 458, 464, 465, 467, 469, 472, 473,
  38. 612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693,
  39. 728,
  40. 809, 824,
  41. 1030, 1058, 1060, 1066,
  42. 1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
  43. 1607, 1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692, 1695, 1696, 1697, 1699,
  44. 1700, 1701, 1702, 1709, 1711, 1717, 1718, 1720, 1735,
  45. 1901, 1956, 1981, 1998,
  46. 2002, 2023, 2029,
  47. 3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,
  48. 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019,
  49. 3021, 3022, 3023, 3024, 3026, 3027,
  50. 4014
  51. };
  52. static HashSet<int> AllWarningsHashSet;
  53. public Report (CompilerContext context, ReportPrinter printer)
  54. {
  55. if (context == null)
  56. throw new ArgumentNullException ("settings");
  57. if (printer == null)
  58. throw new ArgumentNullException ("printer");
  59. this.settings = context.Settings;
  60. this.printer = printer;
  61. }
  62. public void DisableReporting ()
  63. {
  64. ++reporting_disabled;
  65. }
  66. public void EnableReporting ()
  67. {
  68. --reporting_disabled;
  69. }
  70. public void FeatureIsNotAvailable (CompilerContext compiler, Location loc, string feature)
  71. {
  72. string version;
  73. switch (compiler.Settings.Version) {
  74. case LanguageVersion.ISO_1:
  75. version = "1.0";
  76. break;
  77. case LanguageVersion.ISO_2:
  78. version = "2.0";
  79. break;
  80. case LanguageVersion.V_3:
  81. version = "3.0";
  82. break;
  83. case LanguageVersion.V_4:
  84. version = "4.0";
  85. break;
  86. case LanguageVersion.V_5:
  87. version = "5.0";
  88. break;
  89. default:
  90. throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version);
  91. }
  92. Error (1644, loc,
  93. "Feature `{0}' cannot be used because it is not part of the C# {1} language specification",
  94. feature, version);
  95. }
  96. public void FeatureIsNotSupported (Location loc, string feature)
  97. {
  98. Error (1644, loc,
  99. "Feature `{0}' is not supported in Mono mcs1 compiler. Consider using the `gmcs' compiler instead",
  100. feature);
  101. }
  102. public void RuntimeMissingSupport (Location loc, string feature)
  103. {
  104. Error (-88, loc, "Your .NET Runtime does not support `{0}'. Please use the latest Mono runtime instead.", feature);
  105. }
  106. /// <summary>
  107. /// In most error cases is very useful to have information about symbol that caused the error.
  108. /// Call this method before you call Report.Error when it makes sense.
  109. /// </summary>
  110. public void SymbolRelatedToPreviousError (Location loc, string symbol)
  111. {
  112. SymbolRelatedToPreviousError (loc.ToString ());
  113. }
  114. public void SymbolRelatedToPreviousError (MemberSpec ms)
  115. {
  116. if (reporting_disabled > 0 || !printer.HasRelatedSymbolSupport)
  117. return;
  118. var mc = ms.MemberDefinition as MemberCore;
  119. while (ms is ElementTypeSpec) {
  120. ms = ((ElementTypeSpec) ms).Element;
  121. mc = ms.MemberDefinition as MemberCore;
  122. }
  123. if (mc != null) {
  124. SymbolRelatedToPreviousError (mc);
  125. } else {
  126. if (ms.DeclaringType != null)
  127. ms = ms.DeclaringType;
  128. var imported_type = ms.MemberDefinition as ImportedTypeDefinition;
  129. if (imported_type != null) {
  130. var iad = imported_type.DeclaringAssembly as ImportedAssemblyDefinition;
  131. SymbolRelatedToPreviousError (iad.Location);
  132. }
  133. }
  134. }
  135. public void SymbolRelatedToPreviousError (MemberCore mc)
  136. {
  137. SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
  138. }
  139. public void SymbolRelatedToPreviousError (string loc)
  140. {
  141. string msg = String.Format ("{0} (Location of the symbol related to previous ", loc);
  142. if (extra_information.Contains (msg))
  143. return;
  144. extra_information.Add (msg);
  145. }
  146. public bool CheckWarningCode (int code, Location loc)
  147. {
  148. if (AllWarningsHashSet == null)
  149. AllWarningsHashSet = new HashSet<int> (AllWarnings);
  150. if (AllWarningsHashSet.Contains (code))
  151. return true;
  152. Warning (1691, 1, loc, "`{0}' is not a valid warning number", code);
  153. return false;
  154. }
  155. public void ExtraInformation (Location loc, string msg)
  156. {
  157. extra_information.Add (String.Format ("{0} {1}", loc, msg));
  158. }
  159. public WarningRegions RegisterWarningRegion (Location location)
  160. {
  161. WarningRegions regions;
  162. if (warning_regions_table == null) {
  163. regions = null;
  164. warning_regions_table = new Dictionary<int, WarningRegions> ();
  165. } else {
  166. warning_regions_table.TryGetValue (location.File, out regions);
  167. }
  168. if (regions == null) {
  169. regions = new WarningRegions ();
  170. warning_regions_table.Add (location.File, regions);
  171. }
  172. return regions;
  173. }
  174. public void Warning (int code, int level, Location loc, string message)
  175. {
  176. if (reporting_disabled > 0)
  177. return;
  178. if (!settings.IsWarningEnabled (code, level))
  179. return;
  180. if (warning_regions_table != null && !loc.IsNull) {
  181. WarningRegions regions;
  182. if (warning_regions_table.TryGetValue (loc.File, out regions) && !regions.IsWarningEnabled (code, loc.Row))
  183. return;
  184. }
  185. AbstractMessage msg;
  186. if (settings.IsWarningAsError (code)) {
  187. message = "Warning as Error: " + message;
  188. msg = new ErrorMessage (code, loc, message, extra_information);
  189. } else {
  190. msg = new WarningMessage (code, loc, message, extra_information);
  191. }
  192. extra_information.Clear ();
  193. printer.Print (msg, settings.ShowFullPaths);
  194. }
  195. public void Warning (int code, int level, Location loc, string format, string arg)
  196. {
  197. Warning (code, level, loc, String.Format (format, arg));
  198. }
  199. public void Warning (int code, int level, Location loc, string format, string arg1, string arg2)
  200. {
  201. Warning (code, level, loc, String.Format (format, arg1, arg2));
  202. }
  203. public void Warning (int code, int level, Location loc, string format, params object[] args)
  204. {
  205. Warning (code, level, loc, String.Format (format, args));
  206. }
  207. public void Warning (int code, int level, string message)
  208. {
  209. Warning (code, level, Location.Null, message);
  210. }
  211. public void Warning (int code, int level, string format, string arg)
  212. {
  213. Warning (code, level, Location.Null, format, arg);
  214. }
  215. public void Warning (int code, int level, string format, string arg1, string arg2)
  216. {
  217. Warning (code, level, Location.Null, format, arg1, arg2);
  218. }
  219. public void Warning (int code, int level, string format, params string[] args)
  220. {
  221. Warning (code, level, Location.Null, String.Format (format, args));
  222. }
  223. //
  224. // Warnings encountered so far
  225. //
  226. public int Warnings {
  227. get { return printer.WarningsCount; }
  228. }
  229. public void Error (int code, Location loc, string error)
  230. {
  231. if (reporting_disabled > 0)
  232. return;
  233. ErrorMessage msg = new ErrorMessage (code, loc, error, extra_information);
  234. extra_information.Clear ();
  235. printer.Print (msg, settings.ShowFullPaths);
  236. if (settings.Stacktrace)
  237. Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
  238. if (printer.ErrorsCount == settings.FatalCounter)
  239. throw new FatalException (msg.Text);
  240. }
  241. public void Error (int code, Location loc, string format, string arg)
  242. {
  243. Error (code, loc, String.Format (format, arg));
  244. }
  245. public void Error (int code, Location loc, string format, string arg1, string arg2)
  246. {
  247. Error (code, loc, String.Format (format, arg1, arg2));
  248. }
  249. public void Error (int code, Location loc, string format, params string[] args)
  250. {
  251. Error (code, loc, String.Format (format, args));
  252. }
  253. public void Error (int code, string error)
  254. {
  255. Error (code, Location.Null, error);
  256. }
  257. public void Error (int code, string format, string arg)
  258. {
  259. Error (code, Location.Null, format, arg);
  260. }
  261. public void Error (int code, string format, string arg1, string arg2)
  262. {
  263. Error (code, Location.Null, format, arg1, arg2);
  264. }
  265. public void Error (int code, string format, params string[] args)
  266. {
  267. Error (code, Location.Null, String.Format (format, args));
  268. }
  269. //
  270. // Errors encountered so far
  271. //
  272. public int Errors {
  273. get { return printer.ErrorsCount; }
  274. }
  275. public bool IsDisabled {
  276. get {
  277. return reporting_disabled > 0;
  278. }
  279. }
  280. public ReportPrinter Printer {
  281. get { return printer; }
  282. }
  283. public ReportPrinter SetPrinter (ReportPrinter printer)
  284. {
  285. ReportPrinter old = this.printer;
  286. this.printer = printer;
  287. return old;
  288. }
  289. [Conditional ("MCS_DEBUG")]
  290. static public void Debug (string message, params object[] args)
  291. {
  292. Debug (4, message, args);
  293. }
  294. [Conditional ("MCS_DEBUG")]
  295. static public void Debug (int category, string message, params object[] args)
  296. {
  297. // if ((category & DebugFlags) == 0)
  298. // return;
  299. StringBuilder sb = new StringBuilder (message);
  300. if ((args != null) && (args.Length > 0)) {
  301. sb.Append (": ");
  302. bool first = true;
  303. foreach (object arg in args) {
  304. if (first)
  305. first = false;
  306. else
  307. sb.Append (", ");
  308. if (arg == null)
  309. sb.Append ("null");
  310. // else if (arg is ICollection)
  311. // sb.Append (PrintCollection ((ICollection) arg));
  312. else
  313. sb.Append (arg);
  314. }
  315. }
  316. Console.WriteLine (sb.ToString ());
  317. }
  318. /*
  319. static public string PrintCollection (ICollection collection)
  320. {
  321. StringBuilder sb = new StringBuilder ();
  322. sb.Append (collection.GetType ());
  323. sb.Append ("(");
  324. bool first = true;
  325. foreach (object o in collection) {
  326. if (first)
  327. first = false;
  328. else
  329. sb.Append (", ");
  330. sb.Append (o);
  331. }
  332. sb.Append (")");
  333. return sb.ToString ();
  334. }
  335. */
  336. static string FriendlyStackTrace (StackTrace t)
  337. {
  338. StringBuilder sb = new StringBuilder ();
  339. bool foundUserCode = false;
  340. for (int i = 0; i < t.FrameCount; i++) {
  341. StackFrame f = t.GetFrame (i);
  342. var mb = f.GetMethod ();
  343. if (!foundUserCode && mb.ReflectedType == typeof (Report))
  344. continue;
  345. foundUserCode = true;
  346. sb.Append ("\tin ");
  347. if (f.GetFileLineNumber () > 0)
  348. sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
  349. sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
  350. bool first = true;
  351. foreach (var pi in mb.GetParameters ()) {
  352. if (!first)
  353. sb.Append (", ");
  354. first = false;
  355. sb.Append (pi.ParameterType.FullName);
  356. }
  357. sb.Append (")\n");
  358. }
  359. return sb.ToString ();
  360. }
  361. }
  362. public abstract class AbstractMessage
  363. {
  364. readonly string[] extra_info;
  365. protected readonly int code;
  366. protected readonly Location location;
  367. readonly string message;
  368. protected AbstractMessage (int code, Location loc, string msg, List<string> extraInfo)
  369. {
  370. this.code = code;
  371. if (code < 0)
  372. this.code = 8000 - code;
  373. this.location = loc;
  374. this.message = msg;
  375. if (extraInfo.Count != 0) {
  376. this.extra_info = extraInfo.ToArray ();
  377. }
  378. }
  379. protected AbstractMessage (AbstractMessage aMsg)
  380. {
  381. this.code = aMsg.code;
  382. this.location = aMsg.location;
  383. this.message = aMsg.message;
  384. this.extra_info = aMsg.extra_info;
  385. }
  386. public int Code {
  387. get { return code; }
  388. }
  389. public override bool Equals (object obj)
  390. {
  391. AbstractMessage msg = obj as AbstractMessage;
  392. if (msg == null)
  393. return false;
  394. return code == msg.code && location.Equals (msg.location) && message == msg.message;
  395. }
  396. public override int GetHashCode ()
  397. {
  398. return code.GetHashCode ();
  399. }
  400. public abstract bool IsWarning { get; }
  401. public Location Location {
  402. get { return location; }
  403. }
  404. public abstract string MessageType { get; }
  405. public string[] RelatedSymbols {
  406. get { return extra_info; }
  407. }
  408. public string Text {
  409. get { return message; }
  410. }
  411. }
  412. sealed class WarningMessage : AbstractMessage
  413. {
  414. public WarningMessage (int code, Location loc, string message, List<string> extra_info)
  415. : base (code, loc, message, extra_info)
  416. {
  417. }
  418. public override bool IsWarning {
  419. get { return true; }
  420. }
  421. public override string MessageType {
  422. get {
  423. return "warning";
  424. }
  425. }
  426. }
  427. sealed class ErrorMessage : AbstractMessage
  428. {
  429. public ErrorMessage (int code, Location loc, string message, List<string> extraInfo)
  430. : base (code, loc, message, extraInfo)
  431. {
  432. }
  433. public ErrorMessage (AbstractMessage aMsg)
  434. : base (aMsg)
  435. {
  436. }
  437. public override bool IsWarning {
  438. get { return false; }
  439. }
  440. public override string MessageType {
  441. get {
  442. return "error";
  443. }
  444. }
  445. }
  446. //
  447. // Generic base for any message writer
  448. //
  449. public abstract class ReportPrinter
  450. {
  451. #region Properties
  452. public int ErrorsCount { get; protected set; }
  453. public int WarningsCount { get; private set; }
  454. //
  455. // When (symbols related to previous ...) can be used
  456. //
  457. public virtual bool HasRelatedSymbolSupport {
  458. get { return true; }
  459. }
  460. #endregion
  461. protected virtual string FormatText (string txt)
  462. {
  463. return txt;
  464. }
  465. public virtual void Print (AbstractMessage msg, bool showFullPath)
  466. {
  467. if (msg.IsWarning) {
  468. ++WarningsCount;
  469. } else {
  470. ++ErrorsCount;
  471. }
  472. }
  473. protected void Print (AbstractMessage msg, TextWriter output, bool showFullPath)
  474. {
  475. StringBuilder txt = new StringBuilder ();
  476. if (!msg.Location.IsNull) {
  477. if (showFullPath)
  478. txt.Append (msg.Location.ToStringFullName ());
  479. else
  480. txt.Append (msg.Location.ToString ());
  481. txt.Append (" ");
  482. }
  483. txt.AppendFormat ("{0} CS{1:0000}: {2}", msg.MessageType, msg.Code, msg.Text);
  484. if (!msg.IsWarning)
  485. output.WriteLine (FormatText (txt.ToString ()));
  486. else
  487. output.WriteLine (txt.ToString ());
  488. if (msg.RelatedSymbols != null) {
  489. foreach (string s in msg.RelatedSymbols)
  490. output.WriteLine (s + msg.MessageType + ")");
  491. }
  492. }
  493. public void Reset ()
  494. {
  495. // HACK: Temporary hack for broken repl flow
  496. ErrorsCount = WarningsCount = 0;
  497. }
  498. }
  499. sealed class NullReportPrinter : ReportPrinter
  500. {
  501. }
  502. //
  503. // Default message recorder, it uses two types of message groups.
  504. // Common messages: messages reported in all sessions.
  505. // Merged messages: union of all messages in all sessions.
  506. //
  507. // Used by the Lambda expressions to compile the code with various
  508. // parameter values, or by attribute resolver
  509. //
  510. class SessionReportPrinter : ReportPrinter
  511. {
  512. List<AbstractMessage> session_messages;
  513. //
  514. // A collection of exactly same messages reported in all sessions
  515. //
  516. List<AbstractMessage> common_messages;
  517. //
  518. // A collection of unique messages reported in all sessions
  519. //
  520. List<AbstractMessage> merged_messages;
  521. bool showFullPaths;
  522. public void ClearSession ()
  523. {
  524. session_messages = null;
  525. }
  526. public override void Print (AbstractMessage msg, bool showFullPath)
  527. {
  528. //
  529. // This line is useful when debugging recorded messages
  530. //
  531. // Console.WriteLine ("RECORDING: {0}", msg.Text);
  532. if (session_messages == null)
  533. session_messages = new List<AbstractMessage> ();
  534. session_messages.Add (msg);
  535. this.showFullPaths = showFullPath;
  536. base.Print (msg, showFullPath);
  537. }
  538. public void EndSession ()
  539. {
  540. if (session_messages == null)
  541. return;
  542. //
  543. // Handles the first session
  544. //
  545. if (common_messages == null) {
  546. common_messages = new List<AbstractMessage> (session_messages);
  547. merged_messages = session_messages;
  548. session_messages = null;
  549. return;
  550. }
  551. //
  552. // Store common messages if any
  553. //
  554. for (int i = 0; i < common_messages.Count; ++i) {
  555. AbstractMessage cmsg = common_messages[i];
  556. bool common_msg_found = false;
  557. foreach (AbstractMessage msg in session_messages) {
  558. if (cmsg.Equals (msg)) {
  559. common_msg_found = true;
  560. break;
  561. }
  562. }
  563. if (!common_msg_found)
  564. common_messages.RemoveAt (i);
  565. }
  566. //
  567. // Merge session and previous messages
  568. //
  569. for (int i = 0; i < session_messages.Count; ++i) {
  570. AbstractMessage msg = session_messages[i];
  571. bool msg_found = false;
  572. for (int ii = 0; ii < merged_messages.Count; ++ii) {
  573. if (msg.Equals (merged_messages[ii])) {
  574. msg_found = true;
  575. break;
  576. }
  577. }
  578. if (!msg_found)
  579. merged_messages.Add (msg);
  580. }
  581. }
  582. public bool IsEmpty {
  583. get {
  584. return merged_messages == null && common_messages == null;
  585. }
  586. }
  587. //
  588. // Prints collected messages, common messages have a priority
  589. //
  590. public bool Merge (ReportPrinter dest)
  591. {
  592. var messages_to_print = merged_messages;
  593. if (common_messages != null && common_messages.Count > 0) {
  594. messages_to_print = common_messages;
  595. }
  596. if (messages_to_print == null)
  597. return false;
  598. bool error_msg = false;
  599. foreach (AbstractMessage msg in messages_to_print) {
  600. dest.Print (msg, showFullPaths);
  601. error_msg |= !msg.IsWarning;
  602. }
  603. return error_msg;
  604. }
  605. }
  606. public class StreamReportPrinter : ReportPrinter
  607. {
  608. readonly TextWriter writer;
  609. public StreamReportPrinter (TextWriter writer)
  610. {
  611. this.writer = writer;
  612. }
  613. public override void Print (AbstractMessage msg, bool showFullPath)
  614. {
  615. Print (msg, writer, showFullPath);
  616. base.Print (msg, showFullPath);
  617. }
  618. }
  619. public class ConsoleReportPrinter : StreamReportPrinter
  620. {
  621. static readonly string prefix, postfix;
  622. static ConsoleReportPrinter ()
  623. {
  624. string term = Environment.GetEnvironmentVariable ("TERM");
  625. bool xterm_colors = false;
  626. switch (term){
  627. case "xterm":
  628. case "rxvt":
  629. case "rxvt-unicode":
  630. if (Environment.GetEnvironmentVariable ("COLORTERM") != null){
  631. xterm_colors = true;
  632. }
  633. break;
  634. case "xterm-color":
  635. case "xterm-256color":
  636. xterm_colors = true;
  637. break;
  638. }
  639. if (!xterm_colors)
  640. return;
  641. if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2)))
  642. return;
  643. string config = Environment.GetEnvironmentVariable ("MCS_COLORS");
  644. if (config == null){
  645. config = "errors=red";
  646. //config = "brightwhite,red";
  647. }
  648. if (config == "disable")
  649. return;
  650. if (!config.StartsWith ("errors="))
  651. return;
  652. config = config.Substring (7);
  653. int p = config.IndexOf (",");
  654. if (p == -1)
  655. prefix = GetForeground (config);
  656. else
  657. prefix = GetBackground (config.Substring (p+1)) + GetForeground (config.Substring (0, p));
  658. postfix = "\x001b[0m";
  659. }
  660. public ConsoleReportPrinter ()
  661. : base (Console.Error)
  662. {
  663. }
  664. public ConsoleReportPrinter (TextWriter writer)
  665. : base (writer)
  666. {
  667. }
  668. static int NameToCode (string s)
  669. {
  670. switch (s) {
  671. case "black":
  672. return 0;
  673. case "red":
  674. return 1;
  675. case "green":
  676. return 2;
  677. case "yellow":
  678. return 3;
  679. case "blue":
  680. return 4;
  681. case "magenta":
  682. return 5;
  683. case "cyan":
  684. return 6;
  685. case "grey":
  686. case "white":
  687. return 7;
  688. }
  689. return 7;
  690. }
  691. //
  692. // maps a color name to its xterm color code
  693. //
  694. static string GetForeground (string s)
  695. {
  696. string highcode;
  697. if (s.StartsWith ("bright")) {
  698. highcode = "1;";
  699. s = s.Substring (6);
  700. } else
  701. highcode = "";
  702. return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m";
  703. }
  704. static string GetBackground (string s)
  705. {
  706. return "\x001b[" + (40 + NameToCode (s)).ToString () + "m";
  707. }
  708. protected override string FormatText (string txt)
  709. {
  710. if (prefix != null)
  711. return prefix + txt + postfix;
  712. return txt;
  713. }
  714. }
  715. class TimeReporter
  716. {
  717. public enum TimerType
  718. {
  719. ParseTotal,
  720. AssemblyBuilderSetup,
  721. CreateTypeTotal,
  722. ReferencesLoading,
  723. ReferencesImporting,
  724. PredefinedTypesInit,
  725. ModuleDefinitionTotal,
  726. EmitTotal,
  727. CloseTypes,
  728. Resouces,
  729. OutputSave,
  730. DebugSave,
  731. }
  732. readonly Stopwatch[] timers;
  733. Stopwatch total;
  734. public TimeReporter (bool enabled)
  735. {
  736. if (!enabled)
  737. return;
  738. timers = new Stopwatch[System.Enum.GetValues(typeof (TimerType)).Length];
  739. }
  740. public void Start (TimerType type)
  741. {
  742. if (timers != null) {
  743. var sw = new Stopwatch ();
  744. timers[(int) type] = sw;
  745. sw.Start ();
  746. }
  747. }
  748. public void StartTotal ()
  749. {
  750. total = new Stopwatch ();
  751. total.Start ();
  752. }
  753. public void Stop (TimerType type)
  754. {
  755. if (timers != null) {
  756. timers[(int) type].Stop ();
  757. }
  758. }
  759. public void StopTotal ()
  760. {
  761. total.Stop ();
  762. }
  763. public void ShowStats ()
  764. {
  765. if (timers == null)
  766. return;
  767. Dictionary<TimerType, string> timer_names = new Dictionary<TimerType,string> () {
  768. { TimerType.ParseTotal, "Parsing source files" },
  769. { TimerType.AssemblyBuilderSetup, "Assembly builder setup" },
  770. { TimerType.CreateTypeTotal, "Compiled types created" },
  771. { TimerType.ReferencesLoading, "Referenced assemblies loading" },
  772. { TimerType.ReferencesImporting, "Referenced assemblies importing" },
  773. { TimerType.PredefinedTypesInit, "Predefined types initialization" },
  774. { TimerType.ModuleDefinitionTotal, "Module definition" },
  775. { TimerType.EmitTotal, "Resolving and emitting members blocks" },
  776. { TimerType.CloseTypes, "Module types closed" },
  777. { TimerType.Resouces, "Embedding resources" },
  778. { TimerType.OutputSave, "Writing output file" },
  779. { TimerType.DebugSave, "Writing debug symbols file" },
  780. };
  781. int counter = 0;
  782. double percentage = (double) total.ElapsedMilliseconds / 100;
  783. long subtotal = total.ElapsedMilliseconds;
  784. foreach (var timer in timers) {
  785. string msg = timer_names[(TimerType) counter++];
  786. var ms = timer == null ? 0 : timer.ElapsedMilliseconds;
  787. Console.WriteLine ("{0,4:0.0}% {1,5}ms {2}", ms / percentage, ms, msg);
  788. subtotal -= ms;
  789. }
  790. Console.WriteLine ("{0,4:0.0}% {1,5}ms Other tasks", subtotal / percentage, subtotal);
  791. Console.WriteLine ();
  792. Console.WriteLine ("Total elapsed time: {0}", total.Elapsed);
  793. }
  794. }
  795. public class InternalErrorException : Exception {
  796. public InternalErrorException (MemberCore mc, Exception e)
  797. : base (mc.Location + " " + mc.GetSignatureForError (), e)
  798. {
  799. }
  800. public InternalErrorException ()
  801. : base ("Internal error")
  802. {
  803. }
  804. public InternalErrorException (string message)
  805. : base (message)
  806. {
  807. }
  808. public InternalErrorException (string message, params object[] args)
  809. : base (String.Format (message, args))
  810. {
  811. }
  812. public InternalErrorException (Exception exception, string message, params object[] args)
  813. : base (String.Format (message, args), exception)
  814. {
  815. }
  816. public InternalErrorException (Exception e, Location loc)
  817. : base (loc.ToString (), e)
  818. {
  819. }
  820. }
  821. class FatalException : Exception
  822. {
  823. public FatalException (string message)
  824. : base (message)
  825. {
  826. }
  827. }
  828. /// <summary>
  829. /// Handles #pragma warning
  830. /// </summary>
  831. public class WarningRegions {
  832. abstract class PragmaCmd
  833. {
  834. public int Line;
  835. protected PragmaCmd (int line)
  836. {
  837. Line = line;
  838. }
  839. public abstract bool IsEnabled (int code, bool previous);
  840. }
  841. class Disable : PragmaCmd
  842. {
  843. int code;
  844. public Disable (int line, int code)
  845. : base (line)
  846. {
  847. this.code = code;
  848. }
  849. public override bool IsEnabled (int code, bool previous)
  850. {
  851. return this.code == code ? false : previous;
  852. }
  853. }
  854. class DisableAll : PragmaCmd
  855. {
  856. public DisableAll (int line)
  857. : base (line) {}
  858. public override bool IsEnabled(int code, bool previous)
  859. {
  860. return false;
  861. }
  862. }
  863. class Enable : PragmaCmd
  864. {
  865. int code;
  866. public Enable (int line, int code)
  867. : base (line)
  868. {
  869. this.code = code;
  870. }
  871. public override bool IsEnabled(int code, bool previous)
  872. {
  873. return this.code == code ? true : previous;
  874. }
  875. }
  876. class EnableAll : PragmaCmd
  877. {
  878. public EnableAll (int line)
  879. : base (line) {}
  880. public override bool IsEnabled(int code, bool previous)
  881. {
  882. return true;
  883. }
  884. }
  885. List<PragmaCmd> regions = new List<PragmaCmd> ();
  886. public void WarningDisable (int line)
  887. {
  888. regions.Add (new DisableAll (line));
  889. }
  890. public void WarningDisable (Location location, int code, Report Report)
  891. {
  892. if (Report.CheckWarningCode (code, location))
  893. regions.Add (new Disable (location.Row, code));
  894. }
  895. public void WarningEnable (int line)
  896. {
  897. regions.Add (new EnableAll (line));
  898. }
  899. public void WarningEnable (Location location, int code, CompilerContext context)
  900. {
  901. if (!context.Report.CheckWarningCode (code, location))
  902. return;
  903. if (context.Settings.IsWarningDisabledGlobally (code))
  904. context.Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code);
  905. regions.Add (new Enable (location.Row, code));
  906. }
  907. public bool IsWarningEnabled (int code, int src_line)
  908. {
  909. bool result = true;
  910. foreach (PragmaCmd pragma in regions) {
  911. if (src_line < pragma.Line)
  912. break;
  913. result = pragma.IsEnabled (code, result);
  914. }
  915. return result;
  916. }
  917. }
  918. }