PageRenderTime 71ms CodeModel.GetById 21ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 1ms

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