2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / corlib / System.Diagnostics / StackTrace.cs
index 302f4cf65a396e3d150970013341b063eca60563..e8e7abb0e783e0bb159a664f7cd6665e1cc082a6 100644 (file)
 //
 // Author:
 //      Alexander Klyubin (klyubin@aqris.com)
+//      Dietmar Maurer (dietmar@ximian.com)
 //
 // (C) 2001
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
+using System.Collections;
+using System.Globalization;
 using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
 using System.Threading;
 
 namespace System.Diagnostics {
-        /// <summary>
-        ///   Stack trace.
-        ///   TODO: more information.
-        /// </summary>
-        public class StackTrace {
-                /// <value>
-                ///   Uses a constant to define the number of methods that are
-                ///   to be omitted from the stack trace.
-                /// </value>
-                public const int METHODS_TO_SKIP = 0;
-                
-                /// <value>
-                ///   Frames. First frame is the last stack frame pushed.
-                /// </value>
-                private StackFrame[] frames;
 
+       [Serializable]
+       [MonoTODO ("Fix serialization compatibility with MS.NET")]
+       public class StackTrace {
+
+               public const int METHODS_TO_SKIP = 0;
+
+               private StackFrame[] frames;
+
+               public StackTrace ()
+               {
+                       init_frames (METHODS_TO_SKIP, false);
+               }
+
+               public StackTrace (bool needFileInfo)
+               {
+                       init_frames (METHODS_TO_SKIP, needFileInfo);
+               }
+
+               public StackTrace (int skipFrames)
+               {
+                       init_frames (skipFrames, false);
+               }
+
+               public StackTrace (int skipFrames, bool needFileInfo)
+               {
+                       init_frames (skipFrames, needFileInfo);
+               }
+
+               void init_frames (int skipFrames, bool needFileInfo)
+               {
+                       if (skipFrames < 0)
+                               throw new ArgumentOutOfRangeException ("< 0", "skipFrames");
+
+                       StackFrame sf;
+                       ArrayList al = new ArrayList ();
+
+                       skipFrames += 2;
+                       
+                       while ((sf = new StackFrame (skipFrames, needFileInfo)) != null &&
+                              sf.GetMethod () != null) {
+                               
+                               al.Add (sf);
+                               skipFrames++;
+                       };
+
+                       frames = (StackFrame [])al.ToArray (typeof (StackFrame));       
+               }
+               
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static StackFrame [] get_trace (Exception e, int skipFrames, bool needFileInfo);
+
+               public StackTrace (Exception e)
+                       : this (e, METHODS_TO_SKIP, false)
+               {
+               }
+
+               public StackTrace (Exception e, bool needFileInfo)
+                       : this (e, METHODS_TO_SKIP, needFileInfo)
+               {
+               }
+
+               public StackTrace (Exception e, int skipFrames)
+                       : this (e, skipFrames, false)
+               {
+               }
+
+               public StackTrace (Exception e, int skipFrames, bool needFileInfo)
+               {
+                       if (e == null)
+                               throw new ArgumentNullException ("e");
+                       if (skipFrames < 0)
+                               throw new ArgumentOutOfRangeException ("< 0", "skipFrames");
+
+                       frames = get_trace (e, skipFrames, needFileInfo);
+               }
+
+               public StackTrace (StackFrame frame)
+               {
+                       this.frames = new StackFrame [1];
+                       this.frames [0] = frame;
+               }
+
+               [MonoTODO]
+               public StackTrace (Thread targetThread, bool needFileInfo)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public virtual int FrameCount {
+                       get {
+                               return (frames == null) ? 0 : frames.Length;
+                       }
+               }
+
+               public virtual StackFrame GetFrame (int index)
+               {
+                       if ((index < 0) || (index >= FrameCount)) {
+                               return null;
+                       }
+
+                       return frames [index];
+               }
+
+#if NET_2_0
+               [ComVisibleAttribute (false)]
+               public virtual
+#else
+               // used for CAS implementation (before Fx 2.0)
+               internal
+#endif
+               StackFrame[] GetFrames ()
+               {
+                       return frames;
+               }
+
+               public override string ToString ()
+               {
+                       string newline = String.Format ("{0}\t {1} ", Environment.NewLine, Locale.GetText ("at"));
+                       string unknown = Locale.GetText ("<unknown method>");
+                       StringBuilder sb = new StringBuilder ();
+                       for (int i = 0; i < FrameCount; i++) {
+                               StackFrame frame = GetFrame (i);
+                               sb.Append (newline);
+                               MethodBase method = frame.GetMethod ();
+                               if (method != null) {
+                                       // Method information available
+                                       sb.AppendFormat ("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
+                               }
+                               else {
+                                       // Method information not available
+                                       sb.Append (unknown);
+                               }
+                       }
 
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class.
-                /// </summary>
-                public StackTrace() {
-                        throw new NotImplementedException();
-                }
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class.
-                /// </summary>
-                /// <param name="needFileInfo">
-                ///   TODO:
-                /// </param>
-                public StackTrace(bool needFileInfo) : this() {}
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class.
-                /// </summary>
-                /// <param name="e">
-                ///   TODO:
-                /// </param>
-                public StackTrace(Exception e) {
-                        throw new NotImplementedException();
-                }
-                
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class,
-                ///   using the provided exception object. The resulting stack
-                ///   trace describes the stack at the time of the exception.
-                /// </summary>
-                /// <param name="e">
-                ///   TODO:
-                /// </param>
-                /// <param name="needFileInfo">
-                ///   TODO:
-                /// </param>
-                public StackTrace(Exception e, bool needFileInfo) : this(e) {}
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class,
-                ///   using the provided exception object. The resulting stack
-                ///   trace describes the stack at the time of the exception.
-                /// </summary>
-                /// <param name="e">
-                ///   Exception.
-                /// </param>
-                /// <param name="skipFrames">
-                ///   The number of frames up the stack to start the trace
-                ///   from.
-                /// </param>
-                public StackTrace(Exception e, int skipFrames) {
-                        throw new NotImplementedException();
-                }
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class,
-                ///   using the provided exception object. The resulting stack
-                ///   trace describes the stack at the time of the exception.
-                /// </summary>
-                /// <param name="e">
-                ///   Exception.
-                /// </param>
-                /// <param name="skipFrames">
-                ///   The number of frames up the stack to start the trace
-                ///   from.
-                /// </param>
-                /// <param name="needFileInfo">
-                ///   TODO:
-                /// </param>
-                public StackTrace(Exception e, int skipFrames, bool needFileInfo)
-                : this(e, skipFrames) {}
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class
-                ///   from the current location, in a caller's frame.
-                /// </summary>
-                /// <param name="skipFrames">
-                ///   The number of frames up the stack to start the trace
-                ///   from.
-                /// </param>
-                public StackTrace(int skipFrames) {
-                        throw new NotImplementedException();
-                }
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class
-                ///   containing a single frame.
-                /// </summary>
-                /// <param name="frame">
-                ///   The frame that the StackTrace object should contain.
-                /// </param>
-                public StackTrace(StackFrame frame) {
-                        this.frames = new StackFrame[1];
-                        this.frames[0] = frame;
-                }
-                
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class
-                ///   from the current location, in a caller's frame.
-                /// </summary>
-                /// <param name="skipFrames">
-                ///   The number of frames up the stack to start the trace
-                ///   from.
-                /// </param>
-                /// <param name="needFileInfo">
-                ///   TODO:
-                /// </param>
-                public StackTrace(int skipFrames, bool needFileInfo)
-                : this(skipFrames) {}
-                
-                /// <summary>
-                ///   Initializes a new instance of the StackTrace class.
-                /// </summary>
-                /// <param name="targetThread">
-                ///   TODO:
-                /// </param>
-                /// <param name="needFileInfo">
-                ///   TODO:
-                /// </param>
-                public StackTrace(Thread targetThread, bool needFileInfo) {
-                        throw new NotImplementedException();
-                }
-                
-                
-                                  
-                /// <summary>
-                ///   Holds the number of frames in the stack trace.
-                /// </summary>
-                public virtual int FrameCount {
-                        get {
-                                return (frames == null) ? 0 : frames.Length;
-                        }
-                }             
-                              
-                /// <summary>
-                ///   Gets the specified stack frame.
-                /// </summary>
-                /// <param name="index">
-                ///   The index of the stack frame requested.
-                /// </param>
-                /// <returns>
-                ///   The specified stack frame. Returns <code>null</code> if
-                ///   frame with specified index does not exist in this stack
-                ///   trace.
-                /// </returns>
-                /// <remarks>
-                ///   Stack frames are numbered starting at zero, which is the
-                ///   last stack frame pushed.
-                /// </remarks>
-                public virtual StackFrame GetFrame(int index) {
-                        if ((index < 0) || (index >= FrameCount)) {
-                                return null;
-                        }
-                        
-                        return frames[index];
-                }              
-                
-                /// <summary>
-                ///   Builds a readable representation of the stack trace.
-                /// </summary>
-                /// <returns>
-                ///   A readable representation of the stack trace.
-                /// </returns>
-                public override string ToString() {
-                        string result = "";
-                        for (int i = 0; i < FrameCount; i++) {
-                                StackFrame frame = GetFrame(i);
-                                result += "\n\tat " + FrameToString(frame);
-                        }
-                        
-                        return result;
-                }
-                
-                public override bool Equals(Object obj) {
-                        if ((obj == null) || (!(obj is StackTrace))) {
-                                return false;
-                        }
-                        
-                        StackTrace rhs = (StackTrace) obj;
-                        
-                        if (FrameCount != rhs.FrameCount) {
-                                return false;
-                        }
-                        
-                        for (int i = 0; i < FrameCount; i++) {
-                                if (!GetFrame(i).Equals(rhs.GetFrame(i))) {
-                                        return false;
-                                }
-                        }
-                        
-                        return true;
-                }
-                
-                public override int GetHashCode() {
-                        return FrameCount;
-                }
-                
-                /// <summary>
-                ///   Converts single stack frame to string to be used in
-                ///   ToString method.
-                /// </summary>
-                /// <param name="frame">
-                ///   Frame to convert.
-                /// </param>
-                /// <returns>
-                ///   A readable representation of stack frame for using
-                ///   ToString.
-                /// </returns>
-                private static String FrameToString(StackFrame frame) {
-                        string locationInfo;
-                        
-                        if (frame.GetFileName() == null) {
-                                // File name not available
-                                locationInfo = "";
-                        } else {
-                                // File name available
-                                locationInfo = frame.GetFileName();
-                                if (frame.GetFileLineNumber() != 0) {
-                                        // Line number information available
-                                        locationInfo += ":line "
-                                                + frame.GetFileLineNumber();
-                                        if (frame.GetFileColumnNumber() != 0) {
-                                                // Column number information available
-                                                locationInfo += ":column"
-                                                        + frame.GetFileColumnNumber();
-                                        }
-                                }
-                                
-                        }
-                        
-                        MethodBase method = frame.GetMethod();
-                        if (method != null) {
-                                // Method information available
-                                return  method.DeclaringType.Name
-                                        + "." + method.Name + "()"
-                                        + ((locationInfo != null)
-                                                ? " at " + locationInfo
-                                                  : "");
-                        } else {
-                                // Method information not available
-                                string methodInfo = "<unknown method>";
-                                if ("".Equals(locationInfo)) {
-                                        // No location information available
-                                        return methodInfo;
-                                }
-                                
-                                // Location information available
-                                return methodInfo + " at " + locationInfo;
-                        }
-                }
-        }
-}
\ No newline at end of file
+                       return sb.ToString ();
+               }
+       }
+}