doxygen icon indicating copy to clipboard operation
doxygen copied to clipboard

Error handling subclass with the same name as generic base class (Origin: bugzilla #677294)

Open doxygen opened this issue 7 years ago • 9 comments

status NEW severity normal in component general for --- Reported in version 1.8.1 on platform Other Assigned to: Dimitri van Heesch

Original attachment names and IDs:

On 2012-06-01 17:11:04 +0000, Drew wrote:

Created attachment 215454
Illustrate cases where generic inheritance is handled correctly or
incorrectly

In C#, if you have a Generic base class, and child classes that specify the
Generic Type parameter, inheritance is not handled correctly by Doxygen.

A non-Generic child with the same name of a Generic parent produces a
warning about "potential recursive class relation".  It appears that Doxygen
makes an implicit assumption about the relationship between a Generic and
non-Generic class  with the same name.  Having a non-generic child with the
same name as a generic parent also appears to confuse the hierarchy of other
children of the same generic parent.

doxygen avatar Jul 02 '18 07:07 doxygen

I think I have a related issue, though it's reversed:

public class MyClass
{
    public void BaseMethod() { }
}

public class MyClass<T> : MyClass
{
    public T SubMethod() { }
}

A generic class that inherits from a non-generic base class and has the same name as said base class will be recognized as the same type. Both methods from the example end up on the same page, and it's unclear what method belongs to which class (i.e. whether BaseMethod can be called through a MyClass reference or requires a MyClass<T> reference).

Found in 1.9.1.

Edit: Aaand I just stumbled upon #7768...

FlaShG avatar Apr 20 '21 19:04 FlaShG

I tried to run the example from @FlaShG with a simple Doxyfile:

EXTRACT_ALL=YES

though with the versions 1.9.0 and 1.9.1 this crashed. with the version 1.8.20 it ran.

Also setting HAVE_DOT=YES made all above mentioned versions running again.

A bisect gave:

963caeef1c24d66a51376f77d8692f1a3c5d4a62 is the first bad commit
commit 963caeef1c24d66a51376f77d8692f1a3c5d4a62
Author: Dimitri van Heesch <[email protected]>
Date:   Sat Dec 19 20:15:16 2020 +0100

    Refactoring: replace ClassSDict by ClassLinkedMap/ClassLinkedRefMap

The crash occurs in th file diagram.cpp routine DiagramRow::insertClass in the part:

    for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses())
    {
      ClassDef *ccd=bcd.classDef;
      if (ccd && ccd->isVisibleInHierarchy())
      {
        row->insertClass(di_ptr,ccd,doBases,bcd.prot,
            doBases?bcd.virt:Normal,
            doBases?bcd.templSpecifiers.data():"");
      }
    }

and more precise in the row->insertClass call

albert-github avatar Apr 21 '21 13:04 albert-github

With and without the HAVE_DOT option, 1.9.1 produced results for me, but they're very wrong: MyClass<T>

FlaShG avatar Apr 21 '21 18:04 FlaShG

That is strange.

  • on which platform are you running?
  • with the HAVE_DOT=NO I get as last lines on the console
    Generating class documentation...
    Generating docs for compound MyClass...
    
  • with the HAVE_DOT=YES I get as last lines on the console
    lookup cache used 1/65536 hits=5 misses=2
    finished...
    
  • between the 2 runs did you remove the html directory (otherwise, depending of the order of the executed settings, you night have been looking to the same results.

albert-github avatar Apr 22 '21 07:04 albert-github

Hi!

  • Windows 10, using Doxywizard.
  • My logs continue normally after Generating docs for compound MyClass... even with HAVE_DOT=NO, all the way up to finished....
  • I had indeed not deleted the output. But even when doing so, the results stay as in the screenshot. With HAVE_DOT=NO, I additionally see that MyClass<T> is considered to be both inheriting from and inherited by itself. I would probably see the same with HAVE_DOT=YES, if I had Dot installed :)

FlaShG avatar Apr 23 '21 19:04 FlaShG

Remains strange that you don't get the crash. Maybe @doxygen has an idea.

albert-github avatar Apr 24 '21 08:04 albert-github

This issue is more general according to my observation. Let's say, you have (under the same namespace):

public static class ArrayExtension
{
    public static T[] QToArray<T>(this T[] value)
    {
        // not relevant ...
    }
}

public static class ArrayExtension<T>
{
    public static readonly T[] Empty = new T[0];
}

This will produce a single page for "ArrayExtension< T >" with both members listed in it, as if both members were declared by this type, but nothing for "ArrayExtension", which is a separate type in C#. It feels as if Doxygen interprets the two type declaration as definitions of one type instead? Like it would be in C++ with a header file and a code file?

I have the same issue with 1.9.3, with the above two classes.

jadaml avatar Jul 05 '22 10:07 jadaml

@jadaml

  • What are you exactly missing?
  • Did you set EXTRACT_STATIC=YES in your doxygen configuration file?
  • Can you please attach a, small, self contained example (source+configuration file in a, compressed, tar or zip file) that allows us to reproduce the problem? Please don't add external links as they might not be persistent.

albert-github avatar Jul 05 '22 10:07 albert-github

  • What I'm missing:
    The ArrayExtension and ArrayExtension<T> are two independent types in C#—Like a ClassA and a ClassB would be—and should create a separate page for the type ĄrrayExtension with the method QToArray<T> and a page for ArrayExtension<T> with the field Empty, regardless of the fact that they share the same name. Since in C# one cannot refer to the ArrayExtension<T> type without the generic type parameters, whether it would be the name T as in the declaration, or a valid type name, like int, string or System.Guid.
    So one cannot read the field Empty like ArrayExtension.Empty, they must type ArrayExtension<int>.Empty, and vica-versa, QToArray must be called as ArrayExtension.QToArray<int>(new int[5]), and cannot be called as ArrayExtension<object>.QToArray<int>(new int[5]) for example.
    The current output suggest that everything is under either ArrayExtension or ArrayExtension<T> which is simply not correct.
  • Did I set: Yes, it is set, and the page does appear, although just a single one.
  • Can you attach: The code block in my previous comment for a Doxygen sample works perfectly as is, if copied to a *.cs file. It cannot compile though, since nothing is returned in the QToArray<T> method, but that should not inhibit Doxygen in generating a documentation, and no other error present in the above code. I've attached the Doxygen configuration file with this comment, removing anything that I felt would be sensitive (string values and absolute paths). Doxyfile.zip

One more thing to add: I've just noticed, the entry leading up to the page (in class list) is named "ArrayExtension," while the page title refers to it as "ArrayExtension< T >." This is problematic for the reason I highlighted in the first point.

jadaml avatar Jul 05 '22 12:07 jadaml