View Source ExPropriate.MarkedFunctions (ExPropriate v0.1.0)
This module handles expropriation of function-level granularity.
It can be set up like this:
defmodule MyModule do
use ExPropriate
# Function becomes public
@expropriate true
defp expropriated_function,
do: :am_expropriated
# Functions with multiple bodies only need to be tagged on the first body
@expropriate true
defp divide_by(number) when is_integer(number) and number > 0,
do: {:ok, div(100, number)}
defp divide_by(_other),
do: :error
# Untagged functions remain private
defp remains_private,
do: :am_private
end
MyModule.expropriated_function
# :am_expropriated
MyModule.divide_by(2)
# { :ok, 50 }
MyModule.divide_by(0)
# :error
MyModule.remains_private
# (UndefinedFunctionError) function MyModule.remains_private/0 is undefined or private.The objective of this module was to be able to explicitly state which functions need to be
expropriated. The tradeoff is that this module is more "intrusive" than the module-level
granularity, since it overrides both Kernel.def/2 and Kernel.defp/2.
Also a friendly reminder that the functions and macros contained in this module are for internal use of the library and it's advised against using them directly.
Link to this section Summary
Types
AST containing the definition of a function's body.
AST containing the definition of a function's head.
Tuple containing a function's name and arity.
Functions
An override of Kernel.def/2.
Defines a public function via Kernel.def/2, and sets the necessary attributes for the following
bodies.
Defines a private function via Kernel.defp/2
Defines a public function via Kernel.def/2
An override of Kernel.defp/2.
Transforms a function's head AST into a tuple containing the name and arity of the function.
Generates AST to prevent warnings for unused @expropriate attributes.
Generates the AST necessary to expropriate only tagged functions on compile time.
Link to this section Types
Specs
fn_body() :: Macro.t() | nil
AST containing the definition of a function's body.
Typically it's a keyword list containing at least a [do: expr]. It also may be nil (if only
the function head is being declared), and it may also contain other keys like :rescue, :catch,
:after, etc.
[do: {:+, [], [1, 2]}]
|> Macro.to_string
# "[do: 1 + 2]"
[
do: {
:/,
[],
[{:a, [], nil}, {:b, [], Elixir}]
},
rescue: [{
:->,
[],
[
[{:error, [], nil}],
{{:., [], [{:__aliases__, [], [:IO]}, :puts]}, [],
[{:error, [], nil}]}
]
}]
]
|> Macro.to_string
# "[do: a / b, rescue: (error -> IO.puts(error))]"
Specs
fn_head() :: Macro.t()
AST containing the definition of a function's head.
Contains at least the function name, arguments and clauses.
Does not contain def or defp.
Examples:
{:with_no_args, [], []}
|> Macro.to_string
# "with_no_args()"
{:with_two_args, [], [{:arg1, [], nil}, {:arg2, [], nil}}
|> Macro.to_string
# "with_two_args(arg1, arg2)"
{
:when,
[],
[
{:with_when, [], [{:arg, [], nil}]},
{:>, [], [{:arg, [], nil}, 0]}
]
}
|> Macro.to_string
# "with_when(arg) when arg > 1"
Specs
fn_name() :: {name :: atom(), arity :: non_neg_integer()}
Tuple containing a function's name and arity.
{:my_function, 2}
Link to this section Functions
An override of Kernel.def/2.
This macro checks if the @expropriate attribute was set to true before defining a public
function, and outputs a warning if that's the case.
Regardless of the warning, it always defines the fuction using Kernel.def/2
Specs
Defines a public function via Kernel.def/2, and sets the necessary attributes for the following
bodies.
Called by expropriated functions when they define their first body. In addition to defining the
function as public, this function also sets the @expropriate attribute back to false and
registers the function's name to the @expropriated_names attribute.
If the function has multiple bodies, it will directly call define_public/2 instead.
Specs
Defines a private function via Kernel.defp/2
Called by functions that are not being expropriated.
Specs
Defines a public function via Kernel.def/2
Called by functions that are being expropriated.
An override of Kernel.defp/2.
This macro decides whether or not the expropriate the function body based on the following criteria:
- The
@expropriateattribute is set totrue - The function's name (
fn_name/0) was already expropriated. (For functions with multiple bodies)
Specs
Transforms a function's head AST into a tuple containing the name and arity of the function.
Specs
generate_unused_ast() :: Macro.t()
Generates AST to prevent warnings for unused @expropriate attributes.
These warnings happened when the module has @expropriate attributes, but ExPropriate is disabled
at a config level. Eg: in prod environment.
Specs
generate_use_ast() :: Macro.t()
Generates the AST necessary to expropriate only tagged functions on compile time.
- Injects this module's
def/2anddefp/2macro in favor ofKernel.def/2andKernel.defp/2. - Setups attributes that are later used by the
def/2anddefp/2macros.