/// <summary> /// Finds correspondence between Q# and C# stack frames and populates Q# stack frame information from C# stack frames /// </summary> public static StackFrame[] PopulateSourceLocations(Stack <StackFrame> qsharpCallStack, System.Diagnostics.StackFrame[] csharpCallStack) { foreach (StackFrame currentFrame in qsharpCallStack) { ICallable op = currentFrame.Callable.UnwrapCallable(); object[] locations = op.GetType().GetCustomAttributes(typeof(SourceLocationAttribute), true); foreach (object location in locations) { SourceLocationAttribute sourceLocation = (location as SourceLocationAttribute); if (sourceLocation != null && sourceLocation.SpecializationKind == op.Variant) { currentFrame.SourceFile = System.IO.Path.GetFullPath(sourceLocation.SourceFile); currentFrame.DeclarationStartLineNumber = sourceLocation.StartLine; currentFrame.DeclarationEndLineNumber = sourceLocation.EndLine; } } } StackFrame[] qsharpStackFrames = qsharpCallStack.ToArray(); int qsharpStackFrameId = 0; for (int csharpStackFrameId = 0; csharpStackFrameId < csharpCallStack.Length; ++csharpStackFrameId) { string fileName = csharpCallStack[csharpStackFrameId].GetFileName(); if (fileName != null) { fileName = System.IO.Path.GetFullPath(fileName); int failedLineNumber = csharpCallStack[csharpStackFrameId].GetFileLineNumber(); StackFrame currentQsharpStackFrame = qsharpStackFrames[qsharpStackFrameId]; if (fileName == currentQsharpStackFrame.SourceFile && currentQsharpStackFrame.DeclarationStartLineNumber <= failedLineNumber && ( (failedLineNumber < currentQsharpStackFrame.DeclarationEndLineNumber) || (currentQsharpStackFrame.DeclarationEndLineNumber == -1) ) ) { currentQsharpStackFrame.FailedLineNumber = failedLineNumber; qsharpStackFrameId++; if (qsharpStackFrameId == qsharpStackFrames.Length) { break; } } } } return(qsharpStackFrames); }
/// <summary> /// Finds correspondence between Q# and C# stack frames and populates Q# stack frame information from C# stack frames /// </summary> public static StackFrame[] PopulateSourceLocations(Stack <StackFrame> qsharpCallStack, System.Diagnostics.StackFrame[] csharpStackFrames) { // Populate source location information in QSharp stack from attributes foreach (StackFrame currentFrame in qsharpCallStack) { ICallable op = currentFrame.Callable.UnwrapCallable(); object[] locations = op.GetType().GetCustomAttributes(typeof(SourceLocationAttribute), true); foreach (object location in locations) { SourceLocationAttribute sourceLocation = (location as SourceLocationAttribute); if (sourceLocation != null && sourceLocation.SpecializationKind == op.Variant) { currentFrame.SourceFile = System.IO.Path.GetFullPath(sourceLocation.SourceFile); currentFrame.DeclarationStartLineNumber = sourceLocation.StartLine; currentFrame.DeclarationEndLineNumber = sourceLocation.EndLine; break; } } } StackFrame[] qsharpStackFrames = qsharpCallStack.ToArray(); int currentQSharpFrameIndex = -1; int currentCSharpFrameIndex = -1; // A set of Q# stack frames is assumed to be a subset of C# stack frames. // When a C# stack frame doesn't have enough information to match with corresponding Q# frame // this assumption is essentially broken, which results in missing matches. System.Diagnostics.StackFrame csharpFrame = GetNextCSharpStackFrame(csharpStackFrames, ref currentCSharpFrameIndex); StackFrame qsharpFrame = GetNextQSharpStackFrame(qsharpStackFrames, ref currentQSharpFrameIndex); while (csharpFrame != null && qsharpFrame != null) { if (IsMatch(csharpFrame, qsharpFrame)) { PopulateQSharpFrameFromCSharpFrame(csharpFrame, qsharpFrame); // Advance to the next Q# stack frame only when it matches C# stack frame. // If corresponding C# stack frame doesn't have enough information to match // this and all subsequent Q# stack frames will not match. qsharpFrame = GetNextQSharpStackFrame(qsharpStackFrames, ref currentQSharpFrameIndex); } csharpFrame = GetNextCSharpStackFrame(csharpStackFrames, ref currentCSharpFrameIndex); } return(qsharpStackFrames); }