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