/// <summary> /// Tries to parse a StackFrame following convention from Environment.StackTrace /// https://docs.microsoft.com/en-us/dotnet/api/system.environment.stacktrace has /// details on output format and expected strings /// /// Example: /// at ConsoleApp4.MyClass.M() in C:\repos\ConsoleApp4\ConsoleApp4\Program.cs:line 26 /// </summary> public bool TryParseLine(string line, [NotNullWhen(true)] out ParsedFrame?parsedFrame) { parsedFrame = null; if (!line.Trim().StartsWith(StackTraceAtStart)) { return(false); } var success = StackFrameParserHelpers.TryParseMethodSignature(line.AsSpan(), out var classSpan, out var methodSpan, out var argsSpan); if (!success) { return(false); } var splitIndex = line.IndexOf(StackTraceSymbolAndFileSplit); // The line has " in <filename>:line <line number>" if (splitIndex > 0) { var fileInformationStart = splitIndex + StackTraceSymbolAndFileSplit.Length; var fileInformationSpan = new TextSpan(fileInformationStart, line.Length - fileInformationStart); parsedFrame = new ParsedStackFrame(line, classSpan, methodSpan, argsSpan, fileInformationSpan); return(true); } parsedFrame = new ParsedStackFrame(line, classSpan, methodSpan, argsSpan); return(true); }
public bool TryParseLine(string line, [NotNullWhen(true)] out ParsedFrame?parsedFrame) { // Example line: // ConsoleApp4.dll!ConsoleApp4.MyClass.ThrowAtOne() Line 19 C# // |--------------------------------| // Symbol data we care about parsedFrame = null; // +1 here because we always want to skip the '!' character var startPoint = line.IndexOf('!') + 1; if (startPoint == 0 || startPoint == line.Length) { return(false); } var success = StackFrameParserHelpers.TryParseMethodSignature(line.AsSpan().Slice(startPoint), out var classSpan, out var methodSpan, out var argsSpan); if (!success) { return(false); } // The spans need to be fixed up by the start point since we didn't // pass everyting from '!' and before to the parser classSpan = new TextSpan(classSpan.Start + startPoint, classSpan.Length); methodSpan = new TextSpan(methodSpan.Start + startPoint, methodSpan.Length); argsSpan = new TextSpan(argsSpan.Start + startPoint, argsSpan.Length); parsedFrame = new ParsedStackFrame(line, classSpan, methodSpan, argsSpan); return(true); }
/// <summary> /// Uses <see cref="StackFrameParser"/> to parse a line if possible /// </summary> public bool TryParseLine(string line, [NotNullWhen(true)] out ParsedFrame?parsedFrame) { parsedFrame = null; var tree = StackFrameParser.TryParse(line); if (tree is null) { return(false); } parsedFrame = new ParsedStackFrame(tree); return(true); }
public bool TryParseLine(VirtualCharSequence line, [NotNullWhen(true)] out ParsedFrame?parsedFrame) { // Example line: // ConsoleApp4.dll!ConsoleApp4.MyClass.ThrowAtOne() Line 19 C# // |--------------------------------| // Symbol data we care about parsedFrame = null; var startPoint = -1; for (var i = 0; i < line.Length; i++) { if (line[i].Value == '!') { // +1 here because we always want to skip the '!' character startPoint = i + 1; break; } } if (startPoint <= 0 || startPoint == line.Length) { return(false); } var textToParse = line.GetSubSequence(TextSpan.FromBounds(startPoint, line.Length)); var tree = StackFrameParser.TryParse(textToParse); if (tree is null) { return(false); } parsedFrame = new ParsedStackFrame(tree); return(true); }