Skip to content

Commit

Permalink
Added type constraint relations for Java generics to dot graphs and X…
Browse files Browse the repository at this point in the history
…ML output
  • Loading branch information
Dimitri van Heesch committed Feb 21, 2015
1 parent 5bfda3d commit 080a465
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 40 deletions.
2 changes: 2 additions & 0 deletions src/arguments.cpp
Expand Up @@ -54,6 +54,7 @@ ArgumentList *ArgumentList::unmarshal(StorageIntf *s)
a->array = unmarshalQCString(s);
a->defval = unmarshalQCString(s);
a->docs = unmarshalQCString(s);
a->typeConstraint = unmarshalQCString(s);
result->append(a);
}
result->constSpecifier = unmarshalBool(s);
Expand Down Expand Up @@ -85,6 +86,7 @@ void ArgumentList::marshal(StorageIntf *s,ArgumentList *argList)
marshalQCString(s,a->array);
marshalQCString(s,a->defval);
marshalQCString(s,a->docs);
marshalQCString(s,a->typeConstraint);
}
}
marshalBool(s,argList->constSpecifier);
Expand Down
39 changes: 21 additions & 18 deletions src/arguments.h
Expand Up @@ -30,44 +30,47 @@ struct Argument
/*! Construct a new argument. */
Argument() {}
/*! Copy an argument (does a deep copy of all strings). */
Argument(const Argument &a)
{
attrib=a.attrib.copy();
type=a.type.copy();
name=a.name.copy();
defval=a.defval.copy();
docs=a.docs.copy();
array=a.array.copy();
Argument(const Argument &a)
{
attrib=a.attrib;
type=a.type;
name=a.name;
array=a.array;
defval=a.defval;
docs=a.docs;
typeConstraint=a.typeConstraint;
}
/*! Assignment of an argument (does a deep copy of all strings). */
Argument &operator=(const Argument &a)
{
if (this!=&a)
{
attrib=a.attrib.copy();
type=a.type.copy();
name=a.name.copy();
defval=a.defval.copy();
docs=a.docs.copy();
array=a.array.copy();
attrib=a.attrib;
type=a.type;
name=a.name;
array=a.array;
defval=a.defval;
docs=a.docs;
typeConstraint=a.typeConstraint;
}
return *this;
}
/*! return TRUE if this argument is documentation and the argument has a
* non empty name.
*/
bool hasDocumentation() const
{
return !name.isEmpty() && !docs.isEmpty();
bool hasDocumentation() const
{
return !name.isEmpty() && !docs.isEmpty();
}

QCString attrib; /*!< Argument's attribute (IDL only) */
QCString type; /*!< Argument's type */
QCString canType; /*!< Cached value of canonical type (after type resolution). Empty initially. */
QCString name; /*!< Argument's name (may be empty) */
QCString array; /*!< Argument's array specifier (may be empty) */
QCString defval; /*!< Argument's default value (may be empty) */
QCString docs; /*!< Argument's documentation (may be empty) */
QCString typeConstraint; /*!< Used for Java generics: <T extends C> */
};

/*! \brief This class represents an function or template argument list.
Expand Down
85 changes: 77 additions & 8 deletions src/classdef.cpp
Expand Up @@ -118,6 +118,8 @@ class ClassDefImpl
UsesClassDict *usedByImplClassDict;
UsesClassDict *usesIntfClassDict;

ConstraintClassDict *constraintClassDict;

/*! Template instances that exists of this class, the key in the
* dictionary is the template argument list.
*/
Expand Down Expand Up @@ -216,6 +218,7 @@ void ClassDefImpl::init(const char *defFileName, const char *name,
usesImplClassDict=0;
usedByImplClassDict=0;
usesIntfClassDict=0;
constraintClassDict=0;
memberGroupSDict = 0;
innerClasses = 0;
subGrouping=Config_getBool("SUBGROUPING");
Expand Down Expand Up @@ -267,6 +270,7 @@ ClassDefImpl::~ClassDefImpl()
delete usesImplClassDict;
delete usedByImplClassDict;
delete usesIntfClassDict;
delete constraintClassDict;
delete incInfo;
delete memberGroupSDict;
delete innerClasses;
Expand Down Expand Up @@ -2526,20 +2530,66 @@ bool ClassDef::hasExamples() const
return result;
}

void ClassDef::addTypeConstraint(const QCString &typeConstraint,const QCString &type)
{
static bool hideUndocRelation = Config_getBool("HIDE_UNDOC_RELATIONS");
if (typeConstraint.isEmpty() || type.isEmpty()) return;
ClassDef *cd = getClass(typeConstraint);
if (cd==0 && !hideUndocRelation)
{
cd = new ClassDef(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class);
cd->setUsedOnly(TRUE);
cd->setLanguage(getLanguage());
Doxygen::hiddenClasses->append(typeConstraint,cd);
//printf("Adding undocumented constraint '%s' to class %s on type %s\n",
// typeConstraint.data(),name().data(),type.data());
}
if (cd)
{
if (m_impl->constraintClassDict==0)
{
m_impl->constraintClassDict = new ConstraintClassDict(17);
m_impl->constraintClassDict->setAutoDelete(TRUE);
}
ConstraintClassDef *ccd=m_impl->constraintClassDict->find(typeConstraint);
if (ccd==0)
{
ccd = new ConstraintClassDef(cd);
m_impl->constraintClassDict->insert(typeConstraint,ccd);
}
ccd->addAccessor(type);
//printf("Adding constraint '%s' to class %s on type %s\n",
// typeConstraint.data(),name().data(),type.data());
}
}

void ClassDef::setTemplateArguments(ArgumentList *al)
// Java Type Constrains: A<T extends C & I>
void ClassDef::addTypeConstraints()
{
if (al==0) return;
if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
m_impl->tempArgs=new ArgumentList;
ArgumentListIterator ali(*al);
Argument *a;
for (;(a=ali.current());++ali)
if (m_impl->tempArgs)
{
m_impl->tempArgs->append(new Argument(*a));
ArgumentListIterator ali(*m_impl->tempArgs);
Argument *a;
for (;(a=ali.current());++ali)
{
if (!a->typeConstraint.isEmpty())
{
QCString typeConstraint;
int i=0,p=0;
while ((i=a->typeConstraint.find('&',p))!=-1) // typeConstraint="A &I" for C<T extends A & I>
{
typeConstraint = a->typeConstraint.mid(p,i-p).stripWhiteSpace();
addTypeConstraint(typeConstraint,a->type);
p=i+1;
}
typeConstraint = a->typeConstraint.right(a->typeConstraint.length()-p).stripWhiteSpace();
addTypeConstraint(typeConstraint,a->type);
}
}
}
}

// C# Type Constraints: D<T> where T : C, I
void ClassDef::setTypeConstraints(ArgumentList *al)
{
if (al==0) return;
Expand All @@ -2553,6 +2603,20 @@ void ClassDef::setTypeConstraints(ArgumentList *al)
}
}

void ClassDef::setTemplateArguments(ArgumentList *al)
{
if (al==0) return;
if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
//printf("setting template args '%s' for '%s'\n",tempArgListToString(al,getLanguage()).data(),name().data());
m_impl->tempArgs=new ArgumentList;
ArgumentListIterator ali(*al);
Argument *a;
for (;(a=ali.current());++ali)
{
m_impl->tempArgs->append(new Argument(*a));
}
}

/*! Returns \c TRUE iff this class or a class inheriting from this class
* is \e not defined in an external tag file.
*/
Expand Down Expand Up @@ -4405,6 +4469,11 @@ UsesClassDict *ClassDef::usedInterfaceClasses() const
return m_impl->usesIntfClassDict;
}

ConstraintClassDict *ClassDef::templateTypeConstraints() const
{
return m_impl->constraintClassDict;
}

bool ClassDef::isTemplateArgument() const
{
return m_impl->isTemplArg;
Expand Down
64 changes: 62 additions & 2 deletions src/classdef.h
Expand Up @@ -24,6 +24,7 @@

#include "definition.h"

struct Argument;
class MemberDef;
class MemberList;
class MemberDict;
Expand All @@ -38,6 +39,7 @@ class MemberDef;
class ExampleSDict;
class MemberNameInfoSDict;
class UsesClassDict;
class ConstraintClassDict;
class MemberGroupSDict;
class QTextStream;
class PackageDef;
Expand Down Expand Up @@ -229,6 +231,8 @@ class ClassDef : public Definition

UsesClassDict *usedInterfaceClasses() const;

ConstraintClassDict *templateTypeConstraints() const;

bool isTemplateArgument() const;

/** Returns the definition of a nested compound if
Expand Down Expand Up @@ -371,6 +375,7 @@ class ClassDef : public Definition
void findSectionsInDocumentation();
void addMembersToMemberGroup();
void addListReferences();
void addTypeConstraints();
void computeAnchors();
void mergeMembers();
void sortMemberLists();
Expand Down Expand Up @@ -441,12 +446,13 @@ class ClassDef : public Definition
void getTitleForMemberListType(MemberListType type,
QCString &title,QCString &subtitle);
QCString includeStatement() const;
void addTypeConstraint(const QCString &typeConstraint,const QCString &type);


ClassDefImpl *m_impl;

};

//------------------------------------------------------------------------

/** Class that contains information about a usage relation.
*/
struct UsesClassDef
Expand Down Expand Up @@ -500,6 +506,8 @@ class UsesClassDictIterator : public QDictIterator<UsesClassDef>
~UsesClassDictIterator() {}
};

//------------------------------------------------------------------------

/** Class that contains information about an inheritance relation.
*/
struct BaseClassDef
Expand Down Expand Up @@ -558,4 +566,56 @@ class BaseClassListIterator : public QListIterator<BaseClassDef>
QListIterator<BaseClassDef>(bcl) {}
};

//------------------------------------------------------------------------


/** Class that contains information about a type constraint relations.
*/
struct ConstraintClassDef
{
ConstraintClassDef(ClassDef *cd) : classDef(cd)
{
accessors = new QDict<void>(17);
}
~ConstraintClassDef()
{
delete accessors;
}
void addAccessor(const char *s)
{
if (accessors->find(s)==0)
{
accessors->insert(s,(void *)666);
}
}
/** Class definition that this relation uses. */
ClassDef *classDef;

/** Dictionary of member types names that form the edge labels of the
* constraint relation.
*/
QDict<void> *accessors;
};

/** Dictionary of constraint relations.
*/
class ConstraintClassDict : public QDict<ConstraintClassDef>
{
public:
ConstraintClassDict(int size) : QDict<ConstraintClassDef>(size) {}
~ConstraintClassDict() {}
};

/** Iterator class to iterate over a dictionary of constraint relations.
*/
class ConstraintClassDictIterator : public QDictIterator<ConstraintClassDef>
{
public:
ConstraintClassDictIterator(const QDict<ConstraintClassDef> &d)
: QDictIterator<ConstraintClassDef>(d) {}
~ConstraintClassDictIterator() {}
};

//------------------------------------------------------------------------

#endif

0 comments on commit 080a465

Please sign in to comment.