Merge pull request #1991 from esdrubal/seq_test_fix
[mono.git] / mcs / class / corlib / System / Exception.cs
index 15adaed837a2fa43edc3bc129b7c84cf9ad28aa4..e07d2e85b62917446160a44c05574c47afa90d0f 100644 (file)
@@ -29,6 +29,7 @@
 //
 
 using System.Collections;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Reflection;
 using System.Text;
@@ -40,52 +41,75 @@ using System.Security.Permissions;
 namespace System
 {
        [Serializable]
-       [ClassInterface (ClassInterfaceType.AutoDual)]
-       public class Exception : ISerializable 
-#if NET_2_0
-       , _Exception
+       [ComVisible(true)]
+       [ComDefaultInterface (typeof (_Exception))]
+       [ClassInterface (ClassInterfaceType.None)]
+       [StructLayout (LayoutKind.Sequential)]
+#if MOBILE
+       public class Exception : ISerializable
+#else
+       public class Exception : ISerializable, _Exception
 #endif
        {
+#pragma warning disable 169, 649
+               #region Sync with object-internals.h
+               /* Stores the IPs and the generic sharing infos
+                  (vtable/MRGCTX) of the frames. */
                IntPtr [] trace_ips;
                Exception inner_exception;
-               internal string message;
+               internal string _message;
                string help_link;
                string class_name;
                string stack_trace;
-               string remote_stack_trace;
+               // formerly known as remote_stack_trace (see #425512):
+               string _remoteStackTraceString;
                int remote_stack_index;
-               internal int hresult = unchecked ((int)0x80004005);
+               internal int hresult = -2146233088;
                string source;
+               IDictionary _data;
+               internal StackTrace[] captured_traces;
+               IntPtr[] native_trace_ips;
+               object dynamic_methods;
+               #endregion
+#pragma warning restore 169, 649
+
+               /* Don't add fields here, the runtime depends on the layout of subclasses */
 
                public Exception ()
                {
                }
 
-               public Exception (string msg)
+               public Exception (string message)
                {
-                       message = msg;
+                       this._message = message;
                }
 
-               protected Exception (SerializationInfo info, StreamingContext sc)
+               protected Exception (SerializationInfo info, StreamingContext context)
                {
                        if (info == null)
                                throw new ArgumentNullException ("info");
 
                        class_name          = info.GetString ("ClassName");
-                       message             = info.GetString ("Message");
+                       _message             = info.GetString ("Message");
                        help_link           = info.GetString ("HelpURL");
                        stack_trace         = info.GetString ("StackTraceString");
-                       remote_stack_trace  = info.GetString ("RemoteStackTraceString");
+                       _remoteStackTraceString  = info.GetString ("RemoteStackTraceString");
                        remote_stack_index  = info.GetInt32  ("RemoteStackIndex");
                        hresult             = info.GetInt32  ("HResult");
                        source              = info.GetString ("Source");
                        inner_exception     = (Exception) info.GetValue ("InnerException", typeof (Exception));
+
+                       try {
+                               _data = (IDictionary) info.GetValue ("Data", typeof (IDictionary));
+                       } catch (SerializationException) {
+                               // member did not exist in .NET 1.x
+                       }
                }
 
-               public Exception (string msg, Exception e)
+               public Exception (string message, Exception innerException)
                {
-                       inner_exception = e;
-                       message = msg;
+                       inner_exception = innerException;
+                       this._message = message;
                }
 
                public Exception InnerException {
@@ -97,14 +121,19 @@ namespace System
                        set { help_link = value; }
                }
 
-               protected int HResult {
+               public int HResult {
                        get { return hresult; }
-                       set { hresult = value; }
+                       protected set { hresult = value; }
+               }
+               
+               internal void SetErrorCode(int hr)
+               {
+                       HResult = hr;
                }
 
                internal void SetMessage (string s)
                {
-                       message = s;
+                       _message = s;
                }
 
                internal void SetStackTrace (string s)
@@ -112,19 +141,33 @@ namespace System
                        stack_trace = s;
                }
 
+               string ClassName {
+                       get {
+                               if (class_name == null)
+                                       class_name = GetType ().ToString ();
+                               return class_name;
+                       }
+               }
+
                public virtual string Message {
                        get {
-                               if (message == null)
-                                       message = string.Format (Locale.GetText ("Exception of type {0} was thrown."), GetType ().ToString());
+                               if (_message == null)
+                                       _message = string.Format (Locale.GetText ("Exception of type '{0}' was thrown."),
+                                               ClassName);
 
-                               return message;
+                               return _message;
+                       }
+               }
+               
+               [MonoTODO]
+               protected event EventHandler<SafeSerializationEventArgs> SerializeObjectState {
+                       add {
+                       }
+                       remove {
                        }
                }
 
                public virtual string Source {
-#if ONLY_1_1
-                       [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
-#endif
                        get {
                                if (source == null) {
                                        StackTrace st = new StackTrace (this, true);
@@ -139,7 +182,7 @@ namespace System
                                        }
                                }
 
-                                // source can be null
+                               // source can be null
                                return source;
                        }
 
@@ -150,55 +193,19 @@ namespace System
 
                public virtual string StackTrace {
                        get {
-                               if (stack_trace == null) {
-                                       if (trace_ips == null)
-                                               /* Not thrown yet */
-                                               return null;
-
-                                       StackTrace st = new StackTrace (this, 0, true, true);
-
-                                       StringBuilder sb = new StringBuilder ();
-
-                                       string newline = String.Format ("{0}  {1} ", Environment.NewLine, Locale.GetText ("at"));
-                                       string unknown = Locale.GetText ("<unknown method>");
-
-                                       for (int i = 0; i < st.FrameCount; i++) {
-                                               StackFrame frame = st.GetFrame (i);
-                                               if (i == 0)
-                                                       sb.AppendFormat ("  {0} ", Locale.GetText ("at"));
-                                               else
-                                                       sb.Append (newline);
-
-                                               if (frame.GetMethod () == null) {
-                                                       string internal_name = frame.GetInternalMethodName ();
-                                                       if (internal_name != null)
-                                                               sb.Append (internal_name);
-                                                       else
-                                                               sb.AppendFormat ("<0x{0:x5}> {1}", frame.GetNativeOffset (), unknown);
-                                               } else {
-                                                       sb.Append (GetFullNameForStackTrace (frame.GetMethod ()));
-
-                                                       if (frame.GetILOffset () == -1)
-                                                               sb.AppendFormat (" <0x{0:x5}> ", frame.GetNativeOffset ());
-                                                       else
-                                                               sb.AppendFormat (" [0x{0:x5}] ", frame.GetILOffset ());
-
-                                                       string fileName = frame.GetFileName ();
-                                                       if (fileName != null)
-                                                               sb.AppendFormat ("in {0}:{1} ", fileName, frame.GetFileLineNumber ());
-                                                       }
-                                       }
-                                       stack_trace = sb.ToString ();
-                               }
+                               if (stack_trace != null)
+                                       return stack_trace;
+
+                               if (trace_ips == null)
+                                       /* Not thrown yet */
+                                       return null;
 
-                               return stack_trace;
+                               StackTrace st = new StackTrace (this, 0, true);
+                               return stack_trace = st.ToString ();
                        }
                }
 
                public MethodBase TargetSite {
-#if ONLY_1_1
-                       [ReflectionPermission (SecurityAction.Demand, TypeInformation = true)]
-#endif
                        get {
                                StackTrace st = new StackTrace (this, true);
                                if (st.FrameCount > 0)
@@ -208,19 +215,15 @@ namespace System
                        }
                }
 
-#if NET_2_0
-               private IDictionary _data;
-
                public virtual IDictionary Data {
                        get {
                                if (_data == null) {
                                        // default to empty dictionary
-                                       _data = (IDictionary) new Hashtable ();
+                                       _data = new Dictionary<object, object> ();
                                }
                                return _data;
                        }
                }
-#endif
 
                public virtual Exception GetBaseException ()
                {
@@ -237,46 +240,38 @@ namespace System
                        return this;
                }
 
-#if ONLY_1_1
-               [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
-#endif
                [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
                public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
                {
                        if (info == null)
                                throw new ArgumentNullException ("info");
 
-                       if (class_name == null)
-                               class_name = GetType ().FullName;
-
-                       info.AddValue ("ClassName", class_name);
-                       info.AddValue ("Message", message);
+                       info.AddValue ("ClassName", ClassName);
+                       info.AddValue ("Message", _message);
                        info.AddValue ("InnerException", inner_exception);
                        info.AddValue ("HelpURL", help_link);
                        info.AddValue ("StackTraceString", StackTrace);
-                       info.AddValue ("RemoteStackTraceString", remote_stack_trace);
+                       info.AddValue ("RemoteStackTraceString", _remoteStackTraceString);
                        info.AddValue ("RemoteStackIndex", remote_stack_index);
                        info.AddValue ("HResult", hresult);
                        info.AddValue ("Source", Source);
                        info.AddValue ("ExceptionMethod", null);
+                       info.AddValue ("Data", _data, typeof (IDictionary));
                }
 
-#if ONLY_1_1
-               [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
-#endif
                public override string ToString ()
                {
-                       System.Text.StringBuilder result = new System.Text.StringBuilder (this.GetType ().FullName);
+                       System.Text.StringBuilder result = new System.Text.StringBuilder (ClassName);
                        result.Append (": ").Append (Message);
 
-                       if (null != remote_stack_trace)
-                               result.Append (remote_stack_trace);
+                       if (null != _remoteStackTraceString)
+                               result.Append (_remoteStackTraceString);
                                
                        if (inner_exception != null) 
                        {
                                result.Append (" ---> ").Append (inner_exception.ToString ());
-                               result.Append (Locale.GetText ("--- End of inner exception stack trace ---"));
                                result.Append (Environment.NewLine);
+                               result.Append (Locale.GetText ("  --- End of inner exception stack trace ---"));
                        }
 
                        if (StackTrace != null)
@@ -291,7 +286,7 @@ namespace System
                                Locale.GetText ("{1}{0}{0}Exception rethrown at [{2}]: {0}");
                        string tmp = String.Format (message, Environment.NewLine, StackTrace, remote_stack_index);
 
-                       remote_stack_trace = tmp;
+                       _remoteStackTraceString = tmp;
                        remote_stack_index++;
 
                        stack_trace = null;
@@ -299,35 +294,43 @@ namespace System
                        return this;
                }
 
-               internal string GetFullNameForStackTrace (MethodBase mi)
+               // For ExceptionDispatchInfo
+               internal void RestoreExceptionDispatchInfo (System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
                {
-                       string parms = String.Empty;
-                       ParameterInfo[] p = mi.GetParameters ();
-                       for (int i = 0; i < p.Length; ++i) {
-                               if (i > 0)
-                                       parms = parms + ", ";
-                               string paramName = (p [i].Name == null) ? String.Empty : (" " + p [i].Name);
-                               Type pt = p[i].ParameterType;
-                               if (pt.IsClass && pt.Namespace != String.Empty)
-                                       parms = parms + pt.Namespace + "." + pt.Name + paramName;
-                               else
-                                       parms = parms + pt.Name + paramName;
-                       }
+                       captured_traces = (StackTrace[]) exceptionDispatchInfo.BinaryStackTraceArray;
+                       trace_ips = null;
+                       stack_trace = null;
+               }
 
-                       string generic = String.Empty;
-#if NET_2_0 || BOOTSTRAP_NET_2_0
-                       if (mi.IsGenericMethod) {
-                               Type[] gen_params = mi.GetGenericArguments ();
-                               generic = "[";
-                               for (int j = 0; j < gen_params.Length; j++) {
-                                       if (j > 0)
-                                               generic += ",";
-                                       generic += gen_params [j].Name;
-                               }
-                               generic += "]";
+               //
+               // The documentation states that this is available in 1.x,
+               // but it was not available (MemberRefing this would fail)
+               // and it states the signature is `override sealed', but the
+               // correct value is `newslot' 
+               //
+               public new Type GetType ()
+               {
+                       return base.GetType ();
+               }
+
+               internal enum ExceptionMessageKind
+               {
+                       ThreadAbort = 1,
+                       ThreadInterrupted = 2,
+                       OutOfMemory = 3
+               }
+
+               internal static String GetMessageFromNativeResources (ExceptionMessageKind kind)
+               {
+                       switch (kind) {
+                       case ExceptionMessageKind.ThreadAbort:
+                               return "";
+                       case ExceptionMessageKind.ThreadInterrupted:
+                               return "";
+                       case ExceptionMessageKind.OutOfMemory:
+                               return "Out of memory";
                        }
-#endif
-                       return mi.DeclaringType.ToString () + "." + mi.Name + generic + " (" + parms + ")";
-               }                               
+                       return "";
+               }
        }
 }