ManuelHentschel / VSCode-R-Debugger

R Debugger Extension for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=RDebugger.r-debugger
MIT License
170 stars 11 forks source link

Jupyter Lab R Debugging Advice #143

Closed JZL closed 3 years ago

JZL commented 3 years ago

Hi,

This is a more open-ended issue which I'll close immediately, but I'm an RStudio expat and was looking into the possibility of adding R debugging support to jupyter lab using its new Jupyter Debug Protocol. Just going off the blog post it seems like it's mostly used MSFT's Debug Adapter Protocol with some slight modifications [1]. It seems like you already did the majority of the hard work with this VScode R-debugger + vscDebugger!

Do you have any advice for trying to adapt this to work with Jupyter? Going off one of the main jupyter PR's, it looks like some of the specification is still in slight flux, but even a bastardized version would be very useful, for me at least. One of the main things I miss from RStudio is its basic support for browser() but it was too buggy with big datasets

Thanks Jonah

[1]

  • In order to support page reloading, or a client connecting at a later stage, Jupyter kernels must store the state of the debugger (breakpoints, whether the debugger is currently stopped). The front-end can request that state over with a debug_request message.
  • In order to support the debugging of notebook cells and of Jupyter consoles, which are not based on source files, we also needed messages to submit code to the debugger to which breakpoints can be added.
ManuelHentschel commented 3 years ago

Hi Jonah, thanks for raising this issue! Adapting the debug adapter to work with jupyter sounds very interesting.

From my experience, the biggest problem with implementing the DAP is that, as far as I know, it's impossible to give flow-control commands (e.g. n, c, Q) from within R. I've had a look at the R source code and the browser seems to read these commands directly from stdin and there is no way to simulate this input using R code.

To overcome this, I wrapped an interactive R session in a "debugger runtime" in typescript. This wrapper mostly just passes DAP-messages through and lets the DAP logic be handled by the code from vscDebugger, but when the debug client requests a step (i.e. n), the debug adapter sends a "writeToStdinRequest" and returns. The typescript wrapper then sends n to the stdin of the R process and calls a listener function from vscDebugger to handle further requests. This method is a bit messy, but so far I couldn't really figure out a better way (Writing a separate R frontend might work but introduce all kinds of other complications. If you can think of a better way, please let me know!).

I'd exptect the plain R-code from vscDebugger to work fine inside Jupyter notebooks (e.g. settings breakpoints, displaying the call stack, getting info about variables), but implementing flow control feels rather complicated. An approach to solve this might be to implement a different kernel that includes a typescript wrapper (this wrapper could also be implemented in any other language) and passes messages to vscDebugger or IRkernel depending on their type.

I'll try to get the jupyterlab-python-debugger running next week and see if I come up with any ideas. If you decide to work on this, I'd suggest focussing on the flow-control. Handling of other DAP messages could probably be copied from vscDebugger.

Edit: Regarding the two modifications to the DAP introduced by Jupyter: I think these will be quite straightforward to implement (vscDebugger already keeps track of its state and some artificial source files), so they shouldn't be much of a problem.