View Source Recode.AST (Recode v0.7.3)
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
Types
An expression in the AST.
The metadata of an expression in the AST.
Abstract Syntax Tree (AST)
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 :do
or :else
block arguments of the given expr
.
Returns the first 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 the last line in which the given AST ends.
Returns a mfa
-tuple for the given .
-call.
Returns the module name as an atom for the given ast
.
Returns true
when the given ast
expression 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.
Performs a depth-first, pre-order traversal of quoted expressions and invokes
fun
for each node in the ast
with the accumulator acc
.
Reduces the ast
until fun
returns {:halt, term}
.
Forces a one line AST expression from a multiline AST expression.
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.
Types
Functions
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}
Concatinates the aliases of an :__aliases__
tuple.
Examples
iex> aliases_concat({:__aliases__, [], [:Alpha, :Bravo]})
Alpha.Bravo
Returns true
if the given AST represents an atom.
Examples
iex> ":atom" |> Code.string_to_quoted!() |> atom?()
true
iex> ast = Sourceror.parse_string!(":atom")
{:__block__, [trailing_comments: [], leading_comments: [], line: 1, column: 1], [:atom]}
...> atom?(ast)
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 :do
or :else
block arguments of the given expr
.
Examples
iex> ast = Sourceror.parse_string!("""
...> defmodule Foo do
...> def bar, do: bar
...> end
...> """)
...> block = block(ast)
...> Sourceror.to_string({:__block__,[], block})
"def bar, do: bar"
iex> {:defmodule, _meta, [_aliases, args]} = Sourceror.parse_string!("""
...> defmodule Foo do
...> def bar, do: bar
...> def baz, do: baz
...> end
...> """)
...> block = block(args)
...> Sourceror.to_string({:__block__,[], block})
"""
def bar, do: bar
def baz, do: baz\
"""
iex> ast = Sourceror.parse_string!("""
...> if x, do: true, else: false
...> """)
...> block(ast, :else)
[false]
...> block(ast)
[true]
...> block(ast, :do)
[true]
iex> ast = Sourceror.parse_string!("x == y")
...> block(ast)
nil
Returns the first line in which the given AST starts.
Note
The AST must be constructed by
Sourceror
or with theCode
module and the optionscolumns: true, token_metadata: true, literal_encoder: &{:ok, {:__block__, &2, [&1]}}
.
Examples
iex> code = """
...> 1 +
...> 2 -
...> 3
...> """
...>
...> ast = Sourceror.parse_string(code)
...> first_line(ast)
1
iex> last_line(ast)
3
iex> code
...> |> Code.string_to_quoted!(
...> columns: true,
...> token_metadata: true,
...> literal_encoder: &{:ok, {:__block__, &2, [&1]}})
...> |> last_line()
3
Returns the newlines
value from meta[:end_of_expression]
, or nil
.
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]
Returns the last line in which the given AST ends.
See first_line/1
for example and note.
Returns a mfa
-tuple for the given .
-call.
Examples
iex> ast = quote do
...> Foo.Bar.baz(x)
...> end
...> mfa(ast)
{Foo.Bar, :baz, 1}
Returns the module name as an atom for the given ast
.
The function accepts {:defmodule, meta, args}
, the args
form the
:defmodule
tuple or the same input as aliases_concat/1
.
Returns true
when the given ast
expression 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
Converts AST representing a name to a string.
This function suppresses the prefix "Elixir."
.
Examples
iex> name([Recode, Task])
"Recode.Task"
iex> name(Recode.Task)
"Recode.Task"
Puts the given value newlines
under the key nevlines
in
meta[:end_of_expression]
.
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"]
Performs a depth-first, pre-order traversal of quoted expressions and invokes
fun
for each node in the ast
with the accumulator acc
.
The initial value of the accumulator is acc
. The function is invoked for each
node in the ast
with the accumulator. The result returned by the function is
used as the accumulator for the next iteration. The function returns the last
accumulator.
Examples
iex> ast = quote do
...> def foo(x), {:oof, x}
...> def bar(x), {:rab, x}
...> end
...> AST.reduce(ast, [], fn
...> {:def, _, [{name, _, _}|_]}, acc -> [name | acc]
...> ast, acc when is_atom(ast) -> [ast|acc]
...> _ast, acc -> acc
...> end)
[:rab, :bar, :oof, :foo]
@spec reduce_while(t(), acc(), (t(), acc() -> result)) :: acc() when result: {:cont, acc()} | {:halt, acc()} | {:skip, acc()}
Reduces the ast
until fun
returns {:halt, term}
.
The return value for fun
is expected to be
{:cont, acc}
to continue the reduction with the next node in the ast andacc
as the new accumulator{:skip, acc}
to continue the reduction while skippin the childrens of current node andacc
as the new accumulator{:halt, acc}
to halt the reduction or
If fun
returns {:halt, acc}
the reduction is halted and the function
returns acc
. Otherwise, if the AST is exhausted, the function returns the
accumulator of the last {:cont, acc}
.
Examples
iex> ast = quote do
...> def foo(x), {:oof, x}
...> def bar(x, y), {:rab, x, y}
...> end
...>
...> AST.reduce_while(ast, [], fn
...> {:def, _, [{name, _, args}|_]}, acc
...> -> acc = [name | acc]
...> if length(args) == 1 do
...> {:cont, acc}
...> else
...> {:skip, acc}
...> end
...> ast, acc when is_atom(ast)
...> -> {:cont, [ast|acc]}
...> _ast, acc
...> -> {:cont, acc}
...> end)
[:bar, :oof, :foo]
Forces a one line AST expression from a multiline AST expression.
Example
iex> """
...> x &&
...> y
...> """
...> |> Sourceror.parse_string!()
...> |> to_same_line()
...> |> Sourceror.to_string()
"x && y"
iex> """
...> def foo,
...> do:
...> :foo
...> """
...> |> Sourceror.parse_string!()
...> |> to_same_line()
...> |> Sourceror.to_string()
"""
def foo,
do: :foo\
"""
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)"
Updates the function name of a capture.
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"
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}]}
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()"