vscode-extensionslanguage-server-protocollaunch-configuration

VS Code Language Server Extension Guide Lacks "Attach" Launch Configuration


I am a beginner, learning the basics of Language Server Extensions in VS Code. I'm following this guide: https://code.visualstudio.com/api/language-extensions/language-server-extension-guide

Everything up to server debugging works, but then the guide states:

Since the server is started by the LanguageClient running in the extension (client), we need to attach a debugger to the running server. To do so, switch to the Run and Debug view and select the launch configuration Attach to Server and press F5. This will attach the debugger to the server.

The thing is, there IS no "Attach to Server" launch configuration in the official repo code.

The entire launch.json file:

// A launch configuration that compiles the extension and then opens it inside a new window
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Client",
            "type": "extensionHost",
            "request": "launch",
            "runtimeExecutable": "${execPath}",
            "args": ["--extensionDevelopmentPath=${workspaceRoot}"],
            "outFiles": ["${workspaceRoot}/client/out/**/*.js"],
            "preLaunchTask": {
                "type": "npm",
                "script": "watch"
            }
        },
        {
            "name": "Language Server E2E Test",
            "type": "extensionHost",
            "request": "launch",
            "runtimeExecutable": "${execPath}",
            "args": [
                "--extensionDevelopmentPath=${workspaceRoot}",
                "--extensionTestsPath=${workspaceRoot}/client/out/test/index",
                "${workspaceRoot}/client/testFixture"
            ],
            "outFiles": ["${workspaceRoot}/client/out/test/**/*.js"]
        },
    ]
}

I've tried to add "Attach" configs using the built-in templates:

        {
            "name": "Attach",
            "port": 9229,
            "request": "attach",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "type": "node"
        },

However, when I run this configuration AFTER the Launch Client config, the service only runs for a few seconds and then quits. I don't see any log output explaining why.

It looks like this has been the case for a long time. Can anyone more expert than me offer a solution? The MS docs act like this problem doesn't exist.

Update: When I try to add a breakpoint in the server.js file, I get an 'unbound breakpoint' tooltip when I hover over it. I think I'm missing something really basic. :|


Solution

  • I'm answering this myself because it's important to anyone starting their LSP journey with VS Code extensions.

    The Language Server Extensions article, as of this date, displays it's own version of the code available on the repo, which is downloaded as part of the Guide. There are two significant differences between the code in the article and the code in the repo. For some reason unknown to me, the present version of the repo omits the code required for server debugging.

    In the extension.ts file, the current main branch of the repo contains this bit of code:

    export function activate(context: ExtensionContext) {
        // The server is implemented in node
        const serverModule = context.asAbsolutePath(
            path.join('server', 'out', 'server.js')
        );
    
        // If the extension is launched in debug mode then the debug server options are used
        // Otherwise the run options are used
        const serverOptions: ServerOptions = {
            run: { module: serverModule, transport: TransportKind.ipc },
            debug: {
                module: serverModule,
                transport: TransportKind.ipc,
            }
        };
    
    

    But a few commits earlier, the code was this:

    export function activate(context: ExtensionContext) {
        // The server is implemented in node
        const serverModule = context.asAbsolutePath(
            path.join('server', 'out', 'server.js')
        );
    
    --> // The debug options for the server
    --> // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
    --> const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
    
        // If the extension is launched in debug mode then the debug server options are used
        // Otherwise the run options are used
        const serverOptions: ServerOptions = {
            run: { module: serverModule, transport: TransportKind.ipc },
            debug: {
                module: serverModule,
                transport: TransportKind.ipc,
    -->         options: debugOptions
            }
        };
    
    

    Also, the current repo lacks the "Attach to Server" launch configuration in launch.json. The earlier commits have this:

            {
                "type": "node",
                "request": "attach",
                "name": "Attach to Server",
                "port": 6009,
                "restart": true,
                "outFiles": ["${workspaceRoot}/server/out/**/*.js"]
            },
    
    

    I added the missing code to the example and viola! Server debugging works, according to the instructions in the guide.

    I don't know what happened, but this fixed it. Hopefully, it will help someone else on the same journey as I. And if MS fixes it, then happily no one will continue to encounter this problem.