microsoft / vscode-js-debug

A DAP-compatible JavaScript debugger. Used in VS Code, VS, + more
MIT License
1.64k stars 269 forks source link

Advice for getting debugger working with extensionHost in monorepo #2036

Closed gauntface closed 3 weeks ago

gauntface commented 3 weeks ago

I'm trying to get the debugger to work in a monorepo which has a vscode extension in a nested directory and uses bazel for its build process.

The directory structure for the project looks like this:

/
├─ clients/
│  ├─ .vscode/
│     ├─ launch.json
│  ├─ my-extension/
│     ├─ package.json
│     ├─ src/
│        ├─ example.ts
├─ bazel-gen/
│  ├─ clients/
│     ├─ my-extension/
│        ├─ package.json
│        ├─ out/
│           ├─ example.js
│           ├─ example.js.map

The launch.json configuration to build the extension and work with the extension host is:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Run Extension (Bazel)",
            "type": "extensionHost",
            "request": "launch",
            "args": [
                "--extensionDevelopmentPath=${workspaceFolder}/../bazel-gen/clients/my-extension"
            ],
            "preLaunchTask": "Watch Extension (Bazel)"
        }
    ]
}

I've tried a number of the options listed the OPTIONS.md page, but without some indication of where the disconnect is from the debugger's perspective, I'm struggling to make any kind of progress. I've tried setting localRoot and remoteRoot to the clients/vscode/ directory but didn't see any noticeable difference.

The debug diagnostics page shows:

We couldn't find a corresponding source location, and didn't find any source with the name example.ts.

Sourcemaps are true in my tsconfig and I removed the outFiles property following the suggestion from the debug diagnostics page.

My hunch is that outFiles and resolveSourceMapPaths should be ${workspaceFolder}/../bazel-bin/clients/vscode/out/**/*.js to tell the debugger where the compiled files are, but I can't find a way to confirm is vscode is finding these sourcemaps before figuring out the config to map the sourcemap to the src/ file.

Any advice on how to diagnose this?

gauntface commented 3 weeks ago

After some more exploration with the "Debug breakpoint problems" command and exploring the sourcemaps being loaded, I realized the JS files weren't being loaded.

It looks like setting the extensionDevelopmentPath outside of the workspace folder will prevent the js files from loading. I can create a symlink from bazel-gen/clients/vscode/out/ to clients/vscode/out/ and then VSCode will list the files in the "What scripts and sourcemaps are loaded", however sourcemaps aren't getting loaded.

I think sourcemaps are failing to load because the path used by vscode is the real path of the js file which is somewhere in my home directory (bazel uses symlinks for directories like bazel-gen).

If I add the absolute path of the real bazel gen files to resolveSourceMapLocations then the sourcemaps seemed to get mapped and the breakpoints work, however I can't hard code this value as it'll be different for each person working on the project.

gauntface commented 3 weeks ago

What I ended up doing:

  1. Once you have a launch task running, some commands become available include "Diagnose Breakpoint Problems"
  2. The "Why my breakpoints don't bind" wasn't particularly helpful so I began relying on "What scripts and sourcemaps are loaded"
    1. First pick a file in your generated JS files that you can debug and type it in the "Filter sources..."
    2. If the file isn't listed, update the outFiles in your launch.json to include the directory with your files
    3. Once your file is in the filtered sources then the sourcemap children is defined, if it's not, update resolveSourceMapLocations with the path of your sourcemaps
    4. Now that you have sourcemap children showing a relationship, click on the linked source file and see if it matches your projects source file, if it doesn't you likely need to add a sourceMapPathOverrides to change the sourcemap path to your project. This may also require a change to your tsconfig, for me I had to set a sourceRoot to make the sourceMapPathOverrides easy to define.