@@ -244,9 +244,9 @@ defmodule Mix.Tasks.Format do
244
244
end
245
245
246
246
{ formatter_opts_and_subs , _sources } =
247
- eval_deps_and_subdirectories ( cwd , dot_formatter , formatter_opts , [ dot_formatter ] )
247
+ eval_deps_and_subdirectories ( cwd , dot_formatter , formatter_opts , [ dot_formatter ] , opts )
248
248
249
- formatter_opts_and_subs = load_plugins ( formatter_opts_and_subs )
249
+ formatter_opts_and_subs = load_plugins ( formatter_opts_and_subs , opts )
250
250
files = expand_args ( args , cwd , dot_formatter , formatter_opts_and_subs , opts )
251
251
252
252
maybe_cache_timestamps ( all_args , files , fn files ->
@@ -290,20 +290,19 @@ defmodule Mix.Tasks.Format do
290
290
291
291
defp maybe_cache_timestamps ( [ _ | _ ] , files , fun ) , do: fun . ( files )
292
292
293
- defp load_plugins ( { formatter_opts , subs } ) do
293
+ defp load_plugins ( { formatter_opts , subs } , opts ) do
294
294
plugins = Keyword . get ( formatter_opts , :plugins , [ ] )
295
295
296
296
if not is_list ( plugins ) do
297
297
Mix . raise ( "Expected :plugins to return a list of modules, got: #{ inspect ( plugins ) } " )
298
298
end
299
299
300
- if plugins != [ ] do
301
- Mix.Task . run ( "loadpaths" , [ ] )
302
- end
303
-
304
- if not Enum . all? ( plugins , & Code . ensure_loaded? / 1 ) do
305
- Mix.Task . run ( "compile" , [ ] )
306
- end
300
+ plugins =
301
+ if plugins != [ ] do
302
+ Keyword . get ( opts , :plugin_loader , & plugin_loader / 1 ) . ( plugins )
303
+ else
304
+ [ ]
305
+ end
307
306
308
307
for plugin <- plugins do
309
308
cond do
@@ -336,7 +335,21 @@ defmodule Mix.Tasks.Format do
336
335
end )
337
336
338
337
{ Keyword . put ( formatter_opts , :sigils , sigils ) ,
339
- Enum . map ( subs , fn { path , opts } -> { path , load_plugins ( opts ) } end ) }
338
+ Enum . map ( subs , fn { path , formatter_opts_and_subs } ->
339
+ { path , load_plugins ( formatter_opts_and_subs , opts ) }
340
+ end ) }
341
+ end
342
+
343
+ defp plugin_loader ( plugins ) do
344
+ if plugins != [ ] do
345
+ Mix.Task . run ( "loadpaths" , [ ] )
346
+ end
347
+
348
+ if not Enum . all? ( plugins , & Code . ensure_loaded? / 1 ) do
349
+ Mix.Task . run ( "compile" , [ ] )
350
+ end
351
+
352
+ plugins
340
353
end
341
354
342
355
@ doc """
@@ -346,24 +359,41 @@ defmodule Mix.Tasks.Format do
346
359
The function must be called with the contents of the file
347
360
to be formatted. The options are returned for reflection
348
361
purposes.
362
+
363
+ ## Options
364
+
365
+ * `:deps_paths` (since v1.18.0) - the dependencies path to be used to resolve
366
+ `import_deps`. It defaults to `Mix.Project.deps_paths`.
367
+
368
+ * `:dot_formatter` - use the given file as the `dot_formatter`
369
+ root. If this option is specified, it uses the default one.
370
+ The default one is cached, so use this option only if necessary.
371
+
372
+ * `:plugin_loader` (since v1.18.0) - a function that receives a list of plugins,
373
+ which may or may not yet be loaded, and ensures all of them are
374
+ loaded. It must return a list of plugins, which is recommended
375
+ to be the exact same list given as argument. You may choose to
376
+ skip plugins, but then it means the code will be partially
377
+ formatted (as in the plugins will be skipped). By default,
378
+ this function calls `mix loadpaths` and then, if not enough,
379
+ `mix compile`.
380
+
381
+ * `:root` - use the given root as the current working directory.
349
382
"""
350
383
@ doc since: "1.13.0"
351
384
def formatter_for_file ( file , opts \\ [ ] ) do
352
385
cwd = Keyword . get_lazy ( opts , :root , & File . cwd! / 0 )
353
386
{ dot_formatter , formatter_opts } = eval_dot_formatter ( cwd , opts )
354
387
355
388
{ formatter_opts_and_subs , _sources } =
356
- eval_deps_and_subdirectories ( cwd , dot_formatter , formatter_opts , [ dot_formatter ] )
389
+ eval_deps_and_subdirectories ( cwd , dot_formatter , formatter_opts , [ dot_formatter ] , opts )
357
390
358
- formatter_opts_and_subs = load_plugins ( formatter_opts_and_subs )
391
+ formatter_opts_and_subs = load_plugins ( formatter_opts_and_subs , opts )
359
392
360
393
find_formatter_and_opts_for_file ( Path . expand ( file , cwd ) , formatter_opts_and_subs )
361
394
end
362
395
363
- @ doc """
364
- Returns formatter options to be used for the given file.
365
- """
366
- # TODO: Remove me Elixir v1.17
396
+ @ doc false
367
397
@ deprecated "Use formatter_for_file/2 instead"
368
398
def formatter_opts_for_file ( file , opts \\ [ ] ) do
369
399
{ _ , formatter_opts } = formatter_for_file ( file , opts )
@@ -391,7 +421,7 @@ defmodule Mix.Tasks.Format do
391
421
# This function reads exported configuration from the imported
392
422
# dependencies and subdirectories and deals with caching the result
393
423
# of reading such configuration in a manifest file.
394
- defp eval_deps_and_subdirectories ( cwd , dot_formatter , formatter_opts , sources ) do
424
+ defp eval_deps_and_subdirectories ( cwd , dot_formatter , formatter_opts , sources , opts ) do
395
425
deps = Keyword . get ( formatter_opts , :import_deps , [ ] )
396
426
subs = Keyword . get ( formatter_opts , :subdirectories , [ ] )
397
427
@@ -410,8 +440,8 @@ defmodule Mix.Tasks.Format do
410
440
411
441
{ { locals_without_parens , subdirectories } , sources } =
412
442
maybe_cache_in_manifest ( dot_formatter , manifest , fn ->
413
- { subdirectories , sources } = eval_subs_opts ( subs , cwd , sources )
414
- { { eval_deps_opts ( deps ) , subdirectories } , sources }
443
+ { subdirectories , sources } = eval_subs_opts ( subs , cwd , sources , opts )
444
+ { { eval_deps_opts ( deps , opts ) , subdirectories } , sources }
415
445
end )
416
446
417
447
formatter_opts =
@@ -457,12 +487,12 @@ defmodule Mix.Tasks.Format do
457
487
{ entry , sources }
458
488
end
459
489
460
- defp eval_deps_opts ( [ ] ) do
490
+ defp eval_deps_opts ( [ ] , _opts ) do
461
491
[ ]
462
492
end
463
493
464
- defp eval_deps_opts ( deps ) do
465
- deps_paths = Mix.Project . deps_paths ( )
494
+ defp eval_deps_opts ( deps , opts ) do
495
+ deps_paths = opts [ :deps_paths ] || Mix.Project . deps_paths ( )
466
496
467
497
for dep <- deps ,
468
498
dep_path = assert_valid_dep_and_fetch_path ( dep , deps_paths ) ,
@@ -474,7 +504,7 @@ defmodule Mix.Tasks.Format do
474
504
do: parenless_call
475
505
end
476
506
477
- defp eval_subs_opts ( subs , cwd , sources ) do
507
+ defp eval_subs_opts ( subs , cwd , sources , opts ) do
478
508
{ subs , sources } =
479
509
Enum . flat_map_reduce ( subs , sources , fn sub , sources ->
480
510
cwd = Path . expand ( sub , cwd )
@@ -488,7 +518,7 @@ defmodule Mix.Tasks.Format do
488
518
formatter_opts = eval_file_with_keyword_list ( sub_formatter )
489
519
490
520
{ formatter_opts_and_subs , sources } =
491
- eval_deps_and_subdirectories ( sub , :in_memory , formatter_opts , sources )
521
+ eval_deps_and_subdirectories ( sub , :in_memory , formatter_opts , sources , opts )
492
522
493
523
{ [ { sub , formatter_opts_and_subs } ] , sources }
494
524
else
0 commit comments