Skip to content

Commit

Permalink
[#22] Add support for record navigation (same module)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertoaloi committed Jul 28, 2019
1 parent af3bddf commit 064de46
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 17 deletions.
8 changes: 3 additions & 5 deletions src/erlang_ls_buffer.erl
Expand Up @@ -61,7 +61,7 @@ get_mfa(Pid, Line, Char) ->
gen_server:call(Pid, {get_mfa, Line, Char}).

-spec get_element_at_pos(pid(), non_neg_integer(), non_neg_integer()) ->
any().
[any()].
get_element_at_pos(Pid, Line, Char) ->
gen_server:call(Pid, {get_element_at_pos, Line, Char}).

Expand Down Expand Up @@ -140,14 +140,12 @@ do_get_mfa(Text, Line, _Character) ->
{M, F, A}.

-spec do_get_element_at_pos(binary(), non_neg_integer(), non_neg_integer()) ->
erlang_ls_parser:poi().
[erlang_ls_parser:poi()].
do_get_element_at_pos(Text, Line, Column) ->
%% TODO: Cache tree
{ok, Tree} = erlang_ls_parser:parse(Text),
AnnotatedTree = erlang_ls_parser:annotate(Tree),
%% TODO: Refine API to handle multiple, overlapping, POIs
[POI] = erlang_ls_parser:find_poi_by_pos(AnnotatedTree, {Line, Column}),
POI.
erlang_ls_parser:find_poi_by_pos(AnnotatedTree, {Line, Column}).

-spec get_line_text(binary(), integer()) -> binary().
get_line_text(Text, Line) ->
Expand Down
7 changes: 7 additions & 0 deletions src/erlang_ls_parser.erl
Expand Up @@ -119,6 +119,11 @@ get_range(_Tree, {Line, Column}, {record_expr, Record}) ->
From = {Line, Column - 1},
To = {Line, Column + length(Record) - 1},
#{ from => From, to => To };
%% TODO: Distinguish between usage poi and definition poi
get_range(_Tree, {Line, _Column}, {record, _Record}) ->
From = {Line - 1, 0},
To = From,
#{ from => From, to => To };
get_range(_Tree, {_Line, _Column}, {spec, _Spec}) ->
%% TODO: The location information for the arity qualifiers are lost during
%% parsing in `epp_dodger`. This requires fixing.
Expand Down Expand Up @@ -211,6 +216,8 @@ analyze(Tree, attribute) ->
_ ->
[]
end;
{record, {Record, _Fields}} ->
[poi(Tree, {record, atom_to_list(Record)})];
{spec, Spec} ->
[poi(Tree, {spec, Spec})];
_ ->
Expand Down
47 changes: 36 additions & 11 deletions src/erlang_ls_server.erl
Expand Up @@ -180,9 +180,12 @@ handle_method(<<"textDocument/definition">>, Params) ->
TextDocument = maps:get(<<"textDocument">>, Params),
Uri = maps:get(<<"uri">> , TextDocument),
{ok, Buffer} = erlang_ls_buffer_server:get_buffer(Uri),
POI = erlang_ls_buffer:get_element_at_pos(Buffer, Line + 1, Character + 1),
Result = definition(Uri, POI),
{response, Result};
case erlang_ls_buffer:get_element_at_pos(Buffer, Line + 1, Character + 1) of
[POI|_] ->
{response, definition(Uri, POI)};
[] ->
{response, null}
end;
handle_method(Method, _Params) ->
lager:warning("[Method not implemented] [method=~s]", [Method]),
Message = <<"Method not implemented: ", Method/binary>>,
Expand Down Expand Up @@ -217,7 +220,7 @@ definition(_Uri, #{ info := {application, {M, F, A}} }) ->
null
end;
definition(Uri, #{ info := {application, {F, A}} }) ->
M = binary_to_atom(filename:basename(erlang_ls_uri:path(Uri), ".erl"), utf8),
M = erlang_ls_uri:module(Uri),
case annotated_tree(M) of
{ok, Uri, AnnotatedTree} ->
%% TODO: Abstract this mapping in a function
Expand Down Expand Up @@ -245,17 +248,21 @@ definition(_Uri, #{ info := {behaviour, Behaviour} }) ->
};
{error, _Error} ->
null
end.
end;
definition(Uri, #{ info := {record_expr, Record} }) ->
search_record(Uri, Record);
definition(_Uri, _) ->
null.

-spec annotated_tree(atom()) ->
{ok, uri(), erlang_ls_parser:syntax_tree()} | {error, any()}.
annotated_tree(Module) ->
%% TODO: Check whether URI is already cached
Path = lists:append( [ otp_path()
, app_path()
, deps_path()
]),
%% TODO: Cache syntax tree here?
Path = lists:append( [ app_path() , deps_path() , otp_path() ]),
annotated_tree(Module, Path).

-spec annotated_tree(atom(), [string()]) ->
{ok, uri(), erlang_ls_parser:syntax_tree()} | {error, any()}.
annotated_tree(Module, Path) ->
case file:path_open(Path, atom_to_list(Module) ++ ".erl", [read]) of
{ok, IoDevice, FullName} ->
%% TODO: Avoid opening file twice
Expand All @@ -278,3 +285,21 @@ app_path() ->
-spec deps_path() -> [string()].
deps_path() ->
filelib:wildcard(filename:join([?DEPS_PATH, "*/src"])).

-spec search_record(uri(), atom()) -> null | map().
search_record(Uri, Record) ->
Module = erlang_ls_uri:module(Uri),
case annotated_tree(Module) of
{ok, Uri, AnnotatedTree} ->
Info = {record, Record},
case erlang_ls_parser:find_poi_by_info(AnnotatedTree, Info) of
[#{ range := Range }|_] ->
#{ uri => Uri
, range => erlang_ls_protocol:range(Range)
};
[] ->
null
end;
{error, _Error} ->
null
end.
7 changes: 6 additions & 1 deletion src/erlang_ls_uri.erl
Expand Up @@ -8,7 +8,8 @@
%%==============================================================================
%% Exports
%%==============================================================================
-export([ path/1
-export([ module/1
, path/1
, uri/1
]).

Expand All @@ -17,6 +18,10 @@
%%==============================================================================
-include("erlang_ls.hrl").

-spec module(uri()) -> atom().
module(Uri) ->
binary_to_atom(filename:basename(erlang_ls_uri:path(Uri), ".erl"), utf8).

-spec path(uri()) -> uri_path().
path(<<"file://", Path/binary>>) ->
Path.
Expand Down

0 comments on commit 064de46

Please sign in to comment.