summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWaldemar Rachwał <waldemar.rachwal@gmail.com>2015-02-11 16:50:35 +0100
committerWaldemar Rachwał <waldemar.rachwal@gmail.com>2015-02-11 16:50:35 +0100
commit048cf5f9f7e8e1b48eded0bab9276c1056f419f8 (patch)
tree3b1982d8a80cd0202ba43ed97ff449541c4e2001 /lib
parentac314728917d75ac23830106d7524d36b8267353 (diff)
downloadelixir-048cf5f9f7e8e1b48eded0bab9276c1056f419f8.tar.gz
Add Record.extract_all/1 returning all records information
Diffstat (limited to 'lib')
-rw-r--r--lib/elixir/lib/record.ex13
-rw-r--r--lib/elixir/lib/record/extractor.ex46
-rw-r--r--lib/elixir/test/elixir/record_test.exs7
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)