- Added missing default
[mono.git] / mcs / gmcs / report.cs
1 //
2 // report.cs: report errors and warnings.
3 //
4 // Author: Miguel de Icaza (miguel@ximian.com)
5 //
6 // (C) 2001 Ximian, Inc. (http://www.ximian.com)
7 //
8
9 //
10 // FIXME: currently our class library does not support custom number format strings
11 //
12 using System;
13 using System.Text;
14 using System.Collections;
15 using System.Collections.Specialized;
16 using System.Diagnostics;
17 using System.Reflection;
18
19 namespace Mono.CSharp {
20
21         /// <summary>
22         ///   This class is used to report errors and warnings t te user.
23         /// </summary>
24         public class Report {
25                 /// <summary>  
26                 ///   Errors encountered so far
27                 /// </summary>
28                 static public int Errors;
29
30                 /// <summary>  
31                 ///   Warnings encountered so far
32                 /// </summary>
33                 static public int Warnings;
34
35                 /// <summary>  
36                 ///   Whether errors should be throw an exception
37                 /// </summary>
38                 static public bool Fatal;
39                 
40                 /// <summary>  
41                 ///   Whether warnings should be considered errors
42                 /// </summary>
43                 static public bool WarningsAreErrors;
44
45                 /// <summary>  
46                 ///   Whether to dump a stack trace on errors. 
47                 /// </summary>
48                 static public bool Stacktrace;
49                 
50                 //
51                 // If the 'expected' error code is reported then the
52                 // compilation succeeds.
53                 //
54                 // Used for the test suite to excercise the error codes
55                 //
56                 static int expected_error = 0;
57
58                 //
59                 // Keeps track of the warnings that we are ignoring
60                 //
61                 static Hashtable warning_ignore_table;
62
63                 /// <summary>
64                 /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
65                 /// </summary>
66                 static StringCollection related_symbols = new StringCollection ();
67                 
68                 static void Check (int code)
69                 {
70                         if (code == expected_error){
71                                 if (Fatal)
72                                         throw new Exception ();
73                                 
74                                 Environment.Exit (0);
75                         }
76                 }
77                 
78                 public static string FriendlyStackTrace (Exception e)
79                 {
80                         return FriendlyStackTrace (new StackTrace (e, true));
81                 }
82                 
83                 static string FriendlyStackTrace (StackTrace t)
84                 {               
85                         StringBuilder sb = new StringBuilder ();
86                         
87                         bool foundUserCode = false;
88                         
89                         for (int i = 0; i < t.FrameCount; i++) {
90                                 StackFrame f = t.GetFrame (i);
91                                 MethodBase mb = f.GetMethod ();
92                                 
93                                 if (!foundUserCode && mb.ReflectedType == typeof (Report))
94                                         continue;
95                                 
96                                 foundUserCode = true;
97                                 
98                                 sb.Append ("\tin ");
99                                 
100                                 if (f.GetFileLineNumber () > 0)
101                                         sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
102                                 
103                                 sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
104                                 
105                                 bool first = true;
106                                 foreach (ParameterInfo pi in mb.GetParameters ()) {
107                                         if (!first)
108                                                 sb.Append (", ");
109                                         first = false;
110                                         
111                                         sb.Append (TypeManager.CSharpName (pi.ParameterType));
112                                 }
113                                 sb.Append (")\n");
114                         }
115         
116                         return sb.ToString ();
117                 }
118                 
119                 static public void LocationOfPreviousError (Location loc)
120                 {
121                         Console.WriteLine (String.Format ("{0}({1}) (Location of symbol related to previous error)", loc.Name, loc.Row));
122                 }                
123
124                 /// <summary>
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.
127                 /// </summary>
128                 static public void SymbolRelatedToPreviousError (Location loc, string symbol)
129                 {
130                         SymbolRelatedToPreviousError (String.Format ("{0}({1})", loc.Name, loc.Row), symbol);
131                 }
132
133                 static public void SymbolRelatedToPreviousError (MemberInfo mi)
134                 {
135                         Type decl = mi.DeclaringType;
136                         if (decl.IsGenericInstance)
137                                 decl = decl.GetGenericTypeDefinition ();
138
139                         TypeContainer temp_ds = TypeManager.LookupTypeContainer (decl);
140                         if (temp_ds == null) {
141                                 SymbolRelatedToPreviousError (decl.Assembly.Location, TypeManager.GetFullNameSignature (mi));
142                         } else {
143                                 if (mi is MethodBase) {
144                                         MethodBase mb = (MethodBase) mi;
145                                         if (mb.Mono_IsInflatedMethod)
146                                                 mb = mb.GetGenericMethodDefinition ();
147
148                                         IMethodData md = TypeManager.GetMethod (mb);
149                                         SymbolRelatedToPreviousError (md.Location, md.GetSignatureForError (temp_ds));
150                                         return;
151                                 }
152
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 ());
156                         }
157                 }
158
159                 static public void SymbolRelatedToPreviousError (MemberCore mc)
160                 {
161                         SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
162                 }
163
164                 static public void SymbolRelatedToPreviousError (Type type)
165                 {
166                         SymbolRelatedToPreviousError (type.Assembly.Location, TypeManager.CSharpName (type));
167                 }
168
169                 static void SymbolRelatedToPreviousError (string loc, string symbol)
170                 {
171                         related_symbols.Add (String.Format ("{0}: ('{1}' name of symbol related to previous ", loc, symbol));
172                 }
173
174                 static public void RealError (string msg)
175                 {
176                         Errors++;
177                         Console.WriteLine (msg);
178
179                         foreach (string s in related_symbols)
180                                 Console.WriteLine (s);
181                         related_symbols.Clear ();
182
183                         if (Stacktrace)
184                                 Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
185                         
186                         if (Fatal)
187                                 throw new Exception (msg);
188                 }
189
190
191                 static public void Error (int code, Location l, string text)
192                 {
193                         if (code < 0)
194                                 code = 8000-code;
195                         
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);
199                         
200                         RealError (msg);
201                         Check (code);
202                 }
203
204                 static public void Warning (int code, Location l, string text)
205                 {
206                         if (code < 0)
207                                 code = 8000-code;
208                         
209                         if (warning_ignore_table != null){
210                                 if (warning_ignore_table.Contains (code)) {
211                                         related_symbols.Clear ();
212                                         return;
213                                 }
214                         }
215                         
216                         if (WarningsAreErrors)
217                                 Error (code, l, text);
218                         else {
219                                 string row;
220                                 
221                                 if (Location.IsNull (l))
222                                         row = "";
223                                 else
224                                         row = l.Row.ToString ();
225                                 
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));
230                                 Warnings++;
231
232                                 foreach (string s in related_symbols)
233                                         Console.WriteLine (s);
234                                 related_symbols.Clear ();
235
236                                 Check (code);
237
238                                 if (Stacktrace)
239                                         Console.WriteLine (new StackTrace ().ToString ());
240                         }
241                 }
242                 
243                 static public void Warning (int code, string text)
244                 {
245                         Warning (code, Location.Null, text);
246                 }
247
248                 static public void Error (int code, string text)
249                 {
250                         if (code < 0)
251                                 code = 8000-code;
252                         
253                         string msg = String.Format ("error CS{0:0000}: {1}", code, text);
254                         
255                         RealError (msg);
256                         Check (code);
257                 }
258
259                 static public void Error (int code, string format, params object[] args)
260                 {
261                         Error (code, Location.Null, String.Format (format, args));
262                 }
263
264                 static public void Error (int code, Location loc, string format, params object[] args)
265                 {
266                         Error (code, loc, String.Format (format, args));
267                 }
268
269                 static public void Warning (int code, string format, params object[] args)
270                 {
271                         Warning (code, Location.Null, String.Format (format, args));
272                 }
273
274                 static public void Warning (int code, Location loc, string format, params object[] args)
275                 {
276                         Warning (code, loc, String.Format (format, args));
277                 }
278
279                 static public void SetIgnoreWarning (int code)
280                 {
281                         if (warning_ignore_table == null)
282                                 warning_ignore_table = new Hashtable ();
283
284                         warning_ignore_table [code] = true;
285                 }
286                 
287                 static public int ExpectedError {
288                         set {
289                                 expected_error = value;
290                         }
291                         get {
292                                 return expected_error;
293                         }
294                 }
295
296                 public static int DebugFlags = 0;
297
298                 [Conditional ("MCS_DEBUG")]
299                 static public void Debug (string message, params object[] args)
300                 {
301                         Debug (4, message, args);
302                 }
303                         
304                 [Conditional ("MCS_DEBUG")]
305                 static public void Debug (int category, string message, params object[] args)
306                 {
307                         if ((category & DebugFlags) == 0)
308                                 return;
309
310                         StringBuilder sb = new StringBuilder (message);
311
312                         if ((args != null) && (args.Length > 0)) {
313                                 sb.Append (": ");
314
315                                 bool first = true;
316                                 foreach (object arg in args) {
317                                         if (first)
318                                                 first = false;
319                                         else
320                                                 sb.Append (", ");
321                                         if (arg == null)
322                                                 sb.Append ("null");
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 ()));
327                                         else
328                                                 sb.Append (arg);
329                                 }
330                         }
331
332                         Console.WriteLine (sb.ToString ());
333                 }
334
335                 static public string PrintCollection (ICollection collection)
336                 {
337                         StringBuilder sb = new StringBuilder ();
338
339                         sb.Append (collection.GetType ());
340                         sb.Append ("(");
341
342                         bool first = true;
343                         foreach (object o in collection) {
344                                 if (first)
345                                         first = false;
346                                 else
347                                         sb.Append (", ");
348                                 sb.Append (o);
349                         }
350
351                         sb.Append (")");
352                         return sb.ToString ();
353                 }
354         }
355
356         public enum TimerType {
357                 FindMembers     = 0,
358                 TcFindMembers   = 1,
359                 MemberLookup    = 2,
360                 CachedLookup    = 3,
361                 CacheInit       = 4,
362                 MiscTimer       = 5,
363                 CountTimers     = 6
364         }
365
366         public enum CounterType {
367                 FindMembers     = 0,
368                 MemberCache     = 1,
369                 MiscCounter     = 2,
370                 CountCounters   = 3
371         }
372
373         public class Timer
374         {
375                 static DateTime[] timer_start;
376                 static TimeSpan[] timers;
377                 static long[] timer_counters;
378                 static long[] counters;
379
380                 static Timer ()
381                 {
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];
386
387                         for (int i = 0; i < (int) TimerType.CountTimers; i++) {
388                                 timer_start [i] = DateTime.Now;
389                                 timers [i] = TimeSpan.Zero;
390                         }
391                 }
392
393                 [Conditional("TIMER")]
394                 static public void IncrementCounter (CounterType which)
395                 {
396                         ++counters [(int) which];
397                 }
398
399                 [Conditional("TIMER")]
400                 static public void StartTimer (TimerType which)
401                 {
402                         timer_start [(int) which] = DateTime.Now;
403                 }
404
405                 [Conditional("TIMER")]
406                 static public void StopTimer (TimerType which)
407                 {
408                         timers [(int) which] += DateTime.Now - timer_start [(int) which];
409                         ++timer_counters [(int) which];
410                 }
411
412                 [Conditional("TIMER")]
413                 static public void ShowTimers ()
414                 {
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");
421
422                         ShowCounter (CounterType.FindMembers, "- Find members");
423                         ShowCounter (CounterType.MemberCache, "- Member cache");
424                         ShowCounter (CounterType.MiscCounter, "- Misc counter");
425                 }
426
427                 static public void ShowCounter (CounterType which, string msg)
428                 {
429                         Console.WriteLine ("{0} {1}", counters [(int) which], msg);
430                 }
431
432                 static public void ShowTimer (TimerType which, string msg)
433                 {
434                         Console.WriteLine (
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]);
439                 }
440         }
441
442         public class InternalErrorException : Exception {
443                 public InternalErrorException ()
444                         : base ("Internal error")
445                 {
446                 }
447
448                 public InternalErrorException (string message)
449                         : base (message)
450                 {
451                 }
452
453                 public InternalErrorException (string format, params object[] args)
454                         : this (String.Format (format, args))
455                 { }
456         }
457 }