Skip to content

Commit 080a465

Browse files
author
Dimitri van Heesch
committed
Added type constraint relations for Java generics to dot graphs and XML output
1 parent 5bfda3d commit 080a465

File tree

11 files changed

+244
-40
lines changed

11 files changed

+244
-40
lines changed

src/arguments.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ ArgumentList *ArgumentList::unmarshal(StorageIntf *s)
5454
a->array = unmarshalQCString(s);
5555
a->defval = unmarshalQCString(s);
5656
a->docs = unmarshalQCString(s);
57+
a->typeConstraint = unmarshalQCString(s);
5758
result->append(a);
5859
}
5960
result->constSpecifier = unmarshalBool(s);
@@ -85,6 +86,7 @@ void ArgumentList::marshal(StorageIntf *s,ArgumentList *argList)
8586
marshalQCString(s,a->array);
8687
marshalQCString(s,a->defval);
8788
marshalQCString(s,a->docs);
89+
marshalQCString(s,a->typeConstraint);
8890
}
8991
}
9092
marshalBool(s,argList->constSpecifier);

src/arguments.h

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,44 +30,47 @@ struct Argument
3030
/*! Construct a new argument. */
3131
Argument() {}
3232
/*! Copy an argument (does a deep copy of all strings). */
33-
Argument(const Argument &a)
34-
{
35-
attrib=a.attrib.copy();
36-
type=a.type.copy();
37-
name=a.name.copy();
38-
defval=a.defval.copy();
39-
docs=a.docs.copy();
40-
array=a.array.copy();
33+
Argument(const Argument &a)
34+
{
35+
attrib=a.attrib;
36+
type=a.type;
37+
name=a.name;
38+
array=a.array;
39+
defval=a.defval;
40+
docs=a.docs;
41+
typeConstraint=a.typeConstraint;
4142
}
4243
/*! Assignment of an argument (does a deep copy of all strings). */
4344
Argument &operator=(const Argument &a)
4445
{
4546
if (this!=&a)
4647
{
47-
attrib=a.attrib.copy();
48-
type=a.type.copy();
49-
name=a.name.copy();
50-
defval=a.defval.copy();
51-
docs=a.docs.copy();
52-
array=a.array.copy();
48+
attrib=a.attrib;
49+
type=a.type;
50+
name=a.name;
51+
array=a.array;
52+
defval=a.defval;
53+
docs=a.docs;
54+
typeConstraint=a.typeConstraint;
5355
}
5456
return *this;
5557
}
5658
/*! return TRUE if this argument is documentation and the argument has a
5759
* non empty name.
5860
*/
59-
bool hasDocumentation() const
60-
{
61-
return !name.isEmpty() && !docs.isEmpty();
61+
bool hasDocumentation() const
62+
{
63+
return !name.isEmpty() && !docs.isEmpty();
6264
}
63-
65+
6466
QCString attrib; /*!< Argument's attribute (IDL only) */
6567
QCString type; /*!< Argument's type */
6668
QCString canType; /*!< Cached value of canonical type (after type resolution). Empty initially. */
6769
QCString name; /*!< Argument's name (may be empty) */
6870
QCString array; /*!< Argument's array specifier (may be empty) */
6971
QCString defval; /*!< Argument's default value (may be empty) */
7072
QCString docs; /*!< Argument's documentation (may be empty) */
73+
QCString typeConstraint; /*!< Used for Java generics: <T extends C> */
7174
};
7275

7376
/*! \brief This class represents an function or template argument list.

src/classdef.cpp

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ class ClassDefImpl
118118
UsesClassDict *usedByImplClassDict;
119119
UsesClassDict *usesIntfClassDict;
120120

121+
ConstraintClassDict *constraintClassDict;
122+
121123
/*! Template instances that exists of this class, the key in the
122124
* dictionary is the template argument list.
123125
*/
@@ -216,6 +218,7 @@ void ClassDefImpl::init(const char *defFileName, const char *name,
216218
usesImplClassDict=0;
217219
usedByImplClassDict=0;
218220
usesIntfClassDict=0;
221+
constraintClassDict=0;
219222
memberGroupSDict = 0;
220223
innerClasses = 0;
221224
subGrouping=Config_getBool("SUBGROUPING");
@@ -267,6 +270,7 @@ ClassDefImpl::~ClassDefImpl()
267270
delete usesImplClassDict;
268271
delete usedByImplClassDict;
269272
delete usesIntfClassDict;
273+
delete constraintClassDict;
270274
delete incInfo;
271275
delete memberGroupSDict;
272276
delete innerClasses;
@@ -2526,20 +2530,66 @@ bool ClassDef::hasExamples() const
25262530
return result;
25272531
}
25282532

2533+
void ClassDef::addTypeConstraint(const QCString &typeConstraint,const QCString &type)
2534+
{
2535+
static bool hideUndocRelation = Config_getBool("HIDE_UNDOC_RELATIONS");
2536+
if (typeConstraint.isEmpty() || type.isEmpty()) return;
2537+
ClassDef *cd = getClass(typeConstraint);
2538+
if (cd==0 && !hideUndocRelation)
2539+
{
2540+
cd = new ClassDef(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class);
2541+
cd->setUsedOnly(TRUE);
2542+
cd->setLanguage(getLanguage());
2543+
Doxygen::hiddenClasses->append(typeConstraint,cd);
2544+
//printf("Adding undocumented constraint '%s' to class %s on type %s\n",
2545+
// typeConstraint.data(),name().data(),type.data());
2546+
}
2547+
if (cd)
2548+
{
2549+
if (m_impl->constraintClassDict==0)
2550+
{
2551+
m_impl->constraintClassDict = new ConstraintClassDict(17);
2552+
m_impl->constraintClassDict->setAutoDelete(TRUE);
2553+
}
2554+
ConstraintClassDef *ccd=m_impl->constraintClassDict->find(typeConstraint);
2555+
if (ccd==0)
2556+
{
2557+
ccd = new ConstraintClassDef(cd);
2558+
m_impl->constraintClassDict->insert(typeConstraint,ccd);
2559+
}
2560+
ccd->addAccessor(type);
2561+
//printf("Adding constraint '%s' to class %s on type %s\n",
2562+
// typeConstraint.data(),name().data(),type.data());
2563+
}
2564+
}
25292565

2530-
void ClassDef::setTemplateArguments(ArgumentList *al)
2566+
// Java Type Constrains: A<T extends C & I>
2567+
void ClassDef::addTypeConstraints()
25312568
{
2532-
if (al==0) return;
2533-
if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
2534-
m_impl->tempArgs=new ArgumentList;
2535-
ArgumentListIterator ali(*al);
2536-
Argument *a;
2537-
for (;(a=ali.current());++ali)
2569+
if (m_impl->tempArgs)
25382570
{
2539-
m_impl->tempArgs->append(new Argument(*a));
2571+
ArgumentListIterator ali(*m_impl->tempArgs);
2572+
Argument *a;
2573+
for (;(a=ali.current());++ali)
2574+
{
2575+
if (!a->typeConstraint.isEmpty())
2576+
{
2577+
QCString typeConstraint;
2578+
int i=0,p=0;
2579+
while ((i=a->typeConstraint.find('&',p))!=-1) // typeConstraint="A &I" for C<T extends A & I>
2580+
{
2581+
typeConstraint = a->typeConstraint.mid(p,i-p).stripWhiteSpace();
2582+
addTypeConstraint(typeConstraint,a->type);
2583+
p=i+1;
2584+
}
2585+
typeConstraint = a->typeConstraint.right(a->typeConstraint.length()-p).stripWhiteSpace();
2586+
addTypeConstraint(typeConstraint,a->type);
2587+
}
2588+
}
25402589
}
25412590
}
25422591

2592+
// C# Type Constraints: D<T> where T : C, I
25432593
void ClassDef::setTypeConstraints(ArgumentList *al)
25442594
{
25452595
if (al==0) return;
@@ -2553,6 +2603,20 @@ void ClassDef::setTypeConstraints(ArgumentList *al)
25532603
}
25542604
}
25552605

2606+
void ClassDef::setTemplateArguments(ArgumentList *al)
2607+
{
2608+
if (al==0) return;
2609+
if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
2610+
//printf("setting template args '%s' for '%s'\n",tempArgListToString(al,getLanguage()).data(),name().data());
2611+
m_impl->tempArgs=new ArgumentList;
2612+
ArgumentListIterator ali(*al);
2613+
Argument *a;
2614+
for (;(a=ali.current());++ali)
2615+
{
2616+
m_impl->tempArgs->append(new Argument(*a));
2617+
}
2618+
}
2619+
25562620
/*! Returns \c TRUE iff this class or a class inheriting from this class
25572621
* is \e not defined in an external tag file.
25582622
*/
@@ -4405,6 +4469,11 @@ UsesClassDict *ClassDef::usedInterfaceClasses() const
44054469
return m_impl->usesIntfClassDict;
44064470
}
44074471

4472+
ConstraintClassDict *ClassDef::templateTypeConstraints() const
4473+
{
4474+
return m_impl->constraintClassDict;
4475+
}
4476+
44084477
bool ClassDef::isTemplateArgument() const
44094478
{
44104479
return m_impl->isTemplArg;

src/classdef.h

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "definition.h"
2626

27+
struct Argument;
2728
class MemberDef;
2829
class MemberList;
2930
class MemberDict;
@@ -38,6 +39,7 @@ class MemberDef;
3839
class ExampleSDict;
3940
class MemberNameInfoSDict;
4041
class UsesClassDict;
42+
class ConstraintClassDict;
4143
class MemberGroupSDict;
4244
class QTextStream;
4345
class PackageDef;
@@ -229,6 +231,8 @@ class ClassDef : public Definition
229231

230232
UsesClassDict *usedInterfaceClasses() const;
231233

234+
ConstraintClassDict *templateTypeConstraints() const;
235+
232236
bool isTemplateArgument() const;
233237

234238
/** Returns the definition of a nested compound if
@@ -371,6 +375,7 @@ class ClassDef : public Definition
371375
void findSectionsInDocumentation();
372376
void addMembersToMemberGroup();
373377
void addListReferences();
378+
void addTypeConstraints();
374379
void computeAnchors();
375380
void mergeMembers();
376381
void sortMemberLists();
@@ -441,12 +446,13 @@ class ClassDef : public Definition
441446
void getTitleForMemberListType(MemberListType type,
442447
QCString &title,QCString &subtitle);
443448
QCString includeStatement() const;
449+
void addTypeConstraint(const QCString &typeConstraint,const QCString &type);
444450

445-
446451
ClassDefImpl *m_impl;
447-
448452
};
449453

454+
//------------------------------------------------------------------------
455+
450456
/** Class that contains information about a usage relation.
451457
*/
452458
struct UsesClassDef
@@ -500,6 +506,8 @@ class UsesClassDictIterator : public QDictIterator<UsesClassDef>
500506
~UsesClassDictIterator() {}
501507
};
502508

509+
//------------------------------------------------------------------------
510+
503511
/** Class that contains information about an inheritance relation.
504512
*/
505513
struct BaseClassDef
@@ -558,4 +566,56 @@ class BaseClassListIterator : public QListIterator<BaseClassDef>
558566
QListIterator<BaseClassDef>(bcl) {}
559567
};
560568

569+
//------------------------------------------------------------------------
570+
571+
572+
/** Class that contains information about a type constraint relations.
573+
*/
574+
struct ConstraintClassDef
575+
{
576+
ConstraintClassDef(ClassDef *cd) : classDef(cd)
577+
{
578+
accessors = new QDict<void>(17);
579+
}
580+
~ConstraintClassDef()
581+
{
582+
delete accessors;
583+
}
584+
void addAccessor(const char *s)
585+
{
586+
if (accessors->find(s)==0)
587+
{
588+
accessors->insert(s,(void *)666);
589+
}
590+
}
591+
/** Class definition that this relation uses. */
592+
ClassDef *classDef;
593+
594+
/** Dictionary of member types names that form the edge labels of the
595+
* constraint relation.
596+
*/
597+
QDict<void> *accessors;
598+
};
599+
600+
/** Dictionary of constraint relations.
601+
*/
602+
class ConstraintClassDict : public QDict<ConstraintClassDef>
603+
{
604+
public:
605+
ConstraintClassDict(int size) : QDict<ConstraintClassDef>(size) {}
606+
~ConstraintClassDict() {}
607+
};
608+
609+
/** Iterator class to iterate over a dictionary of constraint relations.
610+
*/
611+
class ConstraintClassDictIterator : public QDictIterator<ConstraintClassDef>
612+
{
613+
public:
614+
ConstraintClassDictIterator(const QDict<ConstraintClassDef> &d)
615+
: QDictIterator<ConstraintClassDef>(d) {}
616+
~ConstraintClassDictIterator() {}
617+
};
618+
619+
//------------------------------------------------------------------------
620+
561621
#endif

0 commit comments

Comments
 (0)