/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs

http://github.com/icsharpcode/ILSpy · C# · 1144 lines · 843 code · 200 blank · 101 comment · 124 complexity · 0140911e27220957fec1642f2985559b MD5 · raw file

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