Attaching Metals LSP debugger to existing process in Emacs

Metals supports the DAP Protocol which allows to debug Scala code in Emacs. By default all the setup is done to use code lenses to start an instance of the program to debug it, set breakpoints inspect variables, all the good stuff to expect from a debugger. It is not as obvious how to debug a remote Scala process however as this requires a bit of setup.

Setting up the Scala process

Scala, as running on the JVM, allows to be run with the well know flags to be debugged namely

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

When using sbt this can be simplified to running as

sbt -jvm-debug 5005

which launches an sbt shell exposing a debug port 5005 on localhost. It is good practice to always use localhost and if truly remote to use SSH port forwarding, as the debugger has no authentication or any security in place.

Attaching the debugger

In dap-mode in Emacs uses debug-templates to determine what to run, in the case of scala and metals we need to provide the connection information as well as the lsp-project to use as the source for the code to set breakpoints and in general browse the code. The project name to use can normally be found in the build.sbt file this means for a project like the one associated with the FP Tower Foundations Course the setup looks like

(dap-register-debug-template
  "Scala Attach Foundations (localhost:5005)"
  '(:type "scala"
    :request "attach"
    :name "Scala Attach Foundations (localhost:5005)"
    :hostName "localhost"
    :port 5005
    :targets [(:uri "file:///Users/pfehre/source/foundations?id=foundation")]))

important is the targets uri in this case as the default template for scala attach sets the project name to root resulting in the invalid target file:///Users/pfehre/source/foundations?id=root. With this setup and evaluated the commad dap-debug will now contain a Scala Attach Foundations (localhost:5005) target to use to attach to the process.

As this is project specific setup it makes sense to add it to the .dir-locals.el file so it automatically gets registered when visiting the project folder.

((nil . ((eval . (dap-register-debug-template
                  "Scala Attach Foundations (localhost:5005)"
                  '(:type "scala"
                    :request "attach"
                    :name "Scala Attach Foundations (localhost:5005)"
                    :hostName "localhost"
                    :port 5005
                    :targets [(:uri "file:///Users/pfehre/source/foundations?id=foundation")]))))))

would make this work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.