| 
1 | 1 | %% Module responsible for tracking invocations of module calls.  | 
2 | 2 | -module(elixir_locals).  | 
3 | 3 | -export([  | 
4 |  | -  setup/1, stop/1, cache_env/1, get_cached_env/1,  | 
5 |  | -  record_local/5, record_import/4, record_defaults/5,  | 
6 |  | -  yank/2, reattach/6, ensure_no_import_conflict/3,  | 
 | 4 | +  setup/1, cache_env/1, get_cached_env/1,  | 
 | 5 | +  record_import/4,  | 
 | 6 | +  ensure_no_import_conflict/3,  | 
7 | 7 |   format_error/1  | 
8 | 8 | ]).  | 
9 | 9 | 
 
  | 
10 | 10 | -include("elixir.hrl").  | 
11 | 11 | -define(cache_key, {elixir, cache_env}).  | 
12 |  | --define(locals_key, {elixir, locals}).  | 
13 |  | --define(locals, 'Elixir.Module.LocalsTracker').  | 
14 | 12 | 
 
  | 
15 | 13 | setup({DataSet, _DataBag}) ->  | 
16 | 14 |   ets:insert(DataSet, {?cache_key, 0}),  | 
17 |  | - | 
18 |  | -  case elixir_config:is_bootstrap() of  | 
19 |  | -    false -> ets:insert(DataSet, {?locals_key, true});  | 
20 |  | -    true -> ok  | 
21 |  | -  end,  | 
22 |  | - | 
23 | 15 |   ok.  | 
24 | 16 | 
 
  | 
25 |  | -stop({DataSet, _DataBag}) ->  | 
26 |  | -  ets:delete(DataSet, ?locals_key).  | 
27 |  | - | 
28 |  | -yank(Tuple, Module) ->  | 
29 |  | -  if_tracker(Module, fun(Tracker) -> ?locals:yank(Tracker, Tuple) end).  | 
30 |  | - | 
31 |  | -reattach(Tuple, Kind, Module, Function, Neighbours, Meta) ->  | 
32 |  | -  if_tracker(Module, fun(Tracker) -> ?locals:reattach(Tracker, Tuple, Kind, Function, Neighbours, Meta) end).  | 
33 |  | - | 
34 |  | -record_local(_Tuple, _Module, nil, _Meta, _IsMacroDispatch) ->  | 
35 |  | -  ok;  | 
36 |  | -record_local(Tuple, Module, Function, Meta, IsMacroDispatch) ->  | 
37 |  | -  if_tracker(Module, fun(Tracker) -> ?locals:add_local(Tracker, Function, Tuple, Meta, IsMacroDispatch), ok end).  | 
38 |  | - | 
39 | 17 | record_import(_Tuple, Receiver, Module, Function)  | 
40 | 18 |   when Function == nil; Module == Receiver -> false;  | 
41 |  | -record_import(Tuple, Receiver, Module, Function) ->  | 
42 |  | -  if_tracker(Module, fun(Tracker) -> ?locals:add_import(Tracker, Function, Receiver, Tuple), ok end).  | 
43 |  | - | 
44 |  | -record_defaults(_Tuple, _Kind, _Module, 0, _Meta) ->  | 
45 |  | -  ok;  | 
46 |  | -record_defaults(Tuple, Kind, Module, Defaults, Meta) ->  | 
47 |  | -  if_tracker(Module, fun(Tracker) -> ?locals:add_defaults(Tracker, Kind, Tuple, Defaults, Meta), ok end).  | 
48 |  | - | 
49 |  | -if_tracker(Module, Callback) ->  | 
50 |  | -  if_tracker(Module, ok, Callback).  | 
51 |  | - | 
52 |  | -if_tracker(Module, Default, Callback) ->  | 
 | 19 | +record_import(Tuple, Receiver, Module, _Function) ->  | 
53 | 20 |   try  | 
54 |  | -    {DataSet, _} = Tables = elixir_module:data_tables(Module),  | 
55 |  | -    {ets:member(DataSet, ?locals_key), Tables}  | 
56 |  | -  of  | 
57 |  | -    {true, Tracker} -> Callback(Tracker);  | 
58 |  | -    {false, _} -> Default  | 
 | 21 | +    {Set, _Bag} = elixir_module:data_tables(Module),  | 
 | 22 | +    ets:insert(Set, {{import, Tuple}, Receiver}),  | 
 | 23 | +    true  | 
59 | 24 |   catch  | 
60 |  | -    error:badarg -> Default  | 
 | 25 | +    error:badarg -> false  | 
61 | 26 |   end.  | 
62 | 27 | 
 
  | 
63 | 28 | %% CACHING  | 
@@ -89,13 +54,16 @@ get_cached_env(Env) ->  | 
89 | 54 | 
 
  | 
90 | 55 | ensure_no_import_conflict('Elixir.Kernel', _All, _E) ->  | 
91 | 56 |   ok;  | 
92 |  | -ensure_no_import_conflict(Module, All, E) ->  | 
93 |  | -  if_tracker(Module, ok, fun(Tracker) ->  | 
94 |  | -    [elixir_errors:module_error(Meta, E, ?MODULE, {function_conflict, Error})  | 
95 |  | -     || {Meta, Error} <- ?locals:collect_imports_conflicts(Tracker, All)],  | 
96 |  | -    ok  | 
97 |  | -  end).  | 
 | 57 | +ensure_no_import_conflict(Module, AllDefinitions, E) ->  | 
 | 58 | +  {Set, _} = elixir_module:data_tables(Module),  | 
 | 59 | + | 
 | 60 | +  [try  | 
 | 61 | +     Receiver = ets:lookup_element(Set, {import, Pair}, 2),  | 
 | 62 | +     elixir_errors:module_error(Meta, E, ?MODULE, {import_conflict, Receiver, Pair})  | 
 | 63 | +   catch  | 
 | 64 | +    error:badarg -> false  | 
 | 65 | +   end || {Pair, _, Meta, _} <- AllDefinitions].  | 
98 | 66 | 
 
  | 
99 |  | -format_error({function_conflict, {Receiver, {Name, Arity}}}) ->  | 
 | 67 | +format_error({import_conflict, Receiver, {Name, Arity}}) ->  | 
100 | 68 |   io_lib:format("imported ~ts.~ts/~B conflicts with local function",  | 
101 | 69 |     [elixir_aliases:inspect(Receiver), Name, Arity]).  | 
0 commit comments