Created
October 27, 2024 03:42
-
-
Save magicxor/5abc3df8dadd61e1329d87681d6bdf3c to your computer and use it in GitHub Desktop.
Retrieve possible exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections.Concurrent; | |
| using System.Xml.Linq; | |
| using Mono.Cecil; | |
| using Mono.Cecil.Cil; | |
| namespace ExceptionRetriever; | |
| public class ExceptionExtractor | |
| { | |
| public static void ExtractExceptions(string assemblyPath, string xmlDocPath) | |
| { | |
| var assembly = AssemblyDefinition.ReadAssembly(assemblyPath); | |
| var xmlDoc = XDocument.Load(xmlDocPath); | |
| var allMethodsExceptions = new ConcurrentDictionary<string, HashSet<string>>(); | |
| foreach (var type in assembly.MainModule.Types) | |
| { | |
| foreach (var method in type.Methods) | |
| { | |
| if (!method.HasBody) continue; | |
| foreach (var instruction in method.Body.Instructions) | |
| { | |
| MethodReference methodReference = null; | |
| // Проверка на вызов методов | |
| if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Callvirt) | |
| { | |
| methodReference = instruction.Operand as MethodReference; | |
| } | |
| // Проверка на вызов конструкторов | |
| else if (instruction.OpCode == OpCodes.Newobj) | |
| { | |
| methodReference = instruction.Operand as MethodReference; | |
| } | |
| // Если найден вызов метода или конструктора из System.IO | |
| if (methodReference != null && methodReference.DeclaringType.Namespace.StartsWith("System.IO")) | |
| { | |
| // Ищем исключения в XML-документации | |
| var exceptions = GetExceptionsFromXmlDoc(xmlDoc, methodReference); | |
| foreach (var ex in exceptions) | |
| { | |
| var methodExceptions = allMethodsExceptions.GetOrAdd(method.FullName, _ => new HashSet<string>()); | |
| methodExceptions.Add(ex); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| foreach (var methodExceptions in allMethodsExceptions) | |
| { | |
| Console.WriteLine(methodExceptions.Key + " throws: " + string.Join(", ", methodExceptions.Value)); | |
| Console.WriteLine(Environment.NewLine); | |
| } | |
| } | |
| private static IEnumerable<string> GetExceptionsFromXmlDoc(XDocument xmlDoc, MethodReference methodReference) | |
| { | |
| // Собираем имя метода вместе с типами параметров, чтобы точно найти нужную перегрузку | |
| var methodSignature = $"{methodReference.DeclaringType.FullName}.{methodReference.Name}({string.Join(",", methodReference.Parameters.Select(p => p.ParameterType.FullName))})"; | |
| // Ищем элемент member, у которого атрибут name соответствует точной сигнатуре метода | |
| var member = xmlDoc.Descendants("member") | |
| .FirstOrDefault(m => m.Attribute("name")?.Value == $"M:{methodSignature}"); | |
| if (member == null) yield break; | |
| foreach (var exceptionElement in member.Descendants("exception")) | |
| { | |
| yield return exceptionElement.Attribute("cref")?.Value; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment