Skip to content

Instantly share code, notes, and snippets.

@fabjan
Created November 12, 2022 13:16
Show Gist options
  • Save fabjan/7a4d91f4479f085c7bbc60cba241f196 to your computer and use it in GitHub Desktop.
Save fabjan/7a4d91f4479f085c7bbc60cba241f196 to your computer and use it in GitHub Desktop.
diff --git a/apps/els_lsp/src/els_docs.erl b/apps/els_lsp/src/els_docs.erl
index 2f0a93c..3b09f70 100644
--- a/apps/els_lsp/src/els_docs.erl
+++ b/apps/els_lsp/src/els_docs.erl
@@ -100,7 +100,17 @@ function_docs(Type, M, F, A) ->
case eep48_docs(function, M, F, A) of
{ok, Docs} ->
[{text, Docs}];
- {error, not_available} ->
+ {error, Error} ->
+ case Error of
+ doc_chunk_not_found ->
+ ok;
+ _ ->
+ ?LOG_WARNING(#{
+ message => "failed to get docs",
+ mfa => {M, F, A},
+ error => Error
+ })
+ end,
%% We cannot fetch the EEP-48 style docs, so instead we create
%% something similar using the tools we have.
Sig = {h2, signature(Type, M, F, A)},
@@ -149,7 +159,10 @@ signature('remote', M, F, A) ->
%% using edoc.
-ifdef(NATIVE_FORMAT).
-spec eep48_docs(function | type, atom(), atom(), non_neg_integer()) ->
- {ok, string()} | {error, not_available}.
+ {ok, string()} | {error, Reason}
+when
+ Reason :: doc_chunk_not_found | render_failed | {unexpected, {Class, any()}},
+ Class :: atom().
eep48_docs(Type, M, F, A) ->
Render =
case Type of
@@ -168,28 +181,57 @@ eep48_docs(Type, M, F, A) ->
flush_group_leader_proxy(GL),
case els_eep48_docs:Render(M, F, A, DocChunk) of
- {error, _R0} ->
+ {error, MFAError} ->
+ ?LOG_DEBUG(#{
+ message => "failed to render EEP-48 docs, trying just module/function",
+ mfa => {M, F, A},
+ error => MFAError
+ }),
case els_eep48_docs:Render(M, F, DocChunk) of
- {error, _R1} ->
- {error, not_available};
+ {error, MFError} ->
+ ?LOG_WARNING(#{
+ message => "failed to render EEP-48 docs",
+ mfa => {M, F, A},
+ error => MFError
+ }),
+ {error, render_failed};
Docs ->
{ok, els_utils:to_list(Docs)}
end;
Docs ->
{ok, els_utils:to_list(Docs)}
end;
- _R1 ->
- ?LOG_DEBUG(#{error => _R1}),
- {error, not_available}
+ Error ->
+ ?LOG_DEBUG(#{
+ message => "could not get EEP-48 doc chunk",
+ mfa => {M, F, A},
+ error => Error
+ }),
+ {error, doc_chunk_not_found}
catch
C:E:ST ->
%% code:get_doc/1 fails for escriptized modules, so fall back
%% reading docs from source. See #751 for details
IO = flush_group_leader_proxy(GL),
- ?LOG_DEBUG(#{
- slogan => "Error fetching docs, falling back to src.",
- module => M,
- error => {C, E},
+ EdocErrors = improper_filtermap(
+ fun
+ ({L, Where, Format, Args, error}) ->
+ WhereFmt = re:replace(Where, ": $", ":"),
+ {true, {
+ iolist_to_binary(io_lib:format("~s~B", [WhereFmt, L])),
+ iolist_to_binary(io_lib:format(Format, Args))
+ }};
+ (_) ->
+ false
+ end,
+ get(edoc_diagnostics)
+ ),
+ Error = {C, E},
+ ?LOG_WARNING(#{
+ message => "Error fetching docs, falling back to src.",
+ mfa => {M, F, A},
+ error => Error,
+ edoc_diagnostics => EdocErrors,
st => ST,
io => IO
}),
@@ -274,7 +316,7 @@ get_edoc_chunk(M, Uri) ->
{ok, Bin} = file:read_file(Chunk),
{ok, binary_to_term(Bin)};
E ->
- ?LOG_DEBUG("[edoc_chunk] load error", [E]),
+ ?LOG_WARNING("[edoc_chunk] load error: ~p", [E]),
error
end.
-else.
@@ -292,10 +334,12 @@ eep48_docs(_Type, _M, _F, _A) ->
| {'preprocess', 'true'}
].
edoc_options() ->
+ IncludePaths = els_config:get(include_paths) ++ els_config:get(otp_paths),
[
{preprocess, true},
+ % TODO: els_docs should not depend on els_compiler_diagnostics for config
{macros, [{N, V} || {'d', N, V} <- els_compiler_diagnostics:macro_options()]},
- {includes, [I || {i, I} <- els_compiler_diagnostics:include_options()]}
+ {includes, IncludePaths}
].
-spec specs(atom(), atom(), non_neg_integer()) ->
@@ -487,3 +531,17 @@ spawn_group_proxy(Acc) ->
M ->
spawn_group_proxy([M | Acc])
end.
+
+improper_filtermap(F, ImproperList) ->
+ improper_filtermap(F, ImproperList, []).
+improper_filtermap(_, [], Acc) ->
+ lists:reverse(Acc);
+improper_filtermap(F, [H | T], Acc) ->
+ case F(H) of
+ {true, Res} ->
+ improper_filtermap(F, T, [Res | Acc]);
+ _ ->
+ improper_filtermap(F, T, Acc)
+ end;
+improper_filtermap(F, Stop, Acc) ->
+ improper_filtermap(F, [Stop], Acc).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment