Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugger implementation #13433

Draft
wants to merge 540 commits into
base: main
Choose a base branch
from
Draft

Conversation

RemcoSmitsDev
Copy link
Contributor

@RemcoSmitsDev RemcoSmitsDev commented Jun 23, 2024

Closes #5307
Closes #5065

The current state of the debugger implementation:

Screen.Recording.2024-10-16.at.15.02.20.mov
Screen.Recording.2024-10-03.at.22.34.34.mov

All the todo's are in the following channel, so it's easier to work on this together:
https://zed.dev/channel/zed-debugger-11370

If you are on Linux, you can use the following command to join the channel:

zed https://zed.dev/channel/zed-debugger-11370 

Current Features

  • Collab
    • Breakpoints
      • Sync when you (re)join a project
      • Sync when you add/remove a breakpoint
    • Sync active debug line
    • Stack frames
      • Click on stack frame
        • View variables that belong to the stack frame
        • Visit the source file
      • Restart stack frame (if adapter supports this)
    • Variables
    • Loaded sources
    • Modules
    • Controls
      • Continue
      • Step back
        • Stepping granularity (configurable)
      • Step into
        • Stepping granularity (configurable)
      • Step over
        • Stepping granularity (configurable)
      • Step out
        • Stepping granularity (configurable)
  • Breakpoints
    • Log breakpoints
    • line breakpoints
    • Persistent between zed sessions (configurable)
    • Multi buffer support
    • Toggle disable/enable all breakpoints
  • Stack frames
    • Click on stack frame
      • View variables that belong to the stack frame
      • Visit the source file
    • Restart stack frame (if adapter supports this)
  • Loaded sources
    • View all used loaded sources if supported by adapter.
  • Modules
    • View all used modules (if adapter supports this)
  • Variables
    • Copy value
    • Copy name
    • Copy memory reference
    • Set value (if adapter supports this)
    • keyboard navigation
  • Debug Console
    • See logs
    • View output that was sent from debug adapter
      • Output grouping
    • Evaluate code
      • Updates the variable list
      • Auto completion
        • If not supported by adapter, we will show auto-completion for existing variables
  • Debug Terminal
    • Run custom commands and change env values right inside your Zed terminal
  • Attach to process (if adapter supports this)
    • Process picker
  • Controls
    • Continue
    • Step back
      • Stepping granularity (configurable)
    • Step into
      • Stepping granularity (configurable)
    • Step over
      • Stepping granularity (configurable)
    • Step out
      • Stepping granularity (configurable)
    • Disconnect
    • Restart
    • Stop
  • Warning when a debug session exited without hitting any breakpoint
  • Debug view to see Adapter/RPC log messages
  • Testing
    • Fake debug adapter
      • Fake requests & events

Release Notes:

  • Added debugger implementation.

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Jun 23, 2024
@davidbuzz
Copy link
Contributor

Add documententation and/or an example on how to configure and/enable this for a specific debugger... if not as part of this PR then to the todo list ?

@osiewicz
Copy link
Contributor

Change client id to be language id because you should only run one client per language at the same time

What if you have e.g. a monorepo with multiple services written in the same language?

@RemcoSmitsDev
Copy link
Contributor Author

Uhm, I think most of the debug adapters support multiple threads, but need to look more in to that. Not sure how VS Code handles this, if they allow you to run the same debugger adapter twice or more.

@RemcoSmitsDev RemcoSmitsDev force-pushed the debugger branch 2 times, most recently from c71eb06 to 47a5f0c Compare June 29, 2024 14:47
@davidbuzz
Copy link
Contributor

I'd love to see another more up-to-date video of the current status of this, if u can find time. :-)

@RemcoSmitsDev RemcoSmitsDev force-pushed the debugger branch 3 times, most recently from ac95fbd to 515122c Compare July 3, 2024 21:20
@jonahcui
Copy link

jonahcui commented Jul 4, 2024

HI, I have started a dlv(go dap server) to debug go program, but i need bring env to the dlv commend. I read the code DebugAdapterClient, i think when create_tcp_client or create_stdio_client, we should bring env configuration to command.

@RemcoSmitsDev
Copy link
Contributor Author

RemcoSmitsDev commented Jul 4, 2024

HI, I have started a dlv(go dap server) to debug go program, but i need bring env to the dlv commend. I read the code DebugAdapterClient, i think when create_tcp_client or create_stdio_client, we should bring env configuration to command.

Hey, I think most debug adapters support this already by passing in an env prop through the launch or attach request. See the JS debugger config options. We already support passing in your own config values, so I don't think we need to add more configuration for this. Because it's on the debug adapter for getting this data and handling it how they want.

@jonahcui
Copy link

jonahcui commented Jul 4, 2024

HI, I have started a dlv(go dap server) to debug go program, but i need bring env to the dlv commend. I read the code DebugAdapterClient, i think when create_tcp_client or create_stdio_client, we should bring env configuration to command.

Hey, I think most debug adapters support this already by passing in an env prop through the launch or attach request. See the JS debugger config options. We already support passing in your own config values, so I don't think we need to add more configuration for this. Because it's on the debug adapter for getting this data and handling it how they want.

Ok, understand.... I will test it on js debugger and go delve and study your code.

@RemcoSmitsDev RemcoSmitsDev force-pushed the debugger branch 4 times, most recently from 7eacd30 to 3f8581a Compare July 5, 2024 14:54
@RemcoSmitsDev RemcoSmitsDev force-pushed the debugger branch 2 times, most recently from 8adc489 to 8d99f9b Compare July 12, 2024 20:01
@davidbuzz
Copy link
Contributor

davidbuzz commented Jul 15, 2024

for those of us trying to follow-along at home on this PR, it would be helpful of there was a sample tasks.json ( or wherever the debug settings are being stored if not there ) and any relevent settings.json we need enable, as I compiled and ran this PR, but was unable to get the same behaviour as either of the screen recordings.
for example: ctrl-shift-p[command palette] -> 'debug panel: open panel' gave me an empty lower panel with no start/stop/pause etc, and none of the other demonstrated command-palette/s seemed to do anything.

@RemcoSmitsDev
Copy link
Contributor Author

RemcoSmitsDev commented Jul 15, 2024

Hey @davidbuzz, sorry for not posting any examples of starting a debug adapter. I did this for a reason, because I'm not happy yet with the naming of the fields & structure of the task. But here is an example task to start a debug adapter:

If you want to follow a bit more about what we are working on, you can join the following channel: https://zed.dev/channel/zed-debugger-11370.

{
  "label": "Xdebug debug adapter",
  "command": "bun",
  "args": [
    "/Users/remcosmits/Documents/code/vscode-php-debug/out/phpDebug.js",
    "--server=8132"
  ],
  "task_type": "debug",
  "cwd": "/Users/remcosmits/Documents/code/symfony_demo",
  "debug_adapter": {
    "id": "xdebug",
    "port": 8132,
    "request_args": {
      "skipFiles": ["**/vendor/**"],
      "pathMappings": {
        "/Users/remcosmits/Documents/code/symfony_demo/public": "/Users/remcosmits/Documents/code/symfony_demo/public"
      },
      "localSourceRoot": "/Users/remcosmits/Documents/code/symfony_demo",
      "serverSourceRoot": "/Users/remcosmits/Documents/code/symfony_demo",
      "xdebugSettings": {
        "show_hidden": 1
      }
    }
  }
}

@RemcoSmitsDev RemcoSmitsDev force-pushed the debugger branch 2 times, most recently from d9461c3 to b6e677e Compare July 15, 2024 16:44
@davidbuzz
Copy link
Contributor

davidbuzz commented Jul 16, 2024

i think u mean this discord channel, but u were close.. https://discord.com/channels/869392257814519848/1255246362220691456 ... i pop in to the Zed discord occassionally. :-)

@RemcoSmitsDev
Copy link
Contributor Author

i think u mean this discord channel, but u were close.. https://discord.com/channels/869392257814519848/1255246362220691456 ... i pop in to the Zed discord occassionally. :-)

No, that's not what I mean. What do you mean by I'm close? It sounds a bit disparaging...

@davidbuzz
Copy link
Contributor

I was just trying to say that the link u gave starting with https://zed.dev doesn't work for me.

@RemcoSmitsDev
Copy link
Contributor Author

Ahh oké. it seems to work for other people. Also it's the same as the one that i posted in the discord channel. Does it still not work for you?

@davidbuzz
Copy link
Contributor

Ahh oké. it seems to work for other people. Also it's the same as the one that i posted in the discord channel. Does it still not work for you?

... im on linux. :-)

Anthony-Eid and others added 5 commits January 8, 2025 12:17
This PR integrates Zed's Debugger with the Collab database, enabling Zed to guarantee that clients joining a project with active debug sessions in progress will receive and set up those sessions.

* Add test for setting active debug panel items on project join

* Add DebuggerSession proto message

* Modify debugger session

* Get collab server to build

* Get collab test to compile

* Add proto messages

* Set up message handler for get debugger sessions

* Send set debug panel requests when handling get debugger sessions msg

* Get request to send and set debug panel

* Setup ground work for debug sessions collab db table

* Set up debug_client table for collab db

* Remove up GetDebuggerSession proto request code

* Get proto::DebuggerSession during join_project_internal

* Remove debug_sessions table from collab db

* Add migration for debug_client and fix some bugs

* Create dap store event queue for remote daps

When creating a project in from_join_project_response(...) the debug panel hasn't been initialized yet so
it can't handle dap_store events. The solution to this is creating an event queue that debug panel takes
from dap store if it's remote and then handles all the events

* Fix debug panel join project during session test

* Add debug_panel_items table to collab db

* Integrate debug_panel_item table into collab msg handlers

* Finialize debug_panel_item table refactor for collab db

* Integrate UpdateDebugAdapter RPC with collab DB

* Handle ShutdownDebugClient RPC for collab db

* Fix clippy
Before this commit downstream clients in active debug sessions relied
on the host to send them the active debug line. This had three main
limitations (Which are solved by this commit)

1. Downstream clients didn't have the ability to click on their own stack
frame list and go to that frame's location

2. Downstream clients would always follow the host when checking out stack
frames even from a different debug adapter or thread

3. If a user joins an active debug session they wouldn't have an active
debug line until the host's debug adapter sent another stop event
…tinue requests

When thread status is not Stopped users are unable to click buttons. So the thread status
needs to be reset if any of the above requests fail or else a user loses to ability to
click any of the debug buttons related to those requests
@dyaskur
Copy link

dyaskur commented Jan 11, 2025

̶W̶h̶y̶ ̶d̶o̶e̶s̶ ̶i̶t̶ ̶s̶e̶e̶m̶ ̶t̶o̶ ̶o̶n̶l̶y̶ ̶s̶u̶p̶p̶o̶r̶t̶ ̶i̶n̶t̶e̶r̶p̶r̶e̶t̶e̶d̶ ̶l̶a̶n̶g̶u̶a̶g̶e̶s̶ ̶l̶i̶k̶e̶ ̶J̶a̶v̶a̶S̶c̶r̶i̶p̶t̶,̶ ̶P̶H̶P̶,̶ ̶a̶n̶d̶ ̶P̶y̶t̶h̶o̶n̶?̶ ̶W̶o̶u̶l̶d̶n̶'̶t̶ ̶i̶t̶ ̶b̶e̶ ̶b̶e̶n̶e̶f̶i̶c̶i̶a̶l̶ ̶t̶o̶ ̶s̶u̶p̶p̶o̶r̶t̶ ̶c̶o̶m̶p̶i̶l̶e̶d̶ ̶l̶a̶n̶g̶u̶a̶g̶e̶s̶ ̶l̶i̶k̶e̶ ̶G̶o̶ ̶a̶n̶d̶ ̶R̶u̶s̶t̶ ̶a̶s̶ ̶w̶e̶l̶l̶?̶ ̶

Sorry, my bad, I just focus on the channel that I see in the Zed Editor.

@Glasov
Copy link

Glasov commented Jan 11, 2025

Why does it seem to only support interpreted languages like JavaScript, PHP, and Python? Wouldn't it be beneficial to support compiled languages like Go and Rust as well?

doesn't crates/dap_adapters/src/go.rs provide an adapter for go dap server?

RemcoSmitsDev and others added 6 commits January 11, 2025 15:47
* WIP

* Add assert helper for variable list visual entries

* Wip rework toggle entry (scope/variable) code

* Remove commented code

* Move colors to struct

* Add entry to selection if you click on them

* Add selected option to visual entries assert

* Use pretty assertions for visual entries assert helper

* Use focus handle method to give focus handle

* Register select first and last actions

* Correctly format selected entry

* Add tests helper to get active debug panel item

* Add tests for keyboard navigation

* Remove not needed comment

* Move other tests to test helper

This also removes a test that is duplicated with the keyboard navigation tests, it covers the same

* Update console test to use new test helper

* Fix failing test

I forgot to update the test, because we now always send a body back in a error case.

* Fix clippyyyy
I updated the tests so we don't reuse the debug panel item for each operation, instead we request a new instance each time so we can ensure the status actually changed.
* Switch debug session exited without hitting breakpoint to toast notification

* Move notify below the thread event, so we register the thread is added

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this create the file if it doesn’t exist?

@Anthony-Eid
Copy link
Contributor

Anthony-Eid commented Jan 12, 2025

@dyaskur Just to add more context to your question, interpreted languages tend to be easier to bootstrap and quickly test things for the debugger implementation Remco and I have been working on. As well as also being easier and sometimes the only way to test optional features in the debug adapter protocol (DAP) spec.

We support any debugger that implements the server side of DAP, but lldb and gdb have bugs that make them unideal for testing our client side of the DAP. I still haven't reported the gdb bug, but have reported the lldb bug here: llvm/llvm-project#119784.

I'm planning on fixing the lldb DAP bug once debugging over collab has been fully implemented. It should reach feature parity with local debugging by the end of this or next week at the latest. Then I'll probably pivot and work on the lldb bug, or continue working on the debugger until the Zed team takes the project over.

If you have any more questions feel free to ask or shoot me a message. You can also check out our zed debugger channel to see a more up-to-date todo list than what's on GitHub

zed debugger: https://zed.dev/channel/zed-debugger-11370

@JosephTLyons
Copy link
Collaborator

I just wanted to say that this is looking seriously awesome! About to pull the branch and play around with it!

@RemcoSmitsDev
Copy link
Contributor Author

@JosephTLyons thanks for saying that, I hope you like it. Any feedback is welcome!

Anthony-Eid and others added 9 commits January 14, 2025 01:08
* WIP Start work to send all dap client requests with request_dap

* Continue work on converting dap client requests

* WIP setup dap command for proto dap requests

* WIP dap command

Co-authored-by: Remco Smits <djsmits12@gmail.com>

* revert "WIP dap command"

This reverts commit fd2a683.

Co-authored-by: Remco Smits <djsmits12@gmail.com>

* More WIP with Dap Command trait
Co-authored-by: Remco Smits <djsmits12@gmail.com>

* Get step over command to work with remote dap clients

Co-authored-by: Remco Smits <djsmits12@gmail.com>

* Fix thread status not being set to stop on remote debug panel items

* Create a inner wrapper type to use for dap remote step requests

* Implement step in,back,out for remote debugger sessions

* Add Continue Command

* Add more dap command impls

TerminateThreads, Pause, and Disconnect. As well as a shutdown session request downstream clients can send to host

* Add Disconnect & Terminate dap command impls

* Add basic dap proxy test over collab

* Fix clippy error

* Start work on syncing breakpoint thread status

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Co-authored-by: Carter Canedy <cartercanedy42@gmail.com>

* WIP Fix thread status not syncing

* Add thread state model's to remote debug panels when setting panel items

* Sync thread state on step out command

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Co-authored-by: Carter Canedy <cartercanedy42@gmail.com>
* Remove output editor

* Implement output grouping

* Remove OutputGroup when we found the end position

* Fix make gutter smaller

* Render placeholder

* Show group end on the same level as group start

* Add tests

* Add support for collapsed grouped output

* Fix crease placeholder is not showing up

* Don't trim output multiple times

* Update tests

* Fix clippy
* Add restart stack frame

* Add collab support

* Add restart frame to proto capabilities

* Add collab test
…(first) stackframe

So this changes the behavior for providing variables for autocompletion inside the debug console if the adapter does not support autocompletion.

Before this change you would get variables based on the selected stack frame. But this is not correct, as you cannot use variables that are not in scope anymore. So changing it to only provide variables for the current(first) stack frame we should provide variables that could always be used for autocompletion and for expressions.
* Send changed breakpoints to DAP servers on sync breakpoints handle

Co-authored-by: Remco Smits <djsmits12@gmail.com>

* Add more sync breakpoints test

Co-authored-by: Remco Smits <djsmits12@gmail.com>

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
This PR fixes a module list bug where remote clients wouldn't have any modules in their module list when they hit their first breakpoint.

We now send module list changes whenever there is a module list update and don't send update messages in the SetDebuggerPanelItem proto message. This is because the module list usually doesn't change each time a user steps over, so sending the module list was wasting bandwidth.


* Add collab module list test

* Get module list to send during all changes & stop redundant update

* Update module list test for remote clients joining mid session
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed The user has signed the Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Microsoft Debug Adapter Protocol support Build and Debug support