@@ -6,6 +6,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
6
6
require Logger
7
7
8
8
defstruct [
9
+ :project_dir ,
9
10
:parent ,
10
11
:timestamp ,
11
12
:plt ,
@@ -51,10 +52,10 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
51
52
GenServer . start_link ( __MODULE__ , { parent , root_path } , name: { :global , { parent , __MODULE__ } } )
52
53
end
53
54
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
55
56
GenServer . cast (
56
57
{ :global , { parent , __MODULE__ } } ,
57
- { :analyze , build_ref , warn_opts , warning_format }
58
+ { :analyze , build_ref , warn_opts , warning_format , project_dir }
58
59
)
59
60
end
60
61
@@ -111,7 +112,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
111
112
_from ,
112
113
state
113
114
) 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 )
115
116
116
117
Server . dialyzer_finished ( state . parent , diagnostics , build_ref )
117
118
@@ -146,15 +147,15 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
146
147
end
147
148
148
149
@ 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
150
151
state =
151
152
ElixirLS.LanguageServer.Build . with_build_lock ( fn ->
152
153
if Mix.Project . get ( ) do
153
154
Logger . info ( "[ElixirLS Dialyzer] Checking for stale beam files" )
154
155
new_timestamp = adjusted_timestamp ( )
155
156
156
157
{ 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 )
158
159
159
160
state = % {
160
161
state
@@ -163,7 +164,8 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
163
164
removed_files: removed_files ,
164
165
file_changes: file_changes ,
165
166
build_ref: build_ref ,
166
- warning_format: warning_format
167
+ warning_format: warning_format ,
168
+ project_dir: project_dir
167
169
}
168
170
169
171
trigger_analyze ( state )
@@ -213,14 +215,14 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
213
215
defp trigger_analyze ( % { analysis_pid: nil } = state ) , do: do_analyze ( state )
214
216
defp trigger_analyze ( state ) , do: state
215
217
216
- defp update_stale ( md5 , removed_files , file_changes , timestamp ) do
218
+ defp update_stale ( md5 , removed_files , file_changes , timestamp , project_dir ) do
217
219
prev_paths = Map . keys ( md5 ) |> MapSet . new ( )
218
220
219
221
# FIXME: Private API
220
222
all_paths =
221
223
for path <- Mix.Utils . extract_files ( [ Mix.Project . build_path ( ) ] , [ :beam ] ) ,
222
224
into: MapSet . new ( ) ,
223
- do: Path . relative_to_cwd ( path )
225
+ do: Path . relative_to ( path , project_dir )
224
226
225
227
removed =
226
228
prev_paths
@@ -338,7 +340,8 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
338
340
timestamp: timestamp ,
339
341
removed_files: removed_files ,
340
342
file_changes: file_changes ,
341
- build_ref: build_ref
343
+ build_ref: build_ref ,
344
+ project_dir: project_dir
342
345
} = state
343
346
344
347
{ us , { active_plt , mod_deps , md5 , warnings } } =
@@ -408,7 +411,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
408
411
{ active_plt , new_mod_deps , raw_warnings } = Analyzer . analyze ( active_plt , files_to_analyze )
409
412
410
413
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 )
412
415
413
416
md5 = Map . drop ( md5 , removed_files )
414
417
@@ -435,15 +438,15 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
435
438
end
436
439
end
437
440
438
- defp add_warnings ( warnings , raw_warnings ) do
441
+ defp add_warnings ( warnings , raw_warnings , project_dir ) do
439
442
new_warnings =
440
443
for { _ , { file , line , m_or_mfa } , _ } = warning <- raw_warnings ,
441
444
module = resolve_module ( m_or_mfa ) ,
442
445
# Dialyzer warnings have the file path at the start of the app it's
443
446
# in, which breaks umbrella apps. We have to manually resolve the file
444
447
# 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
447
450
{ module , { file , line , warning } }
448
451
end
449
452
@@ -455,18 +458,18 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
455
458
defp resolve_module ( module ) when is_atom ( module ) , do: module
456
459
defp resolve_module ( { module , _ , _ } ) when is_atom ( module ) , do: module
457
460
458
- defp resolve_module_file ( module , fallback ) do
461
+ defp resolve_module_file ( module , fallback , project_dir ) do
459
462
# We try to resolve the module to its source file. The only time the source
460
463
# info may not be available is when it has been stripped by the beam_lib
461
464
# module, but that shouldn't be the case. More info:
462
465
# http://erlang.org/doc/reference_manual/modules.html#module_info-0-and-module_info-1-functions
463
466
if Code . ensure_loaded? ( module ) do
464
467
module . module_info ( :compile )
465
468
|> Keyword . get ( :source , fallback )
466
- |> Path . relative_to_cwd ( )
469
+ |> Path . relative_to ( project_dir )
467
470
else
468
471
# In case the file fails to load return fallback
469
- Path . relative_to_cwd ( fallback )
472
+ Path . relative_to ( fallback , project_dir )
470
473
end
471
474
end
472
475
@@ -486,8 +489,8 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
486
489
end
487
490
end
488
491
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 )
491
494
end
492
495
493
496
defp module_md5 ( file ) do
@@ -505,7 +508,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
505
508
end
506
509
end
507
510
508
- defp to_diagnostics ( warnings_map , warn_opts , warning_format ) do
511
+ defp to_diagnostics ( warnings_map , warn_opts , warning_format , project_dir ) do
509
512
tags_enabled = Analyzer . matching_tags ( warn_opts )
510
513
deps_path = Mix.Project . deps_path ( )
511
514
@@ -514,7 +517,7 @@ defmodule ElixirLS.LanguageServer.Dialyzer do
514
517
{ tag , _ , _ } = data ,
515
518
tag in tags_enabled ,
516
519
source_file = Path . absname ( to_string ( source_file ) ) ,
517
- in_project? ( source_file ) ,
520
+ in_project? ( source_file , project_dir ) ,
518
521
not String . starts_with? ( source_file , deps_path ) do
519
522
% Mix.Task.Compiler.Diagnostic {
520
523
compiler_name: "ElixirLS Dialyzer" ,
0 commit comments