int IDebugProperty2.EnumChildren(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, ref Guid guidFilter, enum_DBG_ATTRIB_FLAGS dwAttribFilter, string pszNameFilter, uint dwTimeout, out IEnumDebugPropertyInfo2 ppEnum) { IEnumerable <DebugEvaluationResult> children = _children.Value; if (!RToolsSettings.Current.ShowDotPrefixedVariables) { children = children.Where(v => v.Name != null && !v.Name.StartsWith(".")); } if (IsFrameEnvironment) { children = children.OrderBy(v => v.Name); } var infos = children.Select(v => new AD7Property(this, v).GetDebugPropertyInfo(dwRadix, dwFields)); var valueResult = EvaluationResult as DebugValueEvaluationResult; if (valueResult != null && valueResult.HasAttributes == true) { string attrExpr = Invariant($"base::attributes({valueResult.Expression})"); var attrResult = TaskExtensions.RunSynchronouslyOnUIThread(ct => StackFrame.StackFrame.EvaluateAsync(attrExpr, "attributes()", PrefetchedFields, ReprMaxLength, ct)); if (!(attrResult is DebugErrorEvaluationResult)) { var attrInfo = new AD7Property(this, attrResult, isSynthetic: true).GetDebugPropertyInfo(dwRadix, dwFields); infos = new[] { attrInfo }.Concat(infos); } } ppEnum = new AD7PropertyInfoEnum(infos.ToArray()); return(VSConstants.S_OK); }
public AD7StackFrame(AD7Engine engine, DebugStackFrame stackFrame) { Engine = engine; StackFrame = stackFrame; _property = Lazy.Create(() => new AD7Property(this, TaskExtensions.RunSynchronouslyOnUIThread(ct => StackFrame.GetEnvironmentAsync(cancellationToken: ct)), isFrameEnvironment: true)); }
int IDebugExpression2.EvaluateSync(enum_EVALFLAGS dwFlags, uint dwTimeout, IDebugEventCallback2 pExprCallback, out IDebugProperty2 ppResult) { var res = TaskExtensions.RunSynchronouslyOnUIThread(ct => StackFrame.StackFrame.EvaluateAsync(_expression, AD7Property.PrefetchedFields, AD7Property.ReprMaxLength, ct)); ppResult = new AD7Property(StackFrame, res); return(VSConstants.S_OK); }
private int Continue(IDebugThread2 pThread) { ThrowIfDisposed(); if (_firstContinue) { _firstContinue = false; } else { // If _sentContinue is true, then this is a dummy Continue issued to notify the // debugger that user has explicitly entered something at the Browse prompt, and // we don't actually need to issue the command to R debugger. Func <CancellationToken, Task> continueMethod = null; lock (_browseLock) { if (_sentContinue != true) { _sentContinue = true; continueMethod = ct => DebugSession.ContinueAsync(ct); } } if (continueMethod != null) { TaskExtensions.RunSynchronouslyOnUIThread(continueMethod); } } return(VSConstants.S_OK); }
private void ResetStackFrames() { _stackFrames = Lazy.Create(() => (IReadOnlyList <DebugStackFrame>) TaskExtensions.RunSynchronouslyOnUIThread(ct => Engine.DebugSession.GetStackFramesAsync(ct)) .Reverse() .ToArray()); }
int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason) { ThrowIfDisposed(); if (rgpPrograms.Length != 1) { throw new ArgumentException("Zero or more than one programs", "rgpPrograms"); } _program = rgpPrograms[0] as RDebugPortSupplier.DebugProgram; if (_program == null) { throw new ArgumentException("rgpPrograms[0] must be an " + nameof(RDebugPortSupplier.DebugProgram), "rgpPrograms"); } Marshal.ThrowExceptionForHR(_program.GetProgramId(out _programId)); _events = pCallback; DebugSession = TaskExtensions.RunSynchronouslyOnUIThread(ct => DebugSessionProvider.GetDebugSessionAsync(_program.Session, ct)); MainThread = new AD7Thread(this); IsConnected = true; // Enable breakpoint instrumentation. TaskExtensions.RunSynchronouslyOnUIThread(ct => DebugSession.EnableBreakpointsAsync(true, ct)); // Send notification after acquiring the session - we need it in case there were any breakpoints pending before // the attach, in which case we'll immediately get breakpoint creation requests as soon as we send these, and // we will need the session to process them. AD7EngineCreateEvent.Send(this); AD7ProgramCreateEvent.Send(this); Send(new AD7LoadCompleteEvent(), AD7LoadCompleteEvent.IID); // Register event handlers after notifying VS that debug engine has loaded. This order is important because // we may get a Browse event immediately, and we want to raise a breakpoint notification in response to that // to pause the debugger - but it will be ignored unless the engine has reported its creation. // Also, AfterRequest must be registered before Browse, so that we never get in a situation where we get // Browse but not AfterRequest that follows it because of a race between raising and registration. DebugSession.RSession.AfterRequest += RSession_AfterRequest; DebugSession.RSession.Disconnected += RSession_Disconnected; // If we're already at the Browse prompt, registering the handler will result in its immediate invocation. // We want to handle that fully before we process any following AfterRequest event to avoid concurrency issues // where we pause and never resume, so hold the lock while adding the handler. lock (_browseLock) { DebugSession.Browse += Session_Browse; } return(VSConstants.S_OK); }
int IDebugProperty3.SetValueAsStringWithError(string pszValue, uint dwRadix, uint dwTimeout, out string errorString) { errorString = null; // TODO: dwRadix var setResult = TaskExtensions.RunSynchronouslyOnUIThread(ct => EvaluationResult.SetValueAsync(pszValue, ct)) as DebugErrorEvaluationResult; if (setResult != null) { errorString = setResult.ErrorText; return(VSConstants.E_FAIL); } return(VSConstants.S_OK); }
private int SetState(enum_BP_STATE state) { if (_state == enum_BP_STATE.BPS_ENABLED) { if (state == enum_BP_STATE.BPS_DISABLED || state == enum_BP_STATE.BPS_DELETED) { if (DebugBreakpoint != null) { DebugBreakpoint.BreakpointHit -= DebugBreakpoint_BreakpointHit; if (Engine.IsConnected) { if (Engine.IsProgramDestroyed) { // If engine is shutting down, do not wait for the delete eval to complete, to avoid // blocking debugger detach if a long-running operation is in progress. This way the // engine can just report successful detach right away, and breakpoints are deleted // later, but as soon as it's actually possible. DebugBreakpoint.DeleteAsync() .SilenceException <MessageTransportException>() .SilenceException <RException>() .DoNotWait(); } else { TaskExtensions.RunSynchronouslyOnUIThread(ct => DebugBreakpoint.DeleteAsync(ct)); } } } } } else { if (state == enum_BP_STATE.BPS_ENABLED) { if (Engine.IsProgramDestroyed) { // Do not allow enabling breakpoints when engine is shutting down. return(VSConstants.E_ABORT); } DebugBreakpoint = TaskExtensions.RunSynchronouslyOnUIThread(ct => Engine.DebugSession.CreateBreakpointAsync(Location, ct)); DebugBreakpoint.BreakpointHit += DebugBreakpoint_BreakpointHit; } } _state = state; return(VSConstants.S_OK); }
private string CreateReprToString() { var ev = TaskExtensions.RunSynchronouslyOnUIThread(ct => EvaluationResult.EvaluateAsync(DebugEvaluationResultFields.Repr | DebugEvaluationResultFields.ReprToString, cancellationToken: ct)); return((ev as DebugValueEvaluationResult)?.GetRepresentation().ToString); }
private IReadOnlyList <DebugEvaluationResult> CreateChildren() { return(TaskExtensions.RunSynchronouslyOnUIThread(ct => (EvaluationResult as DebugValueEvaluationResult)?.GetChildrenAsync(PrefetchedFields, ChildrenMaxLength, ReprMaxLength, ct)) ?? new DebugEvaluationResult[0]); }