Error handling subclass with the same name as generic base class (Origin: bugzilla #677294)
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:
- GenericBug.cs (ID 215454)
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.
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...
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
With and without the HAVE_DOT option, 1.9.1 produced results for me, but they're very wrong:

That is strange.
- on which platform are you running?
- with the
HAVE_DOT=NOI get as last lines on the consoleGenerating class documentation... Generating docs for compound MyClass... - with the
HAVE_DOT=YESI get as last lines on the consolelookup 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.
Hi!
- Windows 10, using Doxywizard.
- My logs continue normally after
Generating docs for compound MyClass...even withHAVE_DOT=NO, all the way up tofinished.... - 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 thatMyClass<T>is considered to be both inheriting from and inherited by itself. I would probably see the same withHAVE_DOT=YES, if I had Dot installed :)
Remains strange that you don't get the crash. Maybe @doxygen has an idea.
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
- What are you exactly missing?
- Did you set
EXTRACT_STATIC=YESin 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.
-
What I'm missing:
TheArrayExtensionandArrayExtension<T>are two independent types in C#—Like aClassAand aClassBwould be—and should create a separate page for the typeĄrrayExtensionwith the methodQToArray<T>and a page forArrayExtension<T>with the fieldEmpty, regardless of the fact that they share the same name. Since in C# one cannot refer to theArrayExtension<T>type without the generic type parameters, whether it would be the nameTas in the declaration, or a valid type name, likeint,stringorSystem.Guid.
So one cannot read the fieldEmptylikeArrayExtension.Empty, they must typeArrayExtension<int>.Empty, and vica-versa,QToArraymust be called asArrayExtension.QToArray<int>(new int[5]), and cannot be called asArrayExtension<object>.QToArray<int>(new int[5])for example.
The current output suggest that everything is under eitherArrayExtensionorArrayExtension<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.