zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

block.ex (6027B)


      1 defmodule Credo.Code.Block do
      2   @moduledoc """
      3   This module provides helper functions to analyse blocks, e.g. the block taken
      4   by the `if` macro.
      5   """
      6 
      7   @doc """
      8   Returns the do: block of a given AST node.
      9   """
     10   def all_blocks_for!(ast) do
     11     [
     12       do_block_for!(ast),
     13       else_block_for!(ast),
     14       rescue_block_for!(ast),
     15       after_block_for!(ast)
     16     ]
     17   end
     18 
     19   @doc """
     20   Returns true if the given `ast` has a do block.
     21   """
     22   def do_block?(ast) do
     23     case do_block_for(ast) do
     24       {:ok, _block} ->
     25         true
     26 
     27       nil ->
     28         false
     29     end
     30   end
     31 
     32   @doc """
     33   Returns the do: block of a given AST node.
     34   """
     35   def do_block_for!(ast) do
     36     case do_block_for(ast) do
     37       {:ok, block} ->
     38         block
     39 
     40       nil ->
     41         nil
     42     end
     43   end
     44 
     45   @doc """
     46   Returns a tuple {:ok, do_block} or nil for a given AST node.
     47   """
     48   def do_block_for({_atom, _meta, arguments}) when is_list(arguments) do
     49     do_block_for(arguments)
     50   end
     51 
     52   def do_block_for(do: block) do
     53     {:ok, block}
     54   end
     55 
     56   def do_block_for(arguments) when is_list(arguments) do
     57     Enum.find_value(arguments, &find_keyword(&1, :do))
     58   end
     59 
     60   def do_block_for(_) do
     61     nil
     62   end
     63 
     64   @doc """
     65   Returns true if the given `ast` has an else block.
     66   """
     67   def else_block?(ast) do
     68     case else_block_for(ast) do
     69       {:ok, _block} ->
     70         true
     71 
     72       nil ->
     73         false
     74     end
     75   end
     76 
     77   @doc """
     78   Returns the `else` block of a given AST node.
     79   """
     80   def else_block_for!(ast) do
     81     case else_block_for(ast) do
     82       {:ok, block} ->
     83         block
     84 
     85       nil ->
     86         nil
     87     end
     88   end
     89 
     90   @doc """
     91   Returns a tuple {:ok, else_block} or nil for a given AST node.
     92   """
     93   def else_block_for({_atom, _meta, arguments}) when is_list(arguments) do
     94     else_block_for(arguments)
     95   end
     96 
     97   def else_block_for(do: _do_block, else: else_block) do
     98     {:ok, else_block}
     99   end
    100 
    101   def else_block_for(arguments) when is_list(arguments) do
    102     Enum.find_value(arguments, &find_keyword(&1, :else))
    103   end
    104 
    105   def else_block_for(_) do
    106     nil
    107   end
    108 
    109   @doc """
    110   Returns true if the given `ast` has an rescue block.
    111   """
    112   def rescue_block?(ast) do
    113     case rescue_block_for(ast) do
    114       {:ok, _block} ->
    115         true
    116 
    117       nil ->
    118         false
    119     end
    120   end
    121 
    122   @doc """
    123   Returns the rescue: block of a given AST node.
    124   """
    125   def rescue_block_for!(ast) do
    126     case rescue_block_for(ast) do
    127       {:ok, block} ->
    128         block
    129 
    130       nil ->
    131         nil
    132     end
    133   end
    134 
    135   @doc """
    136   Returns a tuple {:ok, rescue_block} or nil for a given AST node.
    137   """
    138   def rescue_block_for({_atom, _meta, arguments}) when is_list(arguments) do
    139     rescue_block_for(arguments)
    140   end
    141 
    142   def rescue_block_for(do: _do_block, rescue: rescue_block) do
    143     {:ok, rescue_block}
    144   end
    145 
    146   def rescue_block_for(arguments) when is_list(arguments) do
    147     Enum.find_value(arguments, &find_keyword(&1, :rescue))
    148   end
    149 
    150   def rescue_block_for(_) do
    151     nil
    152   end
    153 
    154   @doc """
    155   Returns true if the given `ast` has an catch block.
    156   """
    157   def catch_block?(ast) do
    158     case catch_block_for(ast) do
    159       {:ok, _block} ->
    160         true
    161 
    162       nil ->
    163         false
    164     end
    165   end
    166 
    167   @doc """
    168   Returns the catch: block of a given AST node.
    169   """
    170   def catch_block_for!(ast) do
    171     case catch_block_for(ast) do
    172       {:ok, block} ->
    173         block
    174 
    175       nil ->
    176         nil
    177     end
    178   end
    179 
    180   @doc """
    181   Returns a tuple {:ok, catch_block} or nil for a given AST node.
    182   """
    183   def catch_block_for({_atom, _meta, arguments}) when is_list(arguments) do
    184     catch_block_for(arguments)
    185   end
    186 
    187   def catch_block_for(do: _do_block, catch: catch_block) do
    188     {:ok, catch_block}
    189   end
    190 
    191   def catch_block_for(arguments) when is_list(arguments) do
    192     Enum.find_value(arguments, &find_keyword(&1, :catch))
    193   end
    194 
    195   def catch_block_for(_) do
    196     nil
    197   end
    198 
    199   @doc """
    200   Returns true if the given `ast` has an after block.
    201   """
    202   def after_block?(ast) do
    203     case after_block_for(ast) do
    204       {:ok, _block} ->
    205         true
    206 
    207       nil ->
    208         false
    209     end
    210   end
    211 
    212   @doc """
    213   Returns the after: block of a given AST node.
    214   """
    215   def after_block_for!(ast) do
    216     case after_block_for(ast) do
    217       {:ok, block} ->
    218         block
    219 
    220       nil ->
    221         nil
    222     end
    223   end
    224 
    225   @doc """
    226   Returns a tuple {:ok, after_block} or nil for a given AST node.
    227   """
    228   def after_block_for({_atom, _meta, arguments}) when is_list(arguments) do
    229     after_block_for(arguments)
    230   end
    231 
    232   def after_block_for(do: _do_block, after: after_block) do
    233     {:ok, after_block}
    234   end
    235 
    236   def after_block_for(arguments) when is_list(arguments) do
    237     Enum.find_value(arguments, &find_keyword(&1, :after))
    238   end
    239 
    240   def after_block_for(_) do
    241     nil
    242   end
    243 
    244   defp find_keyword(list, keyword) when is_list(list) do
    245     if Keyword.has_key?(list, keyword) do
    246       {:ok, list[keyword]}
    247     else
    248       nil
    249     end
    250   end
    251 
    252   defp find_keyword(_, _), do: nil
    253 
    254   @doc """
    255   Returns the children of the `do` block of the given AST node.
    256   """
    257   def calls_in_do_block({_op, _meta, arguments}) do
    258     arguments
    259     |> do_block_for!
    260     |> instructions_for
    261   end
    262 
    263   def calls_in_do_block(arg) do
    264     arg
    265     |> do_block_for!
    266     |> instructions_for
    267   end
    268 
    269   @doc """
    270   Returns the children of the `rescue` block of the given AST node.
    271   """
    272   def calls_in_rescue_block({_op, _meta, arguments}) do
    273     arguments
    274     |> rescue_block_for!
    275     |> instructions_for
    276   end
    277 
    278   def calls_in_rescue_block(arg) do
    279     arg
    280     |> rescue_block_for!
    281     |> instructions_for
    282   end
    283 
    284   @doc """
    285   Returns the children of the `catch` block of the given AST node.
    286   """
    287   def calls_in_catch_block({_op, _meta, arguments}) do
    288     arguments
    289     |> catch_block_for!
    290     |> instructions_for
    291   end
    292 
    293   def calls_in_catch_block(arg) do
    294     arg
    295     |> catch_block_for!
    296     |> instructions_for
    297   end
    298 
    299   defp instructions_for({:__block__, _meta, calls}), do: calls
    300 
    301   defp instructions_for(v)
    302        when is_atom(v) or is_tuple(v) or is_binary(v) or is_float(v) or is_integer(v),
    303        do: List.wrap(v)
    304 
    305   defp instructions_for(v) when is_list(v), do: [v]
    306 end