From 54d00d953a04f88e2facb4eb80e51019b77c80d0 Mon Sep 17 00:00:00 2001 From: Hakan Nilsson Date: Tue, 15 Oct 2024 10:12:50 +0200 Subject: [PATCH] Add code action to export function --- apps/els_lsp/src/els_code_action_provider.erl | 2 + apps/els_lsp/src/els_code_actions.erl | 27 ++++++++++ apps/els_lsp/test/els_code_action_SUITE.erl | 49 +++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/apps/els_lsp/src/els_code_action_provider.erl b/apps/els_lsp/src/els_code_action_provider.erl index 2f0a4286..f48bd07b 100644 --- a/apps/els_lsp/src/els_code_action_provider.erl +++ b/apps/els_lsp/src/els_code_action_provider.erl @@ -62,6 +62,8 @@ make_code_actions( {"function (.*) undefined", fun els_code_actions:suggest_function/4}, {"Cannot find definition for function (.*)", fun els_code_actions:suggest_function/4}, {"Cannot find module (.*)", fun els_code_actions:suggest_module/4}, + {"Function (.+):(.+) is not exported.", + fun els_code_actions:export_external_function/4}, {"Unused file: (.*)", fun els_code_actions:remove_unused/4}, {"Atom typo\\? Did you mean: (.*)", fun els_code_actions:fix_atom_typo/4}, {"undefined callback function (.*) \\\(behaviour '(.*)'\\\)", diff --git a/apps/els_lsp/src/els_code_actions.erl b/apps/els_lsp/src/els_code_actions.erl index c4e8fb5d..9ae1e653 100644 --- a/apps/els_lsp/src/els_code_actions.erl +++ b/apps/els_lsp/src/els_code_actions.erl @@ -3,6 +3,7 @@ extract_function/2, create_function/4, export_function/4, + export_external_function/4, fix_module_name/4, ignore_variable/4, remove_macro/4, @@ -84,6 +85,32 @@ export_function(Uri, _Range, _Data, [UnusedFun]) -> ] end. +-spec export_external_function(uri(), range(), binary(), [binary()]) -> [map()]. +export_external_function(_Uri, _Range, _Data, [ModBin, FABin]) -> + Mod = binary_to_atom(ModBin, utf8), + case els_utils:find_module(Mod) of + {ok, Uri} -> + {ok, Document} = els_utils:lookup_document(Uri), + case els_poi:sort(els_dt_document:pois(Document, [module, export])) of + [] -> + []; + POIs -> + #{range := #{to := {Line, _Col}}} = lists:last(POIs), + Pos = {Line + 1, 1}, + [ + make_edit_action( + Uri, + <<"Export ", FABin/binary>>, + ?CODE_ACTION_KIND_QUICKFIX, + <<"-export([", FABin/binary, "]).\n">>, + els_protocol:range(#{from => Pos, to => Pos}) + ) + ] + end; + {error, not_found} -> + [] + end. + -spec ignore_variable(uri(), range(), binary(), [binary()]) -> [map()]. ignore_variable(Uri, Range, _Data, [UnusedVariable]) -> {ok, Document} = els_utils:lookup_document(Uri), diff --git a/apps/els_lsp/test/els_code_action_SUITE.erl b/apps/els_lsp/test/els_code_action_SUITE.erl index 1e1a51bd..68f1f2f3 100644 --- a/apps/els_lsp/test/els_code_action_SUITE.erl +++ b/apps/els_lsp/test/els_code_action_SUITE.erl @@ -14,6 +14,7 @@ -export([ add_underscore_to_unused_var/1, export_unused_function/1, + export_external_function/1, suggest_variable/1, fix_module_name/1, remove_unused_macro/1, @@ -158,6 +159,54 @@ export_unused_function(Config) -> ?assertEqual(Expected, Result), ok. +-spec export_external_function(config()) -> ok. +export_external_function(Config) -> + Uri = ?config(code_navigation_uri, Config), + %% Don't care + Range = els_protocol:range(#{ + from => {1, 1}, + to => {1, 2} + }), + Diag = #{ + message => <<"Function code_action:function_c/0 is not exported.">>, + range => Range, + severity => 2, + source => <<"CrossRef">> + }, + #{result := Result} = els_client:document_codeaction(Uri, Range, [Diag]), + TargetUri = ?config(code_action_uri, Config), + Expected = + [ + #{ + edit => #{ + changes => + #{ + binary_to_atom(TargetUri, utf8) => + [ + #{ + range => + #{ + 'end' => #{ + character => 0, + line => ?COMMENTS_LINES + 3 + }, + start => #{ + character => 0, + line => ?COMMENTS_LINES + 3 + } + }, + newText => <<"-export([function_c/0]).\n">> + } + ] + } + }, + kind => <<"quickfix">>, + title => <<"Export function_c/0">> + } + ], + ?assertEqual(Expected, Result), + ok. + -spec suggest_variable(config()) -> ok. suggest_variable(Config) -> Uri = ?config(code_action_uri, Config),