Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactoring #303

Merged
merged 5 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions apps/erlangbridge/src/gen_lsp_config_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
-export([standard_modules/0, bifs/0]).
-export([update_config/2, root/0, tmpdir/0, codeLensEnabled/0, includePaths/0, linting/0,
verbose/0, autosave/0, proxy/0, search_files_exclude/0, search_exclude/0,
formatting_line_length/0, inlayHintsEnabled/0]).
formatting_line_length/0, inlayHintsEnabled/0, verbose_is_include/1]).

-include("lsp_log.hrl").
-define(SERVER, ?MODULE).

-record(state, {config, standard_modules, bifs}).
Expand All @@ -23,7 +24,19 @@ bifs() ->
gen_server:call(?SERVER, {bifs}).

update_config(Key, Value) ->
gen_server:call(?SERVER, {update_config, Key, Value}).
Res = gen_server:call(?SERVER, {update_config, Key, Value}),
compute_erlang_section(Key),
Res.

compute_erlang_section(Key) ->
if
Key =:= erlang ->
Excludes = get_config_entry(erlang, verboseExcludeFilter, ""),
Splitted = lists:map(fun(X) -> {lsp_utils:to_binary(X), false} end, lists:flatmap( fun(X) -> string:split(X, ",") end, string:split(Excludes, ";"))),
gen_server:call(?SERVER, {update_config, erlang_computed, #{ verboseExcludeFilter => maps:from_list(Splitted)}});
true -> ok
end.


get_config() ->
gen_server:call(?SERVER, get_config).
Expand All @@ -50,6 +63,10 @@ linting() ->
verbose() ->
get_config_entry(erlang, verbose, false).

verbose_is_include(Method) ->
M = get_config_entry(erlang_computed, verboseExcludeFilter, #{}),
lsp_utils:try_get(Method, M, true).

autosave() ->
get_config_entry(computed, autosave, true).

Expand Down
4 changes: 3 additions & 1 deletion apps/erlangbridge/src/gen_lsp_help_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ eep48_render_fun_doc(_Module, _Function, FnDoc, Docs) ->
list_to_binary(lists:flatten(render_function(FnDoc, Docs))).

render_function([], _D) ->
{error, function_missing};
%{error, function_missing};
% maps at (line:52, column:59), put cursor on iterator_order/0
["function_documentation_missing"];
render_function(FDocs, Docs) ->
Grouping =
lists:foldl(
Expand Down
18 changes: 13 additions & 5 deletions apps/erlangbridge/src/gen_lsp_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ handle_info(_Data, State) ->
lsp_log(Msg, Args) ->
gen_lsp_config_server:verbose() andalso error_logger:info_msg(Msg, Args).

lsp_log(Method, Msg, Args) ->
% Method can be excluded from verbose logging by adding it to verboseExcludeFilter in the config
gen_lsp_config_server:verbose() andalso gen_lsp_config_server:verbose_is_include(Method) andalso error_logger:info_msg(Msg, Args).

remove_text_for_logging(#{params := #{contentChanges := ChangesList} = Params} = Input) ->
Input#{params := Params#{contentChanges := lists:map(fun
(#{text := <<Text/binary>>} = Change) when byte_size(Text) > 20 ->
Expand All @@ -102,7 +106,7 @@ remove_text_for_logging(Input) ->
Input.

do_contents(Socket, #{method := Method} = Input) ->
lsp_log("LSP received ~p", [remove_text_for_logging(Input)]),
lsp_log(Method, "LSP received ~p", [remove_text_for_logging(Input)]),
case call_handler(Socket, Method, maps:get(params, Input, undefined)) of
{ok, Result} ->
send_response_with_id(Socket, Input, #{result => Result});
Expand Down Expand Up @@ -142,20 +146,24 @@ handler_name(<<"$/", Name/binary>>) ->
handler_name(Name) ->
list_to_atom(binary_to_list(binary:replace(Name, <<"/">>, <<"_">>))).

send_response_with_id(Socket, Input, Response) ->
send_response_with_id(Socket, #{method := Method} = Input, Response) ->
case maps:get(id, Input, undefined) of
undefined ->
ok;
Id ->
send_to_client(Socket, Response#{id => Id})
send_to_client(Socket, Method, Response#{id => Id})
end.

send_to_client(Socket, Body) ->
lsp_log("LSP sends ~p", [Body]),
send_to_client(Socket, Method, Body) ->
lsp_log(Method, "LSP sends ~p", [Body]),
{ok, Json} = vscode_jsone:encode(Body),
Header = iolist_to_binary(io_lib:fwrite("Content-Length: ~p", [byte_size(Json)])),
gen_tcp:send(Socket, <<Header/binary, "\r\n\r\n", Json/binary>>).

send_to_client(Socket, Body) ->
send_to_client(Socket, <<"unknown">>, Body).


handle_tcp_data(Socket, Contents, State) ->
StateWithContents = State#state{contents = <<(State#state.contents)/binary, Contents/binary>>},
StateWithLength = case StateWithContents#state.content_length of
Expand Down
13 changes: 13 additions & 0 deletions apps/erlangbridge/src/lsp_utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,42 @@
index_of/2,
try_get/3]).

-export_type([lsp_position/0, lsp_range/0]).


-type lsp_position() :: #{ line => pos_integer(), character => pos_integer()}.
-type lsp_range() :: #{ 'start' => lsp_position(), 'end' => lsp_position()}.

-spec try_get(Key :: term(), Map :: map(), Default :: term()) -> term().
try_get(Key, Map, Default) ->
case maps:find(Key, Map) of
{ok, Value} -> Value;
_ -> Default
end.

-spec client_range(Line :: pos_integer(), StartChar :: pos_integer(), EndChar :: pos_integer()) -> lsp_range().
client_range(Line, StartChar, EndChar) ->
#{
<<"start">> => #{line => Line - 1, character => StartChar - 1},
<<"end">> => #{line => Line - 1, character => EndChar - 1}
}.


-spec client_range(Line :: pos_integer(), StartChar :: pos_integer(), LineEnd :: pos_integer(), EndChar :: pos_integer()) -> lsp_range().
client_range(Line, StartChar, LineEnd, EndChar) ->
#{
<<"start">> => #{line => Line - 1, character => StartChar - 1},
<<"end">> => #{line => LineEnd - 1, character => EndChar - 1}
}.

-spec client_position({Line :: pos_integer(), Column :: pos_integer()}) -> lsp_position().
client_position({Line, Column}) ->
#{
line => Line-1,
character => Column-1
}.

-spec file_uri_to_file(Uri :: binary()) -> binary().
file_uri_to_file(Uri) ->
NewUri = re:replace(case Uri of
<<"file:///", Drive, "%3A", Rest/binary>> -> <<Drive, ":", Rest/binary>>;
Expand All @@ -51,6 +62,7 @@ file_uri_to_file(Uri) ->
end, <<"\\\\">>, <<"/">>, [global, {return, list}]),
lists:flatten(string_replace(NewUri, "%20", " ")).

-spec file_uri_to_vscode_uri(Uri :: binary()) -> binary().
file_uri_to_vscode_uri(Uri) ->
UriWithOutSpace = lists:flatten(string_replace(to_string(Uri), " ", "%20")),
EncodeUri = if
Expand All @@ -62,6 +74,7 @@ file_uri_to_vscode_uri(Uri) ->
_ -> EncodeUri
end.

-spec file_to_file_uri(File :: binary()) -> binary().
file_to_file_uri(<<"//", BinFile/binary>>) ->
<<"file://", BinFile/binary>>;
file_to_file_uri("//" ++ File) ->
Expand Down
11 changes: 1 addition & 10 deletions apps/erlangbridge/test/lsp_navigation_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,7 @@

-compile([export_all, nowarn_export_all]).

-define(logMsg(S),
begin
ct:log(default, 50, "~w:~p", [self(), S], [])
end).

-define(writeConsole(Fmt, Args),
error_logger:info_msg(Msg, Args)).

-define(writeConsole(S),
error_logger:info_msg("~p\n", [S])).
-include("./testlog.hrl").

% Specify a list of all unit test functions
all() -> [testnavigation, test_macros].
Expand Down
78 changes: 78 additions & 0 deletions apps/erlangbridge/test/lsp_utils_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
-module(lsp_utils_SUITE).

-include_lib("common_test/include/ct.hrl").

-include_lib("eunit/include/eunit.hrl").

-compile([export_all, nowarn_export_all]).

-include("./testlog.hrl").

% Specify a list of all unit test functions
all() -> [do_is_path_excluded].

% required, but can just return Config. this is a suite level setup function.
init_per_suite(Config) ->
%tprof:start(#{type => call_memory}),
%tprof:enable_trace(all), tprof:set_pattern('_', '_' , '_'),
% do custom per suite setup here
StartResult = application:start(vscode_lsp, permanent),
?assertEqual(ok, StartResult),
% to intercept traces, set to true
ErlangSection = #{verbose => false},
gen_lsp_config_server:update_config(
erlang,
ErlangSection
),
Config.

% required, but can just return Config. this is a suite level tear down function.
end_per_suite(Config) ->
% do custom per suite cleanup here
application:stop(vscode_lsp),
%tprof:disable_trace(all), Sample = tprof:collect(),
%Inspected = tprof:inspect(Sample, process, measurement), Shell = maps:get(self(), Inspected),
%tprof:format(Shell),
Config.

otp_files() ->
% files list extracted from otp/erts/test/erlc_SUITE_data/src/
% returned by file:list_dir(...)
[
"otp/erts/test/erlc_SUITE_data/src/f_include_1.erl",
"otp/erts/test/erlc_SUITE_data/src/erl_test_bad.erl",
"otp/erts/test/erlc_SUITE_data/src/start_bad.script",
"otp/erts/test/erlc_SUITE_data/src/yecc_test_bad.yrl",
"otp/erts/test/erlc_SUITE_data/src/start_ok.script",
"otp/erts/test/erlc_SUITE_data/src/macro_enabled.hrl",
"otp/erts/test/erlc_SUITE_data/src/GOOD-MIB.mib",
[11,116,112,47,101,114,116,115,47,
116,101,115,116,47,101,114,108,99,95,83,85,73,84,69,95,100,
97,116,97,47,115,114,99,47,128512,47,101,114,108,95,116,101,
115,116,95,117,110,105,99,111,100,101,46,101,114,108], % unicode directory
"otp/erts/test/erlc_SUITE_data/src/CVS/older.erl",
"otp/erts/test/erlc_SUITE_data/src/older.beam"
].

otp_files_withresult() ->
% ensure that File converted to unicode:characters_to_binary before calling is_path_excludedand it works as expected
{
lists:zipwith(fun(X, Y) -> {unicode:characters_to_binary(X),Y} end, otp_files(), [false,false,false,false,false,false,false,false,true,false]),
exclude_map()
}.

exclude_map() ->
% #{'**/.git' => true,'**/.svn' => true,'**/.hg' => true,
% '**/CVS' => true,'**/.DS_Store' => true,
% '**/Thumbs.db' => true}.
#{ ".*/CVS(/.*)?$" => true }.

check_path_excluded({FilesAndResult, Map}) ->
lists:foreach(fun ({F, ExpectedResult}) ->
R = lsp_utils:is_path_excluded(F, Map),
?assertEqual(ExpectedResult, R)
end, FilesAndResult).

do_is_path_excluded(_Config) ->
check_path_excluded(otp_files_withresult()),
ok.
10 changes: 10 additions & 0 deletions apps/erlangbridge/test/testlog.hrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-define(logMsg(S),
begin
ct:log(default, 50, "~w:~p", [self(), S], [])
end).

-define(writeConsole(Fmt, Args),
error_logger:info_msg(Msg, Args)).

-define(writeConsole(S),
error_logger:info_msg("~p\n", [S])).
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@
"description": "Enable/disable technical traces for use in the extension development.",
"default": false
},
"erlang.verboseExcludeFilter": {
"type": "string",
"default": "textDocument/inlayHints,textDocument/hover",
"description": "List of excluded methods (i.e: textDocument/hover,textDocument/inlayHints, ...) from technical traces in the extension development."
},
"erlang.debuggerRunMode": {
"type": "string",
"default": "external",
Expand Down