Skip to content

Commit 6b394be

Browse files
committed
make sure dialyzer uses project dir instead of cwd
1 parent d641d72 commit 6b394be

File tree

2 files changed

+24
-21
lines changed

2 files changed

+24
-21
lines changed

apps/language_server/lib/language_server/dialyzer.ex

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
66
require Logger
77

88
defstruct [
9+
:project_dir,
910
:parent,
1011
:timestamp,
1112
:plt,
@@ -51,10 +52,10 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
5152
GenServer.start_link(__MODULE__, {parent, root_path}, name: {:global, {parent, __MODULE__}})
5253
end
5354

54-
def analyze(parent \\ self(), build_ref, warn_opts, warning_format) do
55+
def analyze(parent \\ self(), build_ref, warn_opts, warning_format, project_dir) do
5556
GenServer.cast(
5657
{:global, {parent, __MODULE__}},
57-
{:analyze, build_ref, warn_opts, warning_format}
58+
{:analyze, build_ref, warn_opts, warning_format, project_dir}
5859
)
5960
end
6061

@@ -111,7 +112,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
111112
_from,
112113
state
113114
) do
114-
diagnostics = to_diagnostics(warnings, state.warn_opts, state.warning_format)
115+
diagnostics = to_diagnostics(warnings, state.warn_opts, state.warning_format, state.project_dir)
115116

116117
Server.dialyzer_finished(state.parent, diagnostics, build_ref)
117118

@@ -146,15 +147,15 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
146147
end
147148

148149
@impl GenServer
149-
def handle_cast({:analyze, build_ref, warn_opts, warning_format}, state) do
150+
def handle_cast({:analyze, build_ref, warn_opts, warning_format, project_dir}, state) do
150151
state =
151152
ElixirLS.LanguageServer.Build.with_build_lock(fn ->
152153
if Mix.Project.get() do
153154
Logger.info("[ElixirLS Dialyzer] Checking for stale beam files")
154155
new_timestamp = adjusted_timestamp()
155156

156157
{removed_files, file_changes} =
157-
update_stale(state.md5, state.removed_files, state.file_changes, state.timestamp)
158+
update_stale(state.md5, state.removed_files, state.file_changes, state.timestamp, project_dir)
158159

159160
state = %{
160161
state
@@ -163,7 +164,8 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
163164
removed_files: removed_files,
164165
file_changes: file_changes,
165166
build_ref: build_ref,
166-
warning_format: warning_format
167+
warning_format: warning_format,
168+
project_dir: project_dir
167169
}
168170

169171
trigger_analyze(state)
@@ -213,14 +215,14 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
213215
defp trigger_analyze(%{analysis_pid: nil} = state), do: do_analyze(state)
214216
defp trigger_analyze(state), do: state
215217

216-
defp update_stale(md5, removed_files, file_changes, timestamp) do
218+
defp update_stale(md5, removed_files, file_changes, timestamp, project_dir) do
217219
prev_paths = Map.keys(md5) |> MapSet.new()
218220

219221
# FIXME: Private API
220222
all_paths =
221223
for path <- Mix.Utils.extract_files([Mix.Project.build_path()], [:beam]),
222224
into: MapSet.new(),
223-
do: Path.relative_to_cwd(path)
225+
do: Path.relative_to(path, project_dir)
224226

225227
removed =
226228
prev_paths
@@ -338,7 +340,8 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
338340
timestamp: timestamp,
339341
removed_files: removed_files,
340342
file_changes: file_changes,
341-
build_ref: build_ref
343+
build_ref: build_ref,
344+
project_dir: project_dir
342345
} = state
343346

344347
{us, {active_plt, mod_deps, md5, warnings}} =
@@ -408,7 +411,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
408411
{active_plt, new_mod_deps, raw_warnings} = Analyzer.analyze(active_plt, files_to_analyze)
409412

410413
mod_deps = update_mod_deps(mod_deps, new_mod_deps, removed_modules)
411-
warnings = add_warnings(warnings, raw_warnings)
414+
warnings = add_warnings(warnings, raw_warnings, project_dir)
412415

413416
md5 = Map.drop(md5, removed_files)
414417

@@ -435,15 +438,15 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
435438
end
436439
end
437440

438-
defp add_warnings(warnings, raw_warnings) do
441+
defp add_warnings(warnings, raw_warnings, project_dir) do
439442
new_warnings =
440443
for {_, {file, line, m_or_mfa}, _} = warning <- raw_warnings,
441444
module = resolve_module(m_or_mfa),
442445
# Dialyzer warnings have the file path at the start of the app it's
443446
# in, which breaks umbrella apps. We have to manually resolve the file
444447
# from the module instead.
445-
file = resolve_module_file(module, file),
446-
in_project?(file) do
448+
file = resolve_module_file(module, file, project_dir),
449+
in_project?(file, project_dir) do
447450
{module, {file, line, warning}}
448451
end
449452

@@ -455,18 +458,18 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
455458
defp resolve_module(module) when is_atom(module), do: module
456459
defp resolve_module({module, _, _}) when is_atom(module), do: module
457460

458-
defp resolve_module_file(module, fallback) do
461+
defp resolve_module_file(module, fallback, project_dir) do
459462
# We try to resolve the module to its source file. The only time the source
460463
# info may not be available is when it has been stripped by the beam_lib
461464
# module, but that shouldn't be the case. More info:
462465
# http://erlang.org/doc/reference_manual/modules.html#module_info-0-and-module_info-1-functions
463466
if Code.ensure_loaded?(module) do
464467
module.module_info(:compile)
465468
|> Keyword.get(:source, fallback)
466-
|> Path.relative_to_cwd()
469+
|> Path.relative_to(project_dir)
467470
else
468471
# In case the file fails to load return fallback
469-
Path.relative_to_cwd(fallback)
472+
Path.relative_to(fallback, project_dir)
470473
end
471474
end
472475

@@ -486,8 +489,8 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
486489
end
487490
end
488491

489-
defp in_project?(path) do
490-
File.exists?(path) and String.starts_with?(Path.absname(path), File.cwd!())
492+
defp in_project?(path, project_dir) do
493+
File.exists?(path) and String.starts_with?(Path.absname(path), project_dir)
491494
end
492495

493496
defp module_md5(file) do
@@ -505,7 +508,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
505508
end
506509
end
507510

508-
defp to_diagnostics(warnings_map, warn_opts, warning_format) do
511+
defp to_diagnostics(warnings_map, warn_opts, warning_format, project_dir) do
509512
tags_enabled = Analyzer.matching_tags(warn_opts)
510513
deps_path = Mix.Project.deps_path()
511514

@@ -514,7 +517,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
514517
{tag, _, _} = data,
515518
tag in tags_enabled,
516519
source_file = Path.absname(to_string(source_file)),
517-
in_project?(source_file),
520+
in_project?(source_file, project_dir),
518521
not String.starts_with?(source_file, deps_path) do
519522
%Mix.Task.Compiler.Diagnostic{
520523
compiler_name: "ElixirLS Dialyzer",

apps/language_server/lib/language_server/server.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ defmodule ElixirLS.LanguageServer.Server do
12781278
(state.settings["dialyzerWarnOpts"] || [])
12791279
|> Enum.map(&String.to_atom/1)
12801280

1281-
Dialyzer.analyze(state.build_ref, warn_opts, dialyzer_default_format(state))
1281+
Dialyzer.analyze(state.build_ref, warn_opts, dialyzer_default_format(state), state.project_dir)
12821282

12831283
state
12841284
end

0 commit comments

Comments
 (0)