@@ -165,14 +165,23 @@ defmodule Mix.Tasks.Xref do
165
165
## Modes
166
166
167
167
defp warnings ( opts ) do
168
- warnings ( & print_warnings / 1 , opts )
168
+ warnings =
169
+ source_warnings ( excludes ( ) , opts )
170
+ |> merge_entries ( )
171
+ |> sort_entries ( )
172
+ |> print_warnings ( )
173
+
174
+ { :ok , warnings }
169
175
end
170
176
171
177
defp unreachable ( opts ) do
172
- case warnings ( & print_unreachables / 1 , opts ) do
173
- { :ok , [ ] } -> :ok
174
- _ -> :error
175
- end
178
+ unreachable =
179
+ source_unreachable ( excludes ( ) , opts )
180
+ |> merge_entries ( )
181
+ |> sort_entries ( )
182
+ |> print_unreachables ( )
183
+
184
+ if unreachable == [ ] , do: :ok , else: :error
176
185
end
177
186
178
187
defp callers ( callee , opts ) do
@@ -256,24 +265,18 @@ defmodule Mix.Tasks.Xref do
256
265
257
266
## Warnings
258
267
259
- defp warnings ( print_warnings , opts ) do
260
- case source_warnings ( excludes ( ) , opts ) do
261
- [ ] ->
262
- { :ok , [ ] }
268
+ defp source_warnings ( excludes , opts ) do
269
+ sources = sources ( opts )
263
270
264
- entries ->
265
- entries =
266
- entries
267
- |> merge_entries ( )
268
- |> sort_entries ( )
269
- |> print_warnings . ( )
271
+ filter_unreachable ( sources , excludes ) ++ filter_deprecated ( sources , excludes )
272
+ end
270
273
271
- { :ok , entries }
272
- end
274
+ defp source_unreachable ( excludes , opts ) do
275
+ sources ( opts ) |> filter_unreachable ( excludes )
273
276
end
274
277
275
- defp source_warnings ( excludes , opts ) do
276
- Enum . flat_map ( sources ( opts ) , fn source ->
278
+ defp filter_unreachable ( sources , excludes ) do
279
+ Enum . flat_map ( sources , fn source ->
277
280
file = source ( source , :source )
278
281
runtime_dispatches = source ( source , :runtime_dispatches )
279
282
@@ -285,6 +288,23 @@ defmodule Mix.Tasks.Xref do
285
288
end )
286
289
end
287
290
291
+ defp filter_deprecated ( sources , excludes ) do
292
+ callers = filter_callers ( sources , fn _ -> true end )
293
+
294
+ called_modules = for { { module , function , arity } , location } <- callers , uniq: true , do: module
295
+
296
+ deprecated =
297
+ for module <- called_modules ,
298
+ { { function , arity } , reason } <- load_deprecated ( module ) ,
299
+ into: % { } ,
300
+ do: { { module , function , arity } , reason }
301
+
302
+ for { mfa , locations } <- callers ,
303
+ reason = deprecated [ mfa ] ,
304
+ { module , function , arity } = mfa ,
305
+ do: { { :deprecated , module , function , arity , reason } , locations }
306
+ end
307
+
288
308
defp load_exports ( module ) do
289
309
if :code . is_loaded ( module ) do
290
310
# If the module is loaded, we will use the faster function_exported?/3 check
@@ -300,6 +320,26 @@ defmodule Mix.Tasks.Xref do
300
320
end
301
321
end
302
322
323
+ defp load_deprecated ( module ) do
324
+ if :code . is_loaded ( module ) do
325
+ # If the module is loaded, we will use __info__
326
+ if function_exported? ( module , :__info__ , 1 ) do
327
+ module . __info__ ( :deprecated )
328
+ else
329
+ [ ]
330
+ end
331
+ else
332
+ # Otherwise we get the ExDp chunk using :beam_lib to avoid loading modules
333
+ with [ _ | _ ] = file <- :code . which ( module ) ,
334
+ { :ok , { ^ module , [ { 'ExDp' , deprecated_bin } ] } } <- :beam_lib . chunks ( file , [ 'ExDp' ] ) ,
335
+ { :elixir_deprecated_v1 , deprecated } = :erlang . binary_to_term ( deprecated_bin ) do
336
+ deprecated
337
+ else
338
+ _ -> [ ]
339
+ end
340
+ end
341
+ end
342
+
303
343
defp unreachable_mfa ( exports , module , func , arity , excludes ) do
304
344
cond do
305
345
excluded? ( module , func , arity , excludes ) ->
@@ -364,6 +404,16 @@ defmodule Mix.Tasks.Xref do
364
404
]
365
405
end
366
406
407
+ defp warning_message ( { :deprecated , module , function , arity , reason } ) do
408
+ [
409
+ "function " ,
410
+ Exception . format_mfa ( module , function , arity ) ,
411
+ " is deprecated. " ,
412
+ reason ,
413
+ "."
414
+ ]
415
+ end
416
+
367
417
defp format_locations ( [ location ] ) do
368
418
format_location ( location )
369
419
end
@@ -414,7 +464,11 @@ defmodule Mix.Tasks.Xref do
414
464
## Callers
415
465
416
466
defp source_callers ( filter , opts ) do
417
- Enum . flat_map ( sources ( opts ) , fn source ->
467
+ sources ( opts ) |> filter_callers ( filter )
468
+ end
469
+
470
+ defp filter_callers ( sources , filter ) do
471
+ Enum . flat_map ( sources , fn source ->
418
472
file = source ( source , :source )
419
473
runtime_dispatches = source ( source , :runtime_dispatches )
420
474
compile_dispatches = source ( source , :compile_dispatches )
0 commit comments