From a8a2f86a23533d80098a62e732c8f39e27a77b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 23 Jun 2013 20:20:32 +0200 Subject: [PATCH] Record type should be private by default, closes #1288 --- lib/elixir/lib/kernel.ex | 9 ++++----- lib/elixir/lib/record.ex | 20 ++++++++++++-------- lib/elixir/test/elixir/typespec_test.exs | 5 +++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/elixir/lib/kernel.ex b/lib/elixir/lib/kernel.ex index 2cc8bea19b..1e5805b442 100644 --- a/lib/elixir/lib/kernel.ex +++ b/lib/elixir/lib/kernel.ex @@ -1491,9 +1491,9 @@ defmodule Kernel do ## Types - `defrecordp` automatically generates an opaque type based - on the record name and the types can be modified too. The - following definition: + `defrecordp` allows a developer to generate a type + automatically by simply providing a type to its fields. + The following definition: defrecordp :user, name: "José" :: binary, @@ -1501,9 +1501,8 @@ defmodule Kernel do Will generate the following type: - @opaque user :: { :user, binary, integer } + @typep user_t :: { :user, binary, integer } - All the fields without a specified type are assumed to have type `term`. """ defmacro defrecordp(name, fields) when is_atom(name) do Record.defrecordp(name, fields) diff --git a/lib/elixir/lib/record.ex b/lib/elixir/lib/record.ex index 290bda7216..60bb09e370 100644 --- a/lib/elixir/lib/record.ex +++ b/lib/elixir/lib/record.ex @@ -253,24 +253,28 @@ defmodule Record do so check it for more information and documentation. """ def defrecordp(name, fields) when is_atom(name) and is_list(fields) do - { fields, types } = recordp_split(fields, [], []) + { fields, types, def_type } = recordp_split(fields, [], [], false) + type = :"#{name}_t" quote do Record.defmacros(unquote(name), unquote(fields), __ENV__) - @opaque unquote(name)() :: { unquote(name), unquote_splicing(types) } + + if unquote(def_type) do + @typep unquote(type)() :: { unquote(name), unquote_splicing(types) } + end end end - defp recordp_split([{ field, { :::, _, [default, type] }}|t], defaults, types) do - recordp_split t, [{ field, default }|defaults], [type|types] + defp recordp_split([{ field, { :::, _, [default, type] }}|t], defaults, types, _) do + recordp_split t, [{ field, default }|defaults], [type|types], true end - defp recordp_split([other|t], defaults, types) do - recordp_split t, [other|defaults], [quote(do: term)|types] + defp recordp_split([other|t], defaults, types, def_type) do + recordp_split t, [other|defaults], [quote(do: term)|types], def_type end - defp recordp_split([], defaults, types) do - { :lists.reverse(defaults), :lists.reverse(types) } + defp recordp_split([], defaults, types, def_type) do + { :lists.reverse(defaults), :lists.reverse(types), def_type } end @doc """ diff --git a/lib/elixir/test/elixir/typespec_test.exs b/lib/elixir/test/elixir/typespec_test.exs index 1bd45be2ae..56f2458280 100644 --- a/lib/elixir/test/elixir/typespec_test.exs +++ b/lib/elixir/test/elixir/typespec_test.exs @@ -262,10 +262,11 @@ defmodule Typespec.TypeTest do test "@type from defrecordp" do types = test_module do defrecordp :user, name: nil, age: 0 :: integer - @opaque + @opaque user :: user_t + @type end - assert [{:user, {:type, _, :tuple, + assert [{:user_t, {:type, _, :tuple, [{:atom, _, :user}, {:type, _, :term, []}, {:type, _, :integer, []}]}, []}] = types end