Replace keyword with concrete keyword lists in specs (#14611)
This commit is contained in:
committed by
José Valim
parent
a0ca37cb8f
commit
db203167e2
+14
-5
@@ -118,6 +118,15 @@ defmodule EEx do
|
||||
| {:expr | :start_expr | :middle_expr | :end_expr, marker, charlist, metadata}
|
||||
| {:eof, metadata}
|
||||
|
||||
@type tokenize_opt ::
|
||||
{:file, binary()}
|
||||
| {:line, line}
|
||||
| {:column, column}
|
||||
| {:indentation, non_neg_integer}
|
||||
| {:trim, boolean()}
|
||||
|
||||
@type compile_opt :: tokenize_opt | {:engine, module()} | {:parser_options, Code.parser_opts()}
|
||||
|
||||
@doc """
|
||||
Generates a function definition from the given string.
|
||||
|
||||
@@ -220,7 +229,7 @@ defmodule EEx do
|
||||
"3"
|
||||
|
||||
"""
|
||||
@spec compile_string(String.t(), keyword) :: Macro.t()
|
||||
@spec compile_string(String.t(), [compile_opt]) :: Macro.t()
|
||||
def compile_string(source, options \\ []) when is_binary(source) and is_list(options) do
|
||||
case tokenize(source, options) do
|
||||
{:ok, tokens} ->
|
||||
@@ -259,7 +268,7 @@ defmodule EEx do
|
||||
#=> "3"
|
||||
|
||||
"""
|
||||
@spec compile_file(Path.t(), keyword) :: Macro.t()
|
||||
@spec compile_file(Path.t(), [compile_opt]) :: Macro.t()
|
||||
def compile_file(filename, options \\ []) when is_list(options) do
|
||||
filename = IO.chardata_to_string(filename)
|
||||
options = Keyword.merge([file: filename, line: 1], options)
|
||||
@@ -277,7 +286,7 @@ defmodule EEx do
|
||||
"foo baz"
|
||||
|
||||
"""
|
||||
@spec eval_string(String.t(), keyword, keyword) :: String.t()
|
||||
@spec eval_string(String.t(), keyword, [compile_opt]) :: String.t()
|
||||
def eval_string(source, bindings \\ [], options \\ [])
|
||||
when is_binary(source) and is_list(bindings) and is_list(options) do
|
||||
compiled = compile_string(source, options)
|
||||
@@ -299,7 +308,7 @@ defmodule EEx do
|
||||
#=> "foo baz"
|
||||
|
||||
"""
|
||||
@spec eval_file(Path.t(), keyword, keyword) :: String.t()
|
||||
@spec eval_file(Path.t(), keyword, [compile_opt]) :: String.t()
|
||||
def eval_file(filename, bindings \\ [], options \\ [])
|
||||
when is_list(bindings) and is_list(options) do
|
||||
filename = IO.chardata_to_string(filename)
|
||||
@@ -339,7 +348,7 @@ defmodule EEx do
|
||||
Note new tokens may be added in the future.
|
||||
"""
|
||||
@doc since: "1.14.0"
|
||||
@spec tokenize([char()] | String.t(), opts :: keyword) ::
|
||||
@spec tokenize([char()] | String.t(), [tokenize_opt]) ::
|
||||
{:ok, [token()]} | {:error, String.t(), metadata()}
|
||||
def tokenize(contents, opts \\ []) do
|
||||
EEx.Compiler.tokenize(contents, opts)
|
||||
|
||||
@@ -10,6 +10,22 @@ defmodule EEx.Compiler do
|
||||
@h_spaces [?\s, ?\t]
|
||||
@all_spaces [?\s, ?\t, ?\n, ?\r]
|
||||
|
||||
@typedoc """
|
||||
Options for EEx compilation functions.
|
||||
|
||||
These options control various aspects of EEx template compilation including
|
||||
file information, parsing behavior, and the template engine to use.
|
||||
"""
|
||||
@type compile_opts :: [
|
||||
file: String.t(),
|
||||
line: pos_integer(),
|
||||
column: pos_integer(),
|
||||
indentation: non_neg_integer(),
|
||||
trim: boolean(),
|
||||
parser_options: Code.parser_opts(),
|
||||
engine: module()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Tokenize EEx contents.
|
||||
"""
|
||||
@@ -290,7 +306,7 @@ defmodule EEx.Compiler do
|
||||
and the engine together by handling the tokens and invoking
|
||||
the engine every time a full expression or text is received.
|
||||
"""
|
||||
@spec compile([EEx.token()], String.t(), keyword) :: Macro.t()
|
||||
@spec compile([EEx.token()], String.t(), compile_opts) :: Macro.t()
|
||||
def compile(tokens, source, opts) do
|
||||
file = opts[:file] || "nofile"
|
||||
line = opts[:line] || 1
|
||||
|
||||
@@ -14,12 +14,29 @@ defmodule EEx.Engine do
|
||||
|
||||
@type state :: term
|
||||
|
||||
@typedoc """
|
||||
Options passed to engine initialization.
|
||||
|
||||
These are the same options passed to `EEx.Compiler.compile/3`,
|
||||
allowing engines to access compilation settings and customize
|
||||
their behavior accordingly.
|
||||
"""
|
||||
@type init_opts :: [
|
||||
file: String.t(),
|
||||
line: pos_integer(),
|
||||
column: pos_integer(),
|
||||
indentation: non_neg_integer(),
|
||||
trim: boolean(),
|
||||
parser_options: Code.parser_opts(),
|
||||
engine: module()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Called at the beginning of every template.
|
||||
|
||||
It must return the initial state.
|
||||
"""
|
||||
@callback init(opts :: keyword) :: state
|
||||
@callback init(opts :: init_opts) :: state
|
||||
|
||||
@doc """
|
||||
Called at the end of every template.
|
||||
|
||||
@@ -162,6 +162,22 @@ defmodule Calendar do
|
||||
"""
|
||||
@type time_zone_database :: module()
|
||||
|
||||
@typedoc """
|
||||
Options for formatting dates and times with `strftime/3`.
|
||||
"""
|
||||
@type strftime_opts :: [
|
||||
preferred_datetime: String.t(),
|
||||
preferred_date: String.t(),
|
||||
preferred_time: String.t(),
|
||||
am_pm_names: (:am | :pm -> String.t()) | (:am | :pm, map() -> String.t()),
|
||||
month_names: (pos_integer() -> String.t()) | (pos_integer(), map() -> String.t()),
|
||||
abbreviated_month_names:
|
||||
(pos_integer() -> String.t()) | (pos_integer(), map() -> String.t()),
|
||||
day_of_week_names: (pos_integer() -> String.t()) | (pos_integer(), map() -> String.t()),
|
||||
abbreviated_day_of_week_names:
|
||||
(pos_integer() -> String.t()) | (pos_integer(), map() -> String.t())
|
||||
]
|
||||
|
||||
@doc """
|
||||
Returns how many days there are in the given month of the given year.
|
||||
"""
|
||||
@@ -617,7 +633,7 @@ defmodule Calendar do
|
||||
|
||||
"""
|
||||
@doc since: "1.11.0"
|
||||
@spec strftime(map(), String.t(), keyword()) :: String.t()
|
||||
@spec strftime(map(), String.t(), strftime_opts()) :: String.t()
|
||||
def strftime(date_or_time_or_datetime, string_format, user_options \\ [])
|
||||
when is_map(date_or_time_or_datetime) and is_binary(string_format) do
|
||||
parse(
|
||||
|
||||
@@ -161,6 +161,22 @@ defmodule Duration do
|
||||
"""
|
||||
@type duration :: t | [unit_pair]
|
||||
|
||||
@typedoc """
|
||||
Options for `Duration.to_string/2`.
|
||||
"""
|
||||
@type to_string_opts :: [
|
||||
units: [
|
||||
year: String.t(),
|
||||
month: String.t(),
|
||||
week: String.t(),
|
||||
day: String.t(),
|
||||
hour: String.t(),
|
||||
minute: String.t(),
|
||||
second: String.t()
|
||||
],
|
||||
separator: String.t()
|
||||
]
|
||||
|
||||
@microseconds_per_second 1_000_000
|
||||
|
||||
@doc """
|
||||
@@ -436,6 +452,7 @@ defmodule Duration do
|
||||
|
||||
"""
|
||||
@doc since: "1.18.0"
|
||||
@spec to_string(t, to_string_opts) :: String.t()
|
||||
def to_string(%Duration{} = duration, opts \\ []) do
|
||||
units = Keyword.get(opts, :units, [])
|
||||
separator = Keyword.get(opts, :separator, " ")
|
||||
|
||||
+72
-25
@@ -248,6 +248,49 @@ defmodule Code do
|
||||
"""
|
||||
@type position() :: line() | {line :: pos_integer(), column :: pos_integer()}
|
||||
|
||||
@typedoc """
|
||||
Options for code formatting functions.
|
||||
"""
|
||||
@type format_opts :: [
|
||||
file: binary(),
|
||||
line: pos_integer(),
|
||||
line_length: pos_integer(),
|
||||
locals_without_parens: keyword(),
|
||||
force_do_end_blocks: boolean(),
|
||||
migrate: boolean(),
|
||||
migrate_bitstring_modifiers: boolean(),
|
||||
migrate_call_parens_on_pipe: boolean(),
|
||||
migrate_charlists_as_sigils: boolean(),
|
||||
migrate_unless: boolean()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for parsing functions that convert strings to quoted expressions.
|
||||
"""
|
||||
@type parser_opts :: [
|
||||
file: binary(),
|
||||
line: pos_integer(),
|
||||
column: pos_integer(),
|
||||
indentation: non_neg_integer(),
|
||||
columns: boolean(),
|
||||
unescape: boolean(),
|
||||
existing_atoms_only: boolean(),
|
||||
token_metadata: boolean(),
|
||||
literal_encoder: (term(), Macro.metadata() -> term()),
|
||||
static_atoms_encoder: (atom() -> term()),
|
||||
emit_warnings: boolean()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for environment evaluation functions like eval_string/3 and eval_quoted/3.
|
||||
"""
|
||||
@type env_eval_opts :: [
|
||||
file: binary(),
|
||||
line: pos_integer(),
|
||||
module: module(),
|
||||
prune_binding: boolean()
|
||||
]
|
||||
|
||||
@boolean_compiler_options [
|
||||
:docs,
|
||||
:debug_info,
|
||||
@@ -560,7 +603,7 @@ defmodule Code do
|
||||
[a: 1, b: 2]
|
||||
|
||||
"""
|
||||
@spec eval_string(List.Chars.t(), binding, Macro.Env.t() | keyword) :: {term, binding}
|
||||
@spec eval_string(List.Chars.t(), binding, Macro.Env.t() | env_eval_opts) :: {term, binding}
|
||||
def eval_string(string, binding \\ [], opts \\ [])
|
||||
|
||||
def eval_string(string, binding, %Macro.Env{} = env) do
|
||||
@@ -615,7 +658,8 @@ defmodule Code do
|
||||
|
||||
"""
|
||||
@doc since: "1.15.0"
|
||||
@spec with_diagnostics(keyword(), (-> result)) :: {result, [diagnostic(:warning | :error)]}
|
||||
@spec with_diagnostics([log: boolean()], (-> result)) ::
|
||||
{result, [diagnostic(:warning | :error)]}
|
||||
when result: term()
|
||||
def with_diagnostics(opts \\ [], fun) do
|
||||
value = :erlang.get(:elixir_code_diagnostics)
|
||||
@@ -648,7 +692,7 @@ defmodule Code do
|
||||
Defaults to `true`.
|
||||
"""
|
||||
@doc since: "1.15.0"
|
||||
@spec print_diagnostic(diagnostic(:warning | :error), keyword()) :: :ok
|
||||
@spec print_diagnostic(diagnostic(:warning | :error), snippet: boolean()) :: :ok
|
||||
def print_diagnostic(diagnostic, opts \\ []) do
|
||||
read_snippet? = Keyword.get(opts, :snippet, true)
|
||||
:elixir_errors.print_diagnostic(diagnostic, read_snippet?)
|
||||
@@ -1035,7 +1079,7 @@ defmodule Code do
|
||||
address the deprecation warnings.
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec format_string!(binary, keyword) :: iodata
|
||||
@spec format_string!(binary, format_opts) :: iodata
|
||||
def format_string!(string, opts \\ []) when is_binary(string) and is_list(opts) do
|
||||
line_length = Keyword.get(opts, :line_length, 98)
|
||||
|
||||
@@ -1060,7 +1104,7 @@ defmodule Code do
|
||||
available options.
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec format_file!(binary, keyword) :: iodata
|
||||
@spec format_file!(binary, format_opts) :: iodata
|
||||
def format_file!(file, opts \\ []) when is_binary(file) and is_list(opts) do
|
||||
string = File.read!(file)
|
||||
formatted = format_string!(string, [file: file, line: 1] ++ opts)
|
||||
@@ -1098,7 +1142,7 @@ defmodule Code do
|
||||
[a: 1, b: 2]
|
||||
|
||||
"""
|
||||
@spec eval_quoted(Macro.t(), binding, Macro.Env.t() | keyword) :: {term, binding}
|
||||
@spec eval_quoted(Macro.t(), binding, Macro.Env.t() | env_eval_opts) :: {term, binding}
|
||||
def eval_quoted(quoted, binding \\ [], env_or_opts \\ []) do
|
||||
{value, binding, _env} =
|
||||
eval_verify(:eval_quoted, [quoted, binding, env_for_eval(env_or_opts)])
|
||||
@@ -1129,8 +1173,15 @@ defmodule Code do
|
||||
* `:line` - the line on which the script starts
|
||||
|
||||
* `:module` - the module to run the environment on
|
||||
|
||||
* `:prune_binding` - (since v1.14.2) prune binding to keep only
|
||||
variables read or written by the evaluated code. Note that
|
||||
variables used by modules are always pruned, even if later used
|
||||
by the modules. You can submit to the `:on_module` tracer event
|
||||
and access the variables used by the module from its environment.
|
||||
"""
|
||||
@doc since: "1.14.0"
|
||||
@spec env_for_eval(Macro.Env.t() | env_eval_opts) :: Macro.Env.t()
|
||||
def env_for_eval(env_or_opts), do: :elixir.env_for_eval(env_or_opts)
|
||||
|
||||
@doc """
|
||||
@@ -1144,15 +1195,11 @@ defmodule Code do
|
||||
|
||||
## Options
|
||||
|
||||
* `:prune_binding` - (since v1.14.2) prune binding to keep only
|
||||
variables read or written by the evaluated code. Note that
|
||||
variables used by modules are always pruned, even if later used
|
||||
by the modules. You can submit to the `:on_module` tracer event
|
||||
and access the variables used by the module from its environment.
|
||||
It accepts the same options as `env_for_eval/1`.
|
||||
|
||||
"""
|
||||
@doc since: "1.14.0"
|
||||
@spec eval_quoted_with_env(Macro.t(), binding, Macro.Env.t(), keyword) ::
|
||||
@spec eval_quoted_with_env(Macro.t(), binding, Macro.Env.t(), env_eval_opts) ::
|
||||
{term, binding, Macro.Env.t()}
|
||||
def eval_quoted_with_env(quoted, binding, %Macro.Env{} = env, opts \\ [])
|
||||
when is_list(binding) do
|
||||
@@ -1263,7 +1310,7 @@ defmodule Code do
|
||||
{:error, {[line: 1, column: 4], "syntax error before: ", "\"3\""}}
|
||||
|
||||
"""
|
||||
@spec string_to_quoted(List.Chars.t(), keyword) ::
|
||||
@spec string_to_quoted(List.Chars.t(), parser_opts) ::
|
||||
{:ok, Macro.t()} | {:error, {location :: keyword, binary | {binary, binary}, binary}}
|
||||
def string_to_quoted(string, opts \\ []) when is_list(opts) do
|
||||
file = Keyword.get(opts, :file, "nofile")
|
||||
@@ -1290,7 +1337,7 @@ defmodule Code do
|
||||
|
||||
Check `string_to_quoted/2` for options information.
|
||||
"""
|
||||
@spec string_to_quoted!(List.Chars.t(), keyword) :: Macro.t()
|
||||
@spec string_to_quoted!(List.Chars.t(), parser_opts) :: Macro.t()
|
||||
def string_to_quoted!(string, opts \\ []) when is_list(opts) do
|
||||
file = Keyword.get(opts, :file, "nofile")
|
||||
line = Keyword.get(opts, :line, 1)
|
||||
@@ -1341,7 +1388,7 @@ defmodule Code do
|
||||
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec string_to_quoted_with_comments(List.Chars.t(), keyword) ::
|
||||
@spec string_to_quoted_with_comments(List.Chars.t(), parser_opts) ::
|
||||
{:ok, Macro.t(), list(map())} | {:error, {location :: keyword, term, term}}
|
||||
def string_to_quoted_with_comments(string, opts \\ []) when is_list(opts) do
|
||||
charlist = to_charlist(string)
|
||||
@@ -1371,7 +1418,7 @@ defmodule Code do
|
||||
Check `string_to_quoted/2` for options information.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec string_to_quoted_with_comments!(List.Chars.t(), keyword) :: {Macro.t(), list(map())}
|
||||
@spec string_to_quoted_with_comments!(List.Chars.t(), parser_opts) :: {Macro.t(), list(map())}
|
||||
def string_to_quoted_with_comments!(string, opts \\ []) do
|
||||
charlist = to_charlist(string)
|
||||
|
||||
@@ -1456,6 +1503,9 @@ defmodule Code do
|
||||
|
||||
## Options
|
||||
|
||||
This function accepts all options supported by `format_string!/2` for controlling
|
||||
code formatting, plus these additional options:
|
||||
|
||||
* `:comments` - the list of comments associated with the quoted expression.
|
||||
Defaults to `[]`. It is recommended that both `:token_metadata` and
|
||||
`:literal_encoder` options are given to `string_to_quoted_with_comments/2`
|
||||
@@ -1466,17 +1516,14 @@ defmodule Code do
|
||||
`string_to_quoted/2`, setting this option to `false` will prevent it from
|
||||
escaping the sequences twice. Defaults to `true`.
|
||||
|
||||
* `:locals_without_parens` - a keyword list of name and arity
|
||||
pairs that should be kept without parens whenever possible.
|
||||
The arity may be the atom `:*`, which implies all arities of
|
||||
that name. The formatter already includes a list of functions
|
||||
and this option augments this list.
|
||||
|
||||
* `:syntax_colors` - a keyword list of colors the output is colorized.
|
||||
See `Inspect.Opts` for more information.
|
||||
See `format_string!/2` for the full list of formatting options including
|
||||
`:file`, `:line`, `:line_length`, `:locals_without_parens`, `:force_do_end_blocks`,
|
||||
`:syntax_colors`, and all migration options like `:migrate_charlists_as_sigils`.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec quoted_to_algebra(Macro.t(), keyword) :: Inspect.Algebra.t()
|
||||
@spec quoted_to_algebra(Macro.t(), [
|
||||
Code.Formatter.to_algebra_opt() | Code.Normalizer.normalize_opt()
|
||||
]) :: Inspect.Algebra.t()
|
||||
def quoted_to_algebra(quoted, opts \\ []) do
|
||||
quoted
|
||||
|> Code.Normalizer.normalize(opts)
|
||||
|
||||
@@ -155,9 +155,32 @@ defmodule Code.Formatter do
|
||||
|
||||
@do_end_keywords [:rescue, :catch, :else, :after]
|
||||
|
||||
@typedoc """
|
||||
Options for `to_algebra/2`.
|
||||
|
||||
These options include all the standard code formatting options plus
|
||||
additional context like comments and syntax highlighting colors.
|
||||
"""
|
||||
@type to_algebra_opt ::
|
||||
{:comments, [term()]}
|
||||
| {:syntax_colors, keyword()}
|
||||
| {:sigils, keyword()}
|
||||
| {:file, binary()}
|
||||
| {:line, pos_integer()}
|
||||
| {:line_length, pos_integer()}
|
||||
| {:locals_without_parens, keyword()}
|
||||
| {:force_do_end_blocks, boolean()}
|
||||
| {:migrate, boolean()}
|
||||
| {:migrate_bitstring_modifiers, boolean()}
|
||||
| {:migrate_call_parens_on_pipe, boolean()}
|
||||
| {:migrate_charlists_as_sigils, boolean()}
|
||||
| {:migrate_unless, boolean()}
|
||||
| {atom(), term()}
|
||||
|
||||
@doc """
|
||||
Converts the quoted expression into an algebra document.
|
||||
"""
|
||||
@spec to_algebra(Macro.t(), [to_algebra_opt]) :: Inspect.Algebra.t()
|
||||
def to_algebra(quoted, opts \\ []) do
|
||||
comments = Keyword.get(opts, :comments, [])
|
||||
|
||||
|
||||
@@ -11,6 +11,26 @@ defmodule Code.Fragment do
|
||||
|
||||
@type position :: {line :: pos_integer(), column :: pos_integer()}
|
||||
|
||||
@typedoc """
|
||||
Options for cursor context functions.
|
||||
|
||||
Currently, these options are not used but reserved for future extensibility.
|
||||
"""
|
||||
@type cursor_opts :: []
|
||||
|
||||
@typedoc """
|
||||
Options for converting code fragments to quoted expressions.
|
||||
"""
|
||||
@type container_cursor_to_quoted_opts :: [
|
||||
file: String.t(),
|
||||
line: pos_integer(),
|
||||
column: pos_integer(),
|
||||
columns: boolean(),
|
||||
token_metadata: boolean(),
|
||||
literal_encoder: (term(), Macro.metadata() -> term()),
|
||||
trailing_fragment: String.t()
|
||||
]
|
||||
|
||||
@doc ~S"""
|
||||
Returns the list of lines in the given string, preserving their line endings.
|
||||
|
||||
@@ -172,7 +192,7 @@ defmodule Code.Fragment do
|
||||
references, and more.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec cursor_context(List.Chars.t(), keyword()) ::
|
||||
@spec cursor_context(List.Chars.t(), cursor_opts()) ::
|
||||
{:alias, charlist}
|
||||
| {:alias, inside_alias, charlist}
|
||||
| {:block_keyword_or_binary_operator, charlist}
|
||||
@@ -662,7 +682,7 @@ defmodule Code.Fragment do
|
||||
of examples and their return values.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec surround_context(List.Chars.t(), position(), keyword()) ::
|
||||
@spec surround_context(List.Chars.t(), position(), cursor_opts()) ::
|
||||
%{begin: position, end: position, context: context} | :none
|
||||
when context:
|
||||
{:alias, charlist}
|
||||
@@ -1215,7 +1235,7 @@ defmodule Code.Fragment do
|
||||
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec container_cursor_to_quoted(List.Chars.t(), keyword()) ::
|
||||
@spec container_cursor_to_quoted(List.Chars.t(), container_cursor_to_quoted_opts()) ::
|
||||
{:ok, Macro.t()} | {:error, {location :: keyword, binary | {binary, binary}, binary}}
|
||||
def container_cursor_to_quoted(fragment, opts \\ []) do
|
||||
{trailing_fragment, opts} = Keyword.pop(opts, :trailing_fragment)
|
||||
|
||||
@@ -10,10 +10,20 @@ defmodule Code.Normalizer do
|
||||
is_binary(x) or
|
||||
is_atom(x)
|
||||
|
||||
@typedoc """
|
||||
Options for `normalize/2`.
|
||||
"""
|
||||
@type normalize_opt ::
|
||||
{:line, pos_integer() | nil}
|
||||
| {:escape, boolean()}
|
||||
| {:locals_without_parens, keyword()}
|
||||
| {atom(), term()}
|
||||
|
||||
@doc """
|
||||
Wraps literals in the quoted expression to conform to the AST format expected
|
||||
by the formatter.
|
||||
"""
|
||||
@spec normalize(Macro.t(), [normalize_opt]) :: Macro.t()
|
||||
def normalize(quoted, opts \\ []) do
|
||||
line = Keyword.get(opts, :line, nil)
|
||||
escape = Keyword.get(opts, :escape, true)
|
||||
|
||||
@@ -98,6 +98,12 @@ defmodule Config do
|
||||
(assembled with `mix release`).
|
||||
"""
|
||||
|
||||
@type config_opts :: [
|
||||
imports: [Path.t()] | :disabled,
|
||||
env: atom(),
|
||||
target: atom()
|
||||
]
|
||||
|
||||
@opts_key {__MODULE__, :opts}
|
||||
@config_key {__MODULE__, :config}
|
||||
@imports_key {__MODULE__, :imports}
|
||||
@@ -306,7 +312,7 @@ defmodule Config do
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec __eval__!(Path.t(), binary(), keyword) :: {keyword, [Path.t()] | :disabled}
|
||||
@spec __eval__!(Path.t(), binary(), config_opts) :: {keyword, [Path.t()] | :disabled}
|
||||
def __eval__!(file, content, opts \\ []) when is_binary(file) and is_list(opts) do
|
||||
env = Keyword.get(opts, :env)
|
||||
target = Keyword.get(opts, :target)
|
||||
|
||||
@@ -111,6 +111,16 @@ defmodule Config.Provider do
|
||||
"""
|
||||
@type config_path :: {:system, binary(), binary()} | binary()
|
||||
|
||||
@typedoc """
|
||||
Options for `init/3`.
|
||||
"""
|
||||
@type init_opts :: [
|
||||
extra_config: config(),
|
||||
prune_runtime_sys_config_after_boot: boolean(),
|
||||
reboot_system_after_config: boolean(),
|
||||
validate_compile_env: [{atom(), [atom()], term()}]
|
||||
]
|
||||
|
||||
@doc """
|
||||
Invoked when initializing a config provider.
|
||||
|
||||
@@ -196,6 +206,7 @@ defmodule Config.Provider do
|
||||
@reboot_mode_key :config_provider_reboot_mode
|
||||
|
||||
@doc false
|
||||
@spec init([{module(), term()}], config_path(), init_opts()) :: config()
|
||||
def init(providers, config_path, opts \\ []) when is_list(providers) and is_list(opts) do
|
||||
validate_config_path!(config_path)
|
||||
providers = for {provider, init} <- providers, do: {provider, provider.init(init)}
|
||||
|
||||
@@ -46,6 +46,12 @@ defmodule Config.Reader do
|
||||
|
||||
@behaviour Config.Provider
|
||||
|
||||
@type config_opts :: [
|
||||
imports: [Path.t()] | :disabled,
|
||||
env: atom(),
|
||||
target: atom()
|
||||
]
|
||||
|
||||
@impl true
|
||||
def init(opts) when is_list(opts) do
|
||||
{path, opts} = Keyword.pop!(opts, :path)
|
||||
@@ -68,7 +74,7 @@ defmodule Config.Reader do
|
||||
Accepts the same options as `read!/2`.
|
||||
"""
|
||||
@doc since: "1.11.0"
|
||||
@spec eval!(Path.t(), binary, keyword) :: keyword
|
||||
@spec eval!(Path.t(), binary, config_opts) :: keyword
|
||||
def eval!(file, contents, opts \\ [])
|
||||
when is_binary(file) and is_binary(contents) and is_list(opts) do
|
||||
Config.__eval__!(Path.expand(file), contents, opts) |> elem(0)
|
||||
@@ -90,7 +96,7 @@ defmodule Config.Reader do
|
||||
|
||||
"""
|
||||
@doc since: "1.9.0"
|
||||
@spec read!(Path.t(), keyword) :: keyword
|
||||
@spec read!(Path.t(), config_opts) :: keyword
|
||||
def read!(file, opts \\ []) when is_binary(file) and is_list(opts) do
|
||||
file = Path.expand(file)
|
||||
Config.__eval__!(file, File.read!(file), opts) |> elem(0)
|
||||
@@ -104,7 +110,7 @@ defmodule Config.Reader do
|
||||
option cannot be disabled in `read_imports!/2`.
|
||||
"""
|
||||
@doc since: "1.9.0"
|
||||
@spec read_imports!(Path.t(), keyword) :: {keyword, [Path.t()]}
|
||||
@spec read_imports!(Path.t(), config_opts) :: {keyword, [Path.t()]}
|
||||
def read_imports!(file, opts \\ []) when is_binary(file) and is_list(opts) do
|
||||
if opts[:imports] == :disabled do
|
||||
raise ArgumentError, ":imports must be a list of paths"
|
||||
|
||||
@@ -115,11 +115,28 @@ defmodule Inspect.Opts do
|
||||
width: non_neg_integer | :infinity
|
||||
}
|
||||
|
||||
@typedoc """
|
||||
Options for building an `Inspect.Opts` struct with `new/1`.
|
||||
"""
|
||||
@type new_opt ::
|
||||
{:base, :decimal | :binary | :hex | :octal}
|
||||
| {:binaries, :infer | :as_binaries | :as_strings}
|
||||
| {:charlists, :infer | :as_lists | :as_charlists}
|
||||
| {:custom_options, keyword}
|
||||
| {:inspect_fun, (any, t -> Inspect.Algebra.t())}
|
||||
| {:limit, non_neg_integer | :infinity}
|
||||
| {:pretty, boolean}
|
||||
| {:printable_limit, non_neg_integer | :infinity}
|
||||
| {:safe, boolean}
|
||||
| {:structs, boolean}
|
||||
| {:syntax_colors, [{color_key, IO.ANSI.ansidata()}]}
|
||||
| {:width, non_neg_integer | :infinity}
|
||||
|
||||
@doc """
|
||||
Builds an `Inspect.Opts` struct.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec new(keyword()) :: t
|
||||
@spec new([new_opt()]) :: t
|
||||
def new(opts) do
|
||||
struct(%Inspect.Opts{inspect_fun: default_inspect_fun()}, opts)
|
||||
end
|
||||
@@ -324,6 +341,14 @@ defmodule Inspect.Algebra do
|
||||
quote do: {:doc_color, unquote(doc), unquote(color)}
|
||||
end
|
||||
|
||||
@typedoc """
|
||||
Options for container documents.
|
||||
"""
|
||||
@type container_opts :: [
|
||||
separator: String.t(),
|
||||
break: :strict | :flex | :maybe
|
||||
]
|
||||
|
||||
@docs [
|
||||
:doc_break,
|
||||
:doc_collapse,
|
||||
@@ -440,7 +465,14 @@ defmodule Inspect.Algebra do
|
||||
updated options from inspection.
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec container_doc(t, [term], t, Inspect.Opts.t(), (term, Inspect.Opts.t() -> t), keyword()) ::
|
||||
@spec container_doc(
|
||||
t,
|
||||
[term],
|
||||
t,
|
||||
Inspect.Opts.t(),
|
||||
(term, Inspect.Opts.t() -> t),
|
||||
container_opts()
|
||||
) ::
|
||||
t
|
||||
def container_doc(left, collection, right, inspect_opts, fun, opts \\ []) do
|
||||
container_doc_with_opts(left, collection, right, inspect_opts, fun, opts) |> elem(0)
|
||||
@@ -496,7 +528,7 @@ defmodule Inspect.Algebra do
|
||||
t,
|
||||
Inspect.Opts.t(),
|
||||
(term, Inspect.Opts.t() -> t),
|
||||
keyword()
|
||||
container_opts()
|
||||
) ::
|
||||
{t, Inspect.Opts.t()}
|
||||
def container_doc_with_opts(left, collection, right, inspect_opts, fun, opts \\ [])
|
||||
|
||||
+22
-3
@@ -128,6 +128,22 @@ defmodule IO do
|
||||
@type nodata :: {:error, term} | :eof
|
||||
@type chardata :: String.t() | maybe_improper_list(char | chardata, String.t() | [])
|
||||
|
||||
@type inspect_opts :: [Inspect.Opts.new_opt() | {:label, term}]
|
||||
|
||||
@typedoc """
|
||||
Stacktrace information as keyword options for `warn/2`.
|
||||
|
||||
At least `:file` is required. Other options are optional and used
|
||||
to provide more precise location information.
|
||||
"""
|
||||
@type warn_stacktrace_opts :: [
|
||||
file: String.t(),
|
||||
line: pos_integer(),
|
||||
column: pos_integer(),
|
||||
module: module(),
|
||||
function: {atom(), arity()}
|
||||
]
|
||||
|
||||
defguardp is_device(term) when is_atom(term) or is_pid(term)
|
||||
defguardp is_iodata(data) when is_list(data) or is_binary(data)
|
||||
|
||||
@@ -346,7 +362,10 @@ defmodule IO do
|
||||
#=> my_app.ex:4: MyApp.main/1
|
||||
|
||||
"""
|
||||
@spec warn(chardata | String.Chars.t(), Exception.stacktrace() | keyword() | Macro.Env.t()) ::
|
||||
@spec warn(
|
||||
chardata | String.Chars.t(),
|
||||
Exception.stacktrace() | warn_stacktrace_opts() | Macro.Env.t()
|
||||
) ::
|
||||
:ok
|
||||
def warn(message, stacktrace_info)
|
||||
|
||||
@@ -476,7 +495,7 @@ defmodule IO do
|
||||
after: [2, 4, 6]
|
||||
|
||||
"""
|
||||
@spec inspect(item, keyword) :: item when item: var
|
||||
@spec inspect(item, inspect_opts) :: item when item: var
|
||||
def inspect(item, opts \\ []) do
|
||||
inspect(:stdio, item, opts)
|
||||
end
|
||||
@@ -486,7 +505,7 @@ defmodule IO do
|
||||
|
||||
See `inspect/2` for a full list of options.
|
||||
"""
|
||||
@spec inspect(device, item, keyword) :: item when item: var
|
||||
@spec inspect(device, item, inspect_opts) :: item when item: var
|
||||
def inspect(device, item, opts) when is_device(device) and is_list(opts) do
|
||||
label = if label = opts[:label], do: [to_chardata(label), ": "], else: []
|
||||
opts = Inspect.Opts.new(opts)
|
||||
|
||||
@@ -5,6 +5,20 @@
|
||||
defmodule IO.ANSI.Docs do
|
||||
@moduledoc false
|
||||
|
||||
@type print_opts :: [
|
||||
enabled: boolean(),
|
||||
doc_bold: [IO.ANSI.ansicode()],
|
||||
doc_code: [IO.ANSI.ansicode()],
|
||||
doc_headings: [IO.ANSI.ansicode()],
|
||||
doc_metadata: [IO.ANSI.ansicode()],
|
||||
doc_quote: [IO.ANSI.ansicode()],
|
||||
doc_inline_code: [IO.ANSI.ansicode()],
|
||||
doc_table_heading: [IO.ANSI.ansicode()],
|
||||
doc_title: [IO.ANSI.ansicode()],
|
||||
doc_underline: [IO.ANSI.ansicode()],
|
||||
width: pos_integer()
|
||||
]
|
||||
|
||||
@bullet_text_unicode "• "
|
||||
@bullet_text_ascii "* "
|
||||
@bullets [?*, ?-, ?+]
|
||||
@@ -52,7 +66,7 @@ defmodule IO.ANSI.Docs do
|
||||
|
||||
See `default_options/0` for docs on the supported options.
|
||||
"""
|
||||
@spec print_headings([String.t()], keyword) :: :ok
|
||||
@spec print_headings([String.t()], print_opts) :: :ok
|
||||
def print_headings(headings, options \\ []) do
|
||||
# It's possible for some of the headings to contain newline characters (`\n`), so in order to prevent it from
|
||||
# breaking the output from `print_headings/2`, as `print_headings/2` tries to pad the whole heading, we first split
|
||||
@@ -77,7 +91,7 @@ defmodule IO.ANSI.Docs do
|
||||
|
||||
See `default_options/0` for docs on the supported options.
|
||||
"""
|
||||
@spec print_metadata(map, keyword) :: :ok
|
||||
@spec print_metadata(map, print_opts) :: :ok
|
||||
def print_metadata(metadata, options \\ []) when is_map(metadata) do
|
||||
options = Keyword.merge(default_options(), options)
|
||||
print_each_metadata(metadata, options) && IO.write("\n")
|
||||
@@ -115,7 +129,7 @@ defmodule IO.ANSI.Docs do
|
||||
|
||||
It takes a set of `options` defined in `default_options/0`.
|
||||
"""
|
||||
@spec print(term(), String.t(), keyword) :: :ok
|
||||
@spec print(term(), String.t(), print_opts) :: :ok
|
||||
def print(doc, format, options \\ [])
|
||||
|
||||
def print(doc, "text/markdown", options) when is_binary(doc) and is_list(options) do
|
||||
|
||||
+17
-1
@@ -328,6 +328,22 @@ defmodule JSON do
|
||||
| {:invalid_byte, non_neg_integer(), byte()}
|
||||
| {:unexpected_sequence, non_neg_integer(), binary()}
|
||||
|
||||
@typedoc """
|
||||
Decoders for customizing JSON decoding behavior.
|
||||
"""
|
||||
@type decoders :: [
|
||||
array_start: (term() -> term()),
|
||||
array_push: (term(), term() -> term()),
|
||||
array_finish: (term(), term() -> {term(), term()}),
|
||||
object_start: (term() -> term()),
|
||||
object_push: (term(), term(), term() -> term()),
|
||||
object_finish: (term(), term() -> {term(), term()}),
|
||||
float: (String.t() -> term()),
|
||||
integer: (String.t() -> term()),
|
||||
string: (String.t() -> term()),
|
||||
null: term()
|
||||
]
|
||||
|
||||
@doc ~S"""
|
||||
Decodes the given JSON.
|
||||
|
||||
@@ -381,7 +397,7 @@ defmodule JSON do
|
||||
|
||||
For streaming decoding, see Erlang's [`:json`](`:json`) module.
|
||||
"""
|
||||
@spec decode(binary(), term(), keyword()) ::
|
||||
@spec decode(binary(), term(), decoders()) ::
|
||||
{term(), term(), binary()} | {:error, decode_error_reason()}
|
||||
def decode(binary, acc, decoders) when is_binary(binary) and is_list(decoders) do
|
||||
decoders = Keyword.put_new(decoders, :null, nil)
|
||||
|
||||
@@ -2456,7 +2456,7 @@ defmodule Kernel do
|
||||
See the "Deriving" section of the documentation of the `Inspect`
|
||||
protocol for more information.
|
||||
"""
|
||||
@spec inspect(Inspect.t(), keyword) :: String.t()
|
||||
@spec inspect(Inspect.t(), [Inspect.Opts.new_opt()]) :: String.t()
|
||||
def inspect(term, opts \\ []) when is_list(opts) do
|
||||
opts = Inspect.Opts.new(opts)
|
||||
|
||||
|
||||
@@ -16,6 +16,38 @@ defmodule Kernel.ParallelCompiler do
|
||||
@type warning() :: {file :: Path.t(), Code.position(), message :: String.t()}
|
||||
@type error() :: {file :: Path.t(), Code.position(), message :: String.t()}
|
||||
|
||||
@typedoc """
|
||||
Options for parallel compilation functions.
|
||||
"""
|
||||
@type compile_opts :: [
|
||||
after_compile: (-> term()),
|
||||
each_file: (Path.t() -> term()),
|
||||
each_long_compilation: (Path.t() -> term()) | (Path.t(), pid() -> term()),
|
||||
each_long_verification: (module() -> term()) | (module(), pid() -> term()),
|
||||
each_module: (Path.t(), module(), binary() -> term()),
|
||||
each_cycle: ([module()], [Code.diagnostic(:warning)] ->
|
||||
{:compile, [module()], [Code.diagnostic(:warning)]}
|
||||
| {:runtime, [module()], [Code.diagnostic(:warning)]}),
|
||||
long_compilation_threshold: pos_integer(),
|
||||
long_verification_threshold: pos_integer(),
|
||||
verification: boolean(),
|
||||
profile: :time,
|
||||
dest: Path.t(),
|
||||
beam_timestamp: term(),
|
||||
return_diagnostics: boolean(),
|
||||
max_concurrency: pos_integer()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for requiring files in parallel.
|
||||
"""
|
||||
@type require_opts :: [
|
||||
each_file: (Path.t() -> term()),
|
||||
each_module: (Path.t(), module(), binary() -> term()),
|
||||
max_concurrency: pos_integer(),
|
||||
return_diagnostics: boolean()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Starts a task for parallel compilation.
|
||||
"""
|
||||
@@ -185,7 +217,7 @@ defmodule Kernel.ParallelCompiler do
|
||||
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec compile([Path.t()], keyword()) ::
|
||||
@spec compile([Path.t()], compile_opts()) ::
|
||||
{:ok, [atom], [warning] | info()}
|
||||
| {:error, [error] | [Code.diagnostic(:error)], [warning] | info()}
|
||||
def compile(files, options \\ []) when is_list(options) do
|
||||
@@ -198,7 +230,7 @@ defmodule Kernel.ParallelCompiler do
|
||||
See `compile/2` for more information.
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec compile_to_path([Path.t()], Path.t(), keyword()) ::
|
||||
@spec compile_to_path([Path.t()], Path.t(), compile_opts()) ::
|
||||
{:ok, [atom], [warning] | info()}
|
||||
| {:error, [error] | [Code.diagnostic(:error)], [warning] | info()}
|
||||
def compile_to_path(files, path, options \\ []) when is_binary(path) and is_list(options) do
|
||||
@@ -233,9 +265,12 @@ defmodule Kernel.ParallelCompiler do
|
||||
Setting this option to 1 will compile files sequentially.
|
||||
Defaults to the number of schedulers online, or at least 2.
|
||||
|
||||
* `:return_diagnostics` - when `true`, returns structured diagnostics
|
||||
as maps instead of the legacy format. Defaults to `false`.
|
||||
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec require([Path.t()], keyword()) ::
|
||||
@spec require([Path.t()], require_opts()) ::
|
||||
{:ok, [atom], [warning] | info()}
|
||||
| {:error, [error] | [Code.diagnostic(:error)], [warning] | info()}
|
||||
def require(files, options \\ []) when is_list(options) do
|
||||
|
||||
+11
-2
@@ -197,6 +197,15 @@ defmodule Macro do
|
||||
@typedoc "A captured remote function in the format of &Mod.fun/arity"
|
||||
@type captured_remote_function :: fun
|
||||
|
||||
@type escape_opts :: [
|
||||
unquote: boolean(),
|
||||
prune_metadata: boolean()
|
||||
]
|
||||
|
||||
@type inspect_atom_opts :: [
|
||||
escape: (binary(), char() -> binary())
|
||||
]
|
||||
|
||||
@doc """
|
||||
Breaks a pipeline expression into a list.
|
||||
|
||||
@@ -835,7 +844,7 @@ defmodule Macro do
|
||||
bound), while `quote/2` produces syntax trees for
|
||||
expressions.
|
||||
"""
|
||||
@spec escape(term, keyword) :: t()
|
||||
@spec escape(term, escape_opts) :: t()
|
||||
def escape(expr, opts \\ []) do
|
||||
unquote = Keyword.get(opts, :unquote, false)
|
||||
kind = if Keyword.get(opts, :prune_metadata, false), do: :prune_metadata, else: :none
|
||||
@@ -2399,7 +2408,7 @@ defmodule Macro do
|
||||
|
||||
"""
|
||||
@doc since: "1.14.0"
|
||||
@spec inspect_atom(:literal | :key | :remote_call, atom, keyword) :: binary
|
||||
@spec inspect_atom(:literal | :key | :remote_call, atom, inspect_atom_opts) :: binary
|
||||
def inspect_atom(source_format, atom, opts \\ [])
|
||||
|
||||
def inspect_atom(:literal, atom, _opts) when is_nil(atom) or is_boolean(atom) do
|
||||
|
||||
@@ -70,6 +70,42 @@ defmodule Macro.Env do
|
||||
@typep tracers :: [module]
|
||||
@typep versioned_vars :: %{optional(variable) => var_version :: non_neg_integer}
|
||||
|
||||
@type define_import_opts :: [
|
||||
trace: boolean(),
|
||||
emit_warnings: boolean(),
|
||||
info_callback: (atom() -> [{atom(), arity()}]),
|
||||
only: :functions | :macros | [{atom(), arity()}],
|
||||
except: [{atom(), arity()}],
|
||||
warn: boolean()
|
||||
]
|
||||
|
||||
@type define_alias_opts :: [
|
||||
trace: boolean(),
|
||||
as: atom(),
|
||||
warn: boolean()
|
||||
]
|
||||
|
||||
@type define_require_opts :: [
|
||||
trace: boolean(),
|
||||
as: atom(),
|
||||
warn: boolean()
|
||||
]
|
||||
|
||||
@type expand_alias_opts :: [
|
||||
trace: boolean()
|
||||
]
|
||||
|
||||
@type expand_import_opts :: [
|
||||
allow_locals: boolean(),
|
||||
check_deprecations: boolean(),
|
||||
trace: boolean()
|
||||
]
|
||||
|
||||
@type expand_require_opts :: [
|
||||
check_deprecations: boolean(),
|
||||
trace: boolean()
|
||||
]
|
||||
|
||||
@type t :: %{
|
||||
__struct__: __MODULE__,
|
||||
aliases: aliases,
|
||||
@@ -331,7 +367,7 @@ defmodule Macro.Env do
|
||||
|
||||
"""
|
||||
@doc since: "1.17.0"
|
||||
@spec define_require(t, Macro.metadata(), module) :: {:ok, t}
|
||||
@spec define_require(t, Macro.metadata(), module, define_require_opts) :: {:ok, t}
|
||||
def define_require(env, meta, module, opts \\ [])
|
||||
when is_list(meta) and is_atom(module) and is_list(opts) do
|
||||
{trace, opts} = Keyword.pop(opts, :trace, true)
|
||||
@@ -391,7 +427,8 @@ defmodule Macro.Env do
|
||||
|
||||
"""
|
||||
@doc since: "1.17.0"
|
||||
@spec define_import(t, Macro.metadata(), module, keyword) :: {:ok, t} | {:error, String.t()}
|
||||
@spec define_import(t, Macro.metadata(), module, define_import_opts) ::
|
||||
{:ok, t} | {:error, String.t()}
|
||||
def define_import(env, meta, module, opts \\ [])
|
||||
when is_list(meta) and is_atom(module) and is_list(opts) do
|
||||
{trace, opts} = Keyword.pop(opts, :trace, true)
|
||||
@@ -441,7 +478,8 @@ defmodule Macro.Env do
|
||||
|
||||
"""
|
||||
@doc since: "1.17.0"
|
||||
@spec define_alias(t, Macro.metadata(), module, keyword) :: {:ok, t} | {:error, String.t()}
|
||||
@spec define_alias(t, Macro.metadata(), module, define_alias_opts) ::
|
||||
{:ok, t} | {:error, String.t()}
|
||||
def define_alias(env, meta, module, opts \\ [])
|
||||
when is_list(meta) and is_atom(module) and is_list(opts) do
|
||||
{trace, opts} = Keyword.pop(opts, :trace, true)
|
||||
@@ -487,7 +525,7 @@ defmodule Macro.Env do
|
||||
|
||||
"""
|
||||
@doc since: "1.17.0"
|
||||
@spec expand_alias(t, keyword, [atom()], keyword) ::
|
||||
@spec expand_alias(t, keyword, [atom()], expand_alias_opts) ::
|
||||
{:alias, atom()} | :error
|
||||
def expand_alias(env, meta, list, opts \\ [])
|
||||
when is_list(meta) and is_list(list) and is_list(opts) do
|
||||
@@ -527,7 +565,7 @@ defmodule Macro.Env do
|
||||
|
||||
"""
|
||||
@doc since: "1.17.0"
|
||||
@spec expand_import(t, keyword, atom(), arity(), keyword) ::
|
||||
@spec expand_import(t, keyword, atom(), arity(), expand_import_opts) ::
|
||||
{:macro, module(), (Macro.metadata(), args :: [Macro.t()] -> Macro.t())}
|
||||
| {:function, module(), atom()}
|
||||
| {:error, :not_found | {:conflict, module()} | {:ambiguous, [module()]}}
|
||||
@@ -583,7 +621,7 @@ defmodule Macro.Env do
|
||||
|
||||
"""
|
||||
@doc since: "1.17.0"
|
||||
@spec expand_require(t, keyword, module(), atom(), arity(), keyword) ::
|
||||
@spec expand_require(t, keyword, module(), atom(), arity(), expand_require_opts) ::
|
||||
{:macro, module(), (Macro.metadata(), args :: [Macro.t()] -> Macro.t())}
|
||||
| :error
|
||||
def expand_require(env, meta, module, name, arity, opts \\ [])
|
||||
|
||||
@@ -687,6 +687,16 @@ defmodule Module do
|
||||
@type definition :: {atom, arity}
|
||||
@type def_kind :: :def | :defp | :defmacro | :defmacrop
|
||||
|
||||
@type create_opts :: [
|
||||
file: binary(),
|
||||
line: pos_integer(),
|
||||
generated: boolean()
|
||||
]
|
||||
|
||||
@type get_definition_opts :: [
|
||||
skip_clauses: boolean()
|
||||
]
|
||||
|
||||
@extra_error_msg_defines? "Use Kernel.function_exported?/3 and Kernel.macro_exported?/3 " <>
|
||||
"to check for public functions and macros instead"
|
||||
|
||||
@@ -918,7 +928,7 @@ defmodule Module do
|
||||
when defining the module, while `Kernel.defmodule/2`
|
||||
automatically uses the environment it is invoked at.
|
||||
"""
|
||||
@spec create(module, Macro.t(), Macro.Env.t() | keyword) :: {:module, module, binary, term}
|
||||
@spec create(module, Macro.t(), Macro.Env.t() | create_opts) :: {:module, module, binary, term}
|
||||
def create(module, quoted, opts)
|
||||
|
||||
def create(module, quoted, %Macro.Env{} = env) when is_atom(module) do
|
||||
@@ -1423,7 +1433,7 @@ defmodule Module do
|
||||
only an interest in fetching the kind and the metadata
|
||||
|
||||
"""
|
||||
@spec get_definition(module, definition, keyword) ::
|
||||
@spec get_definition(module, definition, get_definition_opts) ::
|
||||
{:v1, def_kind, meta :: keyword,
|
||||
[{meta :: keyword, arguments :: [Macro.t()], guards :: [Macro.t()], Macro.t()}]}
|
||||
| nil
|
||||
|
||||
@@ -11,9 +11,20 @@ defmodule Module.ParallelChecker do
|
||||
@type warning() :: term()
|
||||
@type mode() :: :erlang | :elixir | :protocol
|
||||
|
||||
@typedoc """
|
||||
Options for `start_link/1`.
|
||||
"""
|
||||
@type start_link_opts :: [
|
||||
{:max_concurrency, pos_integer()}
|
||||
| {:long_verification_threshold, pos_integer()}
|
||||
| {:each_long_verification, (module() -> term()) | (module(), pid() -> term())}
|
||||
| {atom(), term()}
|
||||
]
|
||||
|
||||
@doc """
|
||||
Initializes the parallel checker process.
|
||||
"""
|
||||
@spec start_link(start_link_opts()) :: {:ok, cache()}
|
||||
def start_link(opts \\ []) do
|
||||
:proc_lib.start_link(__MODULE__, :init, [opts])
|
||||
end
|
||||
|
||||
@@ -51,6 +51,13 @@ defmodule Module.Types.Descr do
|
||||
|
||||
# Type definitions
|
||||
|
||||
@typedoc """
|
||||
Options for `to_quoted/2`.
|
||||
"""
|
||||
@type to_quoted_opts :: [
|
||||
collapse_structs: boolean()
|
||||
]
|
||||
|
||||
defguard is_descr(descr) when is_map(descr) or descr == :term
|
||||
|
||||
defp descr_key?(:term, _key), do: true
|
||||
@@ -552,6 +559,7 @@ defmodule Module.Types.Descr do
|
||||
* `:collapse_structs` - do not show struct fields that match
|
||||
their default type
|
||||
"""
|
||||
@spec to_quoted(term(), to_quoted_opts) :: Macro.t()
|
||||
def to_quoted(descr, opts \\ []) do
|
||||
if term_type?(descr) do
|
||||
{:term, [], []}
|
||||
@@ -620,7 +628,13 @@ defmodule Module.Types.Descr do
|
||||
|
||||
@doc """
|
||||
Converts a descr to its quoted string representation.
|
||||
|
||||
## Options
|
||||
|
||||
* `:collapse_structs` - do not show struct fields that match
|
||||
their default type
|
||||
"""
|
||||
@spec to_quoted(term(), to_quoted_opts) :: String.t()
|
||||
def to_quoted_string(descr, opts \\ []) do
|
||||
descr
|
||||
|> to_quoted(opts)
|
||||
|
||||
@@ -6,6 +6,13 @@ defmodule Module.Types.Helpers do
|
||||
# AST and enumeration helpers.
|
||||
@moduledoc false
|
||||
|
||||
@typedoc """
|
||||
Options for `expr_to_string/2`.
|
||||
"""
|
||||
@type expr_to_string_opts :: [
|
||||
collapse_structs: boolean()
|
||||
]
|
||||
|
||||
## AST helpers
|
||||
|
||||
@doc """
|
||||
@@ -272,6 +279,7 @@ defmodule Module.Types.Helpers do
|
||||
|
||||
We also undo some macro expressions done by the Kernel module.
|
||||
"""
|
||||
@spec expr_to_string(Macro.t(), expr_to_string_opts) :: String.t()
|
||||
def expr_to_string(expr, opts \\ []) do
|
||||
string = prewalk_expr_to_string(expr, opts)
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ defmodule Path do
|
||||
"""
|
||||
@type t :: IO.chardata()
|
||||
|
||||
@type relative_to_opts :: [force: boolean()]
|
||||
|
||||
@doc """
|
||||
Converts the given path to an absolute one.
|
||||
|
||||
@@ -401,7 +403,7 @@ defmodule Path do
|
||||
Path.relative_to("../foo", "/usr/local") #=> "../foo"
|
||||
|
||||
"""
|
||||
@spec relative_to(t, t, keyword) :: binary
|
||||
@spec relative_to(t, t, relative_to_opts) :: binary
|
||||
def relative_to(path, cwd, opts \\ []) when is_list(opts) do
|
||||
os_type = major_os_type()
|
||||
split_path = split(path)
|
||||
@@ -479,7 +481,7 @@ defmodule Path do
|
||||
|
||||
Check `relative_to/3` for the supported options.
|
||||
"""
|
||||
@spec relative_to_cwd(t, keyword) :: binary
|
||||
@spec relative_to_cwd(t, relative_to_opts) :: binary
|
||||
def relative_to_cwd(path, opts \\ []) when is_list(opts) do
|
||||
case :file.get_cwd() do
|
||||
{:ok, base} -> relative_to(path, IO.chardata_to_string(base), opts)
|
||||
@@ -801,7 +803,7 @@ defmodule Path do
|
||||
Path.wildcard("projects/*/ebin/**/*.{beam,app}")
|
||||
|
||||
"""
|
||||
@spec wildcard(t, keyword) :: [binary]
|
||||
@spec wildcard(t, match_dot: boolean()) :: [binary]
|
||||
def wildcard(glob, opts \\ []) when is_list(opts) do
|
||||
mod = if Keyword.get(opts, :match_dot), do: :file, else: Path.Wildcard
|
||||
|
||||
|
||||
@@ -45,6 +45,13 @@ defmodule Record do
|
||||
a module by calling `Code.fetch_docs/1`.
|
||||
"""
|
||||
|
||||
@type extract_opts :: [
|
||||
from: binary(),
|
||||
from_lib: binary(),
|
||||
includes: [binary()],
|
||||
macros: keyword()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Extracts record information from an Erlang file.
|
||||
|
||||
@@ -102,7 +109,7 @@ defmodule Record do
|
||||
]
|
||||
|
||||
"""
|
||||
@spec extract(name :: atom, keyword) :: keyword
|
||||
@spec extract(name :: atom, extract_opts) :: keyword
|
||||
def extract(name, opts) when is_atom(name) and is_list(opts) do
|
||||
Record.Extractor.extract(name, opts)
|
||||
end
|
||||
@@ -119,7 +126,7 @@ defmodule Record do
|
||||
Accepts the same options as listed for `Record.extract/2`.
|
||||
|
||||
"""
|
||||
@spec extract_all(keyword) :: [{name :: atom, keyword}]
|
||||
@spec extract_all(extract_opts) :: [{name :: atom, keyword}]
|
||||
def extract_all(opts) when is_list(opts) do
|
||||
Record.Extractor.extract_all(opts)
|
||||
end
|
||||
|
||||
+30
-4
@@ -164,6 +164,11 @@ defmodule Regex do
|
||||
|
||||
@type t :: %__MODULE__{re_pattern: term, source: binary, opts: [term]}
|
||||
|
||||
@type named_captures_opts :: [
|
||||
return: :binary | :index,
|
||||
offset: non_neg_integer()
|
||||
]
|
||||
|
||||
defmodule CompileError do
|
||||
@moduledoc """
|
||||
An exception raised when a regular expression could not be compiled.
|
||||
@@ -321,7 +326,7 @@ defmodule Regex do
|
||||
["d", ""]
|
||||
|
||||
"""
|
||||
@spec run(t, binary, [term]) :: nil | [binary] | [{integer, integer}]
|
||||
@spec run(t, binary, capture_opts) :: nil | [binary] | [{integer, integer}]
|
||||
def run(regex, string, options \\ [])
|
||||
|
||||
def run(%Regex{} = regex, string, options) when is_binary(string) do
|
||||
@@ -343,6 +348,8 @@ defmodule Regex do
|
||||
|
||||
* `:return` - when set to `:index`, returns byte index and match length.
|
||||
Defaults to `:binary`.
|
||||
* `:offset` - (since v1.12.0) specifies the starting offset to match in the given string.
|
||||
Defaults to zero.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -363,7 +370,7 @@ defmodule Regex do
|
||||
|
||||
You can then use `binary_part/3` to fetch the relevant part from the given string.
|
||||
"""
|
||||
@spec named_captures(t, String.t(), keyword) :: map | nil
|
||||
@spec named_captures(t, String.t(), named_captures_opts) :: map | nil
|
||||
def named_captures(regex, string, options \\ []) when is_binary(string) do
|
||||
names = names(regex)
|
||||
options = Keyword.put(options, :capture, names)
|
||||
@@ -545,7 +552,7 @@ defmodule Regex do
|
||||
[["cd"], ["ce"]]
|
||||
|
||||
"""
|
||||
@spec scan(t(), String.t(), [term()]) :: [[String.t()]] | [[{integer(), integer()}]]
|
||||
@spec scan(t(), String.t(), capture_opts) :: [[String.t()]] | [[{integer(), integer()}]]
|
||||
def scan(regex, string, options \\ [])
|
||||
|
||||
def scan(%Regex{} = regex, string, options) when is_binary(string) do
|
||||
@@ -573,6 +580,25 @@ defmodule Regex do
|
||||
end
|
||||
end
|
||||
|
||||
@typedoc """
|
||||
Options for regex functions that capture matches.
|
||||
"""
|
||||
@type capture_opts :: [
|
||||
return: :binary | :index,
|
||||
capture: :all | :first | :all_but_first | :none | :all_names | [binary() | atom()],
|
||||
offset: non_neg_integer()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for `split/3`.
|
||||
"""
|
||||
@type split_opts :: [
|
||||
parts: pos_integer() | :infinity,
|
||||
trim: boolean(),
|
||||
on: :first | :all | :all_but_first | :none | :all_names | [atom() | integer()],
|
||||
include_captures: boolean()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Splits the given target based on the given pattern and in the given number of
|
||||
parts.
|
||||
@@ -626,7 +652,7 @@ defmodule Regex do
|
||||
["a", "b", "c"]
|
||||
|
||||
"""
|
||||
@spec split(t, String.t(), [term]) :: [String.t()]
|
||||
@spec split(t, String.t(), split_opts) :: [String.t()]
|
||||
def split(regex, string, options \\ [])
|
||||
|
||||
def split(%Regex{}, "", opts) do
|
||||
|
||||
@@ -242,6 +242,11 @@ defmodule Registry do
|
||||
{:register, registry, key, registry_partition :: pid, value}
|
||||
| {:unregister, registry, key, registry_partition :: pid}
|
||||
|
||||
@typedoc """
|
||||
Options used for `dispatch/4`.
|
||||
"""
|
||||
@type dispatch_opts :: [parallel: boolean()]
|
||||
|
||||
## Via callbacks
|
||||
|
||||
@doc false
|
||||
@@ -483,9 +488,15 @@ defmodule Registry do
|
||||
|
||||
See the module documentation for examples of using the `dispatch/3`
|
||||
function for building custom dispatching or a pubsub system.
|
||||
|
||||
## Options
|
||||
|
||||
* `:parallel` - if `true`, the dispatching is done in parallel
|
||||
across all partitions. Defaults to `false`.
|
||||
|
||||
"""
|
||||
@doc since: "1.4.0"
|
||||
@spec dispatch(registry, key, dispatcher, keyword) :: :ok
|
||||
@spec dispatch(registry, key, dispatcher, dispatch_opts) :: :ok
|
||||
when dispatcher: (entries :: [{pid, value}] -> term) | {module(), atom(), [term()]}
|
||||
def dispatch(registry, key, mfa_or_fun, opts \\ [])
|
||||
when is_atom(registry) and is_function(mfa_or_fun, 1)
|
||||
|
||||
@@ -298,6 +298,15 @@ defmodule String do
|
||||
| [nonempty_binary]
|
||||
| (compiled_search_pattern :: :binary.cp())
|
||||
|
||||
@type split_opts :: [
|
||||
parts: pos_integer() | :infinity,
|
||||
trim: boolean()
|
||||
]
|
||||
|
||||
@type splitter_opts :: [trim: boolean()]
|
||||
|
||||
@type replace_opts :: [global: boolean()]
|
||||
|
||||
@conditional_mappings [:greek, :turkic]
|
||||
|
||||
@doc """
|
||||
@@ -502,7 +511,8 @@ defmodule String do
|
||||
["a", "b", " c "]
|
||||
|
||||
"""
|
||||
@spec split(t, pattern | Regex.t(), keyword) :: [t]
|
||||
@spec split(t, pattern, split_opts()) :: [t]
|
||||
@spec split(t, Regex.t(), Regex.split_opts()) :: [t]
|
||||
def split(string, pattern, options \\ [])
|
||||
|
||||
def split(string, %Regex{} = pattern, options) when is_binary(string) and is_list(options) do
|
||||
@@ -607,7 +617,7 @@ defmodule String do
|
||||
["1", "2", "3", "4"]
|
||||
|
||||
"""
|
||||
@spec splitter(t, pattern, keyword) :: Enumerable.t()
|
||||
@spec splitter(t, pattern, splitter_opts) :: Enumerable.t()
|
||||
def splitter(string, pattern, options \\ [])
|
||||
|
||||
def splitter(string, "", options) when is_binary(string) and is_list(options) do
|
||||
@@ -1616,7 +1626,7 @@ defmodule String do
|
||||
"é"
|
||||
|
||||
"""
|
||||
@spec replace(t, pattern | Regex.t(), t | (t -> t | iodata), keyword) :: t
|
||||
@spec replace(t, pattern | Regex.t(), t | (t -> t | iodata), replace_opts) :: t
|
||||
def replace(subject, pattern, replacement, options \\ [])
|
||||
when is_binary(subject) and
|
||||
(is_binary(replacement) or is_function(replacement, 1)) and
|
||||
|
||||
@@ -17,6 +17,11 @@ defmodule StringIO do
|
||||
|
||||
"""
|
||||
|
||||
@type open_opts :: [
|
||||
capture_prompt: boolean(),
|
||||
encoding: :unicode | :latin1
|
||||
]
|
||||
|
||||
# We're implementing the GenServer behaviour instead of using the
|
||||
# `use GenServer` macro, because we don't want the `child_spec/1`
|
||||
# function as it doesn't make sense to be started under a supervisor.
|
||||
@@ -59,7 +64,7 @@ defmodule StringIO do
|
||||
|
||||
"""
|
||||
@doc since: "1.7.0"
|
||||
@spec open(binary, keyword, (pid -> res)) :: {:ok, res} when res: var
|
||||
@spec open(binary, open_opts, (pid -> res)) :: {:ok, res} when res: var
|
||||
def open(string, options, function)
|
||||
when is_binary(string) and is_list(options) and is_function(function, 1) do
|
||||
{:ok, pid} = GenServer.start(__MODULE__, {self(), string, options}, [])
|
||||
@@ -83,7 +88,8 @@ defmodule StringIO do
|
||||
If options are provided, the result will be `{:ok, pid}`, returning the
|
||||
IO device created. The option `:capture_prompt`, when set to `true`, causes
|
||||
prompts (which are specified as arguments to `IO.get*` functions) to be
|
||||
included in the device's output.
|
||||
included in the device's output. See `options/3` for the list of supported
|
||||
options.
|
||||
|
||||
If a function is provided, the device will be created and sent to the
|
||||
function. When the function returns, the device will be closed. The final
|
||||
@@ -111,7 +117,7 @@ defmodule StringIO do
|
||||
{:ok, {"", "The input was foo"}}
|
||||
|
||||
"""
|
||||
@spec open(binary, keyword) :: {:ok, pid}
|
||||
@spec open(binary, open_opts) :: {:ok, pid}
|
||||
@spec open(binary, (pid -> res)) :: {:ok, res} when res: var
|
||||
def open(string, options_or_function \\ [])
|
||||
|
||||
|
||||
@@ -659,6 +659,19 @@ defmodule Supervisor do
|
||||
@typedoc since: "1.16.0"
|
||||
@type module_spec :: {module(), args :: term()} | module()
|
||||
|
||||
@typedoc """
|
||||
Options for overriding child specification fields.
|
||||
"""
|
||||
@type child_spec_overrides :: [
|
||||
id: atom() | term(),
|
||||
start: {module(), atom(), [term()]},
|
||||
restart: restart(),
|
||||
shutdown: shutdown(),
|
||||
type: type(),
|
||||
modules: [module()] | :dynamic,
|
||||
significant: boolean()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Starts a supervisor with the given children.
|
||||
|
||||
@@ -896,7 +909,7 @@ defmodule Supervisor do
|
||||
#=> start: {Agent, :start_link, [fn -> :ok end]}}
|
||||
|
||||
"""
|
||||
@spec child_spec(child_spec() | module_spec(), keyword()) :: child_spec()
|
||||
@spec child_spec(child_spec() | module_spec(), child_spec_overrides()) :: child_spec()
|
||||
def child_spec(module_or_map, overrides)
|
||||
|
||||
def child_spec({_, _, _, _, _, _} = tuple, _overrides) do
|
||||
|
||||
@@ -113,6 +113,28 @@ defmodule System do
|
||||
| :sigusr1
|
||||
| :sigusr2
|
||||
|
||||
@type cmd_opts :: [
|
||||
into: Collectable.t(),
|
||||
lines: pos_integer(),
|
||||
cd: Path.t(),
|
||||
env: [{binary(), binary() | nil}],
|
||||
arg0: binary(),
|
||||
stderr_to_stdout: boolean(),
|
||||
use_stdio: boolean(),
|
||||
parallelism: boolean()
|
||||
]
|
||||
|
||||
@type shell_opts :: [
|
||||
into: Collectable.t(),
|
||||
lines: pos_integer(),
|
||||
cd: Path.t(),
|
||||
env: [{binary(), binary() | nil}],
|
||||
stderr_to_stdout: boolean(),
|
||||
use_stdio: boolean(),
|
||||
parallelism: boolean(),
|
||||
close_stdin: boolean()
|
||||
]
|
||||
|
||||
@vm_signals [:sigquit, :sigterm, :sigusr1]
|
||||
@os_signals [:sighup, :sigabrt, :sigalrm, :sigusr2, :sigchld, :sigstop, :sigtstp]
|
||||
@signals @vm_signals ++ @os_signals
|
||||
@@ -941,7 +963,7 @@ defmodule System do
|
||||
immediately terminate. Defaults to false.
|
||||
"""
|
||||
@doc since: "1.12.0"
|
||||
@spec shell(binary, keyword) :: {Collectable.t(), exit_status :: non_neg_integer}
|
||||
@spec shell(binary, shell_opts) :: {Collectable.t(), exit_status :: non_neg_integer}
|
||||
def shell(command, opts \\ []) when is_binary(command) do
|
||||
command |> String.trim() |> do_shell(opts)
|
||||
end
|
||||
@@ -1101,7 +1123,7 @@ defmodule System do
|
||||
If you desire to execute a trusted command inside a shell, with pipes,
|
||||
redirecting and so on, please check `shell/2`.
|
||||
"""
|
||||
@spec cmd(binary, [binary], keyword) :: {Collectable.t(), exit_status :: non_neg_integer}
|
||||
@spec cmd(binary, [binary], cmd_opts) :: {Collectable.t(), exit_status :: non_neg_integer}
|
||||
def cmd(command, args, opts \\ []) when is_binary(command) and is_list(args) do
|
||||
assert_no_null_byte!(command, "System.cmd/3")
|
||||
|
||||
|
||||
@@ -87,6 +87,18 @@ defmodule Task.Supervisor do
|
||||
@typedoc since: "1.17.0"
|
||||
@type async_stream_option :: Task.async_stream_option() | {:shutdown, Supervisor.shutdown()}
|
||||
|
||||
@typedoc """
|
||||
Options for `async/3`, `async/5`, `async_nolink/3`, and `async_nolink/5` functions.
|
||||
"""
|
||||
@type async_opts :: [
|
||||
shutdown: :brutal_kill | timeout()
|
||||
]
|
||||
|
||||
@type start_child_opts :: [
|
||||
restart: :temporary | :transient | :permanent,
|
||||
shutdown: :brutal_kill | timeout()
|
||||
]
|
||||
|
||||
@doc false
|
||||
def child_spec(opts) when is_list(opts) do
|
||||
id =
|
||||
@@ -175,7 +187,7 @@ defmodule Task.Supervisor do
|
||||
The tasks must trap exits for the timeout to have an effect.
|
||||
|
||||
"""
|
||||
@spec async(Supervisor.supervisor(), (-> any), Keyword.t()) :: Task.t()
|
||||
@spec async(Supervisor.supervisor(), (-> any), async_opts) :: Task.t()
|
||||
def async(supervisor, fun, options \\ []) do
|
||||
async(supervisor, :erlang, :apply, [fun, []], options)
|
||||
end
|
||||
@@ -197,7 +209,7 @@ defmodule Task.Supervisor do
|
||||
The tasks must trap exits for the timeout to have an effect.
|
||||
|
||||
"""
|
||||
@spec async(Supervisor.supervisor(), module, atom, [term], Keyword.t()) :: Task.t()
|
||||
@spec async(Supervisor.supervisor(), module, atom, [term], async_opts) :: Task.t()
|
||||
def async(supervisor, module, fun, args, options \\ []) do
|
||||
async(supervisor, :link, module, fun, args, options)
|
||||
end
|
||||
@@ -284,7 +296,7 @@ defmodule Task.Supervisor do
|
||||
end
|
||||
|
||||
"""
|
||||
@spec async_nolink(Supervisor.supervisor(), (-> any), Keyword.t()) :: Task.t()
|
||||
@spec async_nolink(Supervisor.supervisor(), (-> any), async_opts) :: Task.t()
|
||||
def async_nolink(supervisor, fun, options \\ []) do
|
||||
async_nolink(supervisor, :erlang, :apply, [fun, []], options)
|
||||
end
|
||||
@@ -303,7 +315,7 @@ defmodule Task.Supervisor do
|
||||
as the `:restart` option (the default), as `async_nolink/5` keeps a
|
||||
direct reference to the task which is lost if the task is restarted.
|
||||
"""
|
||||
@spec async_nolink(Supervisor.supervisor(), module, atom, [term], Keyword.t()) :: Task.t()
|
||||
@spec async_nolink(Supervisor.supervisor(), module, atom, [term], async_opts) :: Task.t()
|
||||
def async_nolink(supervisor, module, fun, args, options \\ []) do
|
||||
async(supervisor, :nolink, module, fun, args, options)
|
||||
end
|
||||
@@ -523,7 +535,7 @@ defmodule Task.Supervisor do
|
||||
The task must trap exits for the timeout to have an effect.
|
||||
|
||||
"""
|
||||
@spec start_child(Supervisor.supervisor(), (-> any), keyword) ::
|
||||
@spec start_child(Supervisor.supervisor(), (-> any), start_child_opts) ::
|
||||
DynamicSupervisor.on_start_child()
|
||||
def start_child(supervisor, fun, options \\ []) do
|
||||
restart = options[:restart]
|
||||
@@ -538,7 +550,7 @@ defmodule Task.Supervisor do
|
||||
Similar to `start_child/3` except the task is specified
|
||||
by the given `module`, `fun` and `args`.
|
||||
"""
|
||||
@spec start_child(Supervisor.supervisor(), module, atom, [term], keyword) ::
|
||||
@spec start_child(Supervisor.supervisor(), module, atom, [term], start_child_opts) ::
|
||||
DynamicSupervisor.on_start_child()
|
||||
def start_child(supervisor, module, fun, args, options \\ [])
|
||||
when is_atom(fun) and is_list(args) do
|
||||
|
||||
@@ -118,6 +118,8 @@ defmodule Version do
|
||||
@type build :: String.t() | nil
|
||||
@type t :: %__MODULE__{major: major, minor: minor, patch: patch, pre: pre, build: build}
|
||||
|
||||
@type match_opts :: [allow_pre: boolean()]
|
||||
|
||||
defmodule Requirement do
|
||||
@moduledoc """
|
||||
A struct that holds version requirement information.
|
||||
@@ -296,7 +298,7 @@ defmodule Version do
|
||||
** (Version.InvalidRequirementError) invalid requirement: "== == 1.0.0"
|
||||
|
||||
"""
|
||||
@spec match?(version, requirement, keyword) :: boolean
|
||||
@spec match?(version, requirement, match_opts) :: boolean
|
||||
def match?(version, requirement, opts \\ [])
|
||||
|
||||
def match?(version, requirement, opts) when is_binary(requirement) do
|
||||
|
||||
@@ -93,6 +93,50 @@ defmodule ExUnit do
|
||||
|
||||
@type test_id :: {module, name :: atom}
|
||||
|
||||
@typedoc """
|
||||
Configuration options for ExUnit.
|
||||
|
||||
See `configure/1` for detailed documentation of each option.
|
||||
"""
|
||||
@type configure_opts :: [
|
||||
{:assert_receive_timeout, non_neg_integer()}
|
||||
| {:autorun, boolean()}
|
||||
| {:capture_log, boolean() | [level: Logger.level()]}
|
||||
| {:colors,
|
||||
[
|
||||
enabled: boolean(),
|
||||
success: atom(),
|
||||
invalid: atom(),
|
||||
skipped: atom(),
|
||||
failure: atom(),
|
||||
error_info: atom(),
|
||||
extra_info: atom(),
|
||||
location_info: [atom()],
|
||||
diff_insert: atom(),
|
||||
diff_insert_whitespace: IO.ANSI.ansidata(),
|
||||
diff_delete: atom(),
|
||||
diff_delete_whitespace: IO.ANSI.ansidata()
|
||||
]}
|
||||
| {:exclude, keyword()}
|
||||
| {:exit_status, non_neg_integer()}
|
||||
| {:failures_manifest_path, String.t()}
|
||||
| {:formatters, [module()]}
|
||||
| {:include, keyword()}
|
||||
| {:max_cases, pos_integer()}
|
||||
| {:max_failures, pos_integer() | :infinity}
|
||||
| {:only_test_ids, [test_id()]}
|
||||
| {:rand_algorithm, atom()}
|
||||
| {:refute_receive_timeout, non_neg_integer()}
|
||||
| {:seed, non_neg_integer()}
|
||||
| {:slowest, non_neg_integer()}
|
||||
| {:slowest_modules, non_neg_integer()}
|
||||
| {:stacktrace_depth, non_neg_integer()}
|
||||
| {:timeout, pos_integer()}
|
||||
| {:trace, boolean()}
|
||||
| {:test_location_relative_path, String.t()}
|
||||
| {atom(), term()}
|
||||
]
|
||||
|
||||
defmodule Test do
|
||||
@moduledoc """
|
||||
A struct that keeps information about the test.
|
||||
@@ -218,7 +262,7 @@ defmodule ExUnit do
|
||||
If you want to run tests manually, you can set the `:autorun` option
|
||||
to `false` and use `run/0` to run tests.
|
||||
"""
|
||||
@spec start(Keyword.t()) :: :ok
|
||||
@spec start(configure_opts()) :: :ok
|
||||
def start(options \\ []) do
|
||||
{:ok, _} = Application.ensure_all_started(:ex_unit)
|
||||
|
||||
@@ -357,7 +401,7 @@ defmodule ExUnit do
|
||||
and these options can then be used in places such as custom formatters. These
|
||||
other options will be ignored by ExUnit itself.
|
||||
"""
|
||||
@spec configure(Keyword.t()) :: :ok
|
||||
@spec configure(configure_opts()) :: :ok
|
||||
def configure(options) when is_list(options) do
|
||||
Enum.each(options, fn {k, v} ->
|
||||
Application.put_env(:ex_unit, k, v)
|
||||
|
||||
@@ -169,6 +169,12 @@ defmodule ExUnit.Callbacks do
|
||||
end
|
||||
"""
|
||||
|
||||
@type child_spec_overrides :: [
|
||||
restart: :permanent | :transient | :temporary,
|
||||
shutdown: :brutal_kill | timeout(),
|
||||
type: :worker | :supervisor
|
||||
]
|
||||
|
||||
@doc false
|
||||
def __register__(module) do
|
||||
Module.put_attribute(module, :ex_unit_describe, nil)
|
||||
@@ -560,7 +566,7 @@ defmodule ExUnit.Callbacks do
|
||||
more about these keys in [the `Task` module](`Task#module-ancestor-and-caller-tracking`).
|
||||
"""
|
||||
@doc since: "1.5.0"
|
||||
@spec start_supervised(Supervisor.child_spec() | module | {module, term}, keyword) ::
|
||||
@spec start_supervised(Supervisor.child_spec() | module | {module, term}, child_spec_overrides) ::
|
||||
Supervisor.on_start_child()
|
||||
def start_supervised(child_spec_or_module, opts \\ []) do
|
||||
sup =
|
||||
@@ -581,7 +587,8 @@ defmodule ExUnit.Callbacks do
|
||||
not started properly.
|
||||
"""
|
||||
@doc since: "1.6.0"
|
||||
@spec start_supervised!(Supervisor.child_spec() | module | {module, term}, keyword) :: pid
|
||||
@spec start_supervised!(Supervisor.child_spec() | module | {module, term}, child_spec_overrides) ::
|
||||
pid
|
||||
def start_supervised!(child_spec_or_module, opts \\ []) do
|
||||
case start_supervised(child_spec_or_module, opts) do
|
||||
{:ok, pid} ->
|
||||
@@ -627,7 +634,10 @@ defmodule ExUnit.Callbacks do
|
||||
> *by the test supervisor* in reverse order, ensuring graceful termination.
|
||||
"""
|
||||
@doc since: "1.14.0"
|
||||
@spec start_link_supervised!(Supervisor.child_spec() | module | {module, term}, keyword) ::
|
||||
@spec start_link_supervised!(
|
||||
Supervisor.child_spec() | module | {module, term},
|
||||
child_spec_overrides
|
||||
) ::
|
||||
pid
|
||||
def start_link_supervised!(child_spec_or_module, opts \\ []) do
|
||||
pid = start_supervised!(child_spec_or_module, opts)
|
||||
|
||||
@@ -28,6 +28,12 @@ defmodule ExUnit.CaptureIO do
|
||||
|
||||
"""
|
||||
|
||||
@type capture_io_opts :: [
|
||||
input: String.t(),
|
||||
capture_prompt: boolean(),
|
||||
encoding: :unicode | :latin1
|
||||
]
|
||||
|
||||
@doc """
|
||||
Captures IO generated when evaluating `fun`.
|
||||
|
||||
@@ -152,7 +158,7 @@ defmodule ExUnit.CaptureIO do
|
||||
|
||||
See `capture_io/1` for more information.
|
||||
"""
|
||||
@spec capture_io(atom() | pid() | String.t() | keyword(), (-> any())) :: String.t()
|
||||
@spec capture_io(atom() | pid() | String.t() | capture_io_opts, (-> any())) :: String.t()
|
||||
def capture_io(device_pid_input_or_options, fun)
|
||||
|
||||
def capture_io(device_or_pid, fun)
|
||||
@@ -172,7 +178,7 @@ defmodule ExUnit.CaptureIO do
|
||||
|
||||
See `capture_io/1` for more information.
|
||||
"""
|
||||
@spec capture_io(atom() | pid(), String.t() | keyword(), (-> any())) :: String.t()
|
||||
@spec capture_io(atom() | pid(), String.t() | capture_io_opts, (-> any())) :: String.t()
|
||||
def capture_io(device_or_pid, input_or_options, fun)
|
||||
when (is_atom(device_or_pid) or is_pid(device_or_pid)) and
|
||||
(is_binary(input_or_options) or is_list(input_or_options)) and is_function(fun, 0) do
|
||||
@@ -209,7 +215,7 @@ defmodule ExUnit.CaptureIO do
|
||||
See `with_io/1` for more information.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec with_io(atom() | pid() | String.t() | keyword(), (-> any())) :: {any(), String.t()}
|
||||
@spec with_io(atom() | pid() | String.t() | capture_io_opts, (-> any())) :: {any(), String.t()}
|
||||
def with_io(device_pid_input_or_options, fun)
|
||||
|
||||
def with_io(device, fun) when is_atom(device) and is_function(fun, 0) do
|
||||
@@ -234,7 +240,7 @@ defmodule ExUnit.CaptureIO do
|
||||
See `with_io/1` for more information.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec with_io(atom() | pid(), String.t() | keyword(), (-> any())) :: {any(), String.t()}
|
||||
@spec with_io(atom() | pid(), String.t() | capture_io_opts, (-> any())) :: {any(), String.t()}
|
||||
def with_io(device_or_pid, input_or_options, fun)
|
||||
|
||||
def with_io(device, input, fun)
|
||||
|
||||
@@ -43,6 +43,10 @@ defmodule ExUnit.CaptureLog do
|
||||
|
||||
@compile {:no_warn_undefined, Logger}
|
||||
|
||||
@type capture_log_opts :: [
|
||||
level: Logger.level() | nil
|
||||
]
|
||||
|
||||
@doc """
|
||||
Captures Logger messages generated when evaluating `fun`.
|
||||
|
||||
@@ -74,7 +78,7 @@ defmodule ExUnit.CaptureLog do
|
||||
To get the result of the evaluation along with the captured log,
|
||||
use `with_log/2`.
|
||||
"""
|
||||
@spec capture_log(keyword, (-> any)) :: String.t()
|
||||
@spec capture_log(capture_log_opts, (-> any)) :: String.t()
|
||||
def capture_log(opts \\ [], fun) do
|
||||
{_, log} = with_log(opts, fun)
|
||||
log
|
||||
@@ -98,7 +102,7 @@ defmodule ExUnit.CaptureLog do
|
||||
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec with_log(keyword, (-> result)) :: {result, log :: String.t()} when result: any
|
||||
@spec with_log(capture_log_opts, (-> result)) :: {result, log :: String.t()} when result: any
|
||||
def with_log(opts \\ [], fun) when is_list(opts) do
|
||||
opts =
|
||||
if opts[:level] == :warn do
|
||||
|
||||
@@ -338,6 +338,11 @@ defmodule ExUnit.Case do
|
||||
"""
|
||||
|
||||
@type env :: module() | Macro.Env.t()
|
||||
|
||||
@type register_attribute_opts :: [
|
||||
accumulate: boolean(),
|
||||
persist: boolean()
|
||||
]
|
||||
@compile {:no_warn_undefined, [IEx.Pry]}
|
||||
@reserved [:module, :file, :line, :test, :async, :registered, :describe]
|
||||
|
||||
@@ -767,7 +772,7 @@ defmodule ExUnit.Case do
|
||||
|
||||
"""
|
||||
@doc since: "1.3.0"
|
||||
@spec register_attribute(env, atom, keyword) :: :ok
|
||||
@spec register_attribute(env, atom, register_attribute_opts) :: :ok
|
||||
def register_attribute(env, name, opts \\ [])
|
||||
def register_attribute(%{module: mod}, name, opts), do: register_attribute(mod, name, opts)
|
||||
|
||||
@@ -809,7 +814,7 @@ defmodule ExUnit.Case do
|
||||
|
||||
"""
|
||||
@doc since: "1.10.0"
|
||||
@spec register_describe_attribute(env, atom, keyword) :: :ok
|
||||
@spec register_describe_attribute(env, atom, register_attribute_opts) :: :ok
|
||||
def register_describe_attribute(env, name, opts \\ [])
|
||||
|
||||
def register_describe_attribute(%{module: mod}, name, opts) do
|
||||
@@ -849,7 +854,7 @@ defmodule ExUnit.Case do
|
||||
|
||||
"""
|
||||
@doc since: "1.10.0"
|
||||
@spec register_module_attribute(env, atom, keyword) :: :ok
|
||||
@spec register_module_attribute(env, atom, register_attribute_opts) :: :ok
|
||||
def register_module_attribute(env, name, opts \\ [])
|
||||
|
||||
def register_module_attribute(%{module: mod}, name, opts) do
|
||||
|
||||
+73
-1
@@ -390,6 +390,78 @@ defmodule IEx do
|
||||
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Color settings used by the IEx shell.
|
||||
"""
|
||||
@type colors_opts :: [
|
||||
enabled: boolean(),
|
||||
eval_result: IO.ANSI.ansidata(),
|
||||
eval_info: IO.ANSI.ansidata(),
|
||||
eval_error: IO.ANSI.ansidata(),
|
||||
eval_interrupt: IO.ANSI.ansidata(),
|
||||
stack_info: IO.ANSI.ansidata(),
|
||||
blame_diff: IO.ANSI.ansidata(),
|
||||
ls_directory: IO.ANSI.ansidata(),
|
||||
ls_device: IO.ANSI.ansidata(),
|
||||
doc_code: IO.ANSI.ansidata(),
|
||||
doc_inline_code: IO.ANSI.ansidata(),
|
||||
doc_headings: IO.ANSI.ansidata(),
|
||||
doc_title: IO.ANSI.ansidata(),
|
||||
doc_bold: IO.ANSI.ansidata(),
|
||||
doc_underline: IO.ANSI.ansidata(),
|
||||
syntax_colors: syntax_colors_opts() | false
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Syntax coloring settings for inspected expressions.
|
||||
"""
|
||||
@type syntax_colors_opts :: [
|
||||
atom: IO.ANSI.ansidata(),
|
||||
binary: IO.ANSI.ansidata(),
|
||||
boolean: IO.ANSI.ansidata(),
|
||||
charlist: IO.ANSI.ansidata(),
|
||||
list: IO.ANSI.ansidata(),
|
||||
map: IO.ANSI.ansidata(),
|
||||
nil: IO.ANSI.ansidata(),
|
||||
number: IO.ANSI.ansidata(),
|
||||
string: IO.ANSI.ansidata(),
|
||||
tuple: IO.ANSI.ansidata(),
|
||||
variable: IO.ANSI.ansidata(),
|
||||
call: IO.ANSI.ansidata(),
|
||||
operator: IO.ANSI.ansidata(),
|
||||
reset: IO.ANSI.ansidata()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Inspect settings used by the IEx shell.
|
||||
"""
|
||||
@type inspect_opts :: [
|
||||
base: :binary | :decimal | :octal | :hex,
|
||||
binaries: :infer | :as_binaries | :as_strings,
|
||||
charlists: :infer | :as_charlists | :as_lists,
|
||||
custom_options: keyword(),
|
||||
inspect_fun: (term(), Inspect.Opts.t() -> Inspect.Algebra.t()),
|
||||
limit: pos_integer() | :infinity,
|
||||
pretty: boolean(),
|
||||
printable_limit: pos_integer() | :infinity,
|
||||
safe: boolean(),
|
||||
structs: boolean(),
|
||||
syntax_colors: syntax_colors_opts(),
|
||||
width: pos_integer() | :infinity
|
||||
]
|
||||
|
||||
@type configure_opts :: [
|
||||
auto_reload: boolean(),
|
||||
alive_prompt: String.t(),
|
||||
colors: colors_opts(),
|
||||
default_prompt: String.t(),
|
||||
dot_iex: String.t() | nil,
|
||||
history_size: integer(),
|
||||
inspect: inspect_opts(),
|
||||
parser: {module(), atom(), [any()]},
|
||||
width: pos_integer()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Configures IEx.
|
||||
|
||||
@@ -521,7 +593,7 @@ defmodule IEx do
|
||||
in-memory modules when they get invalidated by a concurrent compilation
|
||||
happening in the Operating System.
|
||||
"""
|
||||
@spec configure(keyword()) :: :ok
|
||||
@spec configure(configure_opts) :: :ok
|
||||
def configure(options) do
|
||||
IEx.Config.configure(options)
|
||||
end
|
||||
|
||||
@@ -9,6 +9,13 @@ defmodule IEx.Broker do
|
||||
@type take_ref :: {takeover_ref :: reference(), server_ref :: reference()}
|
||||
@type shell :: pid | nil
|
||||
|
||||
@typedoc """
|
||||
Options for `take_over/3`.
|
||||
"""
|
||||
@type take_over_opts :: [
|
||||
evaluator: pid()
|
||||
]
|
||||
|
||||
use GenServer
|
||||
|
||||
## Shell API
|
||||
@@ -58,7 +65,7 @@ defmodule IEx.Broker do
|
||||
@doc """
|
||||
Client requests a takeover.
|
||||
"""
|
||||
@spec take_over(binary, iodata, keyword) ::
|
||||
@spec take_over(binary, iodata, take_over_opts) ::
|
||||
{:ok, server :: pid, group_leader :: pid, counter :: integer}
|
||||
| {:error, :no_iex | :refused | atom()}
|
||||
def take_over(location, whereami, opts) do
|
||||
|
||||
@@ -113,6 +113,7 @@ defmodule IEx.Helpers do
|
||||
* `:force` - when `true`, forces the application to recompile
|
||||
|
||||
"""
|
||||
@spec recompile(force: boolean()) :: :ok | :error | :noop
|
||||
def recompile(options \\ []) do
|
||||
cond do
|
||||
not mix_started?() ->
|
||||
|
||||
@@ -14,6 +14,14 @@ defmodule IEx.Server do
|
||||
|
||||
"""
|
||||
|
||||
@type run_opts :: [
|
||||
prefix: String.t(),
|
||||
env: Macro.Env.t(),
|
||||
binding: keyword(),
|
||||
on_eof: :stop_evaluator | :halt,
|
||||
register: boolean()
|
||||
]
|
||||
|
||||
@doc false
|
||||
defstruct parser_state: [],
|
||||
counter: 1,
|
||||
@@ -35,7 +43,7 @@ defmodule IEx.Server do
|
||||
|
||||
"""
|
||||
@doc since: "1.8.0"
|
||||
@spec run(keyword) :: :ok
|
||||
@spec run(run_opts) :: :ok
|
||||
def run(opts) when is_list(opts) do
|
||||
if Keyword.get(opts, :register, true) do
|
||||
IEx.Broker.register(self())
|
||||
|
||||
@@ -62,7 +62,16 @@ defmodule IEx.AutocompleteTest do
|
||||
assert expand(~c"t String") == {:yes, ~c"", [~c"String", ~c"StringIO"]}
|
||||
|
||||
assert expand(~c"t String.") ==
|
||||
{:yes, ~c"", [~c"codepoint/0", ~c"grapheme/0", ~c"pattern/0", ~c"t/0"]}
|
||||
{:yes, ~c"",
|
||||
[
|
||||
~c"codepoint/0",
|
||||
~c"grapheme/0",
|
||||
~c"pattern/0",
|
||||
~c"replace_opts/0",
|
||||
~c"split_opts/0",
|
||||
~c"splitter_opts/0",
|
||||
~c"t/0"
|
||||
]}
|
||||
|
||||
assert expand(~c"t String.grap") == {:yes, ~c"heme", []}
|
||||
assert expand(~c"t String.grap") == {:yes, ~c"heme", []}
|
||||
@@ -85,7 +94,16 @@ defmodule IEx.AutocompleteTest do
|
||||
assert expand(~c"t(String") == {:yes, ~c"", [~c"String", ~c"StringIO"]}
|
||||
|
||||
assert expand(~c"t(String.") ==
|
||||
{:yes, ~c"", [~c"codepoint/0", ~c"grapheme/0", ~c"pattern/0", ~c"t/0"]}
|
||||
{:yes, ~c"",
|
||||
[
|
||||
~c"codepoint/0",
|
||||
~c"grapheme/0",
|
||||
~c"pattern/0",
|
||||
~c"replace_opts/0",
|
||||
~c"split_opts/0",
|
||||
~c"splitter_opts/0",
|
||||
~c"t/0"
|
||||
]}
|
||||
|
||||
assert expand(~c"t(String.grap") == {:yes, ~c"heme", []}
|
||||
end
|
||||
|
||||
@@ -967,7 +967,7 @@ defmodule IEx.HelpersTest do
|
||||
|
||||
describe "t" do
|
||||
test "prints when there is no type information or the type is private" do
|
||||
assert capture_io(fn -> t(IEx) end) == "No type information for IEx was found\n"
|
||||
assert capture_io(fn -> t(List) end) == "No type information for List was found\n"
|
||||
|
||||
assert capture_io(fn -> t(Enum.doesnt_exist()) end) ==
|
||||
"No type information for Enum.doesnt_exist was found or " <>
|
||||
|
||||
@@ -507,6 +507,30 @@ defmodule Logger do
|
||||
@type report :: map() | keyword()
|
||||
@type message :: :unicode.chardata() | String.Chars.t() | report()
|
||||
@type metadata :: keyword()
|
||||
|
||||
@type configure_opts :: [
|
||||
level: level(),
|
||||
translator_inspect_opts: Inspect.Opts.t(),
|
||||
sync_threshold: non_neg_integer(),
|
||||
discard_threshold: non_neg_integer(),
|
||||
truncate: non_neg_integer() | :infinity,
|
||||
utc_log: boolean()
|
||||
]
|
||||
|
||||
@type formatter_opts :: [
|
||||
colors: [
|
||||
enabled: boolean(),
|
||||
debug: atom(),
|
||||
info: atom(),
|
||||
warning: atom(),
|
||||
error: atom()
|
||||
],
|
||||
format: String.t() | {module(), atom()},
|
||||
metadata: :all | [atom()],
|
||||
truncate: pos_integer() | :infinity,
|
||||
utc_log: boolean()
|
||||
]
|
||||
|
||||
@new_erlang_levels [:emergency, :alert, :critical, :warning, :notice]
|
||||
@levels [:error, :info, :debug] ++ @new_erlang_levels
|
||||
@metadata :logger_level
|
||||
@@ -552,7 +576,7 @@ defmodule Logger do
|
||||
instead.
|
||||
"""
|
||||
@doc since: "1.15.0"
|
||||
@spec default_formatter(keyword) :: {module, :logger.formatter_config()}
|
||||
@spec default_formatter(formatter_opts) :: {module, :logger.formatter_config()}
|
||||
def default_formatter(overrides \\ []) when is_list(overrides) do
|
||||
Application.get_env(:logger, :default_formatter, [])
|
||||
|> Keyword.merge(overrides)
|
||||
@@ -712,7 +736,7 @@ defmodule Logger do
|
||||
:translator_inspect_opts
|
||||
]
|
||||
@backend_options [:sync_threshold, :discard_threshold, :truncate, :utc_log]
|
||||
@spec configure(keyword) :: :ok
|
||||
@spec configure(configure_opts) :: :ok
|
||||
def configure(options) do
|
||||
for {k, v} <- options do
|
||||
cond do
|
||||
@@ -973,7 +997,7 @@ defmodule Logger do
|
||||
anonymous functions to `bare_log/3` and they will only be evaluated
|
||||
if there is something to be logged.
|
||||
"""
|
||||
@spec bare_log(level, message | (-> message | {message, keyword}), keyword) :: :ok
|
||||
@spec bare_log(level, message | (-> message | {message, keyword}), metadata) :: :ok
|
||||
def bare_log(level, message_or_fun, metadata \\ []) do
|
||||
level = elixir_level_to_erlang_level(level)
|
||||
|
||||
|
||||
@@ -8,13 +8,32 @@ defmodule Logger.Backends.Internal do
|
||||
@name __MODULE__
|
||||
@type backend :: :gen_event.handler()
|
||||
|
||||
@typedoc """
|
||||
Configuration options for Logger backends.
|
||||
|
||||
These are the built-in backend options that can be configured at runtime.
|
||||
"""
|
||||
@type backend_config_opts :: [
|
||||
sync_threshold: pos_integer(),
|
||||
discard_threshold: pos_integer() | :infinity,
|
||||
truncate: pos_integer() | :infinity,
|
||||
utc_log: boolean()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for `add/2` and `remove/2` operations.
|
||||
"""
|
||||
@type add_remove_opts :: [
|
||||
flush: boolean()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Apply runtime configuration to all backends.
|
||||
|
||||
See the module doc for more information.
|
||||
"""
|
||||
@backend_options [:sync_threshold, :discard_threshold, :truncate, :utc_log]
|
||||
@spec configure(keyword) :: :ok
|
||||
@spec configure(backend_config_opts) :: :ok
|
||||
def configure(options) do
|
||||
ensure_started()
|
||||
Logger.Backends.Config.configure(Keyword.take(options, @backend_options))
|
||||
@@ -65,7 +84,7 @@ defmodule Logger.Backends.Internal do
|
||||
{:ok, _pid} = Logger.add_backend(MyBackend, flush: true)
|
||||
|
||||
"""
|
||||
@spec add(backend, keyword) :: Supervisor.on_start_child()
|
||||
@spec add(backend, add_remove_opts) :: Supervisor.on_start_child()
|
||||
def add(backend, opts \\ []) do
|
||||
ensure_started()
|
||||
_ = if opts[:flush], do: Logger.flush()
|
||||
@@ -91,7 +110,7 @@ defmodule Logger.Backends.Internal do
|
||||
to `Logger` are processed before the backend is removed
|
||||
|
||||
"""
|
||||
@spec remove(backend, keyword) :: :ok | {:error, term}
|
||||
@spec remove(backend, add_remove_opts) :: :ok | {:error, term}
|
||||
def remove(backend, opts \\ []) do
|
||||
ensure_started()
|
||||
_ = if opts[:flush], do: Logger.flush()
|
||||
|
||||
@@ -99,6 +99,20 @@ defmodule Logger.Formatter do
|
||||
@type date_time_ms :: {date, time_ms}
|
||||
|
||||
@type pattern :: :date | :level | :levelpad | :message | :metadata | :node | :time
|
||||
|
||||
@type new_opts :: [
|
||||
colors: [
|
||||
enabled: boolean(),
|
||||
debug: atom(),
|
||||
info: atom(),
|
||||
warning: atom(),
|
||||
error: atom()
|
||||
],
|
||||
format: String.t() | {module(), atom()},
|
||||
metadata: :all | [atom()],
|
||||
truncate: pos_integer() | :infinity,
|
||||
utc_log: boolean()
|
||||
]
|
||||
@valid_patterns [:time, :date, :message, :level, :node, :metadata, :levelpad]
|
||||
@default_pattern "\n$time $metadata[$level] $message\n"
|
||||
@replacement "�"
|
||||
@@ -152,7 +166,7 @@ defmodule Logger.Formatter do
|
||||
The color of the message can also be configured per message via
|
||||
the `:ansi_color` metadata.
|
||||
"""
|
||||
@spec new(keyword) :: formatter when formatter: term
|
||||
@spec new(new_opts) :: formatter when formatter: term
|
||||
def new(options \\ []) do
|
||||
template = compile(options[:format])
|
||||
colors = colors(options[:colors] || [])
|
||||
|
||||
@@ -127,6 +127,12 @@ defmodule Logger.Utils do
|
||||
For information about format scanning and how to consume them,
|
||||
check `:io_lib.scan_format/2`.
|
||||
"""
|
||||
@spec scan_inspect(
|
||||
atom() | binary() | charlist(),
|
||||
list(),
|
||||
non_neg_integer() | :infinity,
|
||||
Inspect.Opts.t()
|
||||
) :: [:io_lib.format_spec()]
|
||||
def scan_inspect(format, args, truncate, opts \\ %Inspect.Opts{})
|
||||
|
||||
def scan_inspect(format, args, truncate, opts) when is_atom(format) do
|
||||
|
||||
@@ -424,6 +424,25 @@ defmodule Mix do
|
||||
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Options for `install/2`.
|
||||
|
||||
See the `install/2` function documentation for detailed information about each option.
|
||||
"""
|
||||
@type install_opts :: [
|
||||
force: boolean(),
|
||||
verbose: boolean(),
|
||||
consolidate_protocols: boolean(),
|
||||
elixir: String.t(),
|
||||
system_env: Enum.t(),
|
||||
config: keyword(),
|
||||
config_path: String.t() | atom(),
|
||||
lockfile: String.t() | atom(),
|
||||
start_applications: boolean(),
|
||||
compilers: [atom()],
|
||||
runtime_config: keyword()
|
||||
]
|
||||
|
||||
@mix_install_project Mix.InstallProject
|
||||
@mix_install_app :mix_install
|
||||
@mix_install_app_string Atom.to_string(@mix_install_app)
|
||||
@@ -845,6 +864,10 @@ defmodule Mix do
|
||||
if `:force` is enabled.
|
||||
"""
|
||||
@doc since: "1.12.0"
|
||||
@spec install(
|
||||
[atom() | {atom(), String.t()} | {atom(), String.t(), keyword()} | {atom(), keyword()}],
|
||||
install_opts()
|
||||
) :: :ok
|
||||
def install(deps, opts \\ [])
|
||||
|
||||
def install(deps, opts) when is_list(deps) and is_list(opts) do
|
||||
|
||||
@@ -7,6 +7,15 @@ defmodule Mix.Compilers.Erlang do
|
||||
|
||||
@manifest_vsn 1
|
||||
|
||||
@typedoc """
|
||||
Options for `compile/6`.
|
||||
"""
|
||||
@type compile_opts :: [
|
||||
force: boolean(),
|
||||
parallel: MapSet.t(Path.t()),
|
||||
preload: (-> term())
|
||||
]
|
||||
|
||||
@doc """
|
||||
Compiles the given `mappings`.
|
||||
|
||||
@@ -58,6 +67,14 @@ defmodule Mix.Compilers.Erlang do
|
||||
`{:error, errors, warnings}` in case of error. This function returns
|
||||
`{status, diagnostics}` as specified in `Mix.Task.Compiler`.
|
||||
"""
|
||||
@spec compile(
|
||||
Path.t(),
|
||||
[{Path.t(), Path.t()}],
|
||||
atom(),
|
||||
atom(),
|
||||
compile_opts,
|
||||
(Path.t(), Path.t() -> {:ok, term(), [term()]} | {:error, [term()], [term()]})
|
||||
) :: {Mix.Task.Compiler.status(), [Mix.Task.Compiler.Diagnostic.t()]}
|
||||
def compile(manifest, mappings, src_ext, dest_ext, opts, callback)
|
||||
when is_atom(src_ext) and is_atom(dest_ext) and is_list(opts) do
|
||||
force = opts[:force]
|
||||
|
||||
@@ -79,6 +79,13 @@ defmodule Mix.Dep do
|
||||
system_env: keyword
|
||||
}
|
||||
|
||||
@typedoc """
|
||||
Options for `filter_by_name/3`.
|
||||
"""
|
||||
@type filter_by_name_opts :: [
|
||||
include_children: boolean()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Returns loaded dependencies from the cache for the current environment.
|
||||
|
||||
@@ -197,6 +204,7 @@ defmodule Mix.Dep do
|
||||
|
||||
Raises if any of the names are missing.
|
||||
"""
|
||||
@spec filter_by_name([atom() | String.t()], [t()], filter_by_name_opts) :: [t()]
|
||||
def filter_by_name(given, all_deps, opts \\ []) do
|
||||
# Ensure all apps are atoms
|
||||
apps = to_app_names(given)
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
defmodule Mix.Dep.Converger do
|
||||
@moduledoc false
|
||||
|
||||
@typedoc """
|
||||
Options for `converge/1` and `converge/4`.
|
||||
"""
|
||||
@type converge_opts :: [
|
||||
env: atom(),
|
||||
target: atom()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Topologically sorts the given dependencies.
|
||||
"""
|
||||
@@ -72,6 +80,7 @@ defmodule Mix.Dep.Converger do
|
||||
|
||||
See `Mix.Dep.Loader.children/1` for options.
|
||||
"""
|
||||
@spec converge(converge_opts) :: [Mix.Dep.t()]
|
||||
def converge(opts \\ []) do
|
||||
converge(nil, nil, opts, &{&1, &2, &3}) |> elem(0)
|
||||
end
|
||||
@@ -89,6 +98,7 @@ defmodule Mix.Dep.Converger do
|
||||
|
||||
See `Mix.Dep.Loader.children/1` for options.
|
||||
"""
|
||||
@spec converge(term(), map() | nil, converge_opts, function()) :: {[Mix.Dep.t()], term(), map()}
|
||||
def converge(acc, lock, opts, callback) do
|
||||
{deps, acc, lock} = all(acc, lock, opts, callback)
|
||||
if remote = Mix.RemoteConverger.get(), do: remote.post_converge()
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
defmodule Mix.Dep.Lock do
|
||||
@moduledoc false
|
||||
|
||||
@typedoc """
|
||||
Options for `write/2`.
|
||||
"""
|
||||
@type write_opts :: [
|
||||
file: Path.t(),
|
||||
check_locked: boolean()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Reads the lockfile, returns a map containing
|
||||
each app name and its current lock information.
|
||||
@@ -30,7 +38,7 @@ defmodule Mix.Dep.Lock do
|
||||
@doc """
|
||||
Receives a map and writes it as the latest lock.
|
||||
"""
|
||||
@spec write(map(), keyword) :: :ok
|
||||
@spec write(map(), write_opts) :: :ok
|
||||
def write(map, opts \\ []) do
|
||||
lockfile = opts[:file] || lockfile()
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@ defmodule Mix.Generator do
|
||||
Conveniences for working with paths and generating content.
|
||||
"""
|
||||
|
||||
@type generator_opts :: [
|
||||
force: boolean(),
|
||||
quiet: boolean(),
|
||||
format_elixir: boolean()
|
||||
]
|
||||
|
||||
@doc ~S"""
|
||||
Creates a file with the given contents.
|
||||
|
||||
@@ -17,6 +23,7 @@ defmodule Mix.Generator do
|
||||
|
||||
* `:force` - forces creation without a shell prompt
|
||||
* `:quiet` - does not log command output
|
||||
* `:format_elixir` (since v1.18.0) - if `true`, apply formatter to the generated file
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -25,7 +32,7 @@ defmodule Mix.Generator do
|
||||
true
|
||||
|
||||
"""
|
||||
@spec create_file(Path.t(), iodata, keyword) :: boolean()
|
||||
@spec create_file(Path.t(), iodata, generator_opts) :: boolean()
|
||||
def create_file(path, contents, opts \\ []) when is_binary(path) do
|
||||
log(:green, :creating, Path.relative_to_cwd(path), opts)
|
||||
|
||||
@@ -62,7 +69,7 @@ defmodule Mix.Generator do
|
||||
true
|
||||
|
||||
"""
|
||||
@spec create_directory(Path.t(), keyword) :: true
|
||||
@spec create_directory(Path.t(), quiet: boolean()) :: true
|
||||
def create_directory(path, options \\ []) when is_binary(path) do
|
||||
log(:green, "creating", Path.relative_to_cwd(path), options)
|
||||
File.mkdir_p!(path)
|
||||
@@ -79,6 +86,7 @@ defmodule Mix.Generator do
|
||||
|
||||
* `:force` - forces copying without a shell prompt
|
||||
* `:quiet` - does not log command output
|
||||
* `:format_elixir` (since v1.18.0) - if `true`, apply formatter to the generated file
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -88,7 +96,7 @@ defmodule Mix.Generator do
|
||||
|
||||
"""
|
||||
@doc since: "1.9.0"
|
||||
@spec copy_file(Path.t(), Path.t(), keyword) :: boolean()
|
||||
@spec copy_file(Path.t(), Path.t(), generator_opts) :: boolean()
|
||||
def copy_file(source, target, options \\ []) do
|
||||
create_file(target, File.read!(source), options)
|
||||
end
|
||||
@@ -116,7 +124,7 @@ defmodule Mix.Generator do
|
||||
|
||||
"""
|
||||
@doc since: "1.9.0"
|
||||
@spec copy_template(Path.t(), Path.t(), keyword, keyword) :: boolean()
|
||||
@spec copy_template(Path.t(), Path.t(), keyword, generator_opts) :: boolean()
|
||||
def copy_template(source, target, assigns, options \\ []) do
|
||||
create_file(target, EEx.eval_file(source, assigns: assigns), options)
|
||||
end
|
||||
|
||||
@@ -23,10 +23,27 @@ defmodule Mix.Local.Installer do
|
||||
| {:url, url :: binary}
|
||||
| {:fetcher, dep_spec :: tuple}
|
||||
|
||||
@typedoc """
|
||||
Options for installer functions.
|
||||
|
||||
These options are used by various installer functions to control behavior
|
||||
during installation, parsing, and uninstallation.
|
||||
"""
|
||||
@type installer_opts :: [
|
||||
app: String.t(),
|
||||
submodules: boolean(),
|
||||
sparse: String.t(),
|
||||
force: boolean(),
|
||||
sha512: String.t(),
|
||||
organization: String.t(),
|
||||
repo: String.t(),
|
||||
timeout: pos_integer()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Checks that the `install_spec` and `opts` are supported by the respective module.
|
||||
"""
|
||||
@callback check_install_spec(install_spec, opts :: keyword) :: :ok | {:error, String.t()}
|
||||
@callback check_install_spec(install_spec, opts :: installer_opts) :: :ok | {:error, String.t()}
|
||||
|
||||
@doc """
|
||||
Returns a list of already installed version of the same artifact.
|
||||
@@ -37,7 +54,7 @@ defmodule Mix.Local.Installer do
|
||||
Builds a local artifact either from a remote dependency or for
|
||||
the current project.
|
||||
"""
|
||||
@callback build(install_spec, opts :: Keyword.t()) :: Path.t()
|
||||
@callback build(install_spec, opts :: installer_opts) :: Path.t()
|
||||
|
||||
@doc """
|
||||
The installation itself.
|
||||
@@ -175,7 +192,7 @@ defmodule Mix.Local.Installer do
|
||||
@doc """
|
||||
Receives `argv` and `opts` from options parsing and returns an `install_spec`.
|
||||
"""
|
||||
@spec parse_args([String.t()], keyword) :: install_spec | {:error, String.t()}
|
||||
@spec parse_args([String.t()], installer_opts) :: install_spec | {:error, String.t()}
|
||||
def parse_args(argv, opts)
|
||||
|
||||
def parse_args([], _opts) do
|
||||
|
||||
@@ -158,6 +158,22 @@ defmodule Mix.Project do
|
||||
|
||||
"""
|
||||
|
||||
@type build_structure_opts :: [
|
||||
symlink_ebin: boolean(),
|
||||
source: String.t()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for dependency traversal functions.
|
||||
|
||||
These options control how dependency trees are traversed and filtered
|
||||
in functions like `deps_scms/1`, `deps_paths/1`, and `deps_tree/1`.
|
||||
"""
|
||||
@type deps_traversal_opts :: [
|
||||
depth: pos_integer(),
|
||||
parents: [atom()]
|
||||
]
|
||||
|
||||
@doc false
|
||||
defmacro __using__(_) do
|
||||
quote do
|
||||
@@ -540,7 +556,7 @@ defmodule Mix.Project do
|
||||
|
||||
"""
|
||||
@doc since: "1.10.0"
|
||||
@spec deps_scms(keyword) :: %{optional(atom) => Mix.SCM.t()}
|
||||
@spec deps_scms(deps_traversal_opts) :: %{optional(atom) => Mix.SCM.t()}
|
||||
def deps_scms(opts \\ []) when is_list(opts) do
|
||||
traverse_deps(opts, fn %{scm: scm} -> scm end)
|
||||
end
|
||||
@@ -561,7 +577,7 @@ defmodule Mix.Project do
|
||||
#=> %{foo: "deps/foo", bar: "custom/path/dep"}
|
||||
|
||||
"""
|
||||
@spec deps_paths(keyword) :: %{optional(atom) => Path.t()}
|
||||
@spec deps_paths(deps_traversal_opts) :: %{optional(atom) => Path.t()}
|
||||
def deps_paths(opts \\ []) when is_list(opts) do
|
||||
traverse_deps(opts, fn %{opts: opts} -> opts[:dest] end)
|
||||
end
|
||||
@@ -583,7 +599,7 @@ defmodule Mix.Project do
|
||||
|
||||
"""
|
||||
@doc since: "1.15.0"
|
||||
@spec deps_tree(keyword) :: %{optional(atom) => [atom]}
|
||||
@spec deps_tree(deps_traversal_opts) :: %{optional(atom) => [atom]}
|
||||
def deps_tree(opts \\ []) when is_list(opts) do
|
||||
traverse_deps(opts, fn %{deps: deps} -> Enum.map(deps, & &1.app) end)
|
||||
end
|
||||
@@ -843,8 +859,11 @@ defmodule Mix.Project do
|
||||
|
||||
* `:symlink_ebin` - symlink ebin instead of copying it
|
||||
|
||||
* `:source` - the source directory to copy from.
|
||||
Defaults to the current working directory.
|
||||
|
||||
"""
|
||||
@spec build_structure(keyword, keyword) :: :ok
|
||||
@spec build_structure(keyword, build_structure_opts) :: :ok
|
||||
def build_structure(config \\ config(), opts \\ []) do
|
||||
source = opts[:source] || File.cwd!()
|
||||
target = app_path(config)
|
||||
@@ -878,7 +897,7 @@ defmodule Mix.Project do
|
||||
|
||||
`opts` are the same options that can be passed to `build_structure/2`.
|
||||
"""
|
||||
@spec ensure_structure(keyword, keyword) :: :ok
|
||||
@spec ensure_structure(keyword, build_structure_opts) :: :ok
|
||||
def ensure_structure(config \\ config(), opts \\ []) do
|
||||
if File.exists?(app_path(config)) do
|
||||
:ok
|
||||
|
||||
@@ -68,6 +68,23 @@ defmodule Mix.Release do
|
||||
steps: [(t -> t) | :assemble, ...]
|
||||
}
|
||||
|
||||
@typedoc """
|
||||
Options for stripping BEAM files.
|
||||
"""
|
||||
@type strip_beam_opts :: [
|
||||
keep: [String.t()],
|
||||
compress: boolean()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Erlang/OTP sys.config structure.
|
||||
|
||||
A list of tuples where each tuple contains an application name and its
|
||||
configuration as a keyword list. This is the standard format for Erlang
|
||||
application configuration.
|
||||
"""
|
||||
@type sys_config :: [{application(), keyword()}]
|
||||
|
||||
@default_apps [kernel: :permanent, stdlib: :permanent, elixir: :permanent, sasl: :permanent]
|
||||
@safe_modes [:permanent, :temporary, :transient]
|
||||
@unsafe_modes [:load, :none]
|
||||
@@ -445,7 +462,7 @@ defmodule Mix.Release do
|
||||
|
||||
In case there are no config providers, it doesn't change `sys_config`.
|
||||
"""
|
||||
@spec make_sys_config(t, keyword(), Config.Provider.config_path()) ::
|
||||
@spec make_sys_config(t, sys_config(), Config.Provider.config_path()) ::
|
||||
:ok | {:error, String.t()}
|
||||
def make_sys_config(release, sys_config, config_provider_path) do
|
||||
{sys_config, runtime_config?} =
|
||||
@@ -900,8 +917,26 @@ defmodule Mix.Release do
|
||||
|
||||
The exact chunks that are kept are not documented and may change in
|
||||
future versions.
|
||||
|
||||
## Options
|
||||
|
||||
* `:keep` - a list of additional chunk names (as strings) to keep in the
|
||||
stripped BEAM file. These will be added to the significant chunks
|
||||
determined by `:beam_lib.significant_chunks/0`
|
||||
|
||||
* `:compress` - when `true`, the resulting BEAM file will be compressed
|
||||
using gzip. Defaults to `false`
|
||||
|
||||
## Examples
|
||||
|
||||
# Strip with default options
|
||||
Mix.Release.strip_beam(beam_binary)
|
||||
|
||||
# Keep additional chunks and compress
|
||||
Mix.Release.strip_beam(beam_binary, keep: ["Docs", "ChunkName"], compress: true)
|
||||
|
||||
"""
|
||||
@spec strip_beam(binary(), keyword()) :: {:ok, binary()} | {:error, :beam_lib, term()}
|
||||
@spec strip_beam(binary(), strip_beam_opts()) :: {:ok, binary()} | {:error, :beam_lib, term()}
|
||||
def strip_beam(binary, options \\ []) when is_list(options) do
|
||||
chunks_to_keep = options[:keep] |> List.wrap() |> Enum.map(&String.to_charlist/1)
|
||||
all_chunks = Enum.uniq(@additional_chunks ++ :beam_lib.significant_chunks() ++ chunks_to_keep)
|
||||
|
||||
@@ -7,6 +7,29 @@ defmodule Mix.Shell do
|
||||
Defines `Mix.Shell` contract.
|
||||
"""
|
||||
|
||||
@type cmd_opts :: [
|
||||
{:print_app, boolean()}
|
||||
| {:stderr_to_stdout, boolean()}
|
||||
| {:quiet, boolean()}
|
||||
| {:env, [{String.t(), String.t()}]}
|
||||
| {:cd, String.t()}
|
||||
| {atom(), term()}
|
||||
]
|
||||
|
||||
@type yes_opts :: [
|
||||
{:default, :yes | :no}
|
||||
| {atom(), term()}
|
||||
]
|
||||
|
||||
@type stream_cmd_opts :: [
|
||||
{:cd, String.t()}
|
||||
| {:stderr_to_stdout, boolean()}
|
||||
| {:use_stdio, boolean()}
|
||||
| {:env, [{String.t(), String.t()}]}
|
||||
| {:quiet, boolean()}
|
||||
| {atom(), term()}
|
||||
]
|
||||
|
||||
@doc false
|
||||
defstruct [:callback]
|
||||
|
||||
@@ -48,7 +71,7 @@ defmodule Mix.Shell do
|
||||
|
||||
All the built-in shells support these.
|
||||
"""
|
||||
@callback cmd(command :: String.t(), options :: keyword) :: integer
|
||||
@callback cmd(command :: String.t(), options :: cmd_opts) :: integer
|
||||
|
||||
@doc """
|
||||
Prompts the user for input.
|
||||
@@ -69,7 +92,7 @@ defmodule Mix.Shell do
|
||||
|
||||
* `:default` - `:yes` or `:no` (the default is `:yes`)
|
||||
"""
|
||||
@callback yes?(message :: binary, options :: keyword) :: boolean
|
||||
@callback yes?(message :: binary, options :: yes_opts) :: boolean
|
||||
|
||||
@doc """
|
||||
Prints the current application to the shell if
|
||||
@@ -117,7 +140,7 @@ defmodule Mix.Shell do
|
||||
* `:quiet` - overrides the callback to no-op
|
||||
|
||||
"""
|
||||
@spec cmd(String.t() | {String.t(), [String.t()]}, keyword, (binary -> term)) ::
|
||||
@spec cmd(String.t() | {String.t(), [String.t()]}, stream_cmd_opts, (binary -> term)) ::
|
||||
exit_status :: non_neg_integer
|
||||
def cmd(command, options \\ [], callback) when is_function(callback, 1) do
|
||||
callback =
|
||||
|
||||
@@ -11,6 +11,11 @@ defmodule Mix.Shell.IO do
|
||||
|
||||
@behaviour Mix.Shell
|
||||
|
||||
@typedoc """
|
||||
Options for `yes?/2`.
|
||||
"""
|
||||
@type yes_opts :: [default: :yes | :no]
|
||||
|
||||
@doc """
|
||||
Prints the current application to the shell if it
|
||||
was not printed yet.
|
||||
@@ -72,6 +77,7 @@ defmodule Mix.Shell.IO do
|
||||
end
|
||||
|
||||
"""
|
||||
@spec yes?(String.t(), yes_opts) :: boolean()
|
||||
def yes?(message, options \\ []) do
|
||||
default = Keyword.get(options, :default, :yes)
|
||||
|
||||
|
||||
@@ -52,11 +52,14 @@ defmodule Mix.Shell.Quiet do
|
||||
the prompt instead. Defaults to `:yes`.
|
||||
|
||||
"""
|
||||
@spec yes?(String.t(), Mix.Shell.IO.yes_opts()) :: boolean()
|
||||
defdelegate yes?(message, options \\ []), to: Mix.Shell.IO
|
||||
|
||||
@doc """
|
||||
Executes the given command quietly without outputting anything.
|
||||
"""
|
||||
@spec cmd(String.t() | {String.t(), [String.t()]}, Mix.Shell.stream_cmd_opts()) ::
|
||||
exit_status :: non_neg_integer
|
||||
def cmd(command, opts \\ []) do
|
||||
Mix.Shell.cmd(command, opts, fn data -> data end)
|
||||
end
|
||||
|
||||
@@ -73,6 +73,13 @@ defmodule Mix.Sync.Lock do
|
||||
@probe_data_size byte_size(@probe_data)
|
||||
@probe_timeout_ms 5_000
|
||||
|
||||
@typedoc """
|
||||
Options for `with_lock/3`.
|
||||
"""
|
||||
@type with_lock_opts :: [
|
||||
on_taken: (String.t() -> any())
|
||||
]
|
||||
|
||||
@doc """
|
||||
Acquires a lock identified by the given key.
|
||||
|
||||
@@ -95,7 +102,7 @@ defmodule Mix.Sync.Lock do
|
||||
is successfully acquired by this process.
|
||||
|
||||
"""
|
||||
@spec with_lock(iodata(), (-> term()), keyword()) :: term()
|
||||
@spec with_lock(iodata(), (-> term()), with_lock_opts()) :: term()
|
||||
def with_lock(key, fun, opts \\ []) do
|
||||
opts = Keyword.validate!(opts, [:on_taken])
|
||||
|
||||
|
||||
@@ -223,15 +223,55 @@ defmodule Mix.Tasks.Format do
|
||||
ins: [text: :green, space: :green_background]
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options passed to plugin `features/1` callback.
|
||||
|
||||
These are the same formatter options from `.formatter.exs` configuration,
|
||||
allowing plugins to access formatting settings when determining their capabilities.
|
||||
"""
|
||||
@type features_opts :: [
|
||||
inputs: [String.t()],
|
||||
plugins: [module()],
|
||||
subdirectories: [String.t()],
|
||||
import_deps: [atom()],
|
||||
export: keyword(),
|
||||
locals_without_parens: keyword(),
|
||||
line_length: pos_integer(),
|
||||
normalize_bitstring_modifiers: boolean(),
|
||||
normalize_charlists_as_binaries: boolean()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options passed to plugin `format/2` callback.
|
||||
|
||||
These options include context-specific information about what is being formatted
|
||||
(sigil, extension, file) along with all the standard formatter configuration options.
|
||||
"""
|
||||
@type format_opts :: [
|
||||
{:sigil, atom()}
|
||||
| {:modifiers, charlist()}
|
||||
| {:extension, String.t()}
|
||||
| {:file, String.t()}
|
||||
| {:inputs, [String.t()]}
|
||||
| {:plugins, [module()]}
|
||||
| {:subdirectories, [String.t()]}
|
||||
| {:import_deps, [atom()]}
|
||||
| {:export, keyword()}
|
||||
| {:locals_without_parens, keyword()}
|
||||
| {:line_length, pos_integer()}
|
||||
| {:normalize_bitstring_modifiers, boolean()}
|
||||
| {:normalize_charlists_as_binaries, boolean()}
|
||||
]
|
||||
|
||||
@doc """
|
||||
Returns which features this plugin should plug into.
|
||||
"""
|
||||
@callback features(Keyword.t()) :: [sigils: [atom()], extensions: [binary()]]
|
||||
@callback features(features_opts) :: [sigils: [atom()], extensions: [binary()]]
|
||||
|
||||
@doc """
|
||||
Receives a string to be formatted with options and returns said string.
|
||||
"""
|
||||
@callback format(String.t(), Keyword.t()) :: String.t()
|
||||
@callback format(String.t(), format_opts) :: String.t()
|
||||
|
||||
@impl true
|
||||
def run(all_args) do
|
||||
@@ -356,6 +396,16 @@ defmodule Mix.Tasks.Format do
|
||||
plugins
|
||||
end
|
||||
|
||||
@typedoc """
|
||||
Options for `formatter_for_file/2`.
|
||||
"""
|
||||
@type formatter_for_file_opts :: [
|
||||
deps_paths: %{atom() => String.t()},
|
||||
dot_formatter: String.t(),
|
||||
plugin_loader: ([module()] -> [module()]),
|
||||
root: String.t()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Returns a formatter function and the formatter options to
|
||||
be used for the given file.
|
||||
@@ -389,6 +439,8 @@ defmodule Mix.Tasks.Format do
|
||||
* `:root` - use the given root as the current working directory.
|
||||
"""
|
||||
@doc since: "1.13.0"
|
||||
@spec formatter_for_file(String.t(), formatter_for_file_opts) ::
|
||||
{(String.t() -> String.t()), keyword()}
|
||||
def formatter_for_file(file, opts \\ []) do
|
||||
cwd = Keyword.get_lazy(opts, :root, &File.cwd!/0)
|
||||
{dot_formatter, formatter_opts} = eval_dot_formatter(cwd, opts)
|
||||
@@ -809,8 +861,18 @@ defmodule Mix.Tasks.Format do
|
||||
end)
|
||||
end
|
||||
|
||||
@typedoc """
|
||||
Options for `text_diff_format/3`.
|
||||
"""
|
||||
@type text_diff_format_opts :: [
|
||||
after: non_neg_integer(),
|
||||
before: non_neg_integer(),
|
||||
color: boolean(),
|
||||
line: pos_integer()
|
||||
]
|
||||
|
||||
@doc false
|
||||
@spec text_diff_format(String.t(), String.t()) :: iolist()
|
||||
@spec text_diff_format(String.t(), String.t(), text_diff_format_opts) :: iolist()
|
||||
def text_diff_format(old, new, opts \\ [])
|
||||
|
||||
def text_diff_format(code, code, _opts), do: []
|
||||
|
||||
@@ -95,6 +95,15 @@ defmodule Mix.Tasks.Profile.Cprof do
|
||||
(for example, 2147483647 in a 32-bit host).
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Options for the cprof profiler.
|
||||
"""
|
||||
@type profile_opts :: [
|
||||
matching: {module() | :_, atom() | :_, arity() | :_},
|
||||
limit: non_neg_integer(),
|
||||
module: module()
|
||||
]
|
||||
|
||||
@switches [
|
||||
parallel: :boolean,
|
||||
require: :keep,
|
||||
@@ -172,7 +181,7 @@ defmodule Mix.Tasks.Profile.Cprof do
|
||||
* `:module` - filters out any results not pertaining to the given module
|
||||
|
||||
"""
|
||||
@spec profile((-> result), keyword()) :: result when result: any()
|
||||
@spec profile((-> result), profile_opts()) :: result when result: any()
|
||||
def profile(fun, opts \\ []) when is_function(fun, 0) do
|
||||
Mix.ensure_application!(:tools)
|
||||
{return_value, num_matched_functions, analysis_result} = profile_and_analyse(fun, opts)
|
||||
|
||||
@@ -101,6 +101,18 @@ defmodule Mix.Tasks.Profile.Eprof do
|
||||
`Mix.Tasks.Profile.Cprof` that uses [`:cprof`](`:cprof`) and has a low performance degradation effect.
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Options for the eprof profiler.
|
||||
"""
|
||||
@type profile_opts :: [
|
||||
matching: {module() | :_, atom() | :_, arity() | :_},
|
||||
calls: non_neg_integer(),
|
||||
time: non_neg_integer(),
|
||||
sort: :time | :calls,
|
||||
warmup: boolean(),
|
||||
set_on_spawn: boolean()
|
||||
]
|
||||
|
||||
@switches [
|
||||
parallel: :boolean,
|
||||
require: :keep,
|
||||
@@ -189,7 +201,7 @@ defmodule Mix.Tasks.Profile.Eprof do
|
||||
* `:set_on_spawn` - if newly spawned processes should be measured (default: `true`)
|
||||
|
||||
"""
|
||||
@spec profile((-> result), keyword()) :: result when result: any()
|
||||
@spec profile((-> result), profile_opts()) :: result when result: any()
|
||||
def profile(fun, opts \\ []) when is_function(fun, 0) do
|
||||
Mix.ensure_application!(:tools)
|
||||
{return_value, results} = profile_and_analyse(fun, opts)
|
||||
|
||||
@@ -114,6 +114,16 @@ defmodule Mix.Tasks.Profile.Fprof do
|
||||
this should provide more realistic insights into bottlenecks.
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Options for the fprof profiler.
|
||||
"""
|
||||
@type profile_opts :: [
|
||||
callers: boolean(),
|
||||
details: boolean(),
|
||||
sort: :acc | :own,
|
||||
trace_to_file: boolean()
|
||||
]
|
||||
|
||||
@switches [
|
||||
parallel: :boolean,
|
||||
require: :keep,
|
||||
@@ -184,7 +194,7 @@ defmodule Mix.Tasks.Profile.Fprof do
|
||||
usage for larger workloads.
|
||||
|
||||
"""
|
||||
@spec profile((-> result), keyword()) :: result when result: any()
|
||||
@spec profile((-> result), profile_opts()) :: result when result: any()
|
||||
def profile(fun, opts \\ []) when is_function(fun, 0) do
|
||||
Mix.ensure_application!(:runtime_tools)
|
||||
Mix.ensure_application!(:tools)
|
||||
|
||||
@@ -144,6 +144,21 @@ defmodule Mix.Tasks.Profile.Tprof do
|
||||
which is more limited but has a lower footprint.
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Options for the tprof profiler.
|
||||
"""
|
||||
@type profile_opts :: [
|
||||
matching: {module() | :_, atom() | :_, arity() | :_},
|
||||
type: :time | :memory | :calls,
|
||||
calls: non_neg_integer(),
|
||||
time: non_neg_integer(),
|
||||
memory: non_neg_integer(),
|
||||
sort: :calls | :per_call | :time | :memory,
|
||||
report: :process | :total,
|
||||
warmup: boolean(),
|
||||
set_on_spawn: boolean()
|
||||
]
|
||||
|
||||
@switches [
|
||||
parallel: :boolean,
|
||||
require: :keep,
|
||||
@@ -260,7 +275,7 @@ defmodule Mix.Tasks.Profile.Tprof do
|
||||
* `:set_on_spawn` - if newly spawned processes should be measured (default: `true`)
|
||||
|
||||
"""
|
||||
@spec profile((-> result), keyword()) :: result when result: any()
|
||||
@spec profile((-> result), profile_opts()) :: result when result: any()
|
||||
def profile(fun, opts \\ []) when is_function(fun, 0) do
|
||||
Mix.ensure_application!(:tools)
|
||||
{type, return_value, results} = profile_and_analyse(fun, opts)
|
||||
|
||||
@@ -65,6 +65,19 @@ defmodule Mix.Tasks.Run do
|
||||
|
||||
"""
|
||||
|
||||
@typedoc """
|
||||
Options for the internal `run/5` function.
|
||||
|
||||
These options are typically parsed from command-line arguments.
|
||||
"""
|
||||
@type run_opts :: [
|
||||
{:parallel_require, String.t()}
|
||||
| {:eval, String.t()}
|
||||
| {:require, String.t()}
|
||||
| {:parallel, boolean()}
|
||||
| {:config, String.t()}
|
||||
]
|
||||
|
||||
@impl true
|
||||
def run(args) do
|
||||
{opts, head} =
|
||||
@@ -99,7 +112,7 @@ defmodule Mix.Tasks.Run do
|
||||
@doc false
|
||||
@spec run(
|
||||
OptionParser.argv(),
|
||||
keyword,
|
||||
run_opts,
|
||||
OptionParser.argv(),
|
||||
(String.t() -> term()),
|
||||
(String.t() -> term())
|
||||
|
||||
@@ -276,7 +276,7 @@ defmodule Mix.Utils do
|
||||
Returns the name of the file written to, or "-" if the output was to STDOUT.
|
||||
This function is made public mostly for testing.
|
||||
"""
|
||||
@spec write_according_to_opts!(Path.t(), iodata(), keyword) :: Path.t()
|
||||
@spec write_according_to_opts!(Path.t(), iodata(), write_opts) :: Path.t()
|
||||
def write_according_to_opts!(default_file_spec, contents, opts) do
|
||||
file_spec = Keyword.get(opts, :output, default_file_spec)
|
||||
|
||||
@@ -305,7 +305,7 @@ defmodule Mix.Utils do
|
||||
If the `:output` option is `-` then prints to standard output,
|
||||
see write_according_to_opts!/3 for details.
|
||||
"""
|
||||
@spec write_json_tree!(Path.t(), [node], (node -> {formatted_node, [node]}), keyword) ::
|
||||
@spec write_json_tree!(Path.t(), [node], (node -> {formatted_node, [node]}), write_opts) ::
|
||||
Path.t()
|
||||
when node: term()
|
||||
def write_json_tree!(default_file_spec, nodes, callback, opts \\ []) do
|
||||
@@ -336,13 +336,36 @@ defmodule Mix.Utils do
|
||||
|
||||
@type formatted_node :: {name :: String.Chars.t(), edge_info :: String.Chars.t()}
|
||||
|
||||
@typedoc """
|
||||
Options for `write_according_to_opts!/3`, `write_json_tree!/4`, and `write_dot_graph!/5`.
|
||||
"""
|
||||
@type write_opts :: [
|
||||
output: String.t()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for `print_tree/3`.
|
||||
"""
|
||||
@type print_tree_opts :: [
|
||||
format: String.t()
|
||||
]
|
||||
|
||||
@typedoc """
|
||||
Options for `read_path/2`.
|
||||
"""
|
||||
@type read_path_opts :: [
|
||||
timeout: pos_integer(),
|
||||
sha512: String.t()
|
||||
]
|
||||
|
||||
@doc """
|
||||
Prints the given tree according to the callback.
|
||||
|
||||
The callback will be invoked for each node and it
|
||||
must return a `{printed, children}` tuple.
|
||||
"""
|
||||
@spec print_tree([node], (node -> {formatted_node, [node]}), keyword) :: :ok when node: term()
|
||||
@spec print_tree([node], (node -> {formatted_node, [node]}), print_tree_opts) :: :ok
|
||||
when node: term()
|
||||
def print_tree(nodes, callback, opts \\ []) do
|
||||
pretty? =
|
||||
case Keyword.get(opts, :format) do
|
||||
@@ -414,7 +437,7 @@ defmodule Mix.Utils do
|
||||
String.t(),
|
||||
[node],
|
||||
(node -> {formatted_node, [node]}),
|
||||
keyword
|
||||
write_opts
|
||||
) :: Path.t()
|
||||
when node: term()
|
||||
def write_dot_graph!(default_file_spec, title, nodes, callback, opts \\ []) do
|
||||
@@ -632,7 +655,7 @@ defmodule Mix.Utils do
|
||||
seconds
|
||||
|
||||
"""
|
||||
@spec read_path(String.t(), keyword) ::
|
||||
@spec read_path(String.t(), read_path_opts) ::
|
||||
{:ok, binary}
|
||||
| :badpath
|
||||
| {:remote, String.t()}
|
||||
|
||||
Reference in New Issue
Block a user