Skip to content

Commit

Permalink
Working prototype for indenting entire function on .
Browse files Browse the repository at this point in the history
Co-authored-by: Andreas Hasselberg <[email protected]>

Delete iostr.erl

Fix linter complaints

Fix proper error

Fix typespec

Maybe make Dialyzer happy?

Temp fixes to get dialyzer to run

Add spec

Better fix for dialyzer errors

Add config to enable on type formatting, defaulting to false

Skip formatting if . is on a commented out line
  • Loading branch information
onno-vos-dev committed Oct 15, 2021
1 parent 51a48ef commit 284ec99
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 9 deletions.
7 changes: 4 additions & 3 deletions apps/els_core/include/els_core.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,8 @@
}.

-type document_ontypeformatting_options() :: false |
#{ first_trigger_character := string()
, more_trigger_character => string()
#{ firstTriggerCharacter := binary()
, moreTriggerCharacter => [binary()]
}.

%%------------------------------------------------------------------------------
Expand Down Expand Up @@ -612,7 +612,8 @@
| {atom(), atom()} %% record_def_field, record_field
| string() %% include, include_lib
| {atom(), arity()}
| {module(), atom(), arity()}.
| {module(), atom(), arity()}
| pos().
-type poi() :: #{ kind := poi_kind()
, id := poi_id()
, data := any()
Expand Down
4 changes: 4 additions & 0 deletions apps/els_core/src/els_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ request_params({initialize, {RootUri, InitOptions}}) ->
#{ <<"contextSupport">> => 'true' }
, <<"hover">> =>
#{ <<"contentFormat">> => ContentFormat }
, <<"documentOnTypeFormattingProvider">> =>
#{ firstTriggerCharacter => <<",">>
, moreTriggercharacter => []
}
},
#{ <<"rootUri">> => RootUri
, <<"initializationOptions">> => InitOptions
Expand Down
2 changes: 2 additions & 0 deletions apps/els_core/src/els_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ do_initialize(RootUri, Capabilities, InitOptions, {ConfigPath, Config}) ->
= maps:get("compiler_telemetry_enabled", Config, false),

IndexingEnabled = maps:get(<<"indexingEnabled">>, InitOptions, true),
FormatOnTypeEnabled = maps:get("format_on_type", Config, false),

%% Passed by the LSP client
ok = set(root_uri , RootUri),
Expand All @@ -138,6 +139,7 @@ do_initialize(RootUri, Capabilities, InitOptions, {ConfigPath, Config}) ->
ok = set(macros , Macros),
ok = set(plt_path , DialyzerPltPath),
ok = set(code_reload , CodeReload),
ok = set(format_on_type , FormatOnTypeEnabled),
?LOG_INFO("Config=~p", [Config]),
ok = set(runtime, maps:merge( els_config_runtime:default_config()
, Runtime)),
Expand Down
10 changes: 8 additions & 2 deletions apps/els_lsp/src/els_dt_document.erl
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@
, lookup/1
]).

-export([ new/2
-export([ get_element_at_pos/3
, new/2
, pois/1
, pois/2
, get_element_at_pos/3
, uri/1
, functions_at_pos/3
, applications_at_pos/3
, wrapping_functions/2
, wrapping_functions/3
, text/1
]).

%%==============================================================================
Expand Down Expand Up @@ -63,6 +64,7 @@
, md5 => binary()
, pois => [poi()]
}.

-export_type([ id/0
, item/0
, kind/0
Expand Down Expand Up @@ -155,6 +157,10 @@ new(Uri, Text, Id, Kind) ->
pois(#{ pois := POIs }) ->
POIs.

-spec text(item()) -> binary().
text(#{text := Text}) ->
Text.

%% @doc Returns the list of POIs of the given types for the current
%% document
-spec pois(item(), [poi_kind()]) -> [poi()].
Expand Down
78 changes: 74 additions & 4 deletions apps/els_lsp/src/els_formatting_provider.erl
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ is_enabled_document() -> true.

-spec is_enabled_range() -> boolean().
is_enabled_range() ->
false.
true.

%% NOTE: because erlang_ls does not send incremental document changes
%% via `textDocument/didChange`, this kind of formatting does not
%% make sense.
-spec is_enabled_on_type() -> document_ontypeformatting_options().
is_enabled_on_type() -> false.
is_enabled_on_type() ->
case els_config:get(format_on_type) of
true -> #{firstTriggerCharacter => <<".">>, moreTriggerCharacter => []};
false -> false
end.

-spec handle_request(any(), state()) -> {any(), state()}.
handle_request({document_formatting, Params}, State) ->
Expand Down Expand Up @@ -157,5 +161,71 @@ rangeformat_document(_Uri, _Document, _Range, _Options) ->
-spec ontypeformat_document(binary(), map()
, number(), number(), string(), formatting_options())
-> {ok, [text_edit()]}.
ontypeformat_document(_Uri, _Document, _Line, _Col, _Char, _Options) ->
{ok, []}.
ontypeformat_document(_Uri, Document, Line, Col, <<".">>, _Options) ->
case find_matching_range(Document, Line) of
[] ->
{ok, []};
[MatchingRange] ->
{StartLine, _} = Id = els_poi:id(MatchingRange),
Text = els_dt_document:text(Document),
RangeText = els_text:range(Text, Id, {Line, Col}),
% Skip formatting if the . is on a commented line.
case string:trim(els_text:line(Text, Line - 1), both) of
<<"%", _/binary>> ->
{ok, []};
_ ->
ParseF =
fun(Dir) ->
TmpFile = tmp_file(Dir),
ok = file:write_file(TmpFile, RangeText),
Opts = #{break_indent => 2, output_dir => current},
RebarState = #{},
T = rebar3_formatter:new(default_formatter, Opts, RebarState),
rebar3_formatter:format_file(TmpFile, T),
{ok, Bin} = file:read_file(TmpFile),
Bin
end,
%% rebar3_formatter adds a newline, since we terminate on .
%% We want to leave the cursor at the current char rather
%% than jumping to a newline
NewText =
string:trim(
tempdir:mktmp(ParseF), trailing, "\n"),
{ok,
[#{range =>
#{start => #{line => StartLine - 1, character => 0},
'end' => #{line => Line - 1, character => Col}},
newText => NewText}]}
end
end;
ontypeformat_document(_Uri, _Document, _Line, _Col, Char, _Options) ->
?LOG_INFO("Got unhandled character in ontypeformat_document. No formatter "
"configured for char: ~p",
[Char]),
{ok, []}.

-spec find_foldable_ranges(els_dt_document:item()) -> [poi()].
find_foldable_ranges(Document) ->
Pois = els_dt_document:pois(Document),
lists:filter(fun (#{kind := folding_range}) ->
true;
(_) ->
false
end,
Pois).

-spec find_matching_range(els_dt_document:item(), number()) -> [poi()].
find_matching_range(Document, Line) ->
lists:filter(fun(#{range := #{from := {FromLine, _}, to := {ToLine, _}}}) ->
Line >= FromLine andalso Line =< ToLine
end,
find_foldable_ranges(Document)).

-spec tmp_file(string()) -> any().
tmp_file(Dir) ->
Unique = erlang:unique_integer([positive]),
{A, B, C} = os:timestamp(),
N = node(),
filename:join(Dir,
lists:flatten(
io_lib:format("~p-~p.~p.~p.~p", [N, A, B, C, Unique]))).
2 changes: 2 additions & 0 deletions apps/els_lsp/src/els_general_provider.erl
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ server_capabilities() ->
els_formatting_provider:is_enabled_document()
, documentRangeFormattingProvider =>
els_formatting_provider:is_enabled_range()
, documentOnTypeFormattingProvider =>
els_formatting_provider:is_enabled_on_type()
, foldingRangeProvider =>
els_folding_range_provider:is_enabled()
, implementationProvider =>
Expand Down
5 changes: 5 additions & 0 deletions apps/els_lsp/src/els_poi.erl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

-export([ match_pos/2
, sort/1
, id/1
]).

%%==============================================================================
Expand Down Expand Up @@ -42,6 +43,10 @@ match_pos(POIs, Pos) ->
, to := To
}} = POI <- POIs, (From =< Pos) andalso (Pos =< To)].

-spec id(poi()) -> poi_id().
id(#{id := Id}) ->
Id.

%% @doc Sorts pois based on their range
%%
%% Order is defined using els_range:compare/2.
Expand Down

0 comments on commit 284ec99

Please sign in to comment.