Skip to content

Commit

Permalink
Safer incremental sync (erlang-ls#1222)
Browse files Browse the repository at this point in the history
* didOpen: Handle indexing through els_index_buffer to avoid race
* didSave: Read and index file through els_index_buffer, this should introduce a
synchronization point if the index data has become out of sync.
  • Loading branch information
plux committed Feb 24, 2022
1 parent c544498 commit e45d7ae
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
30 changes: 30 additions & 0 deletions apps/els_lsp/src/els_index_buffer.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
, stop/0
, apply_edits_async/2
, flush/1
, load/2
]).

-include_lib("kernel/include/logger.hrl").
Expand Down Expand Up @@ -42,6 +43,15 @@ apply_edits_async(Uri, Edits) ->
?SERVER ! {apply_edits, Uri, Edits},
ok.

-spec load(uri(), binary()) -> ok.
load(Uri, Text) ->
Ref = make_ref(),
?SERVER ! {load, self(), Ref, Uri, Text},
receive
{Ref, done} ->
ok
end.

-spec flush(uri()) -> ok.
flush(Uri) ->
Ref = make_ref(),
Expand Down Expand Up @@ -71,6 +81,15 @@ loop() ->
[?SERVER, Uri, {E, R, St}])
end,
Pid ! {Ref, done},
loop();
{load, Pid, Ref, Uri, Text} ->
try
do_load(Uri, Text)
catch E:R:St ->
?LOG_ERROR("[~p] Crashed while loading ~p: ~p",
[?SERVER, Uri, {E, R, St}])
end,
Pid ! {Ref, done},
loop()
end.

Expand All @@ -97,6 +116,17 @@ do_flush(Uri) ->
[?SERVER, Uri, Duration div 1000]),
ok.

-spec do_load(uri(), binary()) -> ok.
do_load(Uri, Text) ->
?LOG_DEBUG("[~p] Loading ~p", [?SERVER, Uri]),
{Duration, ok} =
timer:tc(fun() ->
els_indexing:index(Uri, Text, 'deep')
end),
?LOG_DEBUG("[~p] Done load ~p [duration: ~pms]",
[?SERVER, Uri, Duration div 1000]),
ok.

-spec receive_all(uri(), binary()) -> binary().
receive_all(Uri, Text0) ->
receive
Expand Down
13 changes: 7 additions & 6 deletions apps/els_lsp/src/els_text_synchronization.erl
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,19 @@ did_change(Params) ->

-spec did_open(map()) -> ok.
did_open(Params) ->
TextDocument = maps:get(<<"textDocument">>, Params),
Uri = maps:get(<<"uri">> , TextDocument),
Text = maps:get(<<"text">> , TextDocument),
ok = els_indexing:index(Uri, Text, 'deep'),
#{<<"textDocument">> := #{ <<"uri">> := Uri
, <<"text">> := Text}} = Params,
ok = els_index_buffer:load(Uri, Text),
ok = els_index_buffer:flush(Uri),
Provider = els_diagnostics_provider,
els_provider:handle_request(Provider, {run_diagnostics, Params}),
ok.

-spec did_save(map()) -> ok.
did_save(Params) ->
TextDocument = maps:get(<<"textDocument">>, Params),
Uri = maps:get(<<"uri">> , TextDocument),
#{<<"textDocument">> := #{<<"uri">> := Uri}} = Params,
{ok, Text} = file:read_file(els_uri:path(Uri)),
ok = els_index_buffer:load(Uri, Text),
ok = els_index_buffer:flush(Uri),
Provider = els_diagnostics_provider,
els_provider:handle_request(Provider, {run_diagnostics, Params}),
Expand Down

0 comments on commit e45d7ae

Please sign in to comment.