Skip to content

Instantly share code, notes, and snippets.

Created June 27, 2012 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3003999 to your computer and use it in GitHub Desktop.
Save anonymous/3003999 to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using NDepend.Attributes;
using NDepend.Helpers;
namespace NDepend.Product.ErrorHandling {
#if DEBUG
[FullCovered]
#endif
internal static class StackTraceHelper {
internal static string FormatStackTrace(Exception ex) {
Debug.Assert(ex != null);
#if DEBUG
return FormatUnlocalizedStackTraceFromString(ex.StackTrace);
#else
return FormatUnlocalizedStackTraceWithILOffset(ex);
#endif
}
#region FormatUnlocalizedStackTraceWithILOffset()
// 27June2012: Idea to get the ILOffset from stackTrace: http://www.timstall.com/2008/07/getting-file-and-line-numbers-without.html
#if DEBUG
[IsNotDeadCode] // Coz used by tests and release version!!!
#endif
internal static string FormatUnlocalizedStackTraceWithILOffset(Exception ex) {
Debug.Assert(ex != null);
try {
//Get offset:
var stackTrace = new StackTrace(ex, true);
StackFrame[] stackFrames = stackTrace.GetFrames();
var sb = new StringBuilder();
var stackFramesLength = new int[stackFrames.Length];
for (var i = 0; i < stackFramesLength.Length; i++) {
var stacfkFrame = stackFrames[i];
var method = stacfkFrame.GetMethod();
var parameters = GetMethodParameters(method);
var ilOffset = GetILOffset(stacfkFrame.GetILOffset());
sb.Append(string.Format(" {0}.{1}({2}) {3} \r\n",
method.ReflectedType.FullName,
method.Name,
parameters,
ilOffset));
}
return sb.ToString();
} catch {
return FormatUnlocalizedStackTraceFromString(ex.StackTrace);
}
}
private static string GetILOffset(int ilOffset) {
Debug.Assert(ilOffset >= 0);
// Format to hexadecimal to have a Reflector like IL instruction OffSet
var ilOffsetHexString = ilOffset.ToString("X").ToLower();
// Get a Reflector-like ILOffset like "L_018e"
var sb = new StringBuilder("L_");
if(ilOffsetHexString.Length < 4) {
sb.Append(new string('0', 4 - ilOffsetHexString.Length));
}
sb.Append(ilOffsetHexString);
return sb.ToString();
}
private static string GetMethodParameters(MethodBase method) {
Debug.Assert(method != null);
var parameters = method.GetParameters();
var length = parameters.Length;
var sb = new StringBuilder();
for(var i=0; i< length; i++) {
var parameter = parameters[i];
sb.Append(parameter.ParameterType.Name);
sb.Append(" ");
sb.Append(parameter.Name);
if(i < length -1) {
sb.Append(", ");
}
}
return sb.ToString();
}
#endregion FormatUnlocalizedStackTraceWithILOffset()
#region FormatUnlocalizedStackTraceFromString()
internal const string EMPTY_STACK_TRACE = "Empty StackTrace";
//
// OldVersion, still used in Debug mode to get the Line number
// and used in case FormatUnlocalizedStackTraceWithILOffset() has a problem!
//
#if DEBUG
[IsNotDeadCode] // Coz used by tests and release version!!!
#endif
// StackTrace lines are prefixed with " at " or " à " or " в " or " 場所 " that we need to remove
internal static string FormatUnlocalizedStackTraceFromString(string stackTraceIn) {
if(stackTraceIn.IsNullOrEmpty()) {
return EMPTY_STACK_TRACE;
}
var lines = stackTraceIn.Split(new char[] {'\r'});
Debug.Assert(lines != null);
Debug.Assert(lines.Length >= 1);
var sb = new StringBuilder();
for (var i = 0; i < lines.Length; i++ ) {
var unlocalizedLine = UnlocalizeLine(lines[i]);
if (i > 0) { sb.Append("\r\n"); }
sb.Append(unlocalizedLine);
}
return sb.ToString();
}
private static object UnlocalizeLine(string lineIn) {
Debug.Assert(!lineIn.IsNullOrEmpty());
lineIn = lineIn.Replace("\n", ""); // Eventually discard \n at the beginning
int indexFirstNonWhiteSpace = 0;
for (indexFirstNonWhiteSpace = 0; indexFirstNonWhiteSpace < lineIn.Length; indexFirstNonWhiteSpace++) {
if (lineIn[indexFirstNonWhiteSpace] != ' ') { break; }
}
// lineIn is like
// '\n' 'white' 'white' 'at' 'white' "xxxx
// The idea is to get rid of the localizable 'at' and to transform it in
// 'white' "xxxx
var indexOfSecondSpace = lineIn.IndexOf(' ', indexFirstNonWhiteSpace);
if (indexOfSecondSpace == -1) { return lineIn; }
var lineOut = lineIn.Substring(indexOfSecondSpace, lineIn.Length - indexOfSecondSpace);
return lineOut;
}
#endregion FormatUnlocalizedStackTraceFromString()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment