diff options
author | Waldemar Rachwał <waldemar.rachwal@gmail.com> | 2015-02-11 16:50:35 +0100 |
---|---|---|
committer | Waldemar Rachwał <waldemar.rachwal@gmail.com> | 2015-02-11 16:50:35 +0100 |
commit | 048cf5f9f7e8e1b48eded0bab9276c1056f419f8 (patch) | |
tree | 3b1982d8a80cd0202ba43ed97ff449541c4e2001 /lib | |
parent | ac314728917d75ac23830106d7524d36b8267353 (diff) | |
download | elixir-048cf5f9f7e8e1b48eded0bab9276c1056f419f8.tar.gz |
Add Record.extract_all/1 returning all records information
Diffstat (limited to 'lib')
-rw-r--r-- | lib/elixir/lib/record.ex | 13 | ||||
-rw-r--r-- | lib/elixir/lib/record/extractor.ex | 46 | ||||
-rw-r--r-- | lib/elixir/test/elixir/record_test.exs | 7 |
3 files changed, 55 insertions, 11 deletions
diff --git a/lib/elixir/lib/record.ex b/lib/elixir/lib/record.ex index b7d75d4f8..049edc374 100644 --- a/lib/elixir/lib/record.ex +++ b/lib/elixir/lib/record.ex @@ -57,6 +57,19 @@ defmodule Record do end @doc """ + Extracts all records information from an Erlang file. + + Returns a keyword list containing extracted record names as keys, and + lists of tuples describing the fields as values. It expects a named + argument :from or :from_lib, which correspond to *include* or + *include_lib* attribute from Erlang modules, respectively. + + """ + def extract_all(opts) when is_list(opts) do + Record.Extractor.extract_all(opts) + end + + @doc """ Checks if the given `data` is a record of `kind`. This is implemented as a macro so it can be used in guard clauses. diff --git a/lib/elixir/lib/record/extractor.ex b/lib/elixir/lib/record/extractor.ex index 6fbffc25a..21acf86c8 100644 --- a/lib/elixir/lib/record/extractor.ex +++ b/lib/elixir/lib/record/extractor.ex @@ -4,27 +4,44 @@ defmodule Record.Extractor do # Retrieve a record definition from an Erlang file using # the same lookup as the *include* attribute from Erlang modules. def extract(name, from: file) when is_binary(file) do - file = String.to_char_list(file) - - realfile = - case :code.where_is_file(file) do - :non_existing -> file - realfile -> realfile - end - - extract_record(name, realfile) + extract_record(name, from_file(file)) end # Retrieve a record definition from an Erlang file using # the same lookup as the *include_lib* attribute from Erlang modules. def extract(name, from_lib: file) when is_binary(file) do - [app|path] = :filename.split(String.to_char_list(file)) + extract_record(name, from_lib_file(file)) + end + + # Retrieve all records definitions from an Erlang file using + # the same lookup as the *include* attribute from Erlang modules. + def extract_all(from: file) when is_binary(file) do + extract_all_records(from_file(file)) + end + + # Retrieve all records definitions from an Erlang file using + # the same lookup as the *include_lib* attribute from Erlang modules. + def extract_all(from_lib: file) when is_binary(file) do + extract_all_records(from_lib_file(file)) + end + + # Find file using the same lookup as the *include* attribute from Erlang modules. + defp from_file(file) do + file = String.to_char_list(file) + case :code.where_is_file(file) do + :non_existing -> file + realfile -> realfile + end + end + # Find file using the same lookup as the *include_lib* attribute from Erlang modules. + defp from_lib_file(file) do + [app|path] = :filename.split(String.to_char_list(file)) case :code.lib_dir(List.to_atom(app)) do {:error, _} -> raise ArgumentError, "lib file #{file} could not be found" libpath -> - extract_record name, :filename.join([libpath|path]) + :filename.join([libpath|path]) end end @@ -39,6 +56,13 @@ defmodule Record.Extractor do end end + # Retrieve all records from the given file + defp extract_all_records(file) do + form = read_file(file) + records = extract_records(form) + for rec = {name, _fields} <- records, do: {name, parse_record(rec, form)} + end + # Parse the given file and extract all existent records. defp extract_records(form) do for {:attribute, _, :record, record} <- form, do: record diff --git a/lib/elixir/test/elixir/record_test.exs b/lib/elixir/test/elixir/record_test.exs index 96460b1a9..0f15cdefe 100644 --- a/lib/elixir/test/elixir/record_test.exs +++ b/lib/elixir/test/elixir/record_test.exs @@ -28,6 +28,13 @@ defmodule RecordTest do StructExtract.__struct__ end + test "extract_all/1 extracts all records information from an Erlang file" do + all_extract = Record.extract_all(from_lib: "kernel/include/file.hrl") + assert length(all_extract) == 2 # has been stable over the very long time + assert all_extract[:file_info] + assert all_extract[:file_descriptor] + end + # We need indirection to avoid warnings defp record?(data, kind) do Record.is_record(data, kind) |