Fix unmanaged type check for nested generic types
[mono.git] / mcs / mcs / report.cs
index 2c5111b9337529da30bbb56cd4f3e18372addc17..81561a5cb9b387d48df82648e7b83e7b028c09ab 100644 (file)
@@ -2,9 +2,10 @@
 // report.cs: report errors and warnings.
 //
 // Author: Miguel de Icaza (miguel@ximian.com)
-//         Marek Safar (marek.safar@seznam.cz)         
+//         Marek Safar (marek.safar@gmail.com)         
 //
 // Copyright 2001 Ximian, Inc. (http://www.ximian.com)
+// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 //
 
 using System;
@@ -12,8 +13,6 @@ using System.IO;
 using System.Text;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Reflection;
-using System.Reflection.Emit;
 
 namespace Mono.CSharp {
 
@@ -29,14 +28,14 @@ namespace Mono.CSharp {
                List<int> warnings_as_error;
                List<int> warnings_only;
 
-               public static int DebugFlags = 0;
+               public const int RuntimeErrorId = 10000;
 
                //
                // Keeps track of the warnings that we are ignoring
                //
-               public Dictionary<int, bool> warning_ignore_table;
+               HashSet<int> warning_ignore_table;
 
-               Dictionary<string, WarningRegions> warning_regions_table;
+               Dictionary<int, WarningRegions> warning_regions_table;
 
                int warning_level;
 
@@ -56,25 +55,22 @@ namespace Mono.CSharp {
                        28, 67, 78,
                        105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197,
                        219, 251, 252, 253, 278, 282,
-                       402, 414, 419, 420, 429, 436, 440, 458, 464, 465, 467, 469, 472,
-                       612, 618, 626, 628, 642, 649, 652, 658, 659, 660, 661, 665, 672, 675, 693,
-                       809,
-                       1030, 1058, 1066,
+                       402, 414, 419, 420, 429, 436, 437, 440, 458, 464, 465, 467, 469, 472, 473,
+                       612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693,
+                       728,
+                       809, 824,
+                       1030, 1058, 1060, 1066,
                        1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592,
-                       1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692,
-                       1700, 1717, 1718, 1720,
-                       1901,
+                       1607, 1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692, 1695, 1696, 1699,
+                       1700, 1701, 1702, 1709, 1711, 1717, 1718, 1720, 1735,
+                       1901, 1956, 1981, 1998,
                        2002, 2023, 2029,
                        3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009,
                        3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019,
                        3021, 3022, 3023, 3024, 3026, 3027
                };
 
-               static Report ()
-               {
-                       // Just to be sure that binary search is working
-                       Array.Sort (AllWarnings);
-               }
+               static HashSet<int> AllWarningsHashSet;
 
                public Report (ReportPrinter printer)
                {
@@ -95,10 +91,10 @@ namespace Mono.CSharp {
                        --reporting_disabled;
                }
 
-               public void FeatureIsNotAvailable (Location loc, string feature)
+               public void FeatureIsNotAvailable (CompilerContext compiler, Location loc, string feature)
                {
                        string version;
-                       switch (RootContext.Version) {
+                       switch (compiler.Settings.Version) {
                        case LanguageVersion.ISO_1:
                                version = "1.0";
                                break;
@@ -108,8 +104,14 @@ namespace Mono.CSharp {
                        case LanguageVersion.V_3:
                                version = "3.0";
                                break;
+                       case LanguageVersion.V_4:
+                               version = "4.0";
+                               break;
+                       case LanguageVersion.V_5:
+                               version = "5.0";
+                               break;
                        default:
-                               throw new InternalErrorException ("Invalid feature version", RootContext.Version);
+                               throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version);
                        }
 
                        Error (1644, loc,
@@ -124,32 +126,29 @@ namespace Mono.CSharp {
                                feature);
                }
                
-               static bool IsValidWarning (int code)
-               {       
-                       return Array.BinarySearch (AllWarnings, code) >= 0;
-               }
-
                bool IsWarningEnabled (int code, int level, Location loc)
                {
                        if (WarningLevel < level)
                                return false;
 
-                       if (warning_ignore_table != null) {
-                               if (warning_ignore_table.ContainsKey (code)) {
-                                       return false;
-                               }
-                       }
+                       if (IsWarningDisabledGlobally (code))
+                               return false;
 
                        if (warning_regions_table == null || loc.IsNull)
                                return true;
 
                        WarningRegions regions;
-                       if (!warning_regions_table.TryGetValue (loc.Name, out regions))
+                       if (!warning_regions_table.TryGetValue (loc.File, out regions))
                                return true;
 
                        return regions.IsWarningEnabled (code, loc.Row);
                }
 
+               public bool IsWarningDisabledGlobally (int code)
+               {
+                       return warning_ignore_table != null && warning_ignore_table.Contains (code);
+               }
+
                bool IsWarningAsError (int code)
                {
                        bool is_error = WarningsAreErrors;
@@ -176,7 +175,7 @@ namespace Mono.CSharp {
                /// </summary>
                public void SymbolRelatedToPreviousError (Location loc, string symbol)
                {
-                       SymbolRelatedToPreviousError (loc.ToString (), symbol);
+                       SymbolRelatedToPreviousError (loc.ToString ());
                }
 
                public void SymbolRelatedToPreviousError (MemberSpec ms)
@@ -193,7 +192,14 @@ namespace Mono.CSharp {
                        if (mc != null) {
                                SymbolRelatedToPreviousError (mc);
                        } else {
-                               SymbolRelatedToPreviousError (ms.MemberDefinition.Assembly.Location, "");
+                               if (ms.DeclaringType != null)
+                                       ms = ms.DeclaringType;
+
+                               var imported_type = ms.MemberDefinition as ImportedTypeDefinition;
+                               if (imported_type != null) {
+                                       var iad = imported_type.DeclaringAssembly as ImportedAssemblyDefinition;
+                                       SymbolRelatedToPreviousError (iad.Location);
+                               }
                        }
                }
 
@@ -202,7 +208,7 @@ namespace Mono.CSharp {
                        SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
                }
 
-               void SymbolRelatedToPreviousError (string loc, string symbol)
+               public void SymbolRelatedToPreviousError (string loc)
                {
                        string msg = String.Format ("{0} (Location of the symbol related to previous ", loc);
                        if (extra_information.Contains (msg))
@@ -217,10 +223,11 @@ namespace Mono.CSharp {
                        try {
                                id = int.Parse (warningId);
                        } catch {
-                               id = -1;
+                               CheckWarningCode (warningId, Location.Null);
+                               return;
                        }
 
-                       if (!CheckWarningCode (id, warningId, Location.Null))
+                       if (!CheckWarningCode (id, Location.Null))
                                return;
 
                        if (warnings_as_error == null)
@@ -235,10 +242,11 @@ namespace Mono.CSharp {
                        try {
                                id = int.Parse (warningId);
                        } catch {
-                               id = -1;
+                               CheckWarningCode (warningId, Location.Null);
+                               return;
                        }
 
-                       if (!CheckWarningCode (id, warningId, Location.Null))
+                       if (!CheckWarningCode (id, Location.Null))
                                return;
 
                        if (warnings_only == null)
@@ -247,18 +255,21 @@ namespace Mono.CSharp {
                        warnings_only.Add (id);
                }
 
-               public bool CheckWarningCode (int code, Location loc)
+               public bool CheckWarningCode (string code, Location loc)
                {
-                       return CheckWarningCode (code, code.ToString (), loc);
+                       Warning (1691, 1, loc, "`{0}' is not a valid warning number", code);
+                       return false;
                }
 
-               public bool CheckWarningCode (int code, string scode, Location loc)
+               public bool CheckWarningCode (int code, Location loc)
                {
-                       if (IsValidWarning (code))
+                       if (AllWarningsHashSet == null)
+                               AllWarningsHashSet = new HashSet<int> (AllWarnings);
+
+                       if (AllWarningsHashSet.Contains (code))
                                return true;
 
-                       Warning (1691, 1, loc, "`{0}' is not a valid warning number", scode);
-                       return false;
+                       return CheckWarningCode (code.ToString (), loc);
                }
 
                public void ExtraInformation (Location loc, string msg)
@@ -271,14 +282,14 @@ namespace Mono.CSharp {
                        WarningRegions regions;
                        if (warning_regions_table == null) {
                                regions = null;
-                               warning_regions_table = new Dictionary<string, WarningRegions> ();
+                               warning_regions_table = new Dictionary<int, WarningRegions> ();
                        } else {
-                               warning_regions_table.TryGetValue (location.Name, out regions);
+                               warning_regions_table.TryGetValue (location.File, out regions);
                        }
 
                        if (regions == null) {
                                regions = new WarningRegions ();
-                               warning_regions_table.Add (location.Name, regions);
+                               warning_regions_table.Add (location.File, regions);
                        }
 
                        return regions;
@@ -293,10 +304,12 @@ namespace Mono.CSharp {
                                return;
 
                        AbstractMessage msg;
-                       if (IsWarningAsError (code))
+                       if (IsWarningAsError (code)) {
+                               message = "Warning as Error: " + message;
                                msg = new ErrorMessage (code, loc, message, extra_information);
-                       else
+                       } else {
                                msg = new WarningMessage (code, loc, message, extra_information);
+                       }
 
                        extra_information.Clear ();
                        printer.Print (msg);
@@ -410,9 +423,9 @@ namespace Mono.CSharp {
                public void SetIgnoreWarning (int code)
                {
                        if (warning_ignore_table == null)
-                               warning_ignore_table = new Dictionary<int, bool> ();
+                               warning_ignore_table = new HashSet<int> ();
 
-                       warning_ignore_table [code] = true;
+                       warning_ignore_table.Add (code);
                }
 
                public ReportPrinter SetPrinter (ReportPrinter printer)
@@ -440,8 +453,8 @@ namespace Mono.CSharp {
                [Conditional ("MCS_DEBUG")]
                static public void Debug (int category, string message, params object[] args)
                {
-                       if ((category & DebugFlags) == 0)
-                               return;
+//                     if ((category & DebugFlags) == 0)
+//                             return;
 
                        StringBuilder sb = new StringBuilder (message);
 
@@ -595,27 +608,23 @@ namespace Mono.CSharp {
        //
        // Generic base for any message writer
        //
-       public abstract class ReportPrinter {
-               /// <summary>  
-               ///   Whether to dump a stack trace on errors. 
-               /// </summary>
-               public bool Stacktrace;
-               
-               int warnings, errors;
+       public abstract class ReportPrinter
+       {
+               #region Properties
 
-               public int WarningsCount {
-                       get { return warnings; }
-               }
-               
-               public int ErrorsCount {
-                       get { return errors; }
-               }
+               public int FatalCounter { get; set; }
 
-               protected virtual string FormatText (string txt)
-               {
-                       return txt;
-               }
+               public int ErrorsCount { get; protected set; }
+       
+               public bool ShowFullPaths { get; set; }
 
+               //
+               // Whether to dump a stack trace on errors. 
+               //
+               public bool Stacktrace { get; set; }
+
+               public int WarningsCount { get; private set; }
+       
                //
                // When (symbols related to previous ...) can be used
                //
@@ -623,19 +632,35 @@ namespace Mono.CSharp {
                        get { return true; }
                }
 
+               #endregion
+
+
+               protected virtual string FormatText (string txt)
+               {
+                       return txt;
+               }
+
                public virtual void Print (AbstractMessage msg)
                {
-                       if (msg.IsWarning)
-                               ++warnings;
-                       else
-                               ++errors;
+                       if (msg.IsWarning) {
+                               ++WarningsCount;
+                       } else {
+                               ++ErrorsCount;
+
+                               if (ErrorsCount == FatalCounter)
+                                       throw new Exception (msg.Text);
+                       }
                }
 
                protected void Print (AbstractMessage msg, TextWriter output)
                {
                        StringBuilder txt = new StringBuilder ();
                        if (!msg.Location.IsNull) {
-                               txt.Append (msg.Location.ToString ());
+                               if (ShowFullPaths)
+                                       txt.Append (msg.Location.ToStringFullName ());
+                               else
+                                       txt.Append (msg.Location.ToString ());
+
                                txt.Append (" ");
                        }
 
@@ -651,6 +676,16 @@ namespace Mono.CSharp {
                                        output.WriteLine (s + msg.MessageType + ")");
                        }
                }
+
+               public void Reset ()
+               {
+                       // HACK: Temporary hack for broken repl flow
+                       ErrorsCount = WarningsCount = 0;
+               }
+       }
+
+       sealed class NullReportPrinter : ReportPrinter
+       {
        }
 
        //
@@ -758,14 +793,17 @@ namespace Mono.CSharp {
                        if (messages_to_print == null)
                                return false;
 
-                       foreach (AbstractMessage msg in messages_to_print)
+                       bool error_msg = false;
+                       foreach (AbstractMessage msg in messages_to_print) {
                                dest.Print (msg);
+                               error_msg |= !msg.IsWarning;
+                       }
 
-                       return true;
+                       return error_msg;
                }
        }
 
-       class StreamReportPrinter : ReportPrinter
+       public class StreamReportPrinter : ReportPrinter
        {
                readonly TextWriter writer;
 
@@ -781,7 +819,7 @@ namespace Mono.CSharp {
                }
        }
 
-       class ConsoleReportPrinter : StreamReportPrinter
+       public class ConsoleReportPrinter : StreamReportPrinter
        {
                static readonly string prefix, postfix;
 
@@ -800,6 +838,7 @@ namespace Mono.CSharp {
                                break;
 
                        case "xterm-color":
+                       case "xterm-256color":
                                xterm_colors = true;
                                break;
                        }
@@ -841,8 +880,6 @@ namespace Mono.CSharp {
                {
                }
 
-               public int Fatal { get; set; }
-
                static int NameToCode (string s)
                {
                        switch (s) {
@@ -904,7 +941,7 @@ namespace Mono.CSharp {
                        
                        for (int i = 0; i < t.FrameCount; i++) {
                                StackFrame f = t.GetFrame (i);
-                               MethodBase mb = f.GetMethod ();
+                               var mb = f.GetMethod ();
                                
                                if (!foundUserCode && mb.ReflectedType == typeof (Report))
                                        continue;
@@ -919,7 +956,7 @@ namespace Mono.CSharp {
                                sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
                                
                                bool first = true;
-                               foreach (ParameterInfo pi in mb.GetParameters ()) {
+                               foreach (var pi in mb.GetParameters ()) {
                                        if (!first)
                                                sb.Append (", ");
                                        first = false;
@@ -932,16 +969,12 @@ namespace Mono.CSharp {
                        return sb.ToString ();
                }
 
-               int print_count;
                public override void Print (AbstractMessage msg)
                {
                        base.Print (msg);
 
                        if (Stacktrace)
                                Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
-
-                       if (++print_count == Fatal)
-                               throw new Exception (msg.Text);
                }
 
                public static string FriendlyStackTrace (Exception e)
@@ -955,89 +988,97 @@ namespace Mono.CSharp {
                }
        }
 
-       public enum TimerType {
-               FindMembers     = 0,
-               TcFindMembers   = 1,
-               MemberLookup    = 2,
-               CachedLookup    = 3,
-               CacheInit       = 4,
-               MiscTimer       = 5,
-               CountTimers     = 6
-       }
-
-       public enum CounterType {
-               FindMembers     = 0,
-               MemberCache     = 1,
-               MiscCounter     = 2,
-               CountCounters   = 3
-       }
-
-       public class Timer
+       class TimeReporter
        {
-               static DateTime[] timer_start;
-               static TimeSpan[] timers;
-               static long[] timer_counters;
-               static long[] counters;
-
-               static Timer ()
+               public enum TimerType
                {
-                       timer_start = new DateTime [(int) TimerType.CountTimers];
-                       timers = new TimeSpan [(int) TimerType.CountTimers];
-                       timer_counters = new long [(int) TimerType.CountTimers];
-                       counters = new long [(int) CounterType.CountCounters];
-
-                       for (int i = 0; i < (int) TimerType.CountTimers; i++) {
-                               timer_start [i] = DateTime.Now;
-                               timers [i] = TimeSpan.Zero;
-                       }
+                       ParseTotal,
+                       AssemblyBuilderSetup,
+                       CreateTypeTotal,
+                       ReferencesLoading,
+                       ReferencesImporting,
+                       PredefinedTypesInit,
+                       ModuleDefinitionTotal,
+                       UsingResolve,
+                       EmitTotal,
+                       CloseTypes,
+                       Resouces,
+                       OutputSave,
+                       DebugSave,
                }
 
-               [Conditional("TIMER")]
-               static public void IncrementCounter (CounterType which)
+               readonly Stopwatch[] timers;
+               Stopwatch total;
+
+               public TimeReporter (bool enabled)
                {
-                       ++counters [(int) which];
+                       if (!enabled)
+                               return;
+
+                       timers = new Stopwatch[System.Enum.GetValues(typeof (TimerType)).Length];
                }
 
-               [Conditional("TIMER")]
-               static public void StartTimer (TimerType which)
+               public void Start (TimerType type)
                {
-                       timer_start [(int) which] = DateTime.Now;
+                       if (timers != null) {
+                               var sw = new Stopwatch ();
+                               timers[(int) type] = sw;
+                               sw.Start ();
+                       }
                }
 
-               [Conditional("TIMER")]
-               static public void StopTimer (TimerType which)
+               public void StartTotal ()
                {
-                       timers [(int) which] += DateTime.Now - timer_start [(int) which];
-                       ++timer_counters [(int) which];
+                       total = new Stopwatch ();
+                       total.Start ();
                }
 
-               [Conditional("TIMER")]
-               static public void ShowTimers ()
+               public void Stop (TimerType type)
                {
-                       ShowTimer (TimerType.FindMembers, "- FindMembers timer");
-                       ShowTimer (TimerType.TcFindMembers, "- TypeContainer.FindMembers timer");
-                       ShowTimer (TimerType.MemberLookup, "- MemberLookup timer");
-                       ShowTimer (TimerType.CachedLookup, "- CachedLookup timer");
-                       ShowTimer (TimerType.CacheInit, "- Cache init");
-                       ShowTimer (TimerType.MiscTimer, "- Misc timer");
-
-                       ShowCounter (CounterType.FindMembers, "- Find members");
-                       ShowCounter (CounterType.MemberCache, "- Member cache");
-                       ShowCounter (CounterType.MiscCounter, "- Misc counter");
+                       if (timers != null) {
+                               timers[(int) type].Stop ();
+                       }
                }
 
-               static public void ShowCounter (CounterType which, string msg)
+               public void StopTotal ()
                {
-                       Console.WriteLine ("{0} {1}", counters [(int) which], msg);
+                       total.Stop ();
                }
 
-               static public void ShowTimer (TimerType which, string msg)
+               public void ShowStats ()
                {
-                       Console.WriteLine (
-                               "[{0:00}:{1:000}] {2} (used {3} times)",
-                               (int) timers [(int) which].TotalSeconds,
-                               timers [(int) which].Milliseconds, msg,
-                               timer_counters [(int) which]);
+                       if (timers == null)
+                               return;
+
+                       Dictionary<TimerType, string> timer_names = new Dictionary<TimerType,string> () {
+                               { TimerType.ParseTotal, "Parsing source files" },
+                               { TimerType.AssemblyBuilderSetup, "Assembly builder setup" },
+                               { TimerType.CreateTypeTotal, "Compiled types created" },
+                               { TimerType.ReferencesLoading, "Referenced assemblies loading" },
+                               { TimerType.ReferencesImporting, "Referenced assemblies importing" },
+                               { TimerType.PredefinedTypesInit, "Predefined types initialization" },
+                               { TimerType.ModuleDefinitionTotal, "Module definition" },
+                               { TimerType.UsingResolve, "Top-level usings resolve" },
+                               { TimerType.EmitTotal, "Resolving and emitting members blocks" },
+                               { TimerType.CloseTypes, "Module types closed" },
+                               { TimerType.Resouces, "Embedding resources" },
+                               { TimerType.OutputSave, "Writing output file" },
+                               { TimerType.DebugSave, "Writing debug symbols file" },
+                       };
+
+                       int counter = 0;
+                       double percentage = (double) total.ElapsedMilliseconds / 100;
+                       long subtotal = total.ElapsedMilliseconds;
+                       foreach (var timer in timers) {
+                               string msg = timer_names[(TimerType) counter++];
+                               var ms = timer == null ? 0 : timer.ElapsedMilliseconds;
+                               Console.WriteLine ("{0,4:0.0}% {1,5}ms {2}", ms / percentage, ms, msg);
+                               subtotal -= ms;
+                       }
+
+                       Console.WriteLine ("{0,4:0.0}% {1,5}ms Other tasks", subtotal / percentage, subtotal);
+                       Console.WriteLine ();
+                       Console.WriteLine ("Total elapsed time: {0}", total.Elapsed);
                }
        }
 
@@ -1163,8 +1204,13 @@ namespace Mono.CSharp {
 
                public void WarningEnable (Location location, int code, Report Report)
                {
-                       if (Report.CheckWarningCode (code, location))
-                               regions.Add (new Enable (location.Row, code));
+                       if (!Report.CheckWarningCode (code, location))
+                               return;
+
+                       if (Report.IsWarningDisabledGlobally (code))
+                               Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code);
+
+                       regions.Add (new Enable (location.Row, code));
                }
 
                public bool IsWarningEnabled (int code, int src_line)