daily pastebin goal
39%
SHARE
TWEET

Untitled

a guest Nov 22nd, 2018 81 Never
Upgrade to PRO!
ENDING IN00days00hours00mins00secs
 
  1. -module(plt_cache_server).
  2. -behaviour(gen_server).
  3.  
  4. %%%
  5. %%% Exports
  6. %%%
  7.  
  8. %%
  9. %% API
  10. %%
  11.  
  12. -export([ start_link/1
  13.         , load/1
  14.         , update/0
  15.         , apply/1
  16.         ]).
  17.  
  18. %%
  19. %% gen_server callbacks
  20. %%
  21. -export([ init/1
  22.         , code_change/3
  23.         , handle_call/3
  24.         , handle_cast/2
  25.         , handle_info/2
  26.         , terminate/2
  27.         ]).
  28.  
  29. %%%
  30. %%% Defines
  31. %%%
  32.  
  33. -record(state, {plt, ets, file}).
  34.  
  35. %%%
  36. %%% API
  37. %%%
  38.  
  39. -spec start_link([{file, Path::string()}] | []) -> ok.
  40. start_link(Args) ->
  41.   Name = proplists:get_value(name, Args, ?MODULE),
  42.   gen_server:start_link({local, Name}, ?MODULE, Args, []).
  43.  
  44. %%
  45. %% Load a specified Plt file.
  46. %%
  47. -spec load(Path::string()) -> ok.
  48. load(File) ->
  49.   gen_server:call(?MODULE, {load, File}).
  50.  
  51. %%
  52. %% Update all info from the currently loaded file
  53. %%
  54. -spec update() -> ok.
  55. update() ->
  56.   gen_server:call(?MODULE, update).
  57.  
  58. %%
  59. %% Apply a specified function. Plt will be prepended to the list of arguments
  60. %%
  61. -spec apply({Module::atom(), Func::atom(), Args::list()}) -> any().
  62. apply(MFA) ->
  63.   gen_server:call(?MODULE, {apply, MFA}).
  64.  
  65.  
  66. %%%
  67. %%% Callbacks
  68. %%%
  69.  
  70. init(Args) ->
  71.   Plt = case proplists:lookup(file, Args) of
  72.           undefined -> [];
  73.           {_, File} -> dialyzer_plt:from_file(File)
  74.         end,
  75.   Ets = create_and_update_ets(Plt),
  76.   {ok, #state{plt = Plt, ets = Ets}}.
  77.  
  78. handle_call({load, File}, _From, #state{ets=Ets0}) ->
  79.   Plt  = dialyzer_plt:from_file(File),
  80.   Ets1 = ets:delete_all_objects(Ets0),
  81.   Ets  = update_ets(Ets1, Plt),
  82.   {reply, ok, #state{ets=Ets, plt=Plt, file=File}};
  83.  
  84. handle_call(update, _From, #state{ets=Ets0, file=File}) ->
  85.   Plt  = dialyzer_plt:from_file(File),
  86.   Ets1 = ets:delete_all_objects(Ets0),
  87.   Ets  = update_ets(Ets1, Plt),
  88.   {reply, ok, #state{ets=Ets, plt=Plt}};
  89.  
  90. handle_call({apply, {M, F, A}}, _From, #state{plt=Plt} = State) ->
  91.   {reply, erlang:apply(M, F, [Plt | A]), State}.
  92.  
  93. handle_cast(_, State) ->
  94.   {noreply, State}.
  95.  
  96. handle_info(_, State) ->
  97.   {noreply, State}.
  98.  
  99. code_change(_, State, _) ->
  100.   {ok, State}.
  101.  
  102. terminate(shutdown, #state{ets=Ets}) ->
  103.   ets:delete(Ets),
  104.   ok.
  105.  
  106. %%%
  107. %%% Internal
  108. %%%
  109.  
  110. create_and_update_ets(Plt) ->
  111.   Ets = ets:new(?MODULE, [ ordered_set
  112.                          , public
  113.                          , {write_concurrency,true}
  114.                          , {read_concurrency,true}]),
  115.   update_ets(Ets, Plt).
  116.  
  117. update_ets(Ets0, Plt) ->
  118.   Modules = sets:to_list(dialyzer_plt:all_modules(Plt)),
  119.   MFAList = get_mfas(Modules, Plt),
  120.   Ets = ets:insert(Ets0, MFAList),
  121.   Ets.
  122.  
  123. get_mfas(Modules, Plt) -> get_mfas(Modules, Plt, []).
  124.  
  125. get_mfas([], _, Acc)     ->
  126.   Acc;
  127. get_mfas([H|T], Plt, Acc0) ->
  128.   {value, MFATypes} = dialyzer_plt:lookup_module(Plt,H),
  129.   Acc1 = mfa_from_types(MFATypes, Acc0),
  130.   get_mfas(T, Plt, Acc1).
  131.  
  132. mfa_from_types([], Acc)                -> Acc;
  133. mfa_from_types([{MFA, _, _} | T], Acc) -> mfa_from_types(T, [MFA | Acc]).
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top