From 6f51ea1677b0f508514a03352517e69de8ef9685 Mon Sep 17 00:00:00 2001 From: Roberto Aloi Date: Thu, 9 Jun 2022 12:24:54 +0200 Subject: [PATCH] Optimize unused includes detection by avoiding unnecessary work (#1322) While identifying unused includes, the current implementation performs a go-to-definition operation for all POIs within a document, even if all the .hrl candidates have already been excluded. This change stops the iteration as soon as no candidates are present. The whole detection algorithm could probably be revisited (it would be good to check if this problem has been tackled in literature), but for now this optimization will lower the execution time for "unused includes" diagnostics and reduce the stress on the language server, especially for big modules. As an example, this optimization reduces the computing time for "unused includes" diagnostics for the `els_parser.erl` module from ~1s to ~200ms. --- .../src/els_unused_includes_diagnostics.erl | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/apps/els_lsp/src/els_unused_includes_diagnostics.erl b/apps/els_lsp/src/els_unused_includes_diagnostics.erl index f9810d976..e29c142a0 100644 --- a/apps/els_lsp/src/els_unused_includes_diagnostics.erl +++ b/apps/els_lsp/src/els_unused_includes_diagnostics.erl @@ -86,28 +86,31 @@ find_unused_includes(#{uri := Uri} = Document) -> els_config:get(exclude_unused_includes) ), IncludedUris = IncludedUris1 -- ExcludeUnusedIncludes, - Fun = fun(POI, Acc) -> - update_unused(Graph, Uri, POI, Acc) - end, - UnusedIncludes = lists:foldl(Fun, IncludedUris, POIs), + UnusedIncludes = update_unused(IncludedUris, Graph, Uri, POIs), digraph:delete(Graph), UnusedIncludes. --spec update_unused(digraph:graph(), uri(), els_poi:poi(), [uri()]) -> [uri()]. -update_unused(Graph, Uri, POI, Acc) -> - case els_code_navigation:goto_definition(Uri, POI) of - {ok, Uri, _DefinitionPOI} -> - Acc; - {ok, DefinitionUri, _DefinitionPOI} -> - case digraph:get_path(Graph, DefinitionUri, Uri) of - false -> - Acc; - Path -> - Acc -- Path - end; - {error, _Reason} -> - Acc - end. +-spec update_unused([uri()], digraph:graph(), uri(), [els_poi:poi()]) -> [uri()]. +update_unused(Acc = [], _Graph, _Uri, _POIs) -> + Acc; +update_unused(Acc, _Graph, _Uri, _POIs = []) -> + Acc; +update_unused(Acc, Graph, Uri, [POI | POIs]) -> + NewAcc = + case els_code_navigation:goto_definition(Uri, POI) of + {ok, DefinitionUri, _DefinitionPOI} when DefinitionUri =:= Uri -> + Acc; + {ok, DefinitionUri, _DefinitionPOI} -> + case digraph:get_path(Graph, DefinitionUri, Uri) of + false -> + Acc; + Path -> + Acc -- Path + end; + {error, _Reason} -> + Acc + end, + update_unused(NewAcc, Graph, Uri, POIs). -spec expand_includes(els_dt_document:item()) -> digraph:graph(). expand_includes(Document) ->