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

RefactorErl Diagnostics #1137

Merged
merged 111 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
e5de42f
Configuration for Refactor Erl Node
robertfiko Nov 22, 2021
82dfd3b
Referl unused macros with basic node detect
robertfiko Nov 22, 2021
10f88b8
source() formatted
robertfiko Nov 22, 2021
78c8a94
Unsecure Calls by RefactorErl
robertfiko Nov 22, 2021
70ba798
Behaviour basic approach
robertfiko Nov 22, 2021
4c0f14c
RefactorErl conversion module
robertfiko Nov 23, 2021
c9e7521
Resolved Merge
robertfiko Nov 23, 2021
539b392
Nameing conventions
robertfiko Nov 25, 2021
222ac75
Changed to map, to extend confiureability
robertfiko Nov 26, 2021
9e86bc5
Better node detection, utility module
robertfiko Nov 26, 2021
cf4eaa7
Error management unifying. Code reorganisation
robertfiko Nov 26, 2021
c10e70f
First run for a common diagnostic module
robertfiko Dec 8, 2021
6ff2301
Merge pull request #1 from robertfiko/referl_vscode_0_21
robertfiko Dec 8, 2021
b4f1302
Minor fix
robertfiko Dec 8, 2021
44ead24
Commond diagnostic backend
robertfiko Dec 8, 2021
5c9e80e
Styling conventions
robertfiko Dec 8, 2021
ddc2975
Change 'disabled' to 'notconfigured'
robertfiko Jan 27, 2022
a402ea6
Documentation and utility functions, fixes
robertfiko Jan 27, 2022
b3ca287
Documentation added
robertfiko Jan 27, 2022
4401ef5
Line length changes
robertfiko Jan 28, 2022
e7ddf1d
Merge pull request #2 from robertfiko/referl_diagnostic_common_poi2
robertfiko Jan 28, 2022
cb0c5fa
Minor changes
robertfiko Feb 2, 2022
aa5c787
New, recieve based communication is working
robertfiko Feb 4, 2022
d523dd4
Working with double diagnositc processing
robertfiko Feb 6, 2022
d0c18bb
Poi conversion and diagnostic making merged
robertfiko Feb 6, 2022
73dc49b
Set default to false
robertfiko Feb 6, 2022
0119595
Get the config out of tuple
robertfiko Feb 6, 2022
a574820
Specifyng case mathces and no-match cases
robertfiko Feb 6, 2022
cd437fa
Add as a request
robertfiko Feb 6, 2022
f6517c4
Code clearing
robertfiko Feb 6, 2022
d8925e1
Merge pull request #3 from robertfiko/referl_new_comm
robertfiko Feb 6, 2022
06bb47c
make_diagnostic no result clause
robertfiko Feb 12, 2022
7e8cac5
Diagnostic description made
robertfiko Feb 14, 2022
510cd37
Coding conventions
robertfiko Feb 14, 2022
1776629
a few dyalizer errors
robertfiko Feb 14, 2022
135e0c1
Case clause
robertfiko Feb 14, 2022
5f22e9b
Function spec
robertfiko Feb 14, 2022
7e0a3d4
POI removal
robertfiko Feb 17, 2022
cbee72a
Diagnostic descriptor change
robertfiko Feb 17, 2022
ef7480a
Retry removal, smaller fixes
robertfiko Feb 17, 2022
b66ef5e
Merge pull request #4 from robertfiko/referl_diagnostics_no_retry
robertfiko Feb 17, 2022
42d0a4c
Working logic, cleaning out...
robertfiko Feb 23, 2022
ca7e3a6
Cleaned out
robertfiko Feb 23, 2022
9ff8845
Linting
robertfiko Feb 23, 2022
e17a4ef
Test drafts
robertfiko Feb 24, 2022
c68589f
Timeouting test cases
robertfiko Feb 24, 2022
2f9faf1
Tests
robertfiko Mar 1, 2022
113f3f2
Passing tests, draft
robertfiko Mar 1, 2022
800ac40
Conventions and dialyzer
robertfiko Mar 1, 2022
66809e5
Test failing due to it is not configured
robertfiko Mar 1, 2022
20fbe63
Test
robertfiko Mar 3, 2022
23a4bcd
@doc tag fix
robertfiko Mar 4, 2022
967da50
doc fix2
robertfiko Mar 4, 2022
e5a29be
Diagnostic config option
robertfiko Mar 13, 2022
3b26449
Code clearing and diagnostic config
robertfiko Mar 13, 2022
222c122
Merge pull request #5 from robertfiko/referl_diagnostics_no_retry_no_…
robertfiko Mar 13, 2022
667c4dc
Less error handling
robertfiko Mar 27, 2022
8b9ac4a
Resolved conflict with edoc
robertfiko Mar 27, 2022
f9775e9
Referl unused macros with basic node detect
robertfiko Nov 22, 2021
ed6d143
source() formatted
robertfiko Nov 22, 2021
653347a
Unsecure Calls by RefactorErl
robertfiko Nov 22, 2021
f6c0fa8
RefactorErl conversion module
robertfiko Nov 23, 2021
bc7a0ca
Resolved conflict
robertfiko Mar 27, 2022
0f7e0cc
Nameing conventions
robertfiko Nov 25, 2021
596cf39
Changed to map, to extend confiureability
robertfiko Nov 26, 2021
8d334bb
Better node detection, utility module
robertfiko Nov 26, 2021
3b37faa
Error management unifying. Code reorganisation
robertfiko Nov 26, 2021
44038d1
First run for a common diagnostic module
robertfiko Dec 8, 2021
555a131
Minor fix
robertfiko Dec 8, 2021
3ea4bcc
Commond diagnostic backend
robertfiko Dec 8, 2021
67a06dc
Styling conventions
robertfiko Dec 8, 2021
cc9ae37
Change 'disabled' to 'notconfigured'
robertfiko Jan 27, 2022
c537116
Documentation and utility functions, fixes
robertfiko Jan 27, 2022
66dd3e8
Documentation added
robertfiko Jan 27, 2022
60d7eff
Line length changes
robertfiko Jan 28, 2022
fadc064
Minor changes
robertfiko Feb 2, 2022
77dd860
New, recieve based communication is working
robertfiko Feb 4, 2022
ffb0bea
Working with double diagnositc processing
robertfiko Feb 6, 2022
314dfae
Poi conversion and diagnostic making merged
robertfiko Feb 6, 2022
f9bc32c
Set default to false
robertfiko Feb 6, 2022
eec840c
Get the config out of tuple
robertfiko Feb 6, 2022
239c959
Specifyng case mathces and no-match cases
robertfiko Feb 6, 2022
5d72ecb
Add as a request
robertfiko Feb 6, 2022
a6cef12
Code clearing
robertfiko Feb 6, 2022
88aaccf
make_diagnostic no result clause
robertfiko Feb 12, 2022
84e436a
Diagnostic description made
robertfiko Feb 14, 2022
f5b7518
Coding conventions
robertfiko Feb 14, 2022
6527f1e
a few dyalizer errors
robertfiko Feb 14, 2022
9aa18f9
Case clause
robertfiko Feb 14, 2022
ce85588
Function spec
robertfiko Feb 14, 2022
5268394
POI removal
robertfiko Feb 17, 2022
fc7fc1f
Diagnostic descriptor change
robertfiko Feb 17, 2022
26bc7ad
Retry removal, smaller fixes
robertfiko Feb 17, 2022
9ef5ceb
Working logic, cleaning out...
robertfiko Feb 23, 2022
5cdde72
Cleaned out
robertfiko Feb 23, 2022
694c47a
Linting
robertfiko Feb 23, 2022
65842d6
Test drafts
robertfiko Feb 24, 2022
cc8b487
Rebase conflict
robertfiko Mar 27, 2022
167e6a9
Tests
robertfiko Mar 1, 2022
d9f89e2
Passing tests, draft
robertfiko Mar 1, 2022
1a0e7b8
rebase conflict resolve
robertfiko Mar 27, 2022
8628705
Test failing due to it is not configured
robertfiko Mar 1, 2022
c4c8a3f
Test
robertfiko Mar 3, 2022
0fb3ba6
@doc tag fix
robertfiko Mar 4, 2022
a0e65bd
doc fix2
robertfiko Mar 4, 2022
1389a30
Diagnostic config option
robertfiko Mar 13, 2022
faf0504
Code clearing and diagnostic config
robertfiko Mar 13, 2022
d5e490d
rebase conflict resolve
robertfiko Mar 27, 2022
e9b8dfa
lint
robertfiko Mar 27, 2022
d8ca672
Merge branch 'referl_diagnostics' into referl_diag_conf2
robertfiko Mar 27, 2022
6c56b4d
Merge pull request #7 from robertfiko/referl_diag_conf2
robertfiko Mar 27, 2022
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
6 changes: 6 additions & 0 deletions apps/els_core/src/els_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
| indexing_enabled
| bsp_enabled
| compiler_telemetry_enabled
| refactorerl
| edoc_custom_tags.

-type path() :: file:filename().
Expand All @@ -77,6 +78,7 @@
, indexing_enabled => boolean()
, bsp_enabled => boolean() | auto
, compiler_telemetry_enabled => boolean()
, refactorerl => map() | 'notconfigured'
}.

%%==============================================================================
Expand Down Expand Up @@ -138,6 +140,8 @@ do_initialize(RootUri, Capabilities, InitOptions, {ConfigPath, Config}) ->

IndexingEnabled = maps:get(<<"indexingEnabled">>, InitOptions, true),

RefactorErl = maps:get("refactorerl", Config, notconfigured),

%% Passed by the LSP client
ok = set(root_uri , RootUri),
%% Read from the configuration file
Expand Down Expand Up @@ -180,6 +184,8 @@ do_initialize(RootUri, Capabilities, InitOptions, {ConfigPath, Config}) ->
%% Init Options
ok = set(capabilities , Capabilities),
ok = set(indexing_enabled, IndexingEnabled),

ok = set(refactorerl, RefactorErl),
ok.

-spec start_link() -> {ok, pid()}.
Expand Down
1 change: 1 addition & 0 deletions apps/els_lsp/src/els_diagnostics.erl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ available_diagnostics() ->
, <<"unused_includes">>
, <<"unused_macros">>
, <<"unused_record_fields">>
, <<"refactorerl">>
].

-spec default_diagnostics() -> [diagnostic_id()].
Expand Down
90 changes: 90 additions & 0 deletions apps/els_lsp/src/els_refactorerl_diagnostics.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
%%==============================================================================
%% RefactorErl Diagnostics
%%==============================================================================
-module(els_refactorerl_diagnostics).

%%==============================================================================
%% Behaviours
%%==============================================================================
-behaviour(els_diagnostics).

%%==============================================================================
%% Exports
%%==============================================================================
-export([ is_default/0
, run/1
, source/0
]).

%%==============================================================================
%% Includes & Defines
%%==============================================================================
-include("els_lsp.hrl").

%%==============================================================================
%% Types
%%==============================================================================
-type refactorerl_diagnostic_alias() :: atom().
-type refactorerl_diagnostic_result() :: {range(), string()}.
%-type refactorerl_query() :: [char()].

%%==============================================================================
%% Callback Functions
robertfiko marked this conversation as resolved.
Show resolved Hide resolved
%%==============================================================================

-spec is_default() -> boolean().
is_default() ->
false.

-spec run(uri()) -> [els_diagnostics:diagnostic()].
run(Uri) ->
case filename:extension(Uri) of
<<".erl">> ->
case els_refactorerl_utils:referl_node() of
{error, _} ->
[];
{ok, _} ->
case els_refactorerl_utils:add(Uri) of
error ->
[];
ok ->
Module = els_uri:module(Uri),
Diags = enabled_diagnostics(),
Results = els_refactorerl_utils:run_diagnostics(Diags, Module),
make_diagnostics(Results)
end
end;
_ ->
[]
end.

-spec source() -> binary().
source() ->
els_refactorerl_utils:source_name().

%%==============================================================================
%% Internal Functions
%%==============================================================================
% @doc
% Returns the enabled diagnostics by merging default and configed
-spec enabled_diagnostics() -> [refactorerl_diagnostic_alias()].
enabled_diagnostics() ->
case els_config:get(refactorerl) of
#{"diagnostics" := List} ->
[list_to_atom(Element) || Element <- List];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It would be good to avoid the list_to_atom here.

_ ->
[]
end.


% @doc
% Constructs the ELS diagnostic from RefactorErl result
-spec make_diagnostics([refactorerl_diagnostic_result()]) -> any().
make_diagnostics([{Range, Message} | Tail]) ->
Severity = ?DIAGNOSTIC_WARNING,
Source = source(),
Diag = els_diagnostics:make_diagnostic(Range, Message, Severity, Source),
[ Diag | make_diagnostics(Tail) ];

make_diagnostics([]) ->
[].
160 changes: 160 additions & 0 deletions apps/els_lsp/src/els_refactorerl_utils.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
%%==============================================================================
%% Erlang LS & Refactor Erl communication
%%==============================================================================
-module(els_refactorerl_utils).

%%==============================================================================
%% API
%%==============================================================================
-export([ referl_node/0
, notification/1
, notification/2
, run_diagnostics/2
, source_name/0
, add/1
]).

%%==============================================================================
%% Includes & Defines
%%==============================================================================
-include("els_lsp.hrl").

%%==============================================================================
%% API
%%==============================================================================

%% @doc
%% Returns the RefactorErl node, if it can't, it returns error and its cause.
%% It returns the node given in config, if it is alive.
%% First it runs the validation functions, the result of validation will be
%% notified to the user.
%% If the node once was validated there will be no display messages.
%%
%% The configuration can store the node and its status.
%% - Either a simple NodeString, which needs to be checked and configure
%% - {Node, Status} where boths are atoms
%% Possible statuses: validated, disconnected, disabled
%% 'disabled', when it won't try to reconnect
%% 'disconnected', when it will try to reconnect
%% - notconfigured, the node is not configured in the config file
%%
%%
%% Node can be:
%% - NodeStr
%% - {Status, Node} where both are atoms.
%% - Status can be:
%% - validated: node is running
%% - disconnected: node is not running
%% - disabled: RefactorErl is turned off for this session. T
%% his can happen after an unsuccessfull query attempt.
-spec referl_node() -> {ok, atom()}
| {error, disconnected}
| {error, disabled}
| {error, other}.
referl_node() ->
case els_config:get(refactorerl) of
#{"node" := {Node, validated}} ->
{ok, Node};

#{"node" := {Node, disconnected}} ->
connect_node({retry, Node});

#{"node" := {_Node, disabled}} ->
{error, disabled};

#{"node" := NodeStr} ->
RT = els_config_runtime:get_name_type(),
Node = els_utils:compose_node_name(NodeStr, RT),
connect_node({validate, Node});

notconfigured ->
{error, disabled};

_ ->
{error, other}
end.


%%@doc
%% Adds a module to the RefactorErl node. Using the UI router
%% Returns 'ok' if successfull
%% Returns 'error' if it fails
-spec add(uri()) -> error | ok.
add(Uri) ->
case els_refactorerl_utils:referl_node() of
{ok, Node} ->
Path = [binary_to_list(els_uri:path(Uri))],
rpc:call(Node, referl_els, add, [Path]); %% returns error | ok
_ ->
error
end.

%%@doc
%% Runs list of diagnostic aliases on refactorerl
-spec run_diagnostics(list(), atom()) -> list().
run_diagnostics(DiagnosticAliases, Module) ->
case els_refactorerl_utils:referl_node() of
{ok, Node} ->
%% returns error | ok
rpc:call(Node, referl_els, run_diagnostics, [DiagnosticAliases, Module]);
_ -> % In this case there was probably error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to log a message here.

[]
end.

%%@doc
%% Util for popping up notifications
-spec notification(string(), number()) -> atom().
notification(Msg, Severity) ->
Param = #{ type => Severity,
message => list_to_binary(Msg) },
els_server:send_notification(<<"window/showMessage">>, Param).

-spec notification(string()) -> atom().
notification(Msg) ->
notification(Msg, ?MESSAGE_TYPE_INFO).

%%==============================================================================
%% Internal Functions
%%==============================================================================

%%@doc
%% Checks if the given node is running RefactorErl with ELS interface
-spec is_refactorerl(atom()) -> boolean().
is_refactorerl(Node) ->
case rpc:call(Node, referl_els, ping, [], 500) of
{refactorerl_els, pong} -> true;
_ -> false
end.

%%@doc
%% Tries to connect to a node.
%% When it status is validate, the node hasn't been checked yet,
%% so it will reports the success, and failure as well,
%%
%% when retry, it won't report.
-spec connect_node({validate | retry, atom()}) -> {error, disconnected}
| atom().
connect_node({Status, Node}) ->
Config = els_config:get(refactorerl),
case {Status, is_refactorerl(Node)} of
{validate, false} ->
els_config:set(refactorerl, Config#{"node" => {Node, disconnected}}),
{error, disconnected};
{retry, false} ->
els_config:set(refactorerl, Config#{"node" => {Node, disconnected}}),
{error, disconnected};
{_, true} ->
notification("RefactorErl is connected!", ?MESSAGE_TYPE_INFO),
els_config:set(refactorerl, Config#{"node" => {Node, validated}}),
{ok, Node}
end.

%%==============================================================================
%% Values
%%==============================================================================

%%@doc
%% Common soruce name for all RefactorErl based backend(s)
-spec source_name() -> binary().
source_name() ->
<<"RefactorErl">>.
Loading