jelly-beam / rebar3_ex_doc

rebar3 plugin for generating docs with ex_doc
Apache License 2.0
43 stars 13 forks source link

Does rebar3_ex_doc honor (non) exported types? #43

Closed ausimian closed 9 months ago

ausimian commented 1 year ago

Given some record and type definition:

-record(myrec, {
    foo :: bar | baz
}).
-type myrec() :: #myrec{}.

When the type is not exported, it (correctly) does not appear in edoc generated docs (via rebar3 edoc), but it does appear in the docs generated by ex_doc (via rebar3 ex_doc).

I have tried excluding it via annotating the record and/or type with @private to no effect.

Is it possible to exclude non-exported types from ex_doc?

erlang: 25.1.2 rebar3_ex_doc: 0.2.14

starbelly commented 1 year ago

It seems this only happens when you have a type that is not exported, yet a function that uses that type that is exported. I think that behavior makes sense, but I could see how you might have instances where you don't want the type to be documented with the exported function as to not confuse the user (i.e., if it ends up in the docs but is not exported the user may think that type is available for use). An issue would need to be opened up on ex_doc to resolve this. I'll take a look at the code in ex_doc myself to see how that could be wedged in.

ausimian commented 1 year ago

Ah, interesting thx! - When you say 'uses that type', do you mean that it appears in the typespec of the function? If that's the case, that's a bug on my side I think - I will take a look. But thx for investigating and thx for the library.

starbelly commented 1 year ago

Ah, interesting thx! - When you say 'uses that type', do you mean that it appears in the typespec of the function? If that's the case, that's a bug on my side I think - I will take a look. But thx for investigating and thx for the library.

@ausimian Yup, precisely.

-module(private_type).

-type my_type() :: bar.

-export([foo/0]).

-spec foo() -> my_type().
foo() -> bar.

^ my_type/0 will now end up in the docs.

paulo-ferraz-oliveira commented 1 year ago

Fwiw (late to the party) elvis_core implements a rule for this case. If your function is public the types that go with it should not be "internal", the reasoning be that your function might be simply wrapped around, and having internal types would mean having to redefine them elsewhere. A similar approach is taken on the Erlang/OTP code base itself (though not as "strong"): if a type is exposed via a function it should be available for consumption. If it's opaque or not that's another discussion 😄

paulo-ferraz-oliveira commented 1 year ago

Ah, interesting thx! - When you say 'uses that type', do you mean that it appears in the typespec of the function? If that's the case, that's a bug on my side I think - I will take a look. But thx for investigating and thx for the library.

I could not replicate by having a simple module that only defined a type (without using it), but I did replicate if you have a function that uses said type.

In any case, here's what it'd look like if it were opaque

image

In my opinion the current implementation is sane. Thoughts, @ausimian, @starbelly (?)

starbelly commented 10 months ago

@paulo-ferraz-oliveira Agreed. We can probably close this now, but since we'll be moving this to jelly-beam, it'll work it self out :)