Guest User

Untitled

a guest
Nov 22nd, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.79 KB | None | 0 0
  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]).
Add Comment
Please, Sign In to add comment