-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for C++ using type definitions #226
Conversation
a8ce514
to
85bd459
Compare
Found it, I forgot to register |
Thanks for looking into this! Looks pretty clean, but I'm not sure this warrants a different behaviour than typedefs. The difference I see here is that you're printing out the aliased type in the documentation, but that could be done with the typedef as well in principle, so I'd rather merge those two paths under Two things to consider with regards to printing out the aliased type either way:
By the way, I haven't checked how the Pinging @jnikula as he may have some input here as well. Also, if you don't mind, can you split the test(s) into separate commits. |
Besides the nitpicks regarding the boundaries of parser/doccursor/docstring, not really. I used to be proficient in C++, but I haven't written any in a very long time, and the modern usage seems to have evolved quite a bit. I can't honestly claim to know what C++ users would expect to see. I'm heavily relying on you two to figure this out. |
The test suite can be a bit fussy at times, but it's generally been a life saver! |
It looks a bit different, that why I went for C++ specific implementation. This is it looks with an equal sign with my current theme: Which is quite nice, since that is exactly what you also see in code. Converting this to a C style typedef feels unnatural to me. You can find more examples in the sphinx docs: https://www.sphinx-doc.org/en/master/usage/domains/cpp.html#directive-cpp-type
That is a good point. I mainly use alias typesdefs for function pointers, and there seeing the implementation in the documentation is definitely the thing you want. But I can see that in other scenarios that might not be the case.
Haven't tried, it's not something I would ever use since I don't see the benefit compared to just declaring the type normally. Also thinking about it, this probably doesn't work yet with templated alias definitions. I have to look into that, as that is the most likes the biggest use case / advantages of |
So, I understand you want it to look different from the current The crux for me is: do you know of kind of type alias that can be represented with one of them but not the other? If so, there might be a good case behind splitting the two docstring implementations. Otherwise, they should be handled in the same way. As anecdotal evidence, Sphinx only needs one directive to cover both cases. |
Side note: not sure if that would be an issue, but if the |
Hey @stephanlachnit & @BrunoMSantos, is it clear to you what to do next with this? |
Yes - I have to add support for templates (when I find the time). |
No pressure! I'm just trying to ensure you're not waiting for some input here. |
My earlier objections to the current implementation still stand, I believe, otherwise it's clear. That said, I would prefer to do some clean ups on docstring before tackling new functionality. And even then I intend to start with the namespace as it is a much more limiting issue. So frankly this is not really on my radar right now. Trying to muster the courage for another stint of refactoring 😅 |
85bd459
to
e2044af
Compare
So, after some fighting with clang this now also supports templated aliases. Now, the open question is: do we merge the codepath of The disadvantage when merging is that we need to keep track how the typedef/alias was made. With a C-style typedef we want to use .. cpp:type:: std::vector<int> MyIntList while with a C++ alias we want to use .. cpp:type:: template<typename T> MyList = std::vector<T> See also https://www.sphinx-doc.org/en/master/usage/domains/cpp.html#directive-cpp-type Currently, the typedef implementation does not show the underlying type, while this C++ alias implementation always shows underlying type. The advantage of a code merge would be, that this could be toggable somewhere and we have the functionality in the same class. |
Nice!
Did you test using the C++ format on C? I was hoping the directive would work the same regardless of the domain, but it's still a hope only. Even if it doesn't work in the C domain, I think the right way to handle a
This is for handling overloads, right? I didn't play around with it, but that was the impression I got.
I think the merge should be mostly about whether the code for each path is sufficiently different that it justifies it, not because we want the directives and outputs to be different. I.e. any |
Side note, if by "togglable" you mean it could be a user option, my strong preference is for sane defaults instead. |
Yeah, the question is whether the user wants a type to be opaque or not, and I think there is a case to be made that both are valid. Not the most important thing probably, but it would be a nice enough option in my opinion. The one thing I don't want though is for |
It does not. In C, only the typedef-style definitions work.
Hm, I'm not sure. In modern C++, you wouldn't use typedefs anymore. So I suspect that most typedef are C style, i.e. typedef-ing anonymous structs (in modern C++ you would use a tuple if you don't want to define a struct directly).
Sorry wrong link - I meant https://www.sphinx-doc.org/en/master/usage/domains/cpp.html#directive-cpp-type
The problem is that whether the code path is sufficiently different depends on your assumption. In principle, typedefs and aliases are identical (besides for support of templates, which has to be handled specifically anyway). However, in the real world, typedefs are used for different things. I'm not a C developer so I might be wrong, but from what I saw defining typedefs are mostly used for anonymous structs, while in C++ aliases are mostly used as shorthands for long template expressions. I would not bother to support anonymous struct per alias definitions in C++, it's a code smell anyway and we don't have to support legacy code bases (I'm not even sure if it works). Maybe anonymous structs are something you want to support for C in the future - making this explicitly C where C++ features can be ignored might be useful.
Agreed. I can only tell for me and how I would use C++, but basically you would almost always want to see the definition of a C++ alias. I don't know it is for a C developer with typedefs. If in C one would not expect the definition in the documentation, then I would propose to leave the two classes separate. |
Hmm, I think you're right. Still haven't tested it, but re-reading the documentation it seems like the C domain supports: .. c:type:: typeA
.. c:type:: typeB typeA C++ domain on the other hand supports both of the above and, additionally: .. cpp:type:: typeA = typeC That being the case, I expect both Anyway, I had forgotten that On another topic, if Finally, aliasing an anonymous type is orthogonal to documenting a type as opaque. And defining such opaque types API wise is not legacy, it's actually a very common pattern on libraries (with good reason I think), which is why I think the option should exist in both domains. But we can make that a separate issue and I agree the non-opaque option is the better default for now. I'll try to review the actual code today / tomorrow ;) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think template support may still be lacking, but hopefully I'm wrong and it's just a matter of adding some more tests for that.
Other than that, there's an issue of consistency relative to typedef
s. That would not relate to this code exactly though, and fixing it according to the typedef
would, in my opinion, force us to do the wrong thing again, except it's a bit harder this time due to clang resolving the alias cursor ahead of the aliased one for using
, the opposite of a typedef
. I.e. no promotion to struct
in the current docstring-cursor pairing logic.
Frankly, I think the using
behaviour here is the correct one, but I fought that one with @jnikula already 😅 I'll defer to him on this one.
I'll repeat this for @stephanlachnit's benefit: For both the anonymous If you specifically want to document the typedef, you need to define the struct and the typedef separately. Indeed, if you aim for an opaque type, it's common to have the One might argue that a
Auch, do I need to brush up my C++ now? 😬 Gut feeling says it's fine that |
I tend to disagree when considering modern C++. AFAICT, unnamed types have two purposes:
This pattern is largely a C pattern you would not use modern C++. That is of course fine, not everyone needs to write modern C++, but I can't see why someone would combine a modern C++ feature ( |
Probably not as common no, especially as So yeah, ignoring the inconsistency it is an option here. Though the issue will probably come up later once we try and make |
Hmm, I guess you're right. The use cases I was thinking of (dynamically linked libraries) would explicitly export a C compatible API with C headers, so no |
And thanks for bearing with me @stephanlachnit! We certainly appreciate the interest and help 🥳 |
Signed-off-by: Stephan Lachnit <[email protected]>
C++ native type definitions (aliases) use the `using` keyword and support template arguments. This commit adds support for them. Signed-off-by: Stephan Lachnit <[email protected]>
Signed-off-by: Stephan Lachnit <[email protected]>
Updated the PR with the suggested changes. |
e2044af
to
db250e2
Compare
Thanks for the updates, I think it's all good from my side! |
This PR adds support for
using typeA = typeB
via thecpp:type
type alias declaration.Up for discussion: I stored the "underlying type" in the
value
property of the cursor, since that is what felt most natural to me given the C++ syntax.I added a test case, however two of the three tests fail (
test/test_cautodoc.py::test_directive_text[cpp/using-alias]
andtest/test_cautodoc.py::test_directive_html[cpp/using-alias]
). Since I don't really understand why they fail, I need to help here.