public override CallStack FindStack(Method method) { CallStack getStack = null; CallStack setStack = null; if (this.Get != null) { getStack = this.Get.FindStack(method); } if (this.Set != null) { setStack = this.Set.FindStack(method); } else { return getStack; } if ((getStack == null) || (setStack.Count < getStack.Count)) { return setStack; } else { return getStack; } }
public MethodItem(Method method, ThrownException exception) { this.Method = method; this.Exception = exception; }
public MethodEventArgs(Method method, Method callingMethod, ThrownException exception) { this.Method = method; this.CallingMethod = callingMethod; this.Exception = exception; }
/// <summary>Updates the list.</summary> protected void UpdateList() { Worker worker = new Worker(this, (cancelToken) => { this.InvokeIfRequired(() => { try { this.BeginUpdate(); this.Items.Clear(); } finally { this.EndUpdate(); } }); List<ListViewItem> items = new List<ListViewItem>(); if (this.MethodContainer is Class) { HashSet<string> got = new HashSet<string>(); foreach (Method m in this.MethodContainer.CalledMethods) { foreach (ThrownException ex in m.UnhandledExceptions) { if (this.Exceptions.Contains(ex)) { string id = ex.Method.GetId() + ex.Exception.FullName; if (!got.Contains(id)) { got.Add(id); //ListViewItem item = MakeItem(ex, ex.Method).Item; ListViewItem item = MakeItem(ex, m).Item; items.Add(item); } } } } } else if (this.GroupByType) { // group the exceptions by type ThrownExceptionDictionary dict = new ThrownExceptionDictionary(this.Exceptions); foreach (IEnumerable<ThrownException> list in dict.GetLists()) { Type type = list.First().Exception; ListViewGroup lvg = this.Groups.Add(type.FullName, type.Name); list.ToList().ForEach(item => items.Add(MakeItem(item, item.Method, lvg).Item)); } } else { IEnumerable<Method> methods; if (this.MethodContainer is Method) { } else { methods = new Method[] { this.MethodContainer as Method }.Concat(this.MethodContainer.CalledMethods); } foreach (ThrownException ex in this.Exceptions) { Method m = null; if (ex.Method == this.MethodContainer) { m = this.MethodContainer as Method; } else { m = this.MethodContainer.CalledMethods.FirstOrDefault(md => md.UnhandledExceptions.Contains(ex)); if (m == null) { m = this.MethodContainer as Method; } } ListViewItem item = MakeItem(ex, m).Item; items.Add(item); } } this.InvokeIfRequired(() => { try { this.BeginUpdate(); this.Items.AddRange(items.ToArray()); } finally { this.EndUpdate(); } }); }); worker.RunWorkerAsync(); }
/// <summary> /// Makes a new item. /// </summary> /// <param name="exception">The exception.</param> /// <param name="method">The method.</param> /// <param name="group">The group.</param> /// <returns></returns> protected ItemInfo MakeItem(ThrownException exception, Method method = null, ListViewGroup group = null) { bool isMethod = (method != null); bool isProperty = isMethod && method.MethodBase.IsProperty(); bool isThrow = !isMethod && (exception != null); if (!isMethod) { method = exception.Method; } ListViewItem item; PropertyInfo pi = null; if (isProperty) { bool getter = method.MethodBase.Name.StartsWith("get_"); pi = method.MethodBase.GetMethodProperty(); item = new ListViewItem(string.Format(CultureInfo.InvariantCulture, "{0} ({1})", pi.Name, getter ? "get" : "set")); } else { item = new ListViewItem(method.ToString()); } if (isProperty) { item.ImageKey = NodeInfo.ImageKeyFromObject(pi); } else if (isMethod) { // use the method for the icon item.ImageKey = NodeInfo.ImageKeyFromObject(method.MethodBase); } else { // use the exception for the icon item.ImageKey = NodeInfo.ImageKeyFromObject(exception.Exception); } ItemInfo info; MethodItem me = new MethodItem(method, exception); if (exception == null) { info = new ItemInfo(item, me, NodeType.Method); item.SubItems.Add(""); } else { info = new ItemInfo(item, me, NodeType.Method); info.Expandable = !isThrow; item.SubItems.Add(exception.Exception.Name); } item.Tag = info; item.SubItems.Add(method.MethodBase.DeclaringType.Name); item.SubItems.Add(method.MethodBase.DeclaringType.Module.Name); item.IndentCount = 1; if (group != null) { item.Group = group; } return info; }
/// <summary>Finds the stack.</summary> /// <param name="method">The method.</param> /// <param name="stack">The stack.</param> /// <param name="shortest">The shortest.</param> /// <param name="visited">The visited.</param> /// <returns></returns> private int FindStack(Method method, CallStack stack, CallStack shortest, HashSet<Method> visited) { stack.Push(this); try { visited.Add(this); if ((shortest.Count > 0) && (stack.Count >= shortest.Count)) { // the shortest stack found is less than the current one - don't search any further return -1; } if (this == method) { // copy the current stack shortest.Clear(); foreach (Method m in stack) { shortest.Push(m); } return 0; } // go through the unhandled exceptions for each called method, and see if the method that the exception // matches the one being found. int best = -1; foreach (Method m in this.CalledMethods) { if (visited.Contains(m)) { continue; } // see if this method has an uncaught exception that was thrown in the target method var xx = m.UnhandledExceptions.FirstOrDefault(ex => ex.Method == method); var yy = m.UnhandledExceptions.Where(ex => ex.Method == method); bool found = (m == method) || m.UnhandledExceptions.FirstOrDefault(ex => ex.Method == method) != null; if (found) { int depth = m.FindStack(method, stack, shortest, visited); if (depth == 0) { // it's this one, no need to search the rest return depth + 1; } else if ((depth < best) || (best == -1)) { best = depth; } } } return best; } finally { stack.Pop(); } return -1; }
/// <summary>Finds the shortest callstack to the provided method.</summary> /// <param name="method">The method to search for.</param> /// <returns>The shortest call-stack from this method to the specified method.</returns> public override CallStack FindStack(Method method) { if (method == null) { return null; } HashSet<Method> visited = new HashSet<Method>(); CallStack shortest = new CallStack(); this.FindStack(method, new CallStack(), shortest, visited); visited.Clear(); return shortest; }
public void ReadProperty(ExceptionFinder finder, CancellationToken cancelToken) { MethodInfo[] methods = new MethodInfo[] { this.PropertyInfo.GetGetMethod(true), this.PropertyInfo.GetSetMethod(true) }; this.Set = this.Get = null; foreach (MethodInfo mi in methods) { if (mi != null) { Method m = finder.ReadMethod(mi, cancelToken); if (m != null) { foreach (MethodContainer mc in this.CalledMethods) { this.CalledMethods.Add(mc); } this.ThrownExceptions.AddRange(m.ThrownExceptions); this.UnhandledExceptions.AddRange(m.UnhandledExceptions); this.DocumentedThrownExceptions.AddRange(m.DocumentedThrownExceptions); } if (mi.Name.StartsWith("get_")) { this.Get = m; } else { this.Set = m; } } this._complete = true; } }
/// <summary>Initializes a new instance of the <see cref="ThrownException"/> class.</summary> /// <param name="method">The method.</param> /// <param name="fromXmlDoc">if set to <c>true</c> [from XML doc].</param> /// <param name="exception">The exception.</param> public ThrownException(Method method, bool fromXmlDoc, Type exception) { this.Method = method; this.IsXmlDoc = fromXmlDoc; this.Exception = exception; }
/// <summary> /// Initializes a new instance of the <see cref="ThrownException"/> class. /// </summary> /// <param name="method">The method.</param> /// <param name="offset">The offset.</param> /// <param name="exception">The exception.</param> public ThrownException(Method method, int offset, Type exception) { this.Method = method; this.Offset = offset; this.Exception = exception; }