View Source Recode.AST (Recode v0.7.2)

This module provides functions to get informations from the AST and to manipulate the AST.

Most of the functions in this module require an AST with additional informations. This information is provided by Sourceror or Code.string_to_quoted/2 with the options

[
  columns: true,
  literal_encoder: &{:ok, {:__block__, &2, [&1]}},
  token_metadata: true,
  unescape: false
]

See also Formatting considerations in the docs for Code.quoted_to_algebra/2.

This module provides literal? functions that are also work with encoded literals generate by literal_encoder: %{:ok, {:__block__, &2, [&1]}}. For an example see atom?/1.

Summary

Functions

Returns the infos from an AST representing an alias expression.

Concatinates the aliases of an :__aliases__ tuple.

Returns true if the given AST represents an atom.

Returns the line in which the given AST starts.

Returns the newlines value from meta[:end_of_expression], or nil.

Returns the value from a :__block__ with a single argument.

Returns a mfa-tuple for the given .-call.

Returns true when the given ast represents an expression that spans over multiple lines.

Converts AST representing a name to a string.

Puts the given value newlines under the key nevlines in meta[:end_of_expression].

Puts the given value in the :__block__ AST.

Update a function call.

Updates the function name of a capture.

Updates the AST representing a definition.

Update a dotted function call.

Updates a spec.

Functions

@spec alias_info(Macro.t()) :: {module(), [module()], module() | nil}

Returns the infos from an AST representing an alias expression.

The function returns 3-tuple containing the alias, the multi part and the :as.

Examples

iex> ast = quote do
...>   alias Foo.Bar
...> end
iex> alias_info(ast)
{Foo.Bar, [], nil}

iex> ast = quote do
...>   alias Foo.{Bar, Baz}
...> end
iex> alias_info(ast)
{Foo, [Bar, Baz], nil}

iex> ast = quote do
...>   alias Foo, as: Baz
...> end
iex> alias_info(ast)
{Foo, [], Baz}

iex> ast = Sourceror.parse_string!("alias __MODULE__")
iex> alias_info(ast)
{:__MODULE__, [], nil}

iex> ast = Sourceror.parse_string!("alias __MODULE__.{Foo, Bar.Baz}")
iex> alias_info(ast)
{:__MODULE__, [Foo, Bar.Baz], nil}

iex> ast = Sourceror.parse_string!("alias __MODULE__, as: MyModule")
iex> alias_info(ast)
{:__MODULE__, [], MyModule}
@spec aliases_concat({:__aliases__, Macro.metadata(), [atom()]}) :: module()

Concatinates the aliases of an :__aliases__ tuple.

Examples

iex> aliases_concat({:__aliases__, [], [:Alpha, :Bravo]})
Alpha.Bravo
@spec atom?(Macro.t()) :: boolean()

Returns true if the given AST represents an atom.

Examples

iex> ":atom" |> Code.string_to_quoted!() |> atom?()
true

iex> ":atom" |> Sourceror.parse_string!() |> atom?()
true

iex> "42" |> Sourceror.parse_string!() |> atom?()
false

iex> ast = Code.string_to_quoted!(
...>   ":a", literal_encoder: &{:ok, {:__block__, &2, [&1]}})
{:__block__, [line: 1], [:a]}
iex> atom?(ast)
true

Returns the line in which the given AST starts.

Note: The AST must be constructed by Sourceror or with the Code module and the options columns: true, token_metadata: true.

Examples

iex> code = """
...> 1 +
...>   2 -
...>   3
...> """
iex> code |> Sourceror.parse_string!() |> first_line()
1
iex> code |> Sourceror.parse_string!() |> last_line()
3
iex> code
...> |> Code.string_to_quoted!(
...>   columns: true,
...>   token_metadata: true,
...>   literal_encoder: &{:ok, {:__block__, &2, [&1]}})
...> |> last_line()
3
@spec get_newlines(Macro.t()) :: integer()

Returns the newlines value from meta[:end_of_expression], or nil.

@spec get_value(Macro.t()) :: term()

Returns the value from a :__block__ with a single argument.

Examples

iex> "[1, 2]"
...> |> Sourceror.parse_string!()
...> |> get_value()
...> |> Enum.map(&get_value/1)
[1, 2]
@spec mfa({{:., keyword(), list()}, Macro.metadata(), Macro.t()}) ::
  {module(), atom(), non_neg_integer()}

Returns a mfa-tuple for the given .-call.

@spec multiline?(Macro.t() | Macro.metadata()) :: boolean()

Returns true when the given ast represents an expression that spans over multiple lines.

multiline? does not pay attention to do blocks.

Examples

iex> """
...> def foo(x)
...>     when is_integer(x) do
...>   {:foo, x}
...> end
...> """
...> |> Sourceror.parse_string!() |> multiline?()
true

iex> """
...> def foo(x) when is_integer(x) do
...>   {:foo, x}
...> end
...> """
...> |> Sourceror.parse_string!() |> multiline?()
false

iex> """
...> {
...>   x,
...>   y
...> }
...> """
...> |> Sourceror.parse_string!() |> multiline?()
true

iex> """
...> {x, y}
...> """
...> |> Sourceror.parse_string!() |> multiline?()
false
@spec name(atom() | [atom()]) :: String.t()

Converts AST representing a name to a string.

This function suppresses the prefix "Elixir.".

Examples

iex> name([Recode, AST])
"Recode.AST"

iex> name(Recode.AST)
"Recode.AST"
Link to this function

put_newlines(arg, newlines)

View Source
@spec put_newlines({term(), Macro.metadata(), Macro.t()}, integer()) ::
  {term(), keyword(), list()}

Puts the given value newlines under the key nevlines in meta[:end_of_expression].

@spec put_value(Macro.t(), term()) :: Macro.t()

Puts the given value in the :__block__ AST.

Examples

iex> "[1, 2]"
...> |> Sourceror.parse_string!()
...> |> get_value()
...> |> Enum.map(fn ast -> put_value(ast, "0") end)
...> |> Enum.map(&get_value/1)
["0", "0"]
Link to this function

update_call(arg, updates)

View Source
@spec update_call(Macro.t(), updates :: keyword()) :: Macro.t()

Update a function call.

The keyword list updates can have the keys name, meta and args.

Examples

iex> quote do
...>   foo(x)
...> end
...> |> update_call(name: :bar)
...> |> Macro.to_string()
"bar(x)"
Link to this function

update_capture(arg, list)

View Source
@spec update_capture(Macro.t(), [{:name, atom()}]) :: Macro.t()

Updates the function name of a capture.

Link to this function

update_definition(arg, updates)

View Source
@spec update_definition(Macro.t(), updates :: keyword()) :: Macro.t()

Updates the AST representing a definition.

The keyword list updates can have the keys name, meta and args.

Examples

iex> ast = Sourceror.parse_string!("def foo(x), do: x")
iex> ast |> update_definition(name: :bar) |> Macro.to_string()
"def bar(x), do: x"
iex> ast |> update_definition(args: [{:y, [], nil}]) |> Macro.to_string()
"def foo(y), do: x"
Link to this function

update_dot_call(arg, updates)

View Source
@spec update_dot_call(Macro.t(), updates :: keyword()) :: Macro.t()

Update a dotted function call.

Examples

iex> ast = quote do
...>   Foo.foo(x)
...> end
iex> update_dot_call(ast, name: :bar)
{{:., [], [{:__aliases__, [alias: false], [:Foo]}, :bar]}, [], [{:x, [], Recode.ASTTest}]}
Link to this function

update_spec(arg, updates)

View Source
@spec update_spec(Macro.t(), updates :: keyword()) :: Macro.t()

Updates a spec.

The keyword list updates can have the keys name, meta, args and return.

Examples

iex> quote do
...>   @spec foo(integer()) :: integer()
...> end
...> |> update_spec(name: :bar, return: {:term, [], []})
...> |> Macro.to_string()
"@spec bar(integer()) :: term()"