2002-06-18 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mcs / class / corlib / System.Diagnostics / StackTrace.cs
1 //
2 // System.Diagnostics.StackTrace.cs
3 //
4 // Author:
5 //      Alexander Klyubin (klyubin@aqris.com)
6 //      Dietmar Maurer (dietmar@ximian.com)
7 //
8 // (C) 2001
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Threading;
14 using System.Runtime.CompilerServices;
15
16 namespace System.Diagnostics {
17         /// <summary>
18         ///   Stack trace.
19         ///   TODO: more information.
20         /// </summary>
21         [Serializable]
22         public class StackTrace {
23                 /// <value>
24                 ///   Uses a constant to define the number of methods that are
25                 ///   to be omitted from the stack trace.
26                 /// </value>
27                 public const int METHODS_TO_SKIP = 0;
28                 
29                 /// <value>
30                 ///   Frames. First frame is the last stack frame pushed.
31                 /// </value>
32                 private StackFrame[] frames;
33
34                 /// <summary>
35                 ///   Initializes a new instance of the StackTrace class.
36                 /// </summary>
37                 [MonoTODO]
38                 public StackTrace() : this (METHODS_TO_SKIP, false) {}
39                 
40                 /// <summary>
41                 ///   Initializes a new instance of the StackTrace class.
42                 /// </summary>
43                 /// <param name="needFileInfo">
44                 ///   TODO:
45                 /// </param>
46                 public StackTrace(bool needFileInfo) : this (METHODS_TO_SKIP, needFileInfo) {}
47
48                 /// <summary>
49                 ///   Initializes a new instance of the StackTrace class
50                 ///   from the current location, in a caller's frame.
51                 /// </summary>
52                 /// <param name="skipFrames">
53                 ///   The number of frames up the stack to start the trace
54                 ///   from.
55                 /// </param>
56                 public StackTrace(int skipFrames) : this (skipFrames, false) {}
57
58                 /// <summary>
59                 ///   Initializes a new instance of the StackTrace class
60                 ///   from the current location, in a caller's frame.
61                 /// </summary>
62                 /// <param name="skipFrames">
63                 ///   The number of frames up the stack to start the trace
64                 ///   from.
65                 /// </param>
66                 /// <param name="needFileInfo">
67                 ///   TODO:
68                 /// </param>
69                 public StackTrace(int skipFrames, bool needFileInfo) {
70                         throw new NotImplementedException();                    
71                 }
72                 
73                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
74                 extern static StackFrame [] get_trace (Exception e, int skipFrames, bool needFileInfo);
75
76                 /// <summary>
77                 ///   Initializes a new instance of the StackTrace class.
78                 /// </summary>
79                 /// <param name="e">
80                 ///   TODO:
81                 /// </param>
82                 public StackTrace(Exception e) {
83                         frames = get_trace (e, METHODS_TO_SKIP, false);
84                 }
85                                 
86                 /// <summary>
87                 ///   Initializes a new instance of the StackTrace class,
88                 ///   using the provided exception object. The resulting stack
89                 ///   trace describes the stack at the time of the exception.
90                 /// </summary>
91                 /// <param name="e">
92                 ///   TODO:
93                 /// </param>
94                 /// <param name="needFileInfo">
95                 ///   TODO:
96                 /// </param>
97                 public StackTrace(Exception e, bool needFileInfo) {
98                         frames = get_trace (e, METHODS_TO_SKIP, needFileInfo);
99                 }
100                 
101                 /// <summary>
102                 ///   Initializes a new instance of the StackTrace class,
103                 ///   using the provided exception object. The resulting stack
104                 ///   trace describes the stack at the time of the exception.
105                 /// </summary>
106                 /// <param name="e">
107                 ///   Exception.
108                 /// </param>
109                 /// <param name="skipFrames">
110                 ///   The number of frames up the stack to start the trace
111                 ///   from.
112                 /// </param>
113                 public StackTrace(Exception e, int skipFrames) {
114                         frames = get_trace (e, skipFrames, false);
115                 }
116                 
117                 /// <summary>
118                 ///   Initializes a new instance of the StackTrace class,
119                 ///   using the provided exception object. The resulting stack
120                 ///   trace describes the stack at the time of the exception.
121                 /// </summary>
122                 /// <param name="e">
123                 ///   Exception.
124                 /// </param>
125                 /// <param name="skipFrames">
126                 ///   The number of frames up the stack to start the trace
127                 ///   from.
128                 /// </param>
129                 /// <param name="needFileInfo">
130                 ///   TODO:
131                 /// </param>
132                 public StackTrace(Exception e, int skipFrames, bool needFileInfo) {
133                         frames = get_trace (e, skipFrames, needFileInfo);
134                 }
135                               
136                 /// <summary>
137                 ///   Initializes a new instance of the StackTrace class
138                 ///   containing a single frame.
139                 /// </summary>
140                 /// <param name="frame">
141                 ///   The frame that the StackTrace object should contain.
142                 /// </param>
143                 public StackTrace(StackFrame frame) {
144                         this.frames = new StackFrame[1];
145                         this.frames[0] = frame;
146                 }
147                                
148                 /// <summary>
149                 ///   Initializes a new instance of the StackTrace class.
150                 /// </summary>
151                 /// <param name="targetThread">
152                 ///   TODO:
153                 /// </param>
154                 /// <param name="needFileInfo">
155                 ///   TODO:
156                 /// </param>
157                 [MonoTODO]
158                 public StackTrace(Thread targetThread, bool needFileInfo) {
159                         throw new NotImplementedException();
160                 }
161                
162                 /// <summary>
163                 ///   Holds the number of frames in the stack trace.
164                 /// </summary>
165                 public virtual int FrameCount {
166                         get {
167                                 return (frames == null) ? 0 : frames.Length;
168                         }
169                 }             
170                               
171                 /// <summary>
172                 ///   Gets the specified stack frame.
173                 /// </summary>
174                 /// <param name="index">
175                 ///   The index of the stack frame requested.
176                 /// </param>
177                 /// <returns>
178                 ///   The specified stack frame. Returns <code>null</code> if
179                 ///   frame with specified index does not exist in this stack
180                 ///   trace.
181                 /// </returns>
182                 /// <remarks>
183                 ///   Stack frames are numbered starting at zero, which is the
184                 ///   last stack frame pushed.
185                 /// </remarks>
186                 public virtual StackFrame GetFrame(int index) {
187                         if ((index < 0) || (index >= FrameCount)) {
188                                 return null;
189                         }
190                         
191                         return frames[index];
192                 }              
193                 
194                 /// <summary>
195                 ///   Builds a readable representation of the stack trace.
196                 /// </summary>
197                 /// <returns>
198                 ///   A readable representation of the stack trace.
199                 /// </returns>
200                 public override string ToString() {
201                         string result = "";
202                         for (int i = 0; i < FrameCount; i++) {
203                                 StackFrame frame = GetFrame(i);
204                                 result += "\n\tat " + FrameToString(frame);
205                         }
206                         
207                         return result;
208                 }
209                 
210                 public override bool Equals(Object obj) {
211                         if ((obj == null) || (!(obj is StackTrace))) {
212                                 return false;
213                         }
214                         
215                         StackTrace rhs = (StackTrace) obj;
216                         
217                         if (FrameCount != rhs.FrameCount) {
218                                 return false;
219                         }
220                         
221                         for (int i = 0; i < FrameCount; i++) {
222                                 if (!GetFrame(i).Equals(rhs.GetFrame(i))) {
223                                         return false;
224                                 }
225                         }
226                         
227                         return true;
228                 }
229                 
230                 public override int GetHashCode() {
231                         return FrameCount;
232                 }
233                 
234                 /// <summary>
235                 ///   Converts single stack frame to string to be used in
236                 ///   ToString method.
237                 /// </summary>
238                 /// <param name="frame">
239                 ///   Frame to convert.
240                 /// </param>
241                 /// <returns>
242                 ///   A readable representation of stack frame for using
243                 ///   ToString.
244                 /// </returns>
245                 private static String FrameToString(StackFrame frame) {
246                         MethodBase method = frame.GetMethod();
247                         if (method != null) {
248                                 // Method information available
249                                 return  method.DeclaringType.FullName
250                                         + "." + method.Name + "()";
251                         } else {
252                                 // Method information not available
253                                 return "<unknown method>";
254                         }
255                 }
256         }
257 }