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 558 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.2025-01-19.at.17.45.06.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
      • Show collapsed stack frames
    • 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. :-)

RemcoSmitsDev and others added 16 commits January 14, 2025 19:38
* 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 <[email protected]>

* Add more sync breakpoints test

Co-authored-by: Remco Smits <[email protected]>

---------

Co-authored-by: Remco Smits <[email protected]>
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
* Resend breakpoints when the source/edit has been changed/saved

* Check for dapstore first before checking project path

* Add test to validate we re-send variables when editor is saved

* Add new line after edit

* Also send breakpoints changed when source on disk changed

* Fix the test

* Don't send breakpoints changed for saved event

We send the breakpoints twice, because we already send them when the FileHandleChanged event was received and that is received after the Saved event itself. And the Saved event does not guarantee that the source is already changed on disk. Which it has to be so we can send the new breakpoints.

* Assert in more places that the source modified is false
By sorting the breakpoints based on the line number, the order does not matter.
* Impl VariablesCommand for dap requests

* Have remote variable list generate entries & other fields locally

* Finish first version of collab variable list test (It fails)

* Get variable list collab test to pass

* Update variable test again (it failing)

* Improve tests more WIP

* Remove a test to make merge easier

* Finalize collab test

* Only send variables one time to collab server instead of each rebuild

* Finish variable list fetch!
RemcoSmitsDev and others added 6 commits January 20, 2025 20:34
* Update dap type to include new presentation hint for stack frames

* Implement grouped/collapsed stack frames based on presentation hint

* Add test

Co-Authored-By: Anthony Eid <[email protected]>

---------

Co-authored-by: Anthony Eid <[email protected]>
So before this change, if you have save breakpoints feature enabled. You had to have the buffer open for the breakpoint to be send after you launched Zed again. Because we needed to have a buffer to determine the right position based on a anchor.

This changes that so we fallback the cached position (last known), that we stored in the DB. So it could be that the file has changed on disk without Zed knowning. But it's better then not sending the breakpoints at all

Co-Authored-By: Anthony Eid <[email protected]>
@berkaydedeoglu-eva
Copy link

It truly looks amazing. I was considering switching to Zed, but the lack of a debugger was holding me back. Being able to use it with attach mode is exactly what I was looking for. I suppose we can use it with node --inspect as well. Great work, I’m eagerly following the progress!

@LurkingLearner
Copy link

LurkingLearner commented Jan 21, 2025

Hey, I was really excited to try this for my workflow but have run into some problems/oddities I was hoping to clear up:

In debugger.md it says at the start: "To debug a program using Zed you must first create a debug configuration within your project located at .zed/debug.json"

I have created that file with the following contents:

[
  {
    "label": "Debug Backend",
    "adapter": "python",
    "request": "launch",
    "cwd": "$ZED_WORKPLACE_ROOT",
    "program": "manage.py runserver_plus 0.0.0.0:9002",
    "initialize_args": {}
  }
]

I have a few problems:

  1. I am trying to debug a Django application, but based solely on the example tasks I have no idea how to pass args to a program (i.e. runserver_plus, the IP and port)
  2. This debug.json file located in my project root directory at .zed/debug.json does not seem to register with Zed/the debugger
  3. Modifications to ~/.config/zed/debug.json do not seem to save/matter

When I open the debugger panel and click "Choose a debugger" I am presented with only the default debug options from the ~/.config/zed debug file. My project-local file is completely ignored. If I rename or otherwise modify the defaults it seems to do nothing even after restarting zed with the file modified.

So, my first question is how am I meant to implement a debugger task for something like Django where my target "program" is a file with multiple arguments? Maybe what I have is close, but since I can't actually see this task to run it I haven't been able to verify. Secondly, any ideas why it seems like my changes to either my local or the default debug.json files are being completely ignored?

I am building the latest as of this writing (953843a) on an M2 Mac running MacOS 15.2.

@RemcoSmitsDev
Copy link
Contributor Author

Hey @LurkingLearner, thanks for trying out the debugger branch. I noticed a typo inside the docs $ZED_WORKPLACE_ROOT should be $ZED_WORKTREE_ROOT, but besides that, do you mind if we transfer the question to discord so not 28 people get notifications for all the comments?

RemcoSmitsDev and others added 3 commits January 21, 2025 17:48
* Create collab ignore breakpoint integration test

* Add collab ignore breakpoints message handlers

Still need to enable remote dap_stores the ability to store/manage ignore breakpoint state

* Refactor session to have remote and local modes

This was done to allow remote clients access to some session details they need such as ignore breakpoints.

Co-authored-by: Remco Smits <[email protected]>

* DapStore so both local & remote modes have access to DebugSessions

* Add remote sessions when creating new debug panel items

* Finish implementing collab breakpoints ignore

* Clippy & clean up

* Clean up session information when sessions end on remote clients

* Rename proto message

* Add ignore breakpoints state to collab db

---------

Co-authored-by: Remco Smits <[email protected]>
* Start adding docs for configurations and adapters

* Update debugger setting files with settings, attach config, & themes

I also ran prettier and typos on it too."

---------

Co-authored-by: Anthony Eid <[email protected]>
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