elixir-lsp / elixir-ls

A frontend-independent IDE "smartness" server for Elixir. Implements the "Language Server Protocol" standard and provides debugger support via the "Debug Adapter Protocol"
https://elixir-lsp.github.io/elixir-ls/
Apache License 2.0
1.5k stars 196 forks source link

"File not included in .formatter.exs" even though it is #1099

Closed xxdavid closed 4 months ago

xxdavid commented 5 months ago

Environment

Current behavior

Frequently, when saving a file (with format on save turned on), Elixir LS presents a message saying that

File some_path/some_file.ex not included in path_to_app/.formatter.exs

It does not happen every time, only sometimes. I found out that it's usually related to whether the Elixir LS is currently compiling the project or not. Usually, first save triggers the formatting without any problem. But it also starts the compilation and if I then save the file again, while the project is compiling, then this message pops up. If I then wait until Elixir LS prints the Compile took x milliseconds message, the formatting again works (once, i.e., until it starts compiling again).

It happens on an umbrella project where we have a common formatter.exs rules for all apps but one and we list the apps dynamically:

apps_with_common_rules =
  "{#{"apps/*" |> Path.wildcard() |> Enum.map(&Path.basename/1) |> List.delete("some_app") |> Enum.join(",")}}"

[
  inputs: [
    ".formatter.exs",
    "mix*.exs",
    "{config,rel}/**/*.exs",
    "apps/#{apps_with_common_rules}/mix*.exs",
    "apps/#{apps_with_common_rules}/lib/**/*.ex",
    "apps/#{apps_with_common_rules}/{config,test}/**/*.exs"
  ],
  subdirectories: ["apps/some_app"],
]

My guess is that when the project is compiling, Elixir LS uses a wrong CWD when evaluating the .formatter.exs, or something like that.

Expected behavior

I expect the formatting to work every time.

lukaszsamson commented 5 months ago

Can you create a small repro project?

xxdavid commented 5 months ago

Sure, here it is: https://github.com/xxdavid/elixir_ls_formatter_bug_reproducer

lukaszsamson commented 4 months ago

@xxdavid The bug is in your .formatter.exs. Elixir compiler will change CWD during compilation and your code that may be called during it must be aware of the fact. ElixirLS always calls format formatter_for_file with root option being project dir so ordinary relative paths like lib/ work in includes. Your file defines paths from CWD relative wildcard

apps_with_common_rules =
  "{#{"apps/*" |> Path.wildcard() |> Enum.map(&Path.basename/1) |> List.delete("app_three") |> Enum.join(",")}}"

If i change it to using file relative path the bug goes away

apps_with_common_rules =
  "{#{"#{__DIR__}/apps/*" |> Path.wildcard() |> Enum.map(&Path.basename/1) |> List.delete("app_three") |> Enum.join(",")}}"
xxdavid commented 4 months ago

Ok, thanks for clarification! :)