kidp330

kidp330

Debugging a single .exs without mix.exs

I’m trying to run a script with Mix.install inside, and set some breakpoints. I’m running VSCode with the ElixirLS extension. I can run the script just fine if I mix run --no-mix-exs file.exs but not with the debugger, even If I add the flag to taskArgs. Haven’t found this functionality doccumented in the extension docs so either I’m doing something wrong or it’s not implemented?

Marked As Solved

lukaszsamson

lukaszsamson

ElixirLS Core Team

By debugger do you mean dbg

No @sodapopcan, OP means ElixirLS debug adapter (GitHub - elixir-lsp/vscode-elixir-ls: Elixir language support and debugger for VS Code, powered by ElixirLS. · GitHub)

Haven’t found this functionality doccumented in the extension docs so either I’m doing something wrong or it’s not implemented?

@kidp330 ElixirLS debug adapter currently requires a mix project (I opened Debug adapter does not support no mixfile projects · Issue #1037 · elixir-lsp/elixir-ls · GitHub for tracking). Trying to run in a folder that does not contain mix.exs will raise Mix.NoMixProjectError. You can create a dummy project and run your scripts from there.

However this is tricky in case of .exs files.

  1. OTP debugger which ElixirLS uses underneath requires modules to be interpreted before you can set breakpoints in them. So you need to put your code in module functions
  2. .exs files are compiled in memory. To interpret them you need to include them in requireFiles so they are purged, recompiled and their beam files saved to disk so the OTP debugger can interpret them
  3. .exs script starts executing when you compile it not giving the debugger required time to interpret and set breakpoints. It’s not possible to purge a module when a process executes it’s code. The reasult is that interpretation happens when the script has already returned. You can overcome this with invoking your code in a separate process started from the script
  4. mix run exits when the script return. By default debugger will end the session when mix task finishes. You need to set exitAfterTaskReturns to false so the debug session will continue

I was able to create a proof of concept. The debugger breaks when the breakpoint in Abc.debug_me is hit from the task I start. I needed to add some delay though. Otherwise the code finished before the breakpoint was set.

poc.exs

defmodule Abc do
  def debug_me() do
    a = [1, 2, 3]
    b = Enum.map(a, & &1 + 1)
    b
  end
end

a = [1, 2, 3]
b = Enum.map(a, & &1 + 1)
IO.puts("done #{inspect(b)}, #{Abc.debug_me()}")

Task.start(fn ->
  Process.sleep(4000)
  IO.puts("done from task #{inspect(b)}, #{Abc.debug_me()}")
end)

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "mix_task",
      "name": "mix run",
      "request": "launch",
      "task": "run",
      "taskArgs": [
        "--no-mix-exs",
        "poc.exs"
      ],
      "startApps": false,
      "projectDir": "${workspaceRoot}",
      "exitAfterTaskReturns": false,
      "requireFiles": [
        "poc.exs"
      ]
    }
  ]
}

The other possibility is breaking on Kernel.dbg macro. This is easier to achieve. In this case do not put the script into requireFiles as recompilation and interpreting will deadlock the debugger

Also Liked

lukaszsamson

lukaszsamson

ElixirLS Core Team

ElixirLS Debug adapter will support --no-mix-exs in 0.19 release

sodapopcan

sodapopcan

I don’t have a direct solution but figured I’d respond since you haven’t gotten any bites yet.

By debugger do you mean dbg? If so then I’m not sure this is possible since in order for it to be available, you need to add :runtime_tools to :extra_applications in a mix file. I’m sorry I don’t know the answer but maybe that’s a good enough clue?

…and welcome to Elixir Forum! :slight_smile:

Where Next?

Popular in Questions Top

New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44778 311
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New

We're in Beta

About us Mission Statement