Skip to content

Commit 001599e

Browse files
committed
use project_dir relative Path operations wherever possible
workaround elixir problem fixed in elixir-lang/elixir#13061
1 parent 3e711dd commit 001599e

File tree

17 files changed

+353
-102
lines changed

17 files changed

+353
-102
lines changed

apps/language_server/lib/language_server/build.ex

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
defmodule ElixirLS.LanguageServer.Build do
2-
alias ElixirLS.LanguageServer.{Server, JsonRpc, Diagnostics, Tracer}
2+
alias ElixirLS.LanguageServer.{Server, JsonRpc, Diagnostics, Tracer, SourceFile}
33
alias ElixirLS.Utils.MixfileHelpers
44
require Logger
55

@@ -12,9 +12,9 @@ defmodule ElixirLS.LanguageServer.Build do
1212

1313
# read cache before cleaning up mix state in reload_project
1414
cached_deps = read_cached_deps()
15-
mixfile = Path.absname(MixfileHelpers.mix_exs())
15+
mixfile = SourceFile.Path.absname(MixfileHelpers.mix_exs(), root_path)
1616

17-
case reload_project(mixfile) do
17+
case reload_project(mixfile, root_path) do
1818
{:ok, mixfile_diagnostics} ->
1919
{deps_result, deps_raw_diagnostics} =
2020
with_diagnostics([log: true], fn ->
@@ -87,7 +87,15 @@ defmodule ElixirLS.LanguageServer.Build do
8787
{:error,
8888
mixfile_diagnostics ++
8989
deps_diagnostics ++
90-
[Diagnostics.error_to_diagnostic(kind, err, stacktrace, mixfile)]}
90+
[
91+
Diagnostics.error_to_diagnostic(
92+
kind,
93+
err,
94+
stacktrace,
95+
mixfile,
96+
root_path
97+
)
98+
]}
9199
)
92100

93101
:deps_error
@@ -128,7 +136,7 @@ defmodule ElixirLS.LanguageServer.Build do
128136
:global.trans({__MODULE__, self()}, func)
129137
end
130138

131-
def reload_project(mixfile) do
139+
def reload_project(mixfile, root_path) do
132140
if File.exists?(mixfile) do
133141
if module = Mix.Project.get() do
134142
build_path = Mix.Project.config()[:build_path]
@@ -280,7 +288,7 @@ defmodule ElixirLS.LanguageServer.Build do
280288
{:error,
281289
mixfile_diagnostics ++
282290
config_diagnostics ++
283-
[Diagnostics.error_to_diagnostic(kind, err, stacktrace, config_path)]}
291+
[Diagnostics.error_to_diagnostic(kind, err, stacktrace, config_path, root_path)]}
284292

285293
:ok ->
286294
{:ok, mixfile_diagnostics ++ config_diagnostics}

apps/language_server/lib/language_server/diagnostics.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,21 +247,21 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
247247
}
248248
end
249249

250-
def error_to_diagnostic(kind, payload, stacktrace, path) do
251-
path = Path.absname(path)
250+
def error_to_diagnostic(kind, payload, stacktrace, path, project_dir) do
251+
path = SourceFile.Path.absname(path, project_dir)
252252
message = Exception.format(kind, payload, stacktrace)
253253

254254
line =
255255
stacktrace
256256
|> Enum.find_value(fn {_m, _f, _a, opts} ->
257-
if opts |> Keyword.get(:file) |> Path.absname() == path do
257+
if opts |> Keyword.get(:file) |> SourceFile.Path.absname(project_dir) == path do
258258
opts |> Keyword.get(:line)
259259
end
260260
end)
261261

262262
%Mix.Task.Compiler.Diagnostic{
263263
compiler_name: "ElixirLS",
264-
file: Path.absname(path),
264+
file: SourceFile.Path.absname(path, project_dir),
265265
position: line || 0,
266266
message: message,
267267
severity: :error,

apps/language_server/lib/language_server/dialyzer.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
518518
# in, which breaks umbrella apps. We have to manually resolve the file
519519
# from the module instead.
520520
file = resolve_module_file(module, file, project_dir),
521-
in_project?(Path.absname(file), project_dir) do
521+
in_project?(SourceFile.Path.absname(file, project_dir), project_dir) do
522522
{module, {file, line, warning}}
523523
end
524524

@@ -588,7 +588,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
588588
{source_file, position, data} <- warnings,
589589
{tag, _, _} = data,
590590
tag in tags_enabled,
591-
source_file = Path.absname(to_string(source_file)),
591+
source_file = SourceFile.Path.absname(to_string(source_file), project_dir),
592592
in_project?(source_file, project_dir),
593593
not SourceFile.Path.path_in_dir?(source_file, deps_path) do
594594
%Mix.Task.Compiler.Diagnostic{

apps/language_server/lib/language_server/mix_tasks/format.ex

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
defmodule Mix.Tasks.ElixirLSFormat do
2525
use Mix.Task
26+
alias ElixirLS.LanguageServer.SourceFile
2627

2728
@shortdoc "Formats the given files/patterns"
2829

@@ -360,7 +361,11 @@ defmodule Mix.Tasks.ElixirLSFormat do
360361

361362
formatter_opts_and_subs = load_plugins(formatter_opts_and_subs)
362363

363-
find_formatter_and_opts_for_file(Path.expand(file, cwd), formatter_opts_and_subs, cwd)
364+
find_formatter_and_opts_for_file(
365+
SourceFile.Path.expand(file, cwd),
366+
formatter_opts_and_subs,
367+
cwd
368+
)
364369
end
365370

366371
@doc """
@@ -493,7 +498,7 @@ defmodule Mix.Tasks.ElixirLSFormat do
493498
defp eval_subs_opts(subs, cwd, mix_project, deps_paths, manifest_path, config_mtime, sources) do
494499
{subs, sources} =
495500
Enum.flat_map_reduce(subs, sources, fn sub, sources ->
496-
cwd = Path.expand(sub, cwd)
501+
cwd = SourceFile.Path.expand(sub, cwd)
497502
{Path.wildcard(cwd), [Path.join(cwd, ".formatter.exs") | sources]}
498503
end)
499504

@@ -581,7 +586,8 @@ defmodule Mix.Tasks.ElixirLSFormat do
581586

582587
for file <- files do
583588
if file == :stdin do
584-
stdin_filename = Path.expand(Keyword.get(opts, :stdin_filename, "stdin.exs"), cwd)
589+
stdin_filename =
590+
SourceFile.Path.expand(Keyword.get(opts, :stdin_filename, "stdin.exs"), cwd)
585591

586592
{formatter, _opts, _dir} =
587593
find_formatter_and_opts_for_file(stdin_filename, {formatter_opts, subs}, cwd)
@@ -603,7 +609,7 @@ defmodule Mix.Tasks.ElixirLSFormat do
603609

604610
map =
605611
for input <- List.wrap(formatter_opts[:inputs]),
606-
file <- Path.wildcard(Path.expand(input, cwd), match_dot: true),
612+
file <- Path.wildcard(SourceFile.Path.expand(input, cwd), match_dot: true),
607613
do: {file, {dot_formatter, formatter_opts}},
608614
into: %{}
609615

@@ -686,7 +692,11 @@ defmodule Mix.Tasks.ElixirLSFormat do
686692
defp stdin_or_wildcard("-"), do: [:stdin]
687693

688694
defp stdin_or_wildcard(path),
689-
do: path |> Path.expand() |> Path.wildcard(match_dot: true) |> Enum.filter(&File.regular?/1)
695+
do:
696+
path
697+
|> SourceFile.Path.expand()
698+
|> Path.wildcard(match_dot: true)
699+
|> Enum.filter(&File.regular?/1)
690700

691701
defp elixir_format(content, formatter_opts) do
692702
case Code.format_string!(content, formatter_opts) do

apps/language_server/lib/language_server/protocol/location.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ defmodule ElixirLS.LanguageServer.Protocol.Location do
1313
def new(
1414
%ElixirSense.Location{file: file, line: line, column: column},
1515
current_file_uri,
16-
current_file_text
16+
current_file_text,
17+
project_dir
1718
) do
1819
uri =
1920
case file do
2021
nil -> current_file_uri
21-
_ -> SourceFile.Path.to_uri(file)
22+
_ -> SourceFile.Path.to_uri(file, project_dir)
2223
end
2324

2425
text =

apps/language_server/lib/language_server/providers/definition.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule ElixirLS.LanguageServer.Providers.Definition do
55

66
alias ElixirLS.LanguageServer.{Protocol, SourceFile}
77

8-
def definition(uri, text, line, character) do
8+
def definition(uri, text, line, character, project_dir) do
99
{line, character} = SourceFile.lsp_position_to_elixir(text, {line, character})
1010

1111
result =
@@ -14,7 +14,7 @@ defmodule ElixirLS.LanguageServer.Providers.Definition do
1414
nil
1515

1616
%ElixirSense.Location{} = location ->
17-
Protocol.Location.new(location, uri, text)
17+
Protocol.Location.new(location, uri, text, project_dir)
1818
end
1919

2020
{:ok, result}

apps/language_server/lib/language_server/providers/formatting.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do
66

77
def format(%SourceFile{} = source_file, uri = "file:" <> _, project_dir)
88
when is_binary(project_dir) do
9-
file_path = SourceFile.Path.absolute_from_uri(uri)
9+
file_path = SourceFile.Path.absolute_from_uri(uri, project_dir)
1010
# file_path and project_dir are absolute paths with universal separators
1111
if SourceFile.Path.path_in_dir?(file_path, project_dir) do
1212
# file in project_dir we find formatter and options for file
1313
case SourceFile.formatter_for(uri, project_dir) do
1414
{:ok, {formatter, opts, formatter_exs_dir}} ->
15-
if should_format?(uri, formatter_exs_dir, opts[:inputs]) do
15+
if should_format?(uri, formatter_exs_dir, opts[:inputs], project_dir) do
1616
do_format(source_file, formatter, opts)
1717
else
1818
JsonRpc.show_message(
@@ -61,16 +61,16 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do
6161
IO.iodata_to_binary([Code.format_string!(text, opts), ?\n])
6262
end
6363

64-
defp should_format?(file_uri, formatter_exs_dir, inputs) when is_list(inputs) do
65-
file_path = SourceFile.Path.absolute_from_uri(file_uri)
64+
defp should_format?(file_uri, formatter_exs_dir, inputs, project_dir) when is_list(inputs) do
65+
file_path = SourceFile.Path.absolute_from_uri(file_uri, project_dir)
6666

6767
Enum.any?(inputs, fn input_glob ->
6868
glob = Path.join(formatter_exs_dir, input_glob)
6969
PathGlobVendored.match?(file_path, glob, match_dot: true)
7070
end)
7171
end
7272

73-
defp should_format?(_file_uri, _formatter_exs_dir, _inputs), do: true
73+
defp should_format?(_file_uri, _formatter_exs_dir, _inputs, _project_dir), do: true
7474

7575
defp myers_diff_to_text_edits(myers_diff) do
7676
myers_diff_to_text_edits(myers_diff, {0, 0}, [])

apps/language_server/lib/language_server/providers/implementation.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ defmodule ElixirLS.LanguageServer.Providers.Implementation do
55

66
alias ElixirLS.LanguageServer.{Protocol, SourceFile}
77

8-
def implementation(uri, text, line, character) do
8+
def implementation(uri, text, line, character, project_dir) do
99
{line, character} = SourceFile.lsp_position_to_elixir(text, {line, character})
1010
locations = ElixirSense.implementations(text, line, character)
11-
results = for location <- locations, do: Protocol.Location.new(location, uri, text)
11+
12+
results =
13+
for location <- locations, do: Protocol.Location.new(location, uri, text, project_dir)
1214

1315
{:ok, results}
1416
end

apps/language_server/lib/language_server/providers/references.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
1414
import ElixirLS.LanguageServer.Protocol
1515
require Logger
1616

17-
def references(text, uri, line, character, _include_declaration) do
17+
def references(text, uri, line, character, _include_declaration, project_dir) do
1818
{line, character} = SourceFile.lsp_position_to_elixir(text, {line, character})
1919

2020
Build.with_build_lock(fn ->
@@ -23,7 +23,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
2323
ElixirSense.references(text, line, character, trace)
2424
|> Enum.map(fn elixir_sense_reference ->
2525
elixir_sense_reference
26-
|> build_reference(uri, text)
26+
|> build_reference(uri, text, project_dir)
2727
end)
2828
|> Enum.filter(&(not is_nil(&1)))
2929
# ElixirSense returns references from both compile tracer and current buffer
@@ -32,7 +32,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
3232
end)
3333
end
3434

35-
defp build_reference(ref, current_file_uri, current_file_text) do
35+
defp build_reference(ref, current_file_uri, current_file_text, project_dir) do
3636
case get_text(ref, current_file_text) do
3737
{:ok, text} ->
3838
{start_line, start_column} =
@@ -45,7 +45,7 @@ defmodule ElixirLS.LanguageServer.Providers.References do
4545

4646
%{
4747
"range" => range,
48-
"uri" => build_uri(ref, current_file_uri)
48+
"uri" => build_uri(ref, current_file_uri, project_dir)
4949
}
5050

5151
{:error, :nofile} ->
@@ -60,14 +60,14 @@ defmodule ElixirLS.LanguageServer.Providers.References do
6060
end
6161
end
6262

63-
def build_uri(elixir_sense_ref, current_file_uri) do
63+
def build_uri(elixir_sense_ref, current_file_uri, project_dir) do
6464
case elixir_sense_ref.uri do
6565
# A `nil` uri indicates that the reference was in the passed in text
6666
# https://github.com/elixir-lsp/elixir-ls/pull/82#discussion_r351922803
6767
nil -> current_file_uri
6868
# ElixirSense returns a plain path (e.g. "/home/bob/my_app/lib/a.ex") as
6969
# the "uri" so we convert it to an actual uri
70-
path when is_binary(path) -> SourceFile.Path.to_uri(path)
70+
path when is_binary(path) -> SourceFile.Path.to_uri(path, project_dir)
7171
end
7272
end
7373

0 commit comments

Comments
 (0)