   end
   def def_name_with_op(_), do: nil
 
+
+
   @doc "Returns the name of the functions/macros for the given module's `ast`"
   def def_names(nil), do: []
   def def_names({:defmodule, _, _arguments} = ast) do
     ast
-    |> Code.postwalk(&traverse_mod/2)
+    |> Code.postwalk(&collect_defs/2)
     |> Enum.map(&def_name/1)
     |> Enum.uniq
   end
+
+
 
   @doc "Returns the name of the functions/macros for the given module's `ast`"
   def def_names_with_op(nil), do: []
   def def_names_with_op({:defmodule, _, _arguments} = ast) do
     ast
-    |> Code.postwalk(&traverse_mod/2)
+    |> Code.postwalk(&collect_defs/2)
     |> Enum.map(&def_name_with_op/1)
     |> Enum.uniq
   end
+
+
 
   @doc "Returns the name of the functions/macros for the given module's `ast` if it has the given `arity`."
   def def_names_with_op(nil, _arity), do: []
   def def_names_with_op({:defmodule, _, _arguments} = ast, arity) do
     ast
-    |> Code.postwalk(&traverse_mod/2)
+    |> Code.postwalk(&collect_defs/2)
     |> Enum.map(&def_name_with_op(&1, arity))
     |> Enum.reject(&is_nil/1)
     |> Enum.uniq
   end
 
-  @doc "Returns the list of modules used in a given module source code (dependent modules)"
+  for op <- @def_ops do
+    defp collect_defs({:@, _, [{unquote(op), _, arguments} = ast]}, defs) when is_list(arguments) do
+      {ast, defs -- [ast]}
+    end
+    defp collect_defs({unquote(op), _, arguments} = ast, defs) when is_list(arguments) do
+      {ast, defs ++ [ast]}
+    end
+  end
+  defp collect_defs(ast, defs) do
+    {ast, defs}
+  end
+
+
+
+  @doc "Returns the list of modules used in a given module source code."
   def modules({:defmodule, _, _arguments} = ast) do
     ast
     |> Code.postwalk(&find_dependent_modules/2)
     |> Enum.uniq
-  end
-
-  @doc "Returns the list of aliases defined in a given module source code"
-  def aliases({:defmodule, _, _arguments} = ast) do
-    ast
-    |> Credo.Code.postwalk(&find_aliases/2)
-    |> Enum.uniq
-  end
-
-  #
-  # PRIVATE STUFF
-  #
-
-  # Single alias
-  defp find_aliases({:alias, _, [{:__aliases__, _, mod_list}]} = ast, aliases) do
-    module_names =
-      mod_list
-      |> Credo.Code.Name.full
-      |> List.wrap
-
-    {ast, aliases ++ module_names}
-  end
-  # Multi alias
-  defp find_aliases({:alias, _, [{{:., _, [{:__aliases__, _, mod_list}, :{}]}, _, multi_mod_list}]} = ast, aliases) do
-    module_names =
-      Enum.map(multi_mod_list, fn(tuple) ->
-        Credo.Code.Name.full([Credo.Code.Name.full(mod_list), Credo.Code.Name.full(tuple)])
-      end)
-
-    {ast, aliases ++ module_names}
-  end
-  defp find_aliases(ast, aliases) do
-    {ast, aliases}
-  end
-
-  defp find_attribute({:@, _meta, arguments} = ast, tuple, attribute_name) do
-    case List.first(arguments) do
-      {^attribute_name, _meta, [value]} ->
-        {:ok, value}
-      _ ->
-        {ast, tuple}
-    end
-  end
-  defp find_attribute(ast, tuple, _name) do
-    {ast, tuple}
   end
 
   # exclude module name

    {ast, modules}
  end

  for op <- @def_ops do
    defp traverse_mod({:@, _, [{unquote(op), _, arguments} = ast]}, defs) when is_list(arguments) do
      {ast, defs -- [ast]}
    end
    defp traverse_mod({unquote(op), _, arguments} = ast, defs) when is_list(arguments) do
      {ast, defs ++ [ast]}
    end
  end
  defp traverse_mod(ast, defs) do
    {ast, defs}
  end

  def name({:defmodule, _, [{:__aliases__, _, name_list}, _]}) do
    Enum.join(name_list, ".")
  end
  def name(_), do: "<Unknown Module Name>"

  # TODO: write unit test
  def exception?({:defmodule, _, [{:__aliases__, _, _name_list}, arguments]}) do

  end
  def def_arity(_), do: nil



  @doc "Returns the name of the function/macro defined in the given `ast`"
  for op <- @def_ops do
    def def_name({unquote(op) = op, _, [{:when, _, fun_ast}, _]}) do
