Orb/Doxygen/src/memberlist.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Orb/Doxygen/src/memberlist.cpp	Thu Jan 21 17:29:01 2010 +0000
@@ -0,0 +1,624 @@
+/******************************************************************************
+ *
+ * 
+ *
+ * Copyright (C) 1997-2008 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby 
+ * granted. No representations are made about the suitability of this software 
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include <qregexp.h>
+
+#include "memberlist.h"
+#include "classdef.h"
+#include "message.h"
+#include "util.h"
+#include "language.h"
+#include "doxygen.h"
+#include "outputlist.h"
+#include "groupdef.h"
+#include "marshal.h"
+#include "vhdldocgen.h"
+
+MemberList::MemberList()
+{
+}
+
+MemberList::MemberList(ListType lt) : m_listType(lt)
+{
+  memberGroupList=0;
+  m_numDecMembers=-1; // special value indicating that value needs to be computed
+  m_numDocMembers=-1; // special value indicating that value needs to be computed
+  m_inGroup=FALSE;
+  m_inFile=FALSE;
+}
+
+MemberList::~MemberList()
+{
+  delete memberGroupList;
+}
+
+int MemberList::compareItems(GCI item1, GCI item2)
+{
+  static bool sortConstructorsFirst = Config_getBool("SORT_MEMBERS_CTORS_1ST");
+  MemberDef *c1=(MemberDef *)item1;
+  MemberDef *c2=(MemberDef *)item2;
+  if (sortConstructorsFirst) {
+    int ord1 = c1->isConstructor() ? 2 : (c1->isDestructor() ? 1 : 0);
+    int ord2 = c2->isConstructor() ? 2 : (c2->isDestructor() ? 1 : 0);
+    if (ord1 > ord2)
+      return -1;
+    else if (ord2 > ord1)
+      return 1;
+  }
+  return stricmp(c1->name(),c2->name());
+}
+
+/*! Count the number of members in this list that are visible in
+ *  the declaration part of a compound's documentation page.
+ */
+void MemberList::countDecMembers(bool countEnumValues)
+{
+  if (m_numDecMembers!=-1) return; 
+  
+  //printf("----- countDecMembers count=%d ----\n",count());
+  m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0;
+  m_typeCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
+  m_numDecMembers=0;
+  QListIterator<MemberDef> mli(*this);
+  MemberDef *md;
+  for (mli.toFirst();(md=mli.current());++mli)
+  {
+    //printf("MemberList::countDecMembers(md=%s,%d)\n",md->name().data(),md->isBriefSectionVisible());
+    if (md->isBriefSectionVisible())
+    {
+      switch(md->memberType())
+      {
+        case MemberDef::Variable:    // fall through
+        case MemberDef::Event:       // fall through
+        case MemberDef::Property:    m_varCnt++,m_numDecMembers++;  
+                                     break;
+        case MemberDef::Function:    // fall through
+        case MemberDef::Signal:      // fall through
+        case MemberDef::DCOP:        // fall through
+        case MemberDef::Slot:        if (!md->isRelated() || md->getClassDef())
+                                       m_funcCnt++,m_numDecMembers++; 
+                                     break;
+        case MemberDef::Enumeration: m_enumCnt++,m_numDecMembers++; break;
+        case MemberDef::EnumValue:   if (countEnumValues)
+                                       m_enumValCnt++,m_numDecMembers++; 
+                                     break;
+        case MemberDef::Typedef:     m_typeCnt++,m_numDecMembers++; break;
+        //case MemberDef::Prototype:   m_protoCnt++,m_numDecMembers++; break;
+        case MemberDef::Define:      if (Config_getBool("EXTRACT_ALL") || 
+                                         md->argsString() || 
+                                         !md->initializer().isEmpty() ||
+                                         md->hasDocumentation() 
+                                        ) m_defCnt++,m_numDecMembers++;     
+                                     break;
+        case MemberDef::Friend:      m_friendCnt++,m_numDecMembers++;  
+                                     break;
+        default:
+          err("Error: Unknown member type found for member `%s'\n!",md->name().data());
+      }
+    }
+  }
+  if (memberGroupList)
+  {
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    for (;(mg=mgli.current());++mgli)
+    {
+      mg->countDecMembers();
+      m_varCnt+=mg->varCount();
+      m_funcCnt+=mg->funcCount();
+      m_enumCnt+=mg->enumCount();
+      m_enumValCnt+=mg->enumValueCount();
+      m_typeCnt+=mg->typedefCount();
+      m_protoCnt+=mg->protoCount();
+      m_defCnt+=mg->defineCount();
+      m_friendCnt+=mg->friendCount();
+      m_numDecMembers+=mg->numDecMembers();
+    }
+  }
+  //printf("----- end countDecMembers ----\n");
+
+  //printf("MemberList::countDecMembers()=%d\n",m_numDecMembers);
+}
+
+void MemberList::countDocMembers(bool countEnumValues)
+{
+  if (m_numDocMembers!=-1) return; // used cached value
+  m_numDocMembers=0;
+  QListIterator<MemberDef> mli(*this);
+  MemberDef *md;
+  for (mli.toFirst();(md=mli.current());++mli)
+  {
+    if (md->isDetailedSectionVisible(m_inGroup,m_inFile)) 
+    {
+      // do not count enum values, since they do not produce entries of their own
+      if (countEnumValues || md->memberType()!=MemberDef::EnumValue) 
+        m_numDocMembers++;
+    }
+  }
+  if (memberGroupList)
+  {
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    for (;(mg=mgli.current());++mgli)
+    {
+      mg->countDocMembers();
+      m_numDocMembers+=mg->numDocMembers();
+    }
+  }
+  //printf("MemberList::countDocMembers()=%d memberGroupList=%p\n",m_numDocMembers,memberGroupList);
+}
+
+bool MemberList::insert(uint index,const MemberDef *md)
+{
+  return QList<MemberDef>::insert(index,md);
+}
+
+void MemberList::inSort(const MemberDef *md)
+{
+  QList<MemberDef>::inSort(md);
+}
+
+void MemberList::append(const MemberDef *md)
+{
+  QList<MemberDef>::append(md);
+}
+
+MemberListIterator::MemberListIterator(const QList<MemberDef> &l) :
+  QListIterator<MemberDef>(l) 
+{
+}
+
+void MemberList::writePlainDeclarations(OutputList &ol,
+                       ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd
+                      )
+{
+  //printf("----- writePlainDeclaration() ----\n");
+  countDecMembers();
+  if (numDecMembers()==0) 
+  {
+    //printf("  --> no members!\n");
+    return; // no members in this list
+  }
+  //printf("  --> writePlainDeclaration() numDecMembers()=%d\n",
+  //     numDecMembers());
+  
+  ol.pushGeneratorState();
+
+  bool first=TRUE;
+  MemberDef *md;
+  MemberListIterator mli(*this);
+  for ( ; (md=mli.current()); ++mli )
+  {
+    //printf(">>> Member `%s' type=%d visible=%d\n",
+    //    md->name().data(),md->memberType(),md->isBriefSectionVisible());
+    if (md->isBriefSectionVisible())
+    {
+      switch(md->memberType())
+      {
+        case MemberDef::Define:    // fall through
+        //case MemberDef::Prototype: // fall through
+        case MemberDef::Typedef:   // fall through
+        case MemberDef::Variable:  // fall through
+        case MemberDef::Function:  // fall through
+        case MemberDef::Signal:    // fall through
+        case MemberDef::Slot:      // fall through
+        case MemberDef::DCOP:      // fall through
+        case MemberDef::Property:  // fall through
+        case MemberDef::Event:  
+          {
+            if (first) ol.startMemberList(),first=FALSE;
+            md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup);
+            break;
+          }
+        case MemberDef::Enumeration: 
+          {
+            int enumVars=0;
+            MemberListIterator vmli(*this);
+            MemberDef *vmd;
+            QCString name(md->name());
+            int i=name.findRev("::");
+            if (i!=-1) name=name.right(name.length()-i-2); // strip scope (TODO: is this needed?)
+            if (name[0]=='@') // anonymous enum => append variables
+            {
+              for ( ; (vmd=vmli.current()) ; ++vmli)
+              {
+                QCString vtype=vmd->typeString();
+                if ((vtype.find(name))!=-1) 
+                {
+                  enumVars++;
+                  vmd->setAnonymousEnumType(md);
+                }
+              }
+            }
+            // if this is an anoymous enum and there are variables of this
+            // enum type (i.e. enumVars>0), then we do not show the enum here.
+            if (enumVars==0) // show enum here
+            {
+              //printf("Enum!!\n");
+              if (first) ol.startMemberList(),first=FALSE;
+              ol.startMemberItem(0);
+              ol.writeString("enum ");
+              ol.insertMemberAlign();
+              md->writeEnumDeclaration(ol,cd,nd,fd,gd);
+              ol.endMemberItem();
+              if (!md->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
+              {
+                ol.startMemberDescription();
+                ol.parseDoc(
+                    md->briefFile(),md->briefLine(),
+                    cd,md,
+                    md->briefDescription(),
+                    TRUE,
+                    FALSE
+                    );
+                if (md->isDetailedSectionLinkable())
+                {
+                  ol.disableAllBut(OutputGenerator::Html);
+                  ol.docify(" ");
+                  ol.startTextLink(md->getOutputFileBase(),
+                                   md->anchor());
+                  ol.parseText(theTranslator->trMore());
+                  ol.endTextLink();
+                  ol.enableAll();
+                }
+                ol.endMemberDescription();
+              }
+            }
+            md->warnIfUndocumented();
+            break;
+          }
+        case MemberDef::Friend:
+          {
+            if (first) ol.startMemberList(),first=FALSE;
+            md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup);
+            break;
+          }
+        case MemberDef::EnumValue: 
+          {
+            if (m_inGroup)
+            {
+              //printf("EnumValue!\n");
+              if (first) ol.startMemberList(),first=FALSE;
+              md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup);
+            }
+          }
+          break;
+      }
+    }
+  }
+
+  // handle members that are inside anonymous compounds and for which
+  // no variables of the anonymous compound type exist.
+  if (cd)
+  {
+    MemberListIterator mli(*this);
+    for  ( ; (md=mli.current()) ; ++mli )
+    {
+      if (md->fromAnonymousScope() && !md->anonymousDeclShown())
+      {
+        md->setFromAnonymousScope(FALSE);
+        //printf("anonymous compound members\n");
+        if (md->isBriefSectionVisible())
+        {
+          if (first) ol.startMemberList(),first=FALSE;
+          md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup);
+        }
+        md->setFromAnonymousScope(TRUE);
+      }
+    }
+  }
+ 
+  if (!first) ol.endMemberList(); 
+
+  ol.popGeneratorState();
+  //printf("----- end writePlainDeclaration() ----\n");
+}
+
+void MemberList::writeDeclarations(OutputList &ol,
+             ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+             const char *title,const char *subtitle, bool showEnumValues
+             /*, bool inGroup,bool countSubGroups*/)
+{
+  //printf("----- writeDeclaration() this=%p ----\n",this);
+  static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
+
+  countDecMembers(showEnumValues); // count member not in group
+  Definition *ctx = cd;
+  if (ctx==0 && nd) ctx = nd;
+  if (ctx==0 && gd) ctx = gd;
+  if (ctx==0 && fd) ctx = fd;
+
+  if (numDecMembers()==0) return;
+  //printf("%p: MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d\n",
+  //    this,title,subtitle,numDecMembers());
+  if (title) 
+  {
+    ol.startMemberHeader();
+    ol.parseText(title);
+    ol.endMemberHeader();
+  }
+  if (subtitle) 
+  {
+    QCString st=subtitle;
+    st = st.stripWhiteSpace();
+    if (!st.isEmpty())
+    {
+      ol.startMemberSubtitle();
+      ol.parseDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE);
+      ol.endMemberSubtitle();
+    }
+  }
+
+  // TODO: Two things need to be worked out for proper VHDL output:
+  // 1. Signals and types under the group need to be
+  //    formatted to associate them with the group somehow
+  //    indentation, or at the very least, extra space after
+  //    the group is done
+  // 2. This might need to be repeated below for memberGroupLists
+  if (optimizeVhdl) // use specific declarations function
+  {
+    VhdlDocGen::writeVhdlDeclarations(this,ol,0,cd,0);
+  }
+  else
+  {
+    writePlainDeclarations(ol,cd,nd,fd,gd);
+  }
+ 
+  //printf("memberGroupList=%p\n",memberGroupList);
+  if (memberGroupList)
+  {
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    while ((mg=mgli.current()))
+    {
+      //printf("mg->header=%s\n",mg->header().data());
+      bool hasHeader=mg->header()!="[NOHEADER]";
+      ol.startMemberGroupHeader(hasHeader);
+      if (hasHeader)
+      {
+        ol.parseText(mg->header());
+      }
+      ol.endMemberGroupHeader();
+      if (!mg->documentation().isEmpty())
+      {
+        //printf("Member group has docs!\n");
+        ol.startMemberGroupDocs();
+        ol.parseDoc("[generated]",-1,ctx,0,mg->documentation()+"\n",FALSE,FALSE);
+        ol.endMemberGroupDocs();
+      }
+      ol.startMemberGroup();
+      //printf("--- mg->writePlainDeclarations ---\n");
+      mg->writePlainDeclarations(ol,cd,nd,fd,gd);
+      ol.endMemberGroup(hasHeader);
+      ++mgli;
+    }
+  }
+  //printf("----- end writeDeclaration() ----\n");
+
+}
+
+void MemberList::writeDocumentation(OutputList &ol,
+                     const char *scopeName, Definition *container,
+                     const char *title,bool showEnumValues)
+{
+  //printf("MemberList::writeDocumentation()\n");
+
+  countDocMembers(showEnumValues);
+  if (numDocMembers()==0) return;
+
+  if (title)
+  {
+    ol.writeRuler();
+    ol.startGroupHeader();
+    ol.parseText(title);
+    ol.endGroupHeader();
+  }
+  ol.startMemberDocList();
+  
+  MemberListIterator mli(*this);
+  MemberDef *md;
+  for ( ; (md=mli.current()) ; ++mli)
+  {
+    md->writeDocumentation(this,ol,scopeName,container,m_inGroup,showEnumValues);
+  }
+  if (memberGroupList)
+  {
+    //printf("MemberList::writeDocumentation()  --  member groups\n");
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    for (;(mg=mgli.current());++mgli)
+    {
+      mg->writeDocumentation(ol,scopeName,container);
+    }
+  }
+  ol.endMemberDocList();
+}
+
+void MemberList::writeDocumentationPage(OutputList &ol,
+                     const char *scopeName, Definition *container)
+{
+  MemberListIterator mli(*this);
+  MemberDef *md;
+  for ( ; (md=mli.current()) ; ++mli)
+  {
+    QCString diskName=md->getOutputFileBase();
+    QCString title=md->qualifiedName();
+    startFile(ol,diskName,md->name(),title);
+    container->writeNavigationPath(ol);
+
+    ol.writeString("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n"
+                   "  <tr>\n"
+                   "   <td valign=\"top\">\n");
+
+    container->writeQuickMemberLinks(ol,md);
+
+    ol.writeString("   </td>\n");
+    ol.writeString("   <td valign=\"top\">\n");
+    
+    md->writeDocumentation(this,ol,scopeName,container,m_inGroup);
+
+    ol.writeString("    </td>\n");
+    ol.writeString("  </tr>\n");
+    ol.writeString("</table>\n");
+    
+    endFile(ol);
+  }
+  if (memberGroupList)
+  {
+    //printf("MemberList::writeDocumentation()  --  member groups\n");
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    for (;(mg=mgli.current());++mgli)
+    {
+      mg->writeDocumentationPage(ol,scopeName,container);
+    }
+  }
+}
+
+void MemberList::addMemberGroup(MemberGroup *mg)
+{
+  if (memberGroupList==0)
+  {
+    memberGroupList=new MemberGroupList;
+  }
+  //printf("addMemberGroup: this=%p mg=%p\n",this,mg);
+  memberGroupList->append(mg);
+}
+
+void MemberList::addListReferences(Definition *def)
+{
+  MemberListIterator mli(*this);
+  MemberDef *md;
+  for ( ; (md=mli.current()) ; ++mli)
+  {
+    if (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)
+    {
+      md->addListReference(def);
+      LockingPtr<MemberList> enumFields = md->enumFieldList();
+      if (md->memberType()==MemberDef::Enumeration && enumFields!=0)
+      {
+        MemberListIterator vmli(*enumFields);
+        MemberDef *vmd;
+        for ( ; (vmd=vmli.current()) ; ++vmli)
+        {
+          vmd->addListReference(def);
+        }
+      }
+    }
+  }
+  if (memberGroupList)
+  {
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    for (;(mg=mgli.current());++mgli)
+    {
+      mg->addListReferences(def);
+    }
+  }
+}
+
+void MemberList::findSectionsInDocumentation()
+{
+  MemberListIterator mli(*this);
+  MemberDef *md;
+  for ( ; (md=mli.current()) ; ++mli)
+  {
+    md->findSectionsInDocumentation();
+  }
+  if (memberGroupList)
+  {
+    MemberGroupListIterator mgli(*memberGroupList);
+    MemberGroup *mg;
+    for (;(mg=mgli.current());++mgli)
+    {
+      mg->findSectionsInDocumentation();
+    }
+  }
+}
+
+void MemberList::marshal(StorageIntf *s)
+{
+  marshalInt(s,(int)m_listType);
+  marshalInt(s,m_varCnt);
+  marshalInt(s,m_funcCnt);
+  marshalInt(s,m_enumCnt);
+  marshalInt(s,m_enumValCnt);
+  marshalInt(s,m_typeCnt);
+  marshalInt(s,m_protoCnt);
+  marshalInt(s,m_defCnt);
+  marshalInt(s,m_friendCnt); 
+  marshalInt(s,m_numDecMembers);
+  marshalInt(s,m_numDocMembers);
+  marshalBool(s,m_inGroup);
+  marshalBool(s,m_inFile);
+  if (memberGroupList==0)
+  {
+    marshalUInt(s,NULL_LIST); // null pointer representation
+  }
+  else
+  {
+    marshalUInt(s,memberGroupList->count());
+    QListIterator<MemberGroup> mgi(*memberGroupList);
+    MemberGroup *mg=0;
+    for (mgi.toFirst();(mg=mgi.current());++mgi)
+    {
+      mg->marshal(s);
+    }
+  }
+}
+
+void MemberList::unmarshal(StorageIntf *s)
+{
+  m_listType       = (MemberList::ListType)unmarshalInt(s);
+  m_varCnt         = unmarshalInt(s);
+  m_funcCnt        = unmarshalInt(s);
+  m_enumCnt        = unmarshalInt(s);
+  m_enumValCnt     = unmarshalInt(s);
+  m_typeCnt        = unmarshalInt(s);
+  m_protoCnt       = unmarshalInt(s);
+  m_defCnt         = unmarshalInt(s);
+  m_friendCnt      = unmarshalInt(s); 
+  m_numDecMembers  = unmarshalInt(s);
+  m_numDocMembers  = unmarshalInt(s);
+  m_inGroup        = unmarshalBool(s);
+  m_inFile         = unmarshalBool(s);
+  uint i,count     = unmarshalUInt(s); 
+  if (count==NULL_LIST) // empty list
+  {
+    memberGroupList = 0;
+  }
+  else // add member groups
+  {
+    memberGroupList = new MemberGroupList;
+    for (i=0;i<count;i++)
+    {
+      MemberGroup *mg = new MemberGroup;
+      mg->unmarshal(s);
+      memberGroupList->append(mg);
+    }
+  }
+}
+
+//--------------------------------------------------------------------------
+
+int MemberSDict::compareItems(GCI item1, GCI item2)
+{
+  MemberDef *c1=(MemberDef *)item1;
+  MemberDef *c2=(MemberDef *)item2;
+  return stricmp(c1->name(),c2->name());
+}
+