Exclude static functions from c:autodoc#284
Exclude static functions from c:autodoc#284RastislavTuranyi wants to merge 1 commit intojnikula:masterfrom
Conversation
|
I think the The The Now, what is public? I think this should be based on the visibility another random
I think the only problematic case is opaque types. Say, you have a @BrunoMSantos thoughts? |
Add test cases where your |
|
If there's a way to exclude private members, I think there should also be a way to only include private members, so you can split the documentation into public and private (implementation details). I think that's a valid use case. There's an option to only include private members in autodoc, it's I think we should mimic that. And I guess perhaps |
|
(Oops, sorry for the close/reopen noise, hit the wrong button. 🤦) |
Sure! Would you like to define the behaviour for the C++ exclusive subclasses (e.g.
Are you certain this should be enforced at the library level instead of leaving it to the user? This would mean that the option(s) would have no effect at all with a header file, at which point it might be easier to turn the option off in the directive rather than passing the .c/.h information around.
That could indeed be useful! I am a little bit concerned, though, about potential confusion since the behaviour is different between sphinx and hawkmoth - sphinx autodoc |
|
Also, would you like to continue using the |
I think we'd want a "is this declared / defined in a header" and a "is this static / in an empty namespace" for this purpose instead.
Think so too. I don't think that the cursor could know actually: any file can be
Only what is declared
I think this is confusing the separation of API and non-API with other concepts that are simply not a thing in C and really are a thing in C++, but a different thing altogether (with keywords and everything). Comparisons to Python's autodoc are unfounded in this case, I think. Now, many projects have different levels and definitions of API access. The kernel guys have But, considering we changed what we call this not to clash with C++'s private / protected concepts (probably 'excluded members' like in autodoc), I think there's a good alternative: ---------------8<---------------- We want to (conditionally or not) skip certain symbols, but we don't want to be naming them all the time with Also pause to consider that Doxygen uses a Now, I don't think a In fact looking at We would pass along the cursor with those "am I static / in an empty namespace" and "am I in a header" methods among everything else and the user could easily achieve the same result proposed here without us maintaining the heuristics. |
Fair enough.
I used the term loosely, and for module level symbols, not members. For functions and variables, And
Yeah, sigh, visibility in C alone can be complicated...
I am actually symphatetic to both approaches. On the one hand, it's clean to to put API documentation in the header, next to function declarations. But on the other hand, I like having the documentation above the function definition.
So what would the directive look like with that? To achieve the same end result, I think we'd have to add an option to And would we anyway have to add that functionality in a built-in extension, and maintain it, because it has to be easy for the users too! |
That's the thing: in Python there's no such difference, a
Hmm, we could have a "is this extern" (or even a "is this declared with extern" since some like putting those in function declarations 🤷) as well.
You mean if a user wanted to overrule the skip decision from the event? I'd expect
Not sure we need to. We could document a trivial example that achieves exactly what you've proposed: def skip_member(..., cursor, ...):
return not cursor.in_header and cursor.has_static_linkage
def setup(app):
app.connect('hawkmoth-skip-member', skip_member)Actually, I'm just realizing that I'm using 'member' for file level symbols. In a way I think it's ok to interpret it contextually depending on the directive, but for the event we'd probably need to distinguish them as both could make sense separately. Maybe a I haven't thought it through quite that far. Edit: fixed inverted logic in snippet. Hope I got it right this time 🙃 |
|
[I'm sorry, I'm cherry-picking what I reply to.]
My point is, if a user wants to document external interfaces ( |
Maybe I misunderstood the question. You mean an something like this? .. autodoc:: file.c
.. autodoc:: file.c
:static:Not what I thought this was about, but I'm fine with that, as long as it's rooted on actual C/C++ features. I.e. no cross checking with file extensions, which is just a poor heuristic. I thought we meant something akin to Python's autodoc that would 'know' what is API or not and show what would otherwise be hidden by default with a |
|
Just to clarify, the event filter I'm proposing would be just a dumb filter. By default it filters nothing and you'd be able to do |
Yes, I don't think this is that different from the
Just like
I think we're maybe conflating several more or less brainstormed ideas here, and that's why we're getting confused? There are various things we could do, some orthogonal, some overlapping:
I think I was leaning towards 2) and you were leaning towards 3). I think 2) is easier for the average user, and I believe the heuristic I proposed cover most cases. However 3) is slightly harder for the average user, is obviously more flexible, and can be used to achieve the same as 2). Is that an accurate summary? In any case, I don't think the options rule each other out. The question is what to focus on first. |
|
Side note, I think starting to pass |
Yeah, agreed. Something like a
Sorry, I didn't understand this one.
Hmm, kind of? I think it's still mixing concepts a bit and I'm still uneasy about the way it's phrased. Or maybe I'm taking certain nomenclature too literally in your comments? Or maybe I haven't phrased the crux of my disagreement well enough yet? Trying to digest my ideas above, this is how I see the concepts split in my ideal world. And indeed, all of these could be implemented separately, if not in multiple steps, and only point 3 relates to the feature actually under discussion.
I believe this generalizes at least better than what I understood of the original feature request and the discussion above. And it provides an answer to the desired feature, albeit in a different way. [1] In Python you can do [2] Side note: C++ has namespaces and modules, which do and might have members respectively (never looked into modules). In namespaces, members are not any more private / public than any global symbol in C/C++ though, so nothing changes there. In modules, there seems to be a concept of 'exported' stuff which might map well to the concept of 'private members'. [3] Ultimately I think most serious projects will be more interested in looking for an |
|
So, what would you like to do? I'm not fully able to follow the discussion, but the thing I was originally after in #283 (and still am at the moment) is exactly:
I wouldn't mind doing only that much in this PR and leaving more advanced stuff for a separate one, if that is desirable? That said, learning about the .. autodoc:: main.c
:exclude-symbols: static struct typedefwhich would exclude any symbol with any of the specified strings (i.e. above would exclude all def _match(...):
...
for exclude_symbol in exclude_symbols:
if exclude_symbol in self._ttype:
return False
...This could potentially be combined with a (potentially mutually non-exclusive) |
|
Hey, sorry for the delay.
Yeah, I guess that does allow you to basically hide the stuff selectively, albeit lacking the 'intelligence' to hide things contextually like we were discussing. Assuming @jnikula agrees, I think it's ok to implement that alone for now feature wise, but this implies breaking stuff. Existing projects might suddenly see symbols disappear from the documentation. I have to defer on that one.
Hmm, that sort of thing would probably be a no go I think: it would not scale well and someone else would invariably request yet another filtering option. An event however could allow the user to do that sort of thing globally, not per directive. For 'per directive' filtering, I'd follow Python's autodoc: force the user to explicitly name the symbols. |
|
Hey, I've been away, vacations and all that. Is this waiting for my input?
That's not great. At this stage of the project, I'm kind of okay with making changes that break things loudly. However this one would silently drop stuff from documentation, and might take a while for anyone to notice. |
|
We could also do the converse and keep the default behaviour (which includes everything) and have In that case, the bigger question might be whether to go ahead with this at all - if I remember the discussion correctly, there were a couple proposals (and the default behaviour thing applies to each):
Which (combination?) of these would of interest to implement? |
Indeed. Best I imagine (assuming we prefer the default off semantics):
|
|
I understand the original issue, but apart from adding an event, I don't yet see a solution that would properly address the issue and be acceptable to everyone. One particular point:
I believe these are the relevant use cases for the problem at hand:
I originally suggested the Note how 1 and 2 do not fit Arguably top-level or generic documentation comments would fall into 1, since we have no way to make the distinction otherwise. But before jumping into bikeshedding what to name the option, do you agree the three cases above would cover the problem? |
Yup, I could see a But yeah, ultimately,
In the sense that a user could then implement an event handler with that logic, yes.
edit: sorry, I was half asleep... I can think of cases where macros and types in a |
|
Anyway. I'm looking at the code, and I believe the biggest blocker to implementing any of the features like this cleanly is that the filtering is split between |
Resolves #283
Adds
:exclude-private-members:option toc:autodocwhich, when added, causes the following docstrings to be excluded from the documentation:staticin theircursor.type/Docstring._ttype)typedef struct ...combined declaration, but those seem to be handled the exact same as normalstructdeclarations in hawkmoth and so i haven't been able to find a way to distinguish them)Do let me know if there is anything else that should be excluded as well!
I have attempted to implement this in as general a way as possible, one that would allow the framework to be used for different filtering in the future, but please let me know any comments you have!
Also, do you have any recommendations for how to do the tests for this?