Skip to content

Commit

Permalink
fix dap configuration and add function break points
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGeorge committed Feb 1, 2021
1 parent 0798e34 commit 4b475b0
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 3 deletions.
59 changes: 58 additions & 1 deletion src/els_dap_general_provider.erl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ init() ->

-spec handle_request(request(), state()) -> {result(), state()}.
handle_request({<<"initialize">>, _Params}, State) ->
%% quick fix to satisfy els_config initialization
{ok, RootPath} = file:get_cwd(),
RootUri = unicode:characters_to_binary(["file://", RootPath]),
InitOptions = #{},
ok = els_config:initialize(RootUri, capabilities(), InitOptions),
{capabilities(), State};
handle_request({<<"launch">>, Params}, State) ->
#{<<"cwd">> := Cwd} = Params,
Expand Down Expand Up @@ -138,6 +143,7 @@ handle_request( {<<"setBreakpoints">>, Params}
els_distribution_server:wait_connect_and_monitor(ProjectNode),

%% TODO: Keep a list of interpreted modules, not to re-interpret them
els_dap_rpc:no_break(ProjectNode),
els_dap_rpc:i(ProjectNode, Module),
[els_dap_rpc:break(ProjectNode, Module, Line) ||
#{<<"line">> := Line} <- SourceBreakpoints],
Expand All @@ -146,6 +152,34 @@ handle_request( {<<"setBreakpoints">>, Params}
{#{<<"breakpoints">> => Breakpoints}, State};
handle_request({<<"setExceptionBreakpoints">>, _Params}, State) ->
{#{}, State};
handle_request({<<"setFunctionBreakpoints">>, Params}
, #{project_node := ProjectNode} = State
) ->
FunctionBreakPoints = maps:get(<<"breakpoints">>, Params, []),
els_distribution_server:wait_connect_and_monitor(ProjectNode),

els_dap_rpc:no_break(ProjectNode),
MFAs = [
begin
Spec = {Mod, _, _} = parse_mfa(MFA),
els_dap_rpc:i(ProjectNode, Mod),
Spec
end
||
#{<<"name">> := MFA, <<"enabled">>:= Enabled} <- FunctionBreakPoints,
Enabled andalso parse_mfa(MFA) =/= error
],
[ els_dap_rpc:break_in(ProjectNode, Mod, Func, Arity)
|| {Mod, Func, Arity} <- MFAs
],
Breakpoints =
[ #{ <<"verified">> => true
, <<"line">> => Line
, <<"source">> => #{ <<"path">> => source(Module, ProjectNode)}}
|| {{Module, Line}, [Status, _, _, _]}
<- els_dap_rpc:all_breaks(ProjectNode)
, Status =:= active],
{#{<<"breakpoints">> => Breakpoints}, State};
handle_request({<<"threads">>, _Params}, #{threads := Threads0} = State) ->
Threads =
[ #{ <<"id">> => Id
Expand Down Expand Up @@ -256,7 +290,8 @@ handle_info( {int_cb, ThreadPid}
-spec capabilities() -> capabilities().
capabilities() ->
#{ <<"supportsConfigurationDoneRequest">> => true
, <<"supportsEvaluateForHovers">> => true }.
, <<"supportsEvaluateForHovers">> => true
, <<"supportsFunctionBreakpoints">> => true}.

%%==============================================================================
%% Internal Functions
Expand Down Expand Up @@ -316,3 +351,25 @@ frame_by_id(FrameId, Threads) ->
-spec format_mfa(module(), atom(), integer()) -> binary().
format_mfa(M, F, A) ->
els_utils:to_binary(io_lib:format("~p:~p/~p", [M, F, A])).

-spec parse_mfa(string()) -> {module(), atom(), non_neg_integer()} | error.
parse_mfa(MFABinary) ->
MFA = unicode:characters_to_list(MFABinary),
?LOG_DEBUG("tokens for ~p: ~w", [MFA, erl_scan:string(MFA)]),
case erl_scan:string(MFA) of
{ok, [ {'fun', _}
, {atom, _, Module}
, {':', _}
, {atom, _, Function}
, {'/', _}
, {integer, _, Arity}], _} when Arity >= 0 ->
{Module, Function, Arity};
{ok, [ {atom, _, Module}
, {':', _}
, {atom, _, Function}
, {'/', _}
, {integer, _, Arity}], _} when Arity >= 0 ->
{Module, Function, Arity};
_ ->
error
end.
18 changes: 17 additions & 1 deletion src/els_dap_rpc.erl
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
-module(els_dap_rpc).

-export([ auto_attach/3
-export([ all_breaks/1
, auto_attach/3
, break/3
, break_in/4
, continue/2
, eval/3
, get_meta/2
Expand All @@ -10,11 +12,17 @@
, meta/4
, module_info/3
, next/2
, no_break/1
, snapshot/1
, stack_trace/2
, step/2
]).


-spec all_breaks(node()) -> any().
all_breaks(Node) ->
rpc:call(Node, int, all_breaks, []).

-spec auto_attach(node(), [atom()], {module(), atom(), [any()]}) -> any().
auto_attach(Node, Flags, MFA) ->
rpc:call(Node, int, auto_attach, [Flags, MFA]).
Expand All @@ -23,6 +31,10 @@ auto_attach(Node, Flags, MFA) ->
break(Node, Module, Line) ->
rpc:call(Node, int, break, [Module, Line]).

-spec break_in(node(), module(), atom(), non_neg_integer()) -> any().
break_in(Node, Module, Func, Arity) ->
rpc:call(Node, int, break_in, [ Module, Func, Arity]).

-spec continue(node(), pid()) -> any().
continue(Node, Pid) ->
rpc:call(Node, int, continue, [Pid]).
Expand Down Expand Up @@ -57,6 +69,10 @@ meta(Node, Meta, Flag, Opt) ->
next(Node, Pid) ->
rpc:call(Node, int, next, [Pid]).

-spec no_break(node()) -> ok.
no_break(Node) ->
rpc:call(Node, int, no_break, []).

-spec module_info(node(), module(), atom()) -> any().
module_info(Node, Module, What) ->
rpc:call(Node, Module, module_info, [What]).
Expand Down
6 changes: 5 additions & 1 deletion src/els_dap_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ init([]) ->
?LOG_INFO("Starting session (version ~p)", [Vsn]),
%% Restrict access to stdio when using that transport
restrict_stdio_access(Transport),
ChildSpecs = [ #{ id => els_dap_providers_sup
ChildSpecs = [ #{ id => els_config
, start => {els_config, start_link, []}
, shutdown => brutal_kill
}
, #{ id => els_dap_providers_sup
, start => {els_dap_providers_sup, start_link, []}
, type => supervisor
}
Expand Down

0 comments on commit 4b475b0

Please sign in to comment.