Skip to content

Instantly share code, notes, and snippets.

@JEG2
Created October 19, 2016 20:11
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save JEG2/1685a9df2274ca5cf866122fa2dbc42d to your computer and use it in GitHub Desktop.
Save JEG2/1685a9df2274ca5cf866122fa2dbc42d to your computer and use it in GitHub Desktop.
How to get typespec information from Elixir at runtime.
defmodule TypeSpecs do
def for_module(module) do
{:ok, {^module, [{:abstract_code, {:raw_abstract_v1, attributes}}]}} =
module |> :code.which |> :beam_lib.chunks([:abstract_code])
attributes
|> Enum.filter_map(fn
{:attribute, _, :spec, _function_and_types} -> true
_attribute -> false
end, fn {:attribute, _, :spec, function_and_types} ->
function_and_types
end)
end
end
TypeSpecs.for_module(String)
|> IO.inspect
# [{{:split, 3},
# [{:type, 330, :fun,
# [{:type, 330, :product,
# [{:user_type, 330, :t, []},
# {:type, 330, :union,
# [{:user_type, 330, :pattern, []},
# {:remote_type, 330, [{:atom, 0, Regex}, {:atom, 0, :t}, []]}]},
# {:remote_type, 330, [{:atom, 0, Keyword}, {:atom, 0, :t}, []]}]},
# {:type, 0, :list, [{:user_type, 330, :t, []}]}]}]},
# {{:trim, 2},
# [{:type, 847, :fun,
# [{:type, 847, :product,
# [{:user_type, 847, :t, []}, {:user_type, 847, :t, []}]},
# {:user_type, 847, :t, []}]}]},
# {{:pad_leading, 3},
# [{:type, 884, :fun,
# [{:type, 884, :product,
# [{:user_type, 884, :t, []}, {:type, 884, :non_neg_integer, []},
# {:type, 884, :union,
# [{:user_type, 884, :t, []},
# {:type, 0, :list, [{:user_type, 884, :t, []}]}]}]},
# {:user_type, 884, :t, []}]}]},
# {{:pad_trailing, 3},
# [{:type, 926, :fun,
# [{:type, 926, :product,
# [{:user_type, 926, :t, []}, {:type, 926, :non_neg_integer, []},
# {:type, 926, :union,
# [{:user_type, 926, :t, []},
# {:type, 0, :list, [{:user_type, 926, :t, []}]}]}]},
# {:user_type, 926, :t, []}]}]},
# {{:printable?, 1},
# [{:type, 217, :fun,
# [{:type, 217, :product, [{:user_type, 217, :t, []}]},
# {:type, 217, :boolean, []}]}]},
# {{:valid?, 1},
# [{:type, 1181, :fun,
# [{:type, 1181, :product, [{:user_type, 1181, :t, []}]},
# {:type, 1181, :boolean, []}]}]},
# {{:to_integer, 1},
# [{:type, 1808, :fun,
# [{:type, 1808, :product,
# [{:remote_type, 1808, [{:atom, 0, String}, {:atom, 0, :t}, []]}]},
# {:type, 1808, :integer, []}]}]},
# {{:upcase, 1},
# [{:type, 534, :fun,
# [{:type, 534, :product, [{:user_type, 534, :t, []}]},
# {:user_type, 534, :t, []}]}]},
# {{:downcase, 1},
# [{:type, 552, :fun,
# [{:type, 552, :product, [{:user_type, 552, :t, []}]},
# {:user_type, 552, :t, []}]}]},
# {{:capitalize, 1},
# [{:type, 576, :fun,
# [{:type, 576, :product, [{:user_type, 576, :t, []}]},
# {:user_type, 576, :t, []}]}]},
# {{:reverse, 1},
# [{:type, 1084, :fun,
# [{:type, 1084, :product, [{:user_type, 1084, :t, []}]},
# {:user_type, 1084, :t, []}]}]},
# {{:next_grapheme, 1},
# [{:type, 1305, :fun,
# [{:type, 1305, :product, [{:user_type, 1305, :t, []}]},
# {:type, 1305, :union,
# [{:type, 0, :tuple,
# [{:user_type, 1305, :grapheme, []}, {:user_type, 1305, :t, []}]},
# {:atom, 0, nil}]}]}]},
# {{:next_grapheme_size, 1},
# [{:type, 1326, :fun,
# [{:type, 1326, :product, [{:user_type, 1326, :t, []}]},
# {:type, 1326, :union,
# [{:type, 0, :tuple,
# [{:type, 1326, :pos_integer, []}, {:user_type, 1326, :t, []}]},
# {:atom, 0, nil}]}]}]},
# {{:equivalent?, 2},
# [{:type, 486, :fun,
# [{:type, 486, :product,
# [{:user_type, 486, :t, []}, {:user_type, 486, :t, []}]},
# {:type, 486, :boolean, []}]}]},
# {{:length, 1},
# [{:type, 1386, :fun,
# [{:type, 1386, :product, [{:user_type, 1386, :t, []}]},
# {:type, 1386, :non_neg_integer, []}]}]},
# {{:starts_with?, 2},
# [{:type, 1613, :fun,
# [{:type, 1613, :product,
# [{:user_type, 1613, :t, []},
# {:type, 1613, :union,
# [{:user_type, 1613, :t, []},
# {:type, 0, :list, [{:user_type, 1613, :t, []}]}]}]},
# {:type, 1613, :boolean, []}]}]},
# {{:ends_with?, 2},
# [{:type, 1648, :fun,
# [{:type, 1648, :product,
# [{:user_type, 1648, :t, []},
# {:type, 1648, :union,
# [{:user_type, 1648, :t, []},
# {:type, 0, :list, [{:user_type, 1648, :t, []}]}]}]},
# {:type, 1648, :boolean, []}]}]},
# {{:match?, 2},
# [{:type, 1680, :fun,
# [{:type, 1680, :product,
# [{:user_type, 1680, :t, []},
# {:remote_type, 1680, [{:atom, 0, Regex}, {:atom, 0, :t}, []]}]},
# {:type, 1680, :boolean, []}]}]},
# {{:contains?, 2},
# [{:type, 1713, :fun,
# [{:type, 1713, :product,
# [{:user_type, 1713, :t, []}, {:user_type, 1713, :pattern, []}]},
# {:type, 1713, :boolean, []}]}]},
# {{:to_integer, 2},
# [{:type, 1824, :fun,
# [{:type, 1824, :product,
# [{:remote_type, 1824, [{:atom, 0, String}, {:atom, 0, :t}, []]},
# {:type, 1824, :range, [{:integer, 0, 2}, {:integer, 0, 36}]}]},
# {:type, 1824, :integer, []}]}]},
# {{:normalize, 2},
# [{:type, 516, :fun,
# [{:type, 516, :product,
# [{:user_type, 516, :t, []}, {:type, 516, :atom, []}]},
# {:user_type, 516, :t, []}]}]},
# {{:duplicate, 2},
# [{:type, 1110, :fun,
# [{:type, 1110, :product,
# [{:user_type, 1110, :t, []}, {:type, 1110, :non_neg_integer, []}]},
# {:user_type, 1110, :t, []}]}]},
# {{:slice, 2},
# [{:type, 1540, :fun,
# [{:type, 1540, :product,
# [{:user_type, 1540, :t, []},
# {:remote_type, 1540, [{:atom, 0, Range}, {:atom, 0, :t}, []]}]},
# {:user_type, 1540, :t, []}]}]},
# {{:jaro_distance, 2},
# [{:type, 1868, :fun,
# [{:type, 1868, :product,
# [{:user_type, 1868, :t, []}, {:user_type, 1868, :t, []}]},
# {:type, 1868, :float, []}]}]},
# {{:myers_difference, 2},
# [{:type, 1960, :fun,
# [{:type, 1960, :product,
# [{:user_type, 1960, :t, []}, {:user_type, 1960, :t, []}]},
# {:type, 1960, :union,
# [{:type, 0, :list,
# [{:type, 0, :tuple,
# [{:type, 1960, :union,
# [{:atom, 0, :eq}, {:atom, 0, :ins}, {:atom, 0, :del}]},
# {:user_type, 1960, :t, []}]}]}, {:atom, 0, nil}]}]}]},
# {{:split, 1},
# [{:type, 262, :fun,
# [{:type, 262, :product, [{:user_type, 262, :t, []}]},
# {:type, 0, :list, [{:user_type, 262, :t, []}]}]}]},
# {{:splitter, 3},
# [{:type, 377, :fun,
# [{:type, 377, :product,
# [{:user_type, 377, :t, []}, {:user_type, 377, :pattern, []},
# {:remote_type, 377, [{:atom, 0, Keyword}, {:atom, 0, :t}, []]}]},
# {:remote_type, 377, [{:atom, 0, Enumerable}, {:atom, 0, :t}, []]}]}]},
# {{:next_codepoint, 1},
# [{:type, 1160, :fun,
# [{:type, 1160, :product, [{:user_type, 1160, :t, []}]},
# {:type, 1160, :union,
# [{:type, 0, :tuple,
# [{:user_type, 1160, :codepoint, []}, {:user_type, 1160, :t, []}]},
# {:atom, 0, nil}]}]}]},
# {{:chunk, 2},
# [{:type, 1236, :fun,
# [{:type, 1236, :product,
# [{:user_type, 1236, :t, []},
# {:type, 1236, :union, [{:atom, 0, :valid}, {:atom, 0, :printable}]}]},
# {:type, 0, :list, [{:user_type, 1236, :t, []}]}]}]},
# {{:first, 1},
# [{:type, 1342, :fun,
# [{:type, 1342, :product, [{:user_type, 1342, :t, []}]},
# {:type, 1342, :union,
# [{:user_type, 1342, :grapheme, []}, {:atom, 0, nil}]}]}]},
# {{:last, 1},
# [{:type, 1363, :fun,
# [{:type, 1363, :product, [{:user_type, 1363, :t, []}]},
# {:type, 1363, :union,
# [{:user_type, 1363, :grapheme, []}, {:atom, 0, nil}]}]}]},
# {{:to_charlist, 1},
# [{:type, 1741, :fun,
# [{:type, 1741, :product, [{:user_type, 1741, :t, []}]},
# {:remote_type, 0, [{:atom, 0, :elixir}, {:atom, 0, :charlist}, []]}]}]},
# {{:to_float, 1},
# [{:type, 1848, :fun,
# [{:type, 1848, :product,
# [{:remote_type, 1848, [{:atom, 0, String}, {:atom, 0, :t}, []]}]},
# {:type, 1848, :float, []}]}]},
# {{:to_char_list, 1},
# [{:type, 2049, :fun,
# [{:type, 2049, :product, [{:user_type, 2049, :t, []}]},
# {:remote_type, 0, [{:atom, 0, :elixir}, {:atom, 0, :charlist}, []]}]}]},
# {{:trim_leading, 1},
# [{:type, 770, :fun,
# [{:type, 770, :product, [{:user_type, 770, :t, []}]},
# {:user_type, 770, :t, []}]}]},
# {{:trim_trailing, 1},
# [{:type, 800, :fun,
# [{:type, 800, :product, [{:user_type, 800, :t, []}]},
# {:user_type, 800, :t, []}]}]},
# {{:slice, 3},
# [{:type, 1469, :fun,
# [{:type, 1469, :product,
# [{:user_type, 1469, :t, []}, {:type, 1469, :integer, ...},
# {:type, 1469, :integer, ...}]}, {:user_type, 1469, :grapheme, []}]}]},
# {{:split, 2},
# [{:type, 329, :fun,
# [{:type, 329, :product,
# [{:user_type, 329, :t, ...}, {:type, 329, :union, ...}]},
# {:type, 0, :list, [{:user_type, 329, :t, []}]}]}]},
# {{:split_at, 2},
# [{:type, 439, :fun,
# [{:type, 439, :product, [{:user_type, 439, ...}, {:type, 439, ...}]},
# {:type, 0, :tuple, [{:user_type, 439, ...}, {:user_type, 439, ...}]}]}]},
# {{:trim, 1},
# [{:type, 830, :fun,
# [{:type, 830, :product, [{:user_type, 830, ...}]},
# {:user_type, 830, :t, []}]}]},
# {{:at, 2},
# [{:type, 1411, :fun,
# [{:type, 1411, :product, [{...}, ...]},
# {:type, 1411, :union, [{...}, ...]}]}]},
# {{:to_atom, 1},
# [{:type, 1769, :fun,
# [{:type, 1769, :product, ...}, {:type, 1769, :atom, ...}]}]},
# {{:to_existing_atom, 1},
# [{:type, 1792, :fun, [{:type, 1792, ...}, {:type, 1792, ...}]}]},
# {{:trim_leading, 2}, [{:type, 785, :fun, [{:type, ...}, {:user_type, ...}]}]},
# {{:trim_trailing, 2}, [{:type, 815, :fun, [{...}, ...]}]},
# {{:replace, 4}, [{:type, 1030, :fun, ...}]},
# {{:codepoints, 1}, [{:type, 1138, ...}]}, {{:graphemes, ...}, [{:type, ...}]},
# {{:__info__, ...}, [{:type, ...}]}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment