2 // report.cs: report errors and warnings.
4 // Author: Miguel de Icaza (miguel@ximian.com)
6 // (C) 2001 Ximian, Inc. (http://www.ximian.com)
10 // FIXME: currently our class library does not support custom number format strings
14 using System.Collections;
15 using System.Collections.Specialized;
16 using System.Diagnostics;
17 using System.Reflection;
19 namespace Mono.CSharp {
22 /// This class is used to report errors and warnings t te user.
26 /// Errors encountered so far
28 static public int Errors;
31 /// Warnings encountered so far
33 static public int Warnings;
36 /// Whether errors should be throw an exception
38 static public bool Fatal;
41 /// Whether warnings should be considered errors
43 static public bool WarningsAreErrors;
46 /// Whether to dump a stack trace on errors.
48 static public bool Stacktrace;
51 // If the 'expected' error code is reported then the
52 // compilation succeeds.
54 // Used for the test suite to excercise the error codes
56 static int expected_error = 0;
59 // Keeps track of the warnings that we are ignoring
61 static Hashtable warning_ignore_table;
64 /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
66 static StringCollection related_symbols = new StringCollection ();
68 static void Check (int code)
70 if (code == expected_error){
72 throw new Exception ();
78 public static string FriendlyStackTrace (Exception e)
80 return FriendlyStackTrace (new StackTrace (e, true));
83 static string FriendlyStackTrace (StackTrace t)
85 StringBuilder sb = new StringBuilder ();
87 bool foundUserCode = false;
89 for (int i = 0; i < t.FrameCount; i++) {
90 StackFrame f = t.GetFrame (i);
91 MethodBase mb = f.GetMethod ();
93 if (!foundUserCode && mb.ReflectedType == typeof (Report))
100 if (f.GetFileLineNumber () > 0)
101 sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
103 sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
106 foreach (ParameterInfo pi in mb.GetParameters ()) {
111 sb.Append (TypeManager.CSharpName (pi.ParameterType));
116 return sb.ToString ();
119 static public void LocationOfPreviousError (Location loc)
121 Console.WriteLine (String.Format ("{0}({1}) (Location of symbol related to previous error)", loc.Name, loc.Row));
125 /// In most error cases is very useful to have information about symbol that caused the error.
126 /// Call this method before you call Report.Error when it makes sense.
128 static public void SymbolRelatedToPreviousError (Location loc, string symbol)
130 SymbolRelatedToPreviousError (String.Format ("{0}({1})", loc.Name, loc.Row), symbol);
133 static public void SymbolRelatedToPreviousError (MemberInfo mi)
135 Type decl = mi.DeclaringType;
136 if (decl.IsGenericInstance)
137 decl = decl.GetGenericTypeDefinition ();
139 TypeContainer temp_ds = TypeManager.LookupTypeContainer (decl);
140 if (temp_ds == null) {
141 SymbolRelatedToPreviousError (decl.Assembly.Location, TypeManager.GetFullNameSignature (mi));
143 if (mi is MethodBase) {
144 MethodBase mb = (MethodBase) mi;
145 if (mb.Mono_IsInflatedMethod)
146 mb = mb.GetGenericMethodDefinition ();
148 IMethodData md = TypeManager.GetMethod (mb);
149 SymbolRelatedToPreviousError (md.Location, md.GetSignatureForError (temp_ds));
153 string name = String.Concat (temp_ds.Name, ".", mi.Name);
154 MemberCore mc = temp_ds.GetDefinition (name) as MemberCore;
155 SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
159 static public void SymbolRelatedToPreviousError (MemberCore mc)
161 SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
164 static public void SymbolRelatedToPreviousError (Type type)
166 SymbolRelatedToPreviousError (type.Assembly.Location, TypeManager.CSharpName (type));
169 static void SymbolRelatedToPreviousError (string loc, string symbol)
171 related_symbols.Add (String.Format ("{0}: ('{1}' name of symbol related to previous ", loc, symbol));
174 static public void RealError (string msg)
177 Console.WriteLine (msg);
179 foreach (string s in related_symbols)
180 Console.WriteLine (s);
181 related_symbols.Clear ();
184 Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
187 throw new Exception (msg);
191 static public void Error (int code, Location l, string text)
196 string msg = String.Format (
197 "{0}({1}) error CS{2:0000}: {3}", l.Name, l.Row, code, text);
198 // "{0}({1}) error CS{2}: {3}", l.Name, l.Row, code, text);
204 static public void Warning (int code, Location l, string text)
209 if (warning_ignore_table != null){
210 if (warning_ignore_table.Contains (code)) {
211 related_symbols.Clear ();
216 if (WarningsAreErrors)
217 Error (code, l, text);
221 if (Location.IsNull (l))
224 row = l.Row.ToString ();
226 Console.WriteLine (String.Format (
227 "{0}({1}) warning CS{2:0000}: {3}",
228 // "{0}({1}) warning CS{2}: {3}",
229 l.Name, row, code, text));
232 foreach (string s in related_symbols)
233 Console.WriteLine (s);
234 related_symbols.Clear ();
239 Console.WriteLine (new StackTrace ().ToString ());
243 static public void Warning (int code, string text)
245 Warning (code, Location.Null, text);
248 static public void Error (int code, string text)
253 string msg = String.Format ("error CS{0:0000}: {1}", code, text);
259 static public void Error (int code, string format, params object[] args)
261 Error (code, Location.Null, String.Format (format, args));
264 static public void Error (int code, Location loc, string format, params object[] args)
266 Error (code, loc, String.Format (format, args));
269 static public void Warning (int code, string format, params object[] args)
271 Warning (code, Location.Null, String.Format (format, args));
274 static public void Warning (int code, Location loc, string format, params object[] args)
276 Warning (code, loc, String.Format (format, args));
279 static public void SetIgnoreWarning (int code)
281 if (warning_ignore_table == null)
282 warning_ignore_table = new Hashtable ();
284 warning_ignore_table [code] = true;
287 static public int ExpectedError {
289 expected_error = value;
292 return expected_error;
296 public static int DebugFlags = 0;
298 [Conditional ("MCS_DEBUG")]
299 static public void Debug (string message, params object[] args)
301 Debug (4, message, args);
304 [Conditional ("MCS_DEBUG")]
305 static public void Debug (int category, string message, params object[] args)
307 if ((category & DebugFlags) == 0)
310 StringBuilder sb = new StringBuilder (message);
312 if ((args != null) && (args.Length > 0)) {
316 foreach (object arg in args) {
323 else if (arg is ICollection)
324 sb.Append (PrintCollection ((ICollection) arg));
325 else if (arg is IntPtr)
326 sb.Append (String.Format ("IntPtr(0x{0:x})", ((IntPtr) arg).ToInt32 ()));
332 Console.WriteLine (sb.ToString ());
335 static public string PrintCollection (ICollection collection)
337 StringBuilder sb = new StringBuilder ();
339 sb.Append (collection.GetType ());
343 foreach (object o in collection) {
352 return sb.ToString ();
356 public enum TimerType {
366 public enum CounterType {
375 static DateTime[] timer_start;
376 static TimeSpan[] timers;
377 static long[] timer_counters;
378 static long[] counters;
382 timer_start = new DateTime [(int) TimerType.CountTimers];
383 timers = new TimeSpan [(int) TimerType.CountTimers];
384 timer_counters = new long [(int) TimerType.CountTimers];
385 counters = new long [(int) CounterType.CountCounters];
387 for (int i = 0; i < (int) TimerType.CountTimers; i++) {
388 timer_start [i] = DateTime.Now;
389 timers [i] = TimeSpan.Zero;
393 [Conditional("TIMER")]
394 static public void IncrementCounter (CounterType which)
396 ++counters [(int) which];
399 [Conditional("TIMER")]
400 static public void StartTimer (TimerType which)
402 timer_start [(int) which] = DateTime.Now;
405 [Conditional("TIMER")]
406 static public void StopTimer (TimerType which)
408 timers [(int) which] += DateTime.Now - timer_start [(int) which];
409 ++timer_counters [(int) which];
412 [Conditional("TIMER")]
413 static public void ShowTimers ()
415 ShowTimer (TimerType.FindMembers, "- FindMembers timer");
416 ShowTimer (TimerType.TcFindMembers, "- TypeContainer.FindMembers timer");
417 ShowTimer (TimerType.MemberLookup, "- MemberLookup timer");
418 ShowTimer (TimerType.CachedLookup, "- CachedLookup timer");
419 ShowTimer (TimerType.CacheInit, "- Cache init");
420 ShowTimer (TimerType.MiscTimer, "- Misc timer");
422 ShowCounter (CounterType.FindMembers, "- Find members");
423 ShowCounter (CounterType.MemberCache, "- Member cache");
424 ShowCounter (CounterType.MiscCounter, "- Misc counter");
427 static public void ShowCounter (CounterType which, string msg)
429 Console.WriteLine ("{0} {1}", counters [(int) which], msg);
432 static public void ShowTimer (TimerType which, string msg)
435 "[{0:00}:{1:000}] {2} (used {3} times)",
436 (int) timers [(int) which].TotalSeconds,
437 timers [(int) which].Milliseconds, msg,
438 timer_counters [(int) which]);
442 public class InternalErrorException : Exception {
443 public InternalErrorException ()
444 : base ("Internal error")
448 public InternalErrorException (string message)
453 public InternalErrorException (string format, params object[] args)
454 : this (String.Format (format, args))