@@ -160,28 +160,45 @@ defmodule Mix.Tasks.Xref do
160160
161161 defp unreachable ( pair_fun ) do
162162 excludes = excludes ( )
163-
164163 each_source_entries ( & source_warnings ( & 1 , excludes ) , pair_fun )
165164 end
166165
167166 defp source_warnings ( source , excludes ) do
168167 source ( runtime_dispatches: runtime_dispatches ) = source
169168
170169 for { module , func_arity_lines } <- runtime_dispatches ,
170+ exports = load_exports ( module ) ,
171171 { { 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 ) ,
173173 do: warning
174174 end
175175
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
177192 cond do
178193 excluded? ( module , func , arity , excludes ) ->
179194 nil
180195 skip? ( module , func , arity ) ->
181196 nil
182- not Code . ensure_loaded? ( module ) ->
197+ exports == :unknown_module ->
183198 { 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 ->
185202 { Enum . sort ( lines ) , :unknown_function , module , func , arity }
186203 true ->
187204 nil
@@ -276,7 +293,7 @@ defmodule Mix.Tasks.Xref do
276293 defp source_calls_for_filter ( source , filter ) do
277294 runtime_dispatches = source ( source , :runtime_dispatches )
278295 compile_dispatches = source ( source , :compile_dispatches )
279- dispatches = Stream . concat ( runtime_dispatches , compile_dispatches )
296+ dispatches = runtime_dispatches ++ compile_dispatches
280297
281298 calls =
282299 for { module , func_arity_lines } <- dispatches ,
0 commit comments