// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System.Collections;
+using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
namespace System.Diagnostics {
[Serializable]
- [MonoTODO ("Fix serialization compatibility with MS.NET")]
+ [ComVisible (true)]
+ [MonoTODO ("Serialized objects are not compatible with .NET")]
public class StackTrace {
public const int METHODS_TO_SKIP = 0;
private StackFrame[] frames;
+ private bool debug_info;
public StackTrace ()
{
init_frames (METHODS_TO_SKIP, false);
}
- public StackTrace (bool needFileInfo)
+ public StackTrace (bool fNeedFileInfo)
{
- init_frames (METHODS_TO_SKIP, needFileInfo);
+ init_frames (METHODS_TO_SKIP, fNeedFileInfo);
}
public StackTrace (int skipFrames)
init_frames (skipFrames, false);
}
- public StackTrace (int skipFrames, bool needFileInfo)
+ public StackTrace (int skipFrames, bool fNeedFileInfo)
{
- init_frames (skipFrames, needFileInfo);
+ init_frames (skipFrames, fNeedFileInfo);
}
- void init_frames (int skipFrames, bool needFileInfo)
+ void init_frames (int skipFrames, bool fNeedFileInfo)
{
if (skipFrames < 0)
throw new ArgumentOutOfRangeException ("< 0", "skipFrames");
StackFrame sf;
- ArrayList al = new ArrayList ();
+ var l = new List<StackFrame> ();
skipFrames += 2;
- while ((sf = new StackFrame (skipFrames, needFileInfo)) != null &&
+ while ((sf = new StackFrame (skipFrames, fNeedFileInfo)) != null &&
sf.GetMethod () != null) {
- al.Add (sf);
+ l.Add (sf);
skipFrames++;
};
- frames = (StackFrame [])al.ToArray (typeof (StackFrame));
+ debug_info = fNeedFileInfo;
+ frames = l.ToArray ();
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- extern static StackFrame [] get_trace (Exception e, int skipFrames, bool needFileInfo);
+ extern static StackFrame [] get_trace (Exception e, int skipFrames, bool fNeedFileInfo);
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, bool fNeedFileInfo)
+ : this (e, METHODS_TO_SKIP, fNeedFileInfo)
{
}
{
}
- public StackTrace (Exception e, int skipFrames, bool needFileInfo)
+ public StackTrace (Exception e, int skipFrames, bool fNeedFileInfo)
+ : this (e, skipFrames, fNeedFileInfo, false)
+ {
+ }
+
+ internal StackTrace (Exception e, int skipFrames, bool fNeedFileInfo, bool returnNativeFrames)
{
if (e == null)
throw new ArgumentNullException ("e");
if (skipFrames < 0)
throw new ArgumentOutOfRangeException ("< 0", "skipFrames");
- frames = get_trace (e, skipFrames, needFileInfo);
+ frames = get_trace (e, skipFrames, fNeedFileInfo);
+
+ if (!returnNativeFrames) {
+ bool resize = false;
+ for (int i = 0; i < frames.Length; ++i)
+ if (frames [i].GetMethod () == null)
+ resize = true;
+
+ if (resize) {
+ var l = new List<StackFrame> ();
+
+ for (int i = 0; i < frames.Length; ++i)
+ if (frames [i].GetMethod () != null)
+ l.Add (frames [i]);
+
+ frames = l.ToArray ();
+ }
+ }
}
-#if ONLY_1_1
- [ReflectionPermission (SecurityAction.Demand, TypeInformation = true)]
-#endif
public StackTrace (StackFrame frame)
{
this.frames = new StackFrame [1];
this.frames [0] = frame;
}
-#if ONLY_1_1
- [ReflectionPermission (SecurityAction.Demand, TypeInformation = true)]
-#endif
- [MonoTODO]
+ [MonoLimitation ("Not possible to create StackTraces from other threads")]
public StackTrace (Thread targetThread, bool needFileInfo)
{
+ if (targetThread == Thread.CurrentThread){
+ init_frames (METHODS_TO_SKIP, needFileInfo);
+ return;
+ }
+
throw new NotImplementedException ();
}
return frames [index];
}
-#if NET_2_0
[ComVisibleAttribute (false)]
- public virtual
-#else
- // used for CAS implementation (before Fx 2.0)
- internal
-#endif
- StackFrame[] GetFrames ()
+ public virtual StackFrame[] GetFrames ()
{
return frames;
}
public override string ToString ()
{
- string newline = String.Format ("{0}\t {1} ", Environment.NewLine, Locale.GetText ("at"));
+ string newline = String.Format ("{0} {1} ", Environment.NewLine, Locale.GetText ("at"));
string unknown = Locale.GetText ("<unknown method>");
+ string debuginfo = Locale.GetText (" in {0}:line {1}");
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < FrameCount; i++) {
StackFrame frame = GetFrame (i);
- sb.Append (newline);
+ if (i > 0)
+ sb.Append (newline);
+ else
+ sb.AppendFormat (" {0} ", Locale.GetText ("at"));
MethodBase method = frame.GetMethod ();
if (method != null) {
// Method information available
- sb.AppendFormat ("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
+ sb.AppendFormat ("{0}.{1}", method.DeclaringType.FullName, method.Name);
+ /* Append parameter information */
+ sb.Append ("(");
+ ParameterInfo[] p = method.GetParameters ();
+ for (int j = 0; j < p.Length; ++j) {
+ if (j > 0)
+ sb.Append (", ");
+ Type pt = p[j].ParameterType;
+ bool byref = pt.IsByRef;
+ if (byref)
+ pt = pt.GetElementType ();
+ if (pt.IsClass && pt.Namespace != String.Empty) {
+ sb.Append (pt.Namespace);
+ sb.Append (".");
+ }
+ sb.Append (pt.Name);
+ if (byref)
+ sb.Append (" ByRef");
+ sb.AppendFormat (" {0}", p [j].Name);
+ }
+ sb.Append (")");
}
else {
// Method information not available
sb.Append (unknown);
}
- }
+ if (debug_info) {
+ // we were asked for debugging informations
+ // but that doesn't mean we have the debug information available
+ string fname = frame.GetSecureFileName ();
+ if (fname != "<filename unknown>")
+ sb.AppendFormat (debuginfo, fname, frame.GetFileLineNumber ());
+ }
+ }
return sb.ToString ();
}
}