示例#1
0
        public async Task <IReadOnlyList <DebugStackFrame> > GetStackFramesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            ThrowIfDisposed();

            await TaskUtilities.SwitchToBackgroundThread();

            await InitializeAsync(cancellationToken);

            var jFrames = await InvokeDebugHelperAsync <JArray>("rtvs:::describe_traceback()", cancellationToken);

            Trace.Assert(jFrames.All(t => t is JObject), "rtvs:::describe_traceback(): array of objects expected.\n\n" + jFrames);

            var stackFrames = new List <DebugStackFrame>();

            DebugStackFrame lastFrame = null;
            int             i         = 0;

            foreach (JObject jFrame in jFrames)
            {
                var fallbackFrame = (_bpHitFrame != null && _bpHitFrame.Index == i) ? _bpHitFrame : null;
                lastFrame = new DebugStackFrame(this, i, lastFrame, jFrame, fallbackFrame);
                stackFrames.Add(lastFrame);
                ++i;
            }

            return(stackFrames);
        }
示例#2
0
        internal static DebugEvaluationResult Parse(DebugStackFrame stackFrame, string name, JObject json)
        {
            var expression = json.Value <string>("expression");

            var errorText = json.Value <string>("error");

            if (errorText != null)
            {
                return(new DebugErrorEvaluationResult(stackFrame, expression, name, errorText));
            }

            var code = json.Value <string>("promise");

            if (code != null)
            {
                return(new DebugPromiseEvaluationResult(stackFrame, expression, name, code));
            }

            var isActiveBinding = json.Value <bool?>("active_binding");

            if (isActiveBinding == true)
            {
                return(new DebugActiveBindingEvaluationResult(stackFrame, expression, name));
            }

            return(new DebugValueEvaluationResult(stackFrame, expression, name, json));
        }
示例#3
0
        internal DebugStackFrame(DebugSession session, int index, DebugStackFrame callingFrame, JObject jFrame, DebugStackFrame fallbackFrame = null) {
            Session = session;
            Index = index;
            CallingFrame = callingFrame;

            FileName = jFrame.Value<string>("filename");
            LineNumber = jFrame.Value<int?>("line_number");
            Call = jFrame.Value<string>("call");
            IsGlobal = jFrame.Value<bool?>("is_global") ?? false;

            var match = _doTraceRegex.Match(Call);
            if (match.Success) {
                FrameKind = DebugStackFrameKind.DoTrace;
            }

            if (fallbackFrame != null) {
                // If we still don't have the filename and line number, use those from the fallback frame.
                // This happens during breakpoint hit processing after the context is unwound from within
                // .doTrace back to the function that called it - because we no longer have .doTrace call,
                // we don't have the file/line information that came from it. But DebugSession will have
                // stashed it away when it had it, and then pass it as a fallback frame if index matches.
                FileName = FileName ?? fallbackFrame.FileName;
                LineNumber = LineNumber ?? fallbackFrame.LineNumber;
            }
        }
示例#4
0
        internal DebugStackFrame(DebugSession session, int index, DebugStackFrame callingFrame, JObject jFrame, DebugStackFrame fallbackFrame = null)
        {
            Session      = session;
            Index        = index;
            CallingFrame = callingFrame;

            FileName   = jFrame.Value <string>("filename");
            LineNumber = jFrame.Value <int?>("line_number");
            Call       = jFrame.Value <string>("call");
            IsGlobal   = jFrame.Value <bool?>("is_global") ?? false;

            var match = _doTraceRegex.Match(Call);

            if (match.Success)
            {
                FrameKind = DebugStackFrameKind.DoTrace;
            }

            if (fallbackFrame != null)
            {
                // If we still don't have the filename and line number, use those from the fallback frame.
                // This happens during breakpoint hit processing after the context is unwound from within
                // .doTrace back to the function that called it - because we no longer have .doTrace call,
                // we don't have the file/line information that came from it. But DebugSession will have
                // stashed it away when it had it, and then pass it as a fallback frame if index matches.
                FileName   = FileName ?? fallbackFrame.FileName;
                LineNumber = LineNumber ?? fallbackFrame.LineNumber;
            }
        }
        internal static DebugEvaluationResult Parse(DebugStackFrame stackFrame, string name, JObject json) {
            var expression = json.Value<string>("expression");

            var errorText = json.Value<string>("error");
            if (errorText != null) {
                return new DebugErrorEvaluationResult(stackFrame, expression, name, errorText);
            }

            var code = json.Value<string>("promise");
            if (code != null) {
                return new DebugPromiseEvaluationResult(stackFrame, expression, name, code);
            }

            var isActiveBinding = json.Value<bool?>("active_binding");
            if (isActiveBinding == true) {
                return new DebugActiveBindingEvaluationResult(stackFrame, expression, name);
            }

            return new DebugValueEvaluationResult(stackFrame, expression, name, json);
        }
示例#6
0
        public async Task <DebugEvaluationResult> EvaluateAsync(
            DebugStackFrame stackFrame,
            string expression,
            string name,
            string env,
            DebugEvaluationResultFields fields,
            int?reprMaxLength = null,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            ThrowIfDisposed();

            await TaskUtilities.SwitchToBackgroundThread();

            await InitializeAsync(cancellationToken);

            env = env ?? stackFrame?.SysFrame ?? "NULL";
            var code        = Invariant($"rtvs:::toJSON(rtvs:::eval_and_describe({expression.ToRStringLiteral()}, {env},, {fields.ToRVector()},, {reprMaxLength}))");
            var jEvalResult = await InvokeDebugHelperAsync <JObject>(code, cancellationToken);

            return(DebugEvaluationResult.Parse(stackFrame, name, jEvalResult));
        }
 public DebugErrorEvaluationResult(DebugStackFrame stackFrame, string expression, string name, string errorText)
     : base(stackFrame, expression, name) {
     ErrorText = errorText;
 }
示例#8
0
 internal DebugEvaluationResult(DebugStackFrame stackFrame, string expression, string name)
 {
     StackFrame = stackFrame;
     Expression = expression;
     Name       = name;
 }
示例#9
0
 public DebugActiveBindingEvaluationResult(DebugStackFrame stackFrame, string expression, string name)
     : base(stackFrame, expression, name)
 {
 }
示例#10
0
 public DebugPromiseEvaluationResult(DebugStackFrame stackFrame, string expression, string name, string code)
     : base(stackFrame, expression, name)
 {
     Code = code;
 }
示例#11
0
        internal DebugValueEvaluationResult(DebugStackFrame stackFrame, string expression, string name, JObject json)
            : base(stackFrame, expression, name)
        {
            var repr = json["repr"];

            if (repr != null)
            {
                _reprObj = repr as JObject;
                if (_reprObj == null)
                {
                    throw new InvalidDataException(Invariant($"'repr' must be an object in:\n\n{json}"));
                }
            }

            TypeName       = json.Value <string>("type");
            Length         = json.Value <int?>("length");
            AttributeCount = json.Value <int?>("attr_count");
            SlotCount      = json.Value <int?>("slot_count");
            NameCount      = json.Value <int?>("name_count");

            var classes = json.Value <JArray>("classes");

            if (classes != null)
            {
                Classes = classes.Select(t => t.Value <string>()).ToArray();
            }

            var dim = json.Value <JArray>("dim");

            if (dim != null)
            {
                Dim = dim.Select(t => t.Value <int>()).ToArray();
            }

            var kind = json.Value <string>("kind");

            switch (kind)
            {
            case null:
            case "[[":
                Kind = DebugValueEvaluationResultKind.UnnamedItem;
                break;

            case "$":
                Kind = DebugValueEvaluationResultKind.NamedItem;
                break;

            case "@":
                Kind = DebugValueEvaluationResultKind.Slot;
                break;

            default:
                throw new InvalidDataException(Invariant($"Invalid kind '{kind}' in:\n\n{json}"));
            }

            var flags = json.Value <JArray>("flags")?.Select(v => v.Value <string>());

            if (flags != null)
            {
                foreach (var flag in flags)
                {
                    switch (flag)
                    {
                    case "atomic":
                        Flags |= DebugValueEvaluationResultFlags.Atomic;
                        break;

                    case "recursive":
                        Flags |= DebugValueEvaluationResultFlags.Recursive;
                        break;

                    case "has_parent_env":
                        Flags |= DebugValueEvaluationResultFlags.HasParentEnvironment;
                        break;

                    default:
                        throw new InvalidDataException(Invariant($"Unrecognized flag '{flag}' in:\n\n{json}"));
                    }
                }
            }
        }
示例#12
0
 public DebugErrorEvaluationResult(DebugStackFrame stackFrame, string expression, string name, string errorText)
     : base(stackFrame, expression, name)
 {
     ErrorText = errorText;
 }
示例#13
0
        private async Task ProcessBrowsePromptWorker(IRSessionInteraction inter)
        {
            var frames = await GetStackFramesAsync();

            // If there's .doTrace(rtvs:::breakpoint) anywhere on the stack, we're inside the internal machinery
            // that triggered Browse> prompt when hitting a breakpoint. We need to step out of it until we're
            // back at the frame where the breakpoint was actually set, so that those internal frames do not show
            // on the call stack, and further stepping does not try to step through them.
            // Since browserSetDebug-based step out is not reliable in the presence of loops, we'll just keep
            // stepping over with "n" until we're all the way out. Every step will trigger a new prompt, and
            // we will come back to this method again.
            var doTraceFrame = frames.FirstOrDefault(frame => frame.FrameKind == DebugStackFrameKind.DoTrace);

            if (doTraceFrame != null)
            {
                // Save the .doTrace frame so that we can report file / line number info correctly later, once we're fully stepped out.
                // TODO: remove this hack when injected breakpoints get proper source info (#570).
                _bpHitFrame = doTraceFrame;

                await inter.RespondAsync(Invariant($"n\n"));

                return;
            }

            IReadOnlyCollection <DebugBreakpoint> breakpointsHit = null;
            var lastFrame = frames.LastOrDefault();

            if (lastFrame != null)
            {
                // Report breakpoints first, so that by the time step completion is reported, all actions associated
                // with breakpoints (e.g. printing messages for tracepoints) have already been completed.
                if (lastFrame.FileName != null && lastFrame.LineNumber != null)
                {
                    var             location = new DebugBreakpointLocation(lastFrame.FileName, lastFrame.LineNumber.Value);
                    DebugBreakpoint bp;
                    if (_breakpoints.TryGetValue(location, out bp))
                    {
                        bp.RaiseBreakpointHit();
                        breakpointsHit = Enumerable.Repeat(bp, bp.UseCount).ToArray();
                    }
                }
            }

            bool isStepCompleted = false;

            if (_stepTcs != null)
            {
                var stepTcs = _stepTcs;
                _stepTcs = null;
                stepTcs.TrySetResult(breakpointsHit == null || breakpointsHit.Count == 0);
                isStepCompleted = true;
            }

            EventHandler <DebugBrowseEventArgs> browse;

            lock (_browseLock) {
                browse = _browse;
            }

            var eventArgs = new DebugBrowseEventArgs(inter.Contexts, isStepCompleted, breakpointsHit);

            _currentBrowseEventArgs = eventArgs;
            browse?.Invoke(this, eventArgs);
        }
示例#14
0
 private void InterruptBreakpointHitProcessing()
 {
     _bpHitFrame = null;
 }
        internal DebugValueEvaluationResult(DebugStackFrame stackFrame, string expression, string name, JObject json)
            : base(stackFrame, expression, name) {

            var repr = json["repr"];
            if (repr != null) {
                _reprObj = repr as JObject;
                if (_reprObj == null) {
                    throw new InvalidDataException(Invariant($"'repr' must be an object in:\n\n{json}"));
                }
            }

            TypeName = json.Value<string>("type");
            Length = json.Value<int?>("length");
            AttributeCount = json.Value<int?>("attr_count");
            SlotCount = json.Value<int?>("slot_count");
            NameCount = json.Value<int?>("name_count");

            var classes = json.Value<JArray>("classes");
            if (classes != null) {
                Classes = classes.Select(t => t.Value<string>()).ToArray();
            }

            var dim = json.Value<JArray>("dim");
            if (dim != null) {
                Dim = dim.Select(t => t.Value<int>()).ToArray();
            }

            var kind = json.Value<string>("kind");
            switch (kind) {
                case null:
                case "[[":
                    Kind = DebugValueEvaluationResultKind.UnnamedItem;
                    break;
                case "$":
                    Kind = DebugValueEvaluationResultKind.NamedItem;
                    break;
                case "@":
                    Kind = DebugValueEvaluationResultKind.Slot;
                    break;
                default:
                    throw new InvalidDataException(Invariant($"Invalid kind '{kind}' in:\n\n{json}"));
            }

            var flags = json.Value<JArray>("flags")?.Select(v => v.Value<string>());
            if (flags != null) {
                foreach (var flag in flags) {
                    switch (flag) {
                        case "atomic":
                            Flags |= DebugValueEvaluationResultFlags.Atomic;
                            break;
                        case "recursive":
                            Flags |= DebugValueEvaluationResultFlags.Recursive;
                            break;
                        case "has_parent_env":
                            Flags |= DebugValueEvaluationResultFlags.HasParentEnvironment;
                            break;
                        default:
                            throw new InvalidDataException(Invariant($"Unrecognized flag '{flag}' in:\n\n{json}"));
                    }
                }
            }
        }
 internal DebugEvaluationResult(DebugStackFrame stackFrame, string expression, string name) {
     StackFrame = stackFrame;
     Expression = expression;
     Name = name;
 }
 public DebugActiveBindingEvaluationResult(DebugStackFrame stackFrame, string expression, string name)
     : base(stackFrame, expression, name) {
 }
 public DebugPromiseEvaluationResult(DebugStackFrame stackFrame, string expression, string name, string code)
     : base(stackFrame, expression, name) {
     Code = code;
 }