breathe-doc / breathe

ReStructuredText and Sphinx bridge to Doxygen
https://breathe-doc.org
Other
749 stars 198 forks source link

"The function name is required to be unique in the project." #58

Closed vonj closed 11 years ago

vonj commented 11 years ago

If I understand this correctly, it's a serious issue. We have dozens of functions in our project, all named the same. We can't document these with Breathe, right?

(Besides that, I love that someone is marrying Sphinx to more languages.)

vitaut commented 11 years ago

You can. Support for overloaded functions (with some limitations) was recently implemented in Breathe: https://github.com/michaeljones/breathe/commit/772ce2b7c047d03b8cb6464aa5f751d68667836f So this is a documentation issue.

vonj commented 11 years ago

Anything special one needs to do? Our signatures are also the same, not just the name. They look like hellofun($param1, $param2, $param) { blah; }

all of them :-) Also, did you see my pull request for the typo?

michaeljones commented 11 years ago

Hi,

Thanks for looking at Breathe and for your comments. You might need to supply an example of the code you're working with. I'm afraid I mainly test with C/C++ but it looks like you might be using something different :)

Definitely keen to have Breathe support anything that Doxygen is happy with. However if there is really no difference between the functions, I'm not sure what to do there!

I did see the pull request, thank you for that. I've just merged it in.

Thanks again, Michael

vonj commented 11 years ago

Closing until I know more.

vonj commented 11 years ago

I use PHP. What I find puzzling is, how do I reference a specific function from my index.rst in Sphinx.

say we have this structure:

somedir1/web.php somedir2/web.php

Both the "web.php" contains a function "call()"

.. doxygenfunction:: somedir/web:call :members:

does not work, obviously, but is there any way at all to do this?

mbolivar commented 11 years ago

On 02/19/2013 07:30 AM, vonj wrote:

I use PHP. What I find puzzling is, how do I reference a specific function from my index.rst in Sphinx.

say we have this structure:

somedir1/web.php somedir2/web.php

Both the "web.php" contains a function "call()"

.. doxygenfunction:: somedir/web:call :members:

does not work, obviously, but is there any way at all to do this

Something like that would be really nice. I currently resort (in C) to an input filter hack to trick Doxygen and Breathe into thinking that a variety of structs we use which have the same name are in different C++ namespaces:

https://github.com/leaflabs/libmaple/blob/master/support/doxygen/evil_mangler.awk https://github.com/leaflabs/libmaple/blob/master/support/doxygen/Doxyfile#L685

That lets us pull things out with

.. doxygenfunction:: fake_namespace::func

but is obviously a pretty hackish solution.

— Reply to this email directly or view it on GitHub https://github.com/michaeljones/breathe/issues/58#issuecomment-13770128.

vonj commented 11 years ago

Thanks. I don't think I can use that approach, but it's good to see there are others also liking Breathe so much they use it despite its flaws.

michaeljones commented 11 years ago

Hi,

It seems to me that if the files contain identical functions, then they perhaps are part of different projects? I struggle to see how they could be used in the same project?

Perhaps setting it up so that you have separate doxygen projects/xml output for each set of functions and then referencing them into Breathe under different projects?

.. doxygenfunction:: web:call
   :project: oneProject

.. doxygenfunction:: web:call
   :project: anotherProject

I think that should work. Out of interest, does doxygen handle your set up without complaint? If so, we should be able to find a way for Breathe to accommodate it, it is just a matter of finding the right interface. Perhaps:

.. doxygenfunction:: web::call
   :file: somedir1/web.php

Of course, you are free to find a less flawed alternative :P

Cheers, Michael

mbolivar commented 11 years ago

On 02/20/2013 04:38 AM, Michael Jones wrote:

Hi,

It seems to me that if the files contain identical functions, then they perhaps are part of different projects? I struggle to see how they could be used in the same project?

Our use case is atypical, so we had to bend the rules a bit to get things to work.

We're targeting a few different families of bare metal microcontroller all built by the same manufacturer. One place where we want documented entities with the same name but different definitions is structs which encapsulate contiguous sets of related MMIO registers (e.g. those for a UART or SPI port, or set of GPIOs). In these cases, it's convenient to have e.g. a struct gpio_reg_map, as, although the exact registers present on different supported microcontrollers vary, there are often enough in common that it's possible to write portable routines which only need to operate on a common subset of them. This has obvious benefits for reducing code duplication.

If this were a "normal" C++ application, this is the sort of thing you would handle with inheritance. But all our low-level code is plain C, and anyways, the performance costs would likely have been prohibitive.

We could have gone the route where you do something like this:

struct gpio_reg_map {

ifdef ONE_KIND_OF_MICROCONTROLLER

uint32_t some_register;
uint32_t some_other_register;

elif defined(SOME_OTHER_KIND)

... etc.

endif

};

But that's a recipe for a bloated mess once enough families get support.

We could have also done something like

struct one_kind_gpio_reg_map { ... }; struct another_kind_gpio_reg_map { ... };

and then tried to cast in the portable routines. The problem is that sometimes the manufacturer adds new registers between old ones when introducing a new family, while preserving the meaning of the old ones. Because of that, there's no single struct type you can cast to if you just care about the old registers, as the offsets will be different.

Believe me, I'm not exactly thrilled with the input filter, but it does seem to be the best choice among the alternatives I've come up with.

Perhaps setting it up so that you have separate doxygen projects/xml output for each set of functions and then referencing them into Breathe under different projects?

|.. doxygenfunction:: web:call :project: oneProject

.. doxygenfunction:: web:call :project: anotherProject |

I thought about that, but I don't think it would work for us. Each of the supported families relies heavily on common support code, and I need to be able to refer to it from the docs for the family code, which AFAIK separate projects won't let me do.

I think that should work. Out of interest, does doxygen handle your set up without complaint? If so, we should be able to find a way for Breathe to accommodate it, it is just a matter of finding the right interface. Perhaps:

.. doxygenfunction:: web::call :file: somedir1/web.php

Doxygen doesn't handle this, so there's nothing Breathe can do:

"Doxygen does not work properly if there are multiple classes, structs or unions with the same name in your code. It should not crash however, rather it should ignore all of the classes with the same name except one."

http://www.stack.nl/~dimitri/doxygen/manual/trouble.html#knowproblems

Of course, you are free to find a less flawed alternative :P

I realize you're not talking to me, but I thought I'd chime in and say that we think Breathe is great, and thanks for making it.

Best, Marti

Cheers, Michael

— Reply to this email directly or view it on GitHub https://github.com/michaeljones/breathe/issues/58#issuecomment-13823273.

vonj commented 11 years ago

You said just about everything I would have and more. :-)

michaeljones commented 11 years ago

Thank you for your kind words and the explanation. It does seem to be a rare issue and it is unfortunate that doxygen cannot handle the situation.

Cheers, Michael

vonj commented 11 years ago

Not exactly rare. Even in C program I could see projects using the same function signature in a bunch of places, for instance in a module or plugin system. It is unfortunate that Doxygen does not somehow decorate names with a property or something, to indicate when or where it found.