Reputation: 61121
Looking at Erlang docs, sometimes I come across type specs, that document a function type without really specifying the type...
Hard to explain, so let me give you an example. In the gen_server
the handle_call
function shows up as the following in the docs:
Request = term()
From = {pid(),Tag}
State = term()
Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}
| {reply,Reply,NewState,hibernate}
| {noreply,NewState} | {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}
Reply = term()
NewState = term()
Timeout = int()>=0 | infinity
Reason = term()
Here the type Tag
is never shown (i.e. it's just a variable name).
Is the same possible to do with edoc
? The closest I found was opaque type spec, but that documents it as abstract - is that the same?
Upvotes: 2
Views: 125
Reputation: 2243
It is possible as long as the argument variable name in the function (in all clauses) and that name used in the @spec
are same. For example.
%% @spec start_link(Args) -> {ok, pid()}
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
will generate the following doc
start_link(Args) -> {ok, pid()}
If you have a different name for example
%% @spec start_link(Args) -> {ok, pid()}
start_link(Num) when is_integer(Num) ->
gen_server:start_link(?MODULE, [], []);
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
It would generate as
start_link(Num::Args) -> {ok, pid()}
assuming Args as a type.
I would personally not recommend to use edoc @spec and instead use -spec as they are used by dialyzer and hence can be validated.
edoc can generate the doc from -spec too. Given both -spec and @spec, edoc overrides to @spec directive.
%% @spec start_link(Args) -> {ok, Pid}
-spec start_link(term()) -> {ok, pid()}.
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
Above will result in
start_link(Args) -> {ok, Pid}
And removing @spec from above will result in
start_link(Args::term()) -> {ok, pid()}
Upvotes: 2
Reputation: 41618
As far as I can see, this is not possible with Edoc.
I tried using a spec like this:
-spec foo(Something) -> term().
foo(X) ->
X.
And while Edoc is actually happy about it, and gives the type spec as foo(Something)
in the docs without specifying what Something
is, the compiler complains about it, and says:
type variable 'Something' is only used once (is unbound)
So you'd have to write:
-spec foo(Something::_) -> term().
foo(X) ->
X.
which shows up as foo(Something::term())
, thereby giving a type specification for Something
.
Using an Edoc-only type specification:
%% @spec foo(Something) -> term()
foo(X) ->
X.
Edoc treats Something
as a type name that applies to the variable X
and puts foo(X::Something)
in the documentation.
So neither way would do exactly what you want to achieve.
Upvotes: 0