Skip to content

Commit

Permalink
Merge pull request #61 from erlang-ls/60-erlang-configuration-file
Browse files Browse the repository at this point in the history
[#60] Add support for `erlang_ls.config` file
  • Loading branch information
robertoaloi committed Sep 20, 2019
2 parents c4dceeb + bf893be commit 3f7b6cc
Show file tree
Hide file tree
Showing 16 changed files with 239 additions and 144 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,24 @@ Code completion is available for the following elements:
* Atom names
* Module attributes

## Customization

It is possible to customize the behaviour of the `erlang_ls` server by
adding a `erlang_ls.config` file to the root of your projects.

A sample `erlang_ls.config` file would look like the following:

otp_path: "/path/to/otp/lib/erlang"
deps_dirs:
- "lib/*"

Currently, the following customizations are possible:

| Parameter | Description |
|------------|---------------------------------------------------------------------|
| otp\_path | Path to the OTP installation |
| deps\_dirs | List of directories containing dependencies. It supports wildcards. |

## Troubleshooting

It is possible to compile and start the language server in _debug mode_:
Expand Down
14 changes: 4 additions & 10 deletions include/erlang_ls.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@
%% Language Server Protocol
%%==============================================================================

%%------------------------------------------------------------------------------
%% URI
%%------------------------------------------------------------------------------
-type uri() :: binary().
-type uri_path() :: binary().

%%------------------------------------------------------------------------------
%% Position
%%------------------------------------------------------------------------------
Expand Down Expand Up @@ -156,12 +150,12 @@
%%------------------------------------------------------------------------------
%% Text Document Identifier
%%------------------------------------------------------------------------------
-type text_document_id() :: #{ uri := uri() }.
-type text_document_id() :: #{ uri := erlang_ls_uri:uri() }.

%%------------------------------------------------------------------------------
%% Text Document Item
%%------------------------------------------------------------------------------
-type text_document_item() :: #{ uri := uri()
-type text_document_item() :: #{ uri := erlang_ls_uri:uri()
, languageId := binary()
, version := number()
, text := binary()
Expand Down Expand Up @@ -210,7 +204,7 @@
%%------------------------------------------------------------------------------
%% Initialize Request
%%------------------------------------------------------------------------------
-type workspace_folder() :: #{ uri => uri()
-type workspace_folder() :: #{ uri => erlang_ls_uri:uri()
, name => binary()
}.

Expand All @@ -225,7 +219,7 @@

-type initialize_params() :: #{ processId := number() | null
, rootPath => binary() | null
, rootUri := uri() | null
, rootUri := erlang_ls_uri:uri() | null
, initializationOptions => any()
, capabilities := client_capabilities()
, trace => off
Expand Down
1 change: 1 addition & 0 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
, {cowlib, "2.3.0"}
, {redbug, "1.2.1"}
, {lager, "3.6.8"}
, {yamerl, "0.7.0"}
]
}.

Expand Down
6 changes: 4 additions & 2 deletions rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
{<<"jsx">>,{pkg,<<"jsx">>,<<"2.9.0">>},0},
{<<"lager">>,{pkg,<<"lager">>,<<"3.6.8">>},0},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.5.0">>},0},
{<<"redbug">>,{pkg,<<"redbug">>,<<"1.2.1">>},0}]}.
{<<"redbug">>,{pkg,<<"redbug">>,<<"1.2.1">>},0},
{<<"yamerl">>,{pkg,<<"yamerl">>,<<"0.7.0">>},0}]}.
[
{pkg_hash,[
{<<"cowlib">>, <<"BBD58EF537904E4F7C1DD62E6AA8BC831C8183CE4EFA9BD1150164FE15BE4CAA">>},
{<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>},
{<<"jsx">>, <<"D2F6E5F069C00266CAD52FB15D87C428579EA4D7D73A33669E12679E203329DD">>},
{<<"lager">>, <<"897EFC7679BB82383448646C96768CDC4E747464DD18B999C7AACA485686B0DA">>},
{<<"ranch">>, <<"F04166F456790FEE2AC1AA05A02745CC75783C2BFB26D39FAF6AEFC9A3D3A58A">>},
{<<"redbug">>, <<"9153EE50E42C39CE3F6EFA65EE746F4A52896DA66862CFB59E7C0F838B7B8414">>}]}
{<<"redbug">>, <<"9153EE50E42C39CE3F6EFA65EE746F4A52896DA66862CFB59E7C0F838B7B8414">>},
{<<"yamerl">>, <<"E51DBA652DCE74C20A88294130B48051EBBBB0BE7D76F22DE064F0F3CCF0AAF5">>}]}
].
1 change: 1 addition & 0 deletions src/erlang_ls.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
, jsx
, cowlib
, lager
, yamerl
]},
{env,[]},
{modules, []},
Expand Down
47 changes: 41 additions & 6 deletions src/erlang_ls_buffer_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
-export([ start_link/0
, add_buffer/2
, get_buffer/1
, get_deps_dirs/0
, get_otp_path/0
, get_root_uri/0
, remove_buffer/1
, set_deps_dirs/1
, set_otp_path/1
, set_root_uri/1
, stop/0
]).
Expand All @@ -43,13 +47,18 @@
%%==============================================================================
%% Record Definitions
%%==============================================================================
-record(state, { buffers, root_uri }).
-record(state, { buffers
, deps_dirs = []
, root_uri
, otp_path
}).

%%==============================================================================
%% Type Definitions
%%==============================================================================
-type state() :: #state{}.
-type buffer() :: pid().
-type path() :: file:filename().

%%%=============================================================================
%%% API
Expand All @@ -58,23 +67,39 @@
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, {}, []).

-spec add_buffer(uri(), buffer()) -> ok.
-spec add_buffer(erlang_ls_uri:uri(), buffer()) -> ok.
add_buffer(Uri, Buffer) ->
gen_server:call(?SERVER, {add_buffer, Uri, Buffer}).

-spec get_buffer(uri()) -> {ok, buffer() | undefined}.
-spec get_buffer(erlang_ls_uri:uri()) -> {ok, buffer() | undefined}.
get_buffer(Uri) ->
gen_server:call(?SERVER, {get_buffer, Uri}).

-spec get_root_uri() -> {ok, uri() | undefined}.
-spec get_deps_dirs() -> {ok, [path()]}.
get_deps_dirs() ->
gen_server:call(?SERVER, {get_deps_dirs}).

-spec get_otp_path() -> {ok, path() | undefined}.
get_otp_path() ->
gen_server:call(?SERVER, {get_otp_path}).

-spec get_root_uri() -> {ok, erlang_ls_uri:uri() | undefined}.
get_root_uri() ->
gen_server:call(?SERVER, {get_root_uri}).

-spec remove_buffer(uri()) -> ok.
-spec remove_buffer(erlang_ls_uri:uri()) -> ok.
remove_buffer(Uri) ->
gen_server:call(?SERVER, {remove_buffer, Uri}).

-spec set_root_uri(uri()) -> ok.
-spec set_deps_dirs([erlang_ls_uri:path()]) -> ok.
set_deps_dirs(DepsDirs) ->
gen_server:call(?SERVER, {set_deps_dirs, DepsDirs}).

-spec set_otp_path(erlang_ls_uri:uri()) -> ok.
set_otp_path(Uri) ->
gen_server:call(?SERVER, {set_otp_path, Uri}).

-spec set_root_uri(erlang_ls_uri:uri()) -> ok.
set_root_uri(Uri) ->
gen_server:call(?SERVER, {set_root_uri, Uri}).

Expand All @@ -95,12 +120,22 @@ handle_call({add_buffer, Uri, Buffer}, _From, State) ->
handle_call({get_buffer, Uri}, _From, State) ->
Buffer = proplists:get_value(Uri, State#state.buffers),
{reply, {ok, Buffer}, State};
handle_call({get_deps_dirs}, _From, State) ->
DepsDirs = State#state.deps_dirs,
{reply, {ok, DepsDirs}, State};
handle_call({get_otp_path}, _From, State) ->
OtpPath = State#state.otp_path,
{reply, {ok, OtpPath}, State};
handle_call({get_root_uri}, _From, State) ->
RootUri = State#state.root_uri,
{reply, {ok, RootUri}, State};
handle_call({remove_buffer, Uri}, _From, State) ->
Buffers = proplists:delete(Uri, State#state.buffers),
{reply, ok, State#state{buffers = Buffers}};
handle_call({set_deps_dirs, DepsDirs}, _From, State) ->
{reply, ok, State#state{deps_dirs = DepsDirs}};
handle_call({set_otp_path, Path}, _From, State) ->
{reply, ok, State#state{otp_path = Path}};
handle_call({set_root_uri, Uri}, _From, State) ->
{reply, ok, State#state{root_uri = Uri}}.

Expand Down
32 changes: 18 additions & 14 deletions src/erlang_ls_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
-export([ did_open/4
, did_save/1
, did_close/1
, initialize/1
, initialize/2
, start_link/2
, stop/0
]).
Expand Down Expand Up @@ -51,28 +51,29 @@
%%==============================================================================
%% Type Definitions
%%==============================================================================
-type state() :: #state{}.
-type hostname() :: tuple().
-type port_no() :: pos_integer().
-type state() :: #state{}.
-type hostname() :: tuple().
-type port_no() :: pos_integer().
-type init_options() :: [].

%%==============================================================================
%% API
%%==============================================================================
-spec did_open(uri(), binary(), number(), binary()) -> ok.
-spec did_open(erlang_ls_uri:uri(), binary(), number(), binary()) -> ok.
did_open(Uri, LanguageId, Version, Text) ->
gen_server:call(?SERVER, {did_open, Uri, LanguageId, Version, Text}).

-spec did_save(uri()) -> ok.
-spec did_save(erlang_ls_uri:uri()) -> ok.
did_save(Uri) ->
gen_server:call(?SERVER, {did_save, Uri}).

-spec did_close(uri()) -> ok.
-spec did_close(erlang_ls_uri:uri()) -> ok.
did_close(Uri) ->
gen_server:call(?SERVER, {did_close, Uri}).

-spec initialize(uri()) -> ok.
initialize(RootUri) ->
gen_server:call(?SERVER, {initialize, RootUri}).
-spec initialize(erlang_ls_uri:uri(), init_options()) -> ok.
initialize(RootUri, InitOptions) ->
gen_server:call(?SERVER, {initialize, RootUri, InitOptions}).

-spec start_link(hostname(), port_no()) -> {ok, pid()}.
start_link(Host, Port) ->
Expand Down Expand Up @@ -117,11 +118,14 @@ handle_call({did_close, Uri}, _From, State) ->
Content = erlang_ls_protocol:notification(Method, Params),
ok = gen_tcp:send(State#state.socket, Content),
{reply, ok, State};
handle_call({initialize, RootUri}, From, #state{ request_id = RequestId
, socket = Socket
} = State) ->
handle_call({initialize, RootUri, InitOptions}, From, State) ->
#state{ request_id = RequestId
, socket = Socket
} = State,
Method = <<"initialize">>,
Params = #{ <<"rootUri">> => RootUri },
Params = #{ <<"rootUri">> => RootUri
, <<"initializationOptions">> => InitOptions
},
Content = erlang_ls_protocol:request(RequestId, Method, Params),
gen_tcp:send(Socket, Content),
{noreply, State#state{ request_id = RequestId + 1
Expand Down
32 changes: 21 additions & 11 deletions src/erlang_ls_code_navigation.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@
%%==============================================================================

%% API
-export([ goto_definition/2
, goto_definition/3
]).

-export([ otp_path/0
]).
-export([ goto_definition/2 ]).

%%==============================================================================
%% Includes
Expand All @@ -27,7 +22,7 @@
-spec goto_definition(binary(), erlang_ls_poi:poi()) ->
{ok, binary(), erlang_ls_poi:range()} | {error, any()}.
goto_definition(Filename, POI) ->
goto_definition(Filename, POI, full_path()).
goto_definition(Filename, POI, include_path()).

%% TODO: Abstract pattern
-spec goto_definition(binary(), erlang_ls_poi:poi(), [string()]) ->
Expand Down Expand Up @@ -125,7 +120,7 @@ definition({type_application, {Type, _}}) ->

-spec otp_path() -> [string()].
otp_path() ->
Root = code:root_dir(),
{ok, Root} = erlang_ls_buffer_server:get_otp_path(),
Sources = filename:join([Root, "lib", "*", "src"]),
Includes = filename:join([Root, "lib", "*", "include"]),
lists:append([ filelib:wildcard(Sources)
Expand All @@ -140,9 +135,24 @@ app_path() ->
, filename:join([RootPath, "include"])
].

-spec full_path() -> [string()].
full_path() ->
lists:append( [ app_path(), otp_path() ]).
-spec deps_path() -> [string()].
deps_path() ->
{ok, RootUri} = erlang_ls_buffer_server:get_root_uri(),
RootPath = binary_to_list(erlang_ls_uri:path(RootUri)),
{ok, Dirs} = erlang_ls_buffer_server:get_deps_dirs(),
lists:foldl(fun(Dir, Acc) ->
Sources = filename:join([RootPath, Dir, "src"]),
Includes = filename:join([RootPath, Dir, "include"]),
lists:append([ filelib:wildcard(Sources)
, filelib:wildcard(Includes)
, Acc
])
end
, [], Dirs).

-spec include_path() -> [string()].
include_path() ->
lists:append( [ app_path(), otp_path(), deps_path() ]).

%% Look for a definition recursively in a file and its includes.
-spec search(binary(), [string()], any()) ->
Expand Down
2 changes: 1 addition & 1 deletion src/erlang_ls_compiler_diagnostics.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
%%==============================================================================
%% Callback Functions
%%==============================================================================
-spec diagnostics(uri()) -> [diagnostic()].
-spec diagnostics(erlang_ls_uri:uri()) -> [diagnostic()].
diagnostics(Uri) ->
Path = erlang_ls_uri:path(Uri),
case compile:file(binary_to_list(Path), ?COMPILER_OPTS) of
Expand Down
2 changes: 1 addition & 1 deletion src/erlang_ls_diagnostics.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
%%==============================================================================
%% Callback Functions Definitions
%%==============================================================================
-callback diagnostics(uri()) -> [diagnostic()].
-callback diagnostics(erlang_ls_uri:uri()) -> [diagnostic()].
2 changes: 1 addition & 1 deletion src/erlang_ls_dialyzer_diagnostics.erl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
%%==============================================================================
%% Callback Functions
%%==============================================================================
-spec diagnostics(uri()) -> [diagnostic()].
-spec diagnostics(erlang_ls_uri:uri()) -> [diagnostic()].
diagnostics(Uri) ->
Path = erlang_ls_uri:path(Uri),
WS = try dialyzer:run([{files, [binary_to_list(Path)]}, {from, src_code}])
Expand Down
Loading

0 comments on commit 3f7b6cc

Please sign in to comment.