Packages
credo
1.7.5
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.7-rc.0
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.2-rc.4
1.7.2-rc.3
1.7.2-rc.2
1.7.2-rc.1
1.7.2-rc.0
1.7.1
1.7.0
1.7.0-rc.2
1.7.0-rc.1
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.5
1.5.0-rc.4
1.5.0-rc.3
1.5.0-rc.2
1.5.0-rc.1
1.4.1
1.4.0
1.4.0-rc.2
1.4.0-rc.1
1.3.2
1.3.1
1.3.0
1.3.0-rc3
1.3.0-rc2
1.3.0-rc1
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc4
1.2.0-rc3
1.2.0-rc2
1.2.0-rc1
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.1.0-rc3
1.1.0-rc2
1.1.0-rc1
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.1-rc1
1.0.0
1.0.0-rc1
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.9.0-rc8
0.9.0-rc7
0.9.0-rc6
0.9.0-rc5
0.9.0-rc4
0.9.0-rc3
0.9.0-rc2
0.9.0-rc1
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.8.0-rc7
0.8.0-rc6
0.8.0-rc5
0.8.0-rc4
0.8.0-rc3
0.8.0-rc2
0.8.0-rc1
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.6.0-rc2
0.6.0-rc1
0.5.3
0.5.2
0.5.1
0.5.0
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.10-dev
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.4.0-beta5
0.4.0-beta4
0.4.0-beta3
0.4.0-beta2
0.4.0-beta1
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.3.0-dev2
0.3.0-dev
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
0.0.1-dev
A static code analysis tool with a focus on code consistency and teaching.
Current section
Files
Jump to
Current section
Files
lib/credo/execution/task.ex
defmodule Credo.Execution.Task do
@moduledoc """
A Task is a step in a pipeline, which is given an `Credo.Execution` struct and must return one as well.
Tasks in a pipeline are only called if they are not "halted" (see `Credo.Execution.halt/2`).
It implements a `call/1` or `call/2` callback, which is called with the `Credo.Execution` struct
as first parameter (and the Task's options as the second in case of `call/2`).
"""
@typedoc false
@type t :: module
@doc """
Is called by the pipeline and contains the Task's actual code.
defmodule FooTask do
use Credo.Execution.Task
def call(exec) do
IO.inspect(exec)
end
end
The `call/1` functions receives an `exec` struct and must return a (modified) `Credo.Execution`.
"""
@callback call(exec :: Credo.Execution.t()) :: Credo.Execution.t()
@doc """
Works like `call/1`, but receives the options, which are optional when registering the Task, as second argument.
defmodule FooTask do
use Credo.Execution.Task
def call(exec, opts) do
IO.inspect(opts)
exec
end
end
"""
@callback call(exec :: Credo.Execution.t(), opts :: Keyword.t()) :: Credo.Execution.t()
@doc """
Gets called if `call` holds the execution via `Credo.Execution.halt/1` or `Credo.Execution.halt/2`.
"""
@callback error(exec :: Credo.Execution.t()) :: Credo.Execution.t()
@doc """
Works like `error/1`, but receives the options, which were given during pipeline registration, as second argument.
"""
@callback error(exec :: Credo.Execution.t(), opts :: Keyword.t()) :: Credo.Execution.t()
require Logger
alias Credo.Execution
alias Credo.Execution.ExecutionTiming
defmacro __using__(_opts \\ []) do
quote do
@behaviour Credo.Execution.Task
import Credo.Execution
alias Credo.CLI.Output.UI
alias Credo.Execution
@impl true
def call(%Execution{halted: false} = exec) do
exec
end
@impl true
def call(%Execution{halted: false} = exec, opts) do
call(exec)
end
@impl true
def error(exec) do
case Execution.get_halt_message(exec) do
"" <> halt_message ->
command_name = Execution.get_command_name(exec) || "credo"
UI.warn([:red, "** (#{command_name}) ", halt_message])
_ ->
IO.warn("Execution halted during #{__MODULE__}!")
end
exec
end
@impl true
def error(exec, _opts) do
error(exec)
end
defoverridable call: 1
defoverridable call: 2
defoverridable error: 1
defoverridable error: 2
end
end
@doc false
def run(task, exec, opts \\ [])
def run(task, %Credo.Execution{debug: true} = exec, opts) do
run_with_timing(task, exec, opts)
end
def run(task, %Execution{} = exec, opts) do
do_run(task, exec, opts)
end
def run(_task, exec, _opts) do
IO.warn(
"Expected second parameter of Task.run/3 to match %Credo.Execution{}, " <>
"got: #{inspect(exec)}"
)
exec
end
defp do_run(task, %Credo.Execution{halted: false} = exec, opts) do
old_parent_task = exec.parent_task
old_current_task = exec.current_task
exec =
exec
|> Execution.set_parent_and_current_task(exec.current_task, task)
|> task.call(opts)
|> Execution.ensure_execution_struct("#{task}.call/2")
if exec.halted do
exec
|> task.error(opts)
|> Execution.set_parent_and_current_task(old_parent_task, old_current_task)
else
Execution.set_parent_and_current_task(exec, old_parent_task, old_current_task)
end
end
defp do_run(_task, exec, _opts) do
exec
end
#
defp run_with_timing(task, exec, opts) do
context_tuple = {:task, exec, task, opts}
log(:call_start, context_tuple)
{started_at, time, exec} = ExecutionTiming.run(&do_run/3, [task, exec, opts])
log(:call_end, context_tuple, time)
ExecutionTiming.append(exec, [task: task, parent_task: exec.parent_task], started_at, time)
exec
end
defp log(:call_start, {:task, _exec, task, _opts}) do
Logger.info("Calling #{task} ...")
end
defp log(:call_end, {:task, _exec, task, _opts}, time) do
Logger.info("Finished #{task} in #{format_time(time)} ...")
end
defp format_time(time) do
cond do
time > 1_000_000 ->
"#{div(time, 1_000_000)}s"
time > 1_000 ->
"#{div(time, 1_000)}ms"
true ->
"#{time}μs"
end
end
end