@@ -160,28 +160,45 @@ defmodule Mix.Tasks.Xref do
160
160
161
161
defp unreachable ( pair_fun ) do
162
162
excludes = excludes ( )
163
-
164
163
each_source_entries ( & source_warnings ( & 1 , excludes ) , pair_fun )
165
164
end
166
165
167
166
defp source_warnings ( source , excludes ) do
168
167
source ( runtime_dispatches: runtime_dispatches ) = source
169
168
170
169
for { module , func_arity_lines } <- runtime_dispatches ,
170
+ exports = load_exports ( module ) ,
171
171
{ { func , arity } , lines } <- func_arity_lines ,
172
- warning = unreachable_mfa ( module , func , arity , lines , excludes ) ,
172
+ warning = unreachable_mfa ( exports , module , func , arity , lines , excludes ) ,
173
173
do: warning
174
174
end
175
175
176
- defp unreachable_mfa ( module , func , arity , lines , excludes ) do
176
+ defp load_exports ( module ) do
177
+ if :code . is_loaded ( module ) do
178
+ # If the module is loaded, we will use the faster function_exported?/3 check
179
+ module
180
+ else
181
+ # Otherwise we get all exports from :beam_lib to avoid loading modules
182
+ with file when is_list ( file ) <- :code . which ( module ) ,
183
+ { :ok , { ^ module , [ exports: exports ] } } <- :beam_lib . chunks ( file , [ :exports ] ) do
184
+ exports
185
+ else
186
+ _ -> :unknown_module
187
+ end
188
+ end
189
+ end
190
+
191
+ defp unreachable_mfa ( exports , module , func , arity , lines , excludes ) do
177
192
cond do
178
193
excluded? ( module , func , arity , excludes ) ->
179
194
nil
180
195
skip? ( module , func , arity ) ->
181
196
nil
182
- not Code . ensure_loaded? ( module ) ->
197
+ exports == :unknown_module ->
183
198
{ Enum . sort ( lines ) , :unknown_module , module , func , arity }
184
- not function_exported? ( module , func , arity ) ->
199
+ is_atom ( exports ) and not function_exported? ( module , func , arity ) ->
200
+ { Enum . sort ( lines ) , :unknown_function , module , func , arity }
201
+ is_list ( exports ) and not { func , arity } in exports ->
185
202
{ Enum . sort ( lines ) , :unknown_function , module , func , arity }
186
203
true ->
187
204
nil
@@ -276,7 +293,7 @@ defmodule Mix.Tasks.Xref do
276
293
defp source_calls_for_filter ( source , filter ) do
277
294
runtime_dispatches = source ( source , :runtime_dispatches )
278
295
compile_dispatches = source ( source , :compile_dispatches )
279
- dispatches = Stream . concat ( runtime_dispatches , compile_dispatches )
296
+ dispatches = runtime_dispatches ++ compile_dispatches
280
297
281
298
calls =
282
299
for { module , func_arity_lines } <- dispatches ,
0 commit comments