Skip to content

Commit

Permalink
Fix els_parser crash due to erlfmt returning {skip, _}
Browse files Browse the repository at this point in the history
Erlfmt will skip parsing if it finds pragma @noformat in the text.
In order to trick erlfmt to parse the file we @noformat with @doformat
  • Loading branch information
plux committed Jan 10, 2024
1 parent 7244d7c commit cfa1646
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
16 changes: 15 additions & 1 deletion apps/els_lsp/src/els_parser.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,32 @@ parse(Text) ->
case erlfmt:read_nodes_string("nofile", String) of
{ok, Forms, _ErrorInfo} ->
{ok, lists:flatten(parse_forms(Forms))};
{skip, _} ->
?LOG_INFO("Erlfmt skipped parsing, try to fix it."),
parse(fix_erlfmt(Text));
{error, _ErrorInfo} ->
{ok, []}
end.

-spec fix_erlfmt(binary()) -> binary().
fix_erlfmt(Text) ->
%% erlfmt will skip if it finds pragma @noformat, so we remove it
binary:replace(Text, <<"@noformat">>, <<"@doformat">>).

-spec parse_file(file:name_all()) -> {ok, [tree()]} | {error, term()}.
parse_file(FileName) ->
forms_to_ast(erlfmt:read_nodes(FileName)).

-spec parse_text(binary()) -> {ok, [tree()]} | {error, term()}.
parse_text(Text) ->
String = els_utils:to_list(Text),
forms_to_ast(erlfmt:read_nodes_string("nofile", String)).
case erlfmt:read_nodes_string("nofile", String) of
{skip, _} ->
?LOG_INFO("Erlfmt skipped parsing, try to fix it."),
parse_text(fix_erlfmt(Text));
Result ->
forms_to_ast(Result)
end.

-spec forms_to_ast(tuple()) -> {ok, [tree()]} | {error, term()}.
forms_to_ast({ok, Forms, _ErrorInfo}) ->
Expand Down
12 changes: 11 additions & 1 deletion apps/els_lsp/test/els_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
var_in_application/1,
unicode_clause_pattern/1,
latin1_source_code/1,
record_comment/1
record_comment/1,
pragma_noformat/1
]).

%%==============================================================================
Expand Down Expand Up @@ -472,6 +473,15 @@ record_comment(_Config) ->
),
ok.

%% Issue #1482
%% Erlfmt returns {skip, _} if the text contains pragma @noformat.
%% This would cause els_parser to crash.
-spec pragma_noformat(config()) -> ok.
pragma_noformat(_Config) ->
Text = <<"%% @noformat\nfoo">>,
?assertMatch({ok, _}, els_parser:parse(Text)),
?assertMatch({ok, _}, els_parser:parse_text(Text)).

%%==============================================================================
%% Helper functions
%%==============================================================================
Expand Down

0 comments on commit cfa1646

Please sign in to comment.