breathe icon indicating copy to clipboard operation
breathe copied to clipboard

Duplicate IDs when using INLINE_INHERITED_MEMBERS=YES

Open bmerry opened this issue 7 years ago • 9 comments

I'm not sure if this is a breathe problem or a doxygen one.

When the Doxyfile sets INLINE_INHERITED_MEMBERS to YES, each time a base class member is documented within a subclass it has the same link target. This leads to warnings from Sphinx e.g.

Warning: Duplicate target detected: classBase_1a641e04b3c65c74e058e21a37ae805f98

/home/bmerry/work/sdp/bugs/breathe-dup-ids/doc/index.rst:7: WARNING: Duplicate ID: "classBase_1a641e04b3c65c74e058e21a37ae805f98".
/home/bmerry/work/sdp/bugs/breathe-dup-ids/doc/index.rst:7: WARNING: Duplicate explicit target name: "classBase_1a641e04b3c65c74e058e21a37ae805f98".

Example code:

/**
 * @file
 */

/// Base class
class Base
{
public:
    /// Base-class member function
    void foo();
};

/// Class A
class A : public Base {};
/// Class B
class B : public Base {};

I'm using doxygen 1.8.11, breathe 4.7.3, Sphinx 1.6.4, Python 2.7.12. The Doxyfile is a default-generated one, just with INLINE_INHERITED_MEMBERS changed to YES.

bmerry avatar Oct 18 '17 07:10 bmerry

According to http://www.stack.nl/~dimitri/doxygen/manual/config.html#cfg_inline_inherited_memb

INLINE_INHERITED_MEMB

If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited members of a class in the documentation of that class as if those members were ordinary class members. Constructors, destructors and assignment operators of the base classes will not be shown.

The default value is: NO.

Because of this, Breathe most likely will document each class member twice because Doxygen will list it twice in the XML.

Is there a valid use case for having this set to YES when using Breathe? Or was it an observation?

vermeeren avatar May 21 '18 20:05 vermeeren

I'm expecting the documentation to be duplicated, I just want the link targets to be unique, and I'm not sure if those are being generated by Breathe or by Doxygen.

In my case I have a base class that is an implementation detail rather than part of the public API, so I don't want to document the base class at all. Instead I want to provide separate self-contained documentation for each of the derived classes, which means duplicating the documentation of the methods inherited from the base.

bmerry avatar May 22 '18 08:05 bmerry

Could you try to add the :no-link: attribute to the directive used (only for one, that triggers the warning)?

As in:

.. doxygensomething:: foobar
    :no-link:

http://breathe.readthedocs.io/en/latest/directives.html

To see if that licenses the warning? If that does then we'll know where the actual issue lies and can further discuss how to resolve it.

vermeeren avatar May 22 '18 14:05 vermeeren

It fixes some but not all of the warnings. I've upgraded to breathe 4.7.3, sphinx 1.7.4, docutils 0.14, and with this index.rst

Welcome to demo's documentation!
================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

.. doxygenclass:: A
   :members:

.. doxygenclass:: B
   :members:

I get

Warning: Duplicate target detected: classBase_1a641e04b3c65c74e058e21a37ae805f98

/home/bmerry/work/sdp/bugs/breathe-dup-ids/doc/index.rst:11: WARNING: Duplicate declaration.
/home/bmerry/work/sdp/bugs/breathe-dup-ids/doc/index.rst:2: WARNING: Duplicate ID: "classBase_1a641e04b3c65c74e058e21a37ae805f98".
/home/bmerry/work/sdp/bugs/breathe-dup-ids/doc/index.rst:2: WARNING: Duplicate explicit target name: "classBase_1a641e04b3c65c74e058e21a37ae805f98".

After adding :no-link: to both doxygenclass blocks, I get only

/home/bmerry/work/sdp/bugs/breathe-dup-ids/doc/index.rst:12: WARNING: Duplicate declaration.

bmerry avatar May 24 '18 07:05 bmerry

Here's a zipfile with my minimal example: breathe-dup-ids.zip

bmerry avatar May 24 '18 07:05 bmerry

It looks like Breathe is qualifying the inherited members using the base class instead of the derived class. For the example of @bmerry Sphinx gets the following declarations: For .. doxygenclass:: A

  • class A
  • function void Base::foo()

For .. doxygenclass:: B

  • class B
  • function void Base::foo()

The qualifications are removed from the doctree later by Breathe. The easiest fix is probably to construct the signature with the right qualification. The best fix is probably that Breathe emulates the nesting of declarations and never qualifies declarations.

jakobandersen avatar May 26 '18 09:05 jakobandersen

Should be fixed with #512, released in Breathe v4.17.0. Note that you also need Sphinx 3.x for recent Breathe versions.

vermeeren avatar May 01 '20 19:05 vermeeren

I'd like to re-open this (but for some reason Github isn't showing me the re-open button). If I leave out :no-link: then the resulting document works just as I hoped: A::foo and B::foo have separate HTML anchors and :cpp:func links to them work properly; but I still get duplicate target warnings:

Warning: Duplicate target detected: classBase_1a641e04b3c65c74e058e21a37ae805f98

/home/bmerry/tmp/breathe-dup-ids/doc/index.rst:2: WARNING: Duplicate ID: "classBase_1a641e04b3c65c74e058e21a37ae805f98".
/home/bmerry/tmp/breathe-dup-ids/doc/index.rst:2: WARNING: Duplicate explicit target name: "classBase_1a641e04b3c65c74e058e21a37ae805f98".

I don't want to use :no-link: because that also removes links for member functions defined in the derived classes. I'm attaching a new minimal example that shows the warnings above. breathe-dup-ids2.zip

bmerry avatar May 04 '20 08:05 bmerry

These IDs are entirely on the Breathe side, and I have yet to understand where there are actually used for anything. They may appear in Doxgen-generated HTML, but I'm not sure of the use-cases. So I believe that except for the visual annoyance of getting warning output it is rather harmless. The :no-link:, as you hint at, messes also with the underlying Sphinx stuff.

jakobandersen avatar May 04 '20 08:05 jakobandersen