00001 /****************************************************************************** 00002 * 00003 * $Id: memberlist.cpp,v 1.35 2001/03/19 19:27:41 root Exp $ 00004 * 00005 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00006 * 00007 * Permission to use, copy, modify, and distribute this software and its 00008 * documentation under the terms of the GNU General Public License is hereby 00009 * granted. No representations are made about the suitability of this software 00010 * for any purpose. It is provided "as is" without express or implied warranty. 00011 * See the GNU General Public License for more details. 00012 * 00013 * Documents produced by Doxygen are derivative works derived from the 00014 * input used in their production; they are not affected by this license. 00015 * 00016 */ 00017 00018 #include <qregexp.h> 00019 00020 #include "memberlist.h" 00021 #include "classdef.h" 00022 #include "message.h" 00023 #include "util.h" 00024 #include "language.h" 00025 #include "doxygen.h" 00026 #include "outputlist.h" 00027 #include "groupdef.h" 00028 #include "marshal.h" 00029 00030 MemberList::MemberList() 00031 { 00032 } 00033 00034 MemberList::MemberList(ListType lt) : m_listType(lt) 00035 { 00036 memberGroupList=0; 00037 m_numDecMembers=-1; // special value indicating that value needs to be computed 00038 m_numDocMembers=-1; // special value indicating that value needs to be computed 00039 m_inGroup=FALSE; 00040 m_inFile=FALSE; 00041 } 00042 00043 MemberList::~MemberList() 00044 { 00045 delete memberGroupList; 00046 } 00047 00048 int MemberList::compareItems(GCI item1, GCI item2) 00049 { 00050 MemberDef *c1=(MemberDef *)item1; 00051 MemberDef *c2=(MemberDef *)item2; 00052 return stricmp(c1->name(),c2->name()); 00053 } 00054 00058 void MemberList::countDecMembers(bool countEnumValues) 00059 { 00060 if (m_numDecMembers!=-1) return; 00061 00062 //printf("----- countDecMembers count=%d ----\n",count()); 00063 m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0; 00064 m_typeCnt=m_protoCnt=m_defCnt=m_friendCnt=0; 00065 m_numDecMembers=0; 00066 QListIterator<MemberDef> mli(*this); 00067 MemberDef *md; 00068 for (mli.toFirst();(md=mli.current());++mli) 00069 { 00070 //printf("MemberList::countDecMembers(md=%s,%d)\n",md->name().data(),md->isBriefSectionVisible()); 00071 if (md->isBriefSectionVisible()) 00072 { 00073 switch(md->memberType()) 00074 { 00075 case MemberDef::Variable: // fall through 00076 case MemberDef::Event: // fall through 00077 case MemberDef::Property: m_varCnt++,m_numDecMembers++; 00078 break; 00079 case MemberDef::Function: // fall through 00080 case MemberDef::Signal: // fall through 00081 case MemberDef::DCOP: // fall through 00082 case MemberDef::Slot: if (!md->isRelated() || md->getClassDef()) 00083 m_funcCnt++,m_numDecMembers++; 00084 break; 00085 case MemberDef::Enumeration: m_enumCnt++,m_numDecMembers++; break; 00086 case MemberDef::EnumValue: if (countEnumValues) 00087 m_enumValCnt++,m_numDecMembers++; 00088 break; 00089 case MemberDef::Typedef: m_typeCnt++,m_numDecMembers++; break; 00090 case MemberDef::Prototype: m_protoCnt++,m_numDecMembers++; break; 00091 case MemberDef::Define: if (Config_getBool("EXTRACT_ALL") || 00092 md->argsString() || 00093 !md->initializer().isEmpty() || 00094 md->hasDocumentation() 00095 ) m_defCnt++,m_numDecMembers++; 00096 break; 00097 case MemberDef::Friend: m_friendCnt++,m_numDecMembers++; 00098 break; 00099 default: 00100 err("Error: Unknown member type found for member `%s'\n!",md->name().data()); 00101 } 00102 } 00103 } 00104 if (memberGroupList) 00105 { 00106 MemberGroupListIterator mgli(*memberGroupList); 00107 MemberGroup *mg; 00108 for (;(mg=mgli.current());++mgli) 00109 { 00110 mg->countDecMembers(); 00111 m_varCnt+=mg->varCount(); 00112 m_funcCnt+=mg->funcCount(); 00113 m_enumCnt+=mg->enumCount(); 00114 m_enumValCnt+=mg->enumValueCount(); 00115 m_typeCnt+=mg->typedefCount(); 00116 m_protoCnt+=mg->protoCount(); 00117 m_defCnt+=mg->defineCount(); 00118 m_friendCnt+=mg->friendCount(); 00119 m_numDecMembers+=mg->numDecMembers(); 00120 } 00121 } 00122 //printf("----- end countDecMembers ----\n"); 00123 00124 //printf("MemberList::countDecMembers()=%d\n",m_numDecMembers); 00125 } 00126 00127 void MemberList::countDocMembers(bool countEnumValues) 00128 { 00129 if (m_numDocMembers!=-1) return; // used cached value 00130 m_numDocMembers=0; 00131 QListIterator<MemberDef> mli(*this); 00132 MemberDef *md; 00133 for (mli.toFirst();(md=mli.current());++mli) 00134 { 00135 if (md->isDetailedSectionVisible(m_inGroup,m_inFile)) 00136 { 00137 // do not count enum values, since they do not produce entries of their own 00138 if (countEnumValues || md->memberType()!=MemberDef::EnumValue) 00139 m_numDocMembers++; 00140 } 00141 } 00142 if (memberGroupList) 00143 { 00144 MemberGroupListIterator mgli(*memberGroupList); 00145 MemberGroup *mg; 00146 for (;(mg=mgli.current());++mgli) 00147 { 00148 mg->countDocMembers(); 00149 m_numDocMembers+=mg->numDocMembers(); 00150 } 00151 } 00152 //printf("MemberList::countDocMembers()=%d memberGroupList=%p\n",m_numDocMembers,memberGroupList); 00153 } 00154 00155 bool MemberList::insert(uint index,const MemberDef *md) 00156 { 00157 return QList<MemberDef>::insert(index,md); 00158 } 00159 00160 void MemberList::inSort(const MemberDef *md) 00161 { 00162 QList<MemberDef>::inSort(md); 00163 } 00164 00165 void MemberList::append(const MemberDef *md) 00166 { 00167 QList<MemberDef>::append(md); 00168 } 00169 00170 MemberListIterator::MemberListIterator(const QList<MemberDef> &l) : 00171 QListIterator<MemberDef>(l) 00172 { 00173 } 00174 00175 void MemberList::writePlainDeclarations(OutputList &ol, 00176 ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd 00177 ) 00178 { 00179 //printf("----- writePlainDeclaration() ----\n"); 00180 countDecMembers(); 00181 if (numDecMembers()==0) 00182 { 00183 //printf(" --> no members!\n"); 00184 return; // no members in this list 00185 } 00186 //printf(" --> writePlainDeclaration() numDecMembers()=%d\n", 00187 // numDecMembers()); 00188 00189 ol.pushGeneratorState(); 00190 00191 bool first=TRUE; 00192 MemberDef *md; 00193 MemberListIterator mli(*this); 00194 for ( ; (md=mli.current()); ++mli ) 00195 { 00196 //printf(">>> Member `%s' type=%d visible=%d\n", 00197 // md->name().data(),md->memberType(),md->isBriefSectionVisible()); 00198 if (md->isBriefSectionVisible()) 00199 { 00200 switch(md->memberType()) 00201 { 00202 case MemberDef::Define: // fall through 00203 case MemberDef::Prototype: // fall through 00204 case MemberDef::Typedef: // fall through 00205 case MemberDef::Variable: // fall through 00206 case MemberDef::Function: // fall through 00207 case MemberDef::Signal: // fall through 00208 case MemberDef::Slot: // fall through 00209 case MemberDef::DCOP: // fall through 00210 case MemberDef::Property: // fall through 00211 case MemberDef::Event: 00212 { 00213 if (first) ol.startMemberList(),first=FALSE; 00214 md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup); 00215 break; 00216 } 00217 case MemberDef::Enumeration: 00218 { 00219 if (first) ol.startMemberList(),first=FALSE; 00220 int enumVars=0; 00221 MemberListIterator vmli(*this); 00222 MemberDef *vmd; 00223 QCString name(md->name()); 00224 int i=name.findRev("::"); 00225 if (i!=-1) name=name.right(name.length()-i-2); // strip scope (TODO: is this needed?) 00226 if (name[0]=='@') // anonymous enum => append variables 00227 { 00228 for ( ; (vmd=vmli.current()) ; ++vmli) 00229 { 00230 QCString vtype=vmd->typeString(); 00231 if ((vtype.find(name))!=-1) 00232 { 00233 enumVars++; 00234 vmd->setAnonymousEnumType(md); 00235 } 00236 } 00237 } 00238 // if this is an anoymous enum and there are variables of this 00239 // enum type (i.e. enumVars>0), then we do not show the enum here. 00240 if (enumVars==0) // show enum here 00241 { 00242 ol.startMemberItem(0); 00243 ol.writeString("enum "); 00244 ol.insertMemberAlign(); 00245 md->writeEnumDeclaration(ol,cd,nd,fd,gd); 00246 ol.endMemberItem(); 00247 if (!md->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) 00248 { 00249 ol.startMemberDescription(); 00250 ol.parseDoc( 00251 md->briefFile(),md->briefLine(), 00252 cd,md, 00253 md->briefDescription(), 00254 TRUE, 00255 FALSE 00256 ); 00257 if (md->isDetailedSectionLinkable()) 00258 { 00259 ol.disableAllBut(OutputGenerator::Html); 00260 ol.docify(" "); 00261 ol.startTextLink(md->getOutputFileBase(), 00262 md->anchor()); 00263 ol.parseText(theTranslator->trMore()); 00264 ol.endTextLink(); 00265 ol.enableAll(); 00266 } 00267 ol.endMemberDescription(); 00268 } 00269 } 00270 md->warnIfUndocumented(); 00271 break; 00272 } 00273 case MemberDef::Friend: 00274 { 00275 if (first) ol.startMemberList(),first=FALSE; 00276 md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup); 00277 break; 00278 } 00279 case MemberDef::EnumValue: 00280 { 00281 if (first) ol.startMemberList(),first=FALSE; 00282 md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup); 00283 } 00284 break; 00285 } 00286 } 00287 } 00288 00289 // handle members that are inside anonymous compounds and for which 00290 // no variables of the anonymous compound type exist. 00291 if (cd) 00292 { 00293 MemberListIterator mli(*this); 00294 for ( ; (md=mli.current()) ; ++mli ) 00295 { 00296 if (md->fromAnonymousScope() && !md->anonymousDeclShown()) 00297 { 00298 md->setFromAnonymousScope(FALSE); 00299 //printf("anonymous compound members\n"); 00300 if (md->isBriefSectionVisible()) 00301 { 00302 if (first) ol.startMemberList(),first=FALSE; 00303 md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup); 00304 } 00305 md->setFromAnonymousScope(TRUE); 00306 } 00307 } 00308 } 00309 00310 if (!first) ol.endMemberList(); 00311 00312 ol.popGeneratorState(); 00313 //printf("----- end writePlainDeclaration() ----\n"); 00314 } 00315 00316 void MemberList::writeDeclarations(OutputList &ol, 00317 ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, 00318 const char *title,const char *subtitle, bool showEnumValues 00319 /*, bool inGroup,bool countSubGroups*/) 00320 { 00321 //printf("----- writeDeclaration() this=%p ----\n",this); 00322 countDecMembers(showEnumValues); // count member not in group 00323 if (numDecMembers()==0) return; 00324 //printf("%p: MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d\n", 00325 // this,title,subtitle,numDecMembers()); 00326 if (title) 00327 { 00328 ol.startMemberHeader(); 00329 ol.parseText(title); 00330 ol.endMemberHeader(); 00331 } 00332 if (subtitle && subtitle[0]!=0) 00333 { 00334 //printf("subtitle=`%s'\n",subtitle); 00335 ol.startMemberSubtitle(); 00336 ol.parseDoc("[generated]",-1,0,0,subtitle,FALSE,FALSE); 00337 ol.endMemberSubtitle(); 00338 } 00339 00340 writePlainDeclarations(ol,cd,nd,fd,gd); 00341 00342 //printf("memberGroupList=%p\n",memberGroupList); 00343 if (memberGroupList) 00344 { 00345 MemberGroupListIterator mgli(*memberGroupList); 00346 MemberGroup *mg; 00347 while ((mg=mgli.current())) 00348 { 00349 //printf("mg->header=%s\n",mg->header().data()); 00350 bool hasHeader=mg->header()!="[NOHEADER]"; 00351 ol.startMemberGroupHeader(hasHeader); 00352 if (hasHeader) 00353 { 00354 ol.parseText(mg->header()); 00355 } 00356 ol.endMemberGroupHeader(); 00357 if (!mg->documentation().isEmpty()) 00358 { 00359 //printf("Member group has docs!\n"); 00360 ol.startMemberGroupDocs(); 00361 ol.parseDoc("[generated]",-1,0,0,mg->documentation()+"\n",FALSE,FALSE); 00362 ol.endMemberGroupDocs(); 00363 } 00364 ol.startMemberGroup(); 00365 //printf("--- mg->writePlainDeclarations ---\n"); 00366 mg->writePlainDeclarations(ol,cd,nd,fd,gd); 00367 ol.endMemberGroup(hasHeader); 00368 ++mgli; 00369 } 00370 } 00371 //printf("----- end writeDeclaration() ----\n"); 00372 00373 } 00374 00375 void MemberList::writeDocumentation(OutputList &ol, 00376 const char *scopeName, Definition *container, 00377 const char *title,bool showEnumValues) 00378 { 00379 //printf("MemberList::writeDocumentation()\n"); 00380 00381 countDocMembers(showEnumValues); 00382 if (numDocMembers()==0) return; 00383 00384 if (title) 00385 { 00386 ol.writeRuler(); 00387 ol.startGroupHeader(); 00388 ol.parseText(title); 00389 ol.endGroupHeader(); 00390 } 00391 ol.startMemberDocList(); 00392 00393 MemberListIterator mli(*this); 00394 MemberDef *md; 00395 for ( ; (md=mli.current()) ; ++mli) 00396 { 00397 md->writeDocumentation(this,ol,scopeName,container,m_inGroup,showEnumValues); 00398 } 00399 if (memberGroupList) 00400 { 00401 //printf("MemberList::writeDocumentation() -- member groups\n"); 00402 MemberGroupListIterator mgli(*memberGroupList); 00403 MemberGroup *mg; 00404 for (;(mg=mgli.current());++mgli) 00405 { 00406 mg->writeDocumentation(ol,scopeName,container); 00407 } 00408 } 00409 ol.endMemberDocList(); 00410 } 00411 00412 void MemberList::writeDocumentationPage(OutputList &ol, 00413 const char *scopeName, Definition *container) 00414 { 00415 MemberListIterator mli(*this); 00416 MemberDef *md; 00417 for ( ; (md=mli.current()) ; ++mli) 00418 { 00419 QCString diskName=md->getOutputFileBase(); 00420 QCString title=md->qualifiedName(); 00421 startFile(ol,diskName,md->name(),title); 00422 container->writeNavigationPath(ol); 00423 00424 ol.writeString("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n" 00425 " <tr>\n" 00426 " <td valign=\"top\">\n"); 00427 00428 container->writeQuickMemberLinks(ol,md); 00429 00430 ol.writeString(" </td>\n"); 00431 ol.writeString(" <td valign=\"top\">\n"); 00432 00433 md->writeDocumentation(this,ol,scopeName,container,m_inGroup); 00434 00435 ol.writeString(" </td>\n"); 00436 ol.writeString(" </tr>\n"); 00437 ol.writeString("</table>\n"); 00438 00439 endFile(ol); 00440 } 00441 if (memberGroupList) 00442 { 00443 //printf("MemberList::writeDocumentation() -- member groups\n"); 00444 MemberGroupListIterator mgli(*memberGroupList); 00445 MemberGroup *mg; 00446 for (;(mg=mgli.current());++mgli) 00447 { 00448 mg->writeDocumentationPage(ol,scopeName,container); 00449 } 00450 } 00451 } 00452 00453 void MemberList::addMemberGroup(MemberGroup *mg) 00454 { 00455 if (memberGroupList==0) 00456 { 00457 memberGroupList=new MemberGroupList; 00458 } 00459 //printf("addMemberGroup: this=%p mg=%p\n",this,mg); 00460 memberGroupList->append(mg); 00461 } 00462 00463 void MemberList::addListReferences(Definition *def) 00464 { 00465 MemberListIterator mli(*this); 00466 MemberDef *md; 00467 for ( ; (md=mli.current()) ; ++mli) 00468 { 00469 if (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup) 00470 { 00471 md->addListReference(def); 00472 LockingPtr<MemberList> enumFields = md->enumFieldList(); 00473 if (md->memberType()==MemberDef::Enumeration && enumFields!=0) 00474 { 00475 MemberListIterator vmli(*enumFields); 00476 MemberDef *vmd; 00477 for ( ; (vmd=vmli.current()) ; ++vmli) 00478 { 00479 vmd->addListReference(def); 00480 } 00481 } 00482 } 00483 } 00484 if (memberGroupList) 00485 { 00486 MemberGroupListIterator mgli(*memberGroupList); 00487 MemberGroup *mg; 00488 for (;(mg=mgli.current());++mgli) 00489 { 00490 mg->addListReferences(def); 00491 } 00492 } 00493 } 00494 00495 void MemberList::findSectionsInDocumentation() 00496 { 00497 MemberListIterator mli(*this); 00498 MemberDef *md; 00499 for ( ; (md=mli.current()) ; ++mli) 00500 { 00501 md->findSectionsInDocumentation(); 00502 } 00503 if (memberGroupList) 00504 { 00505 MemberGroupListIterator mgli(*memberGroupList); 00506 MemberGroup *mg; 00507 for (;(mg=mgli.current());++mgli) 00508 { 00509 mg->findSectionsInDocumentation(); 00510 } 00511 } 00512 } 00513 00514 void MemberList::marshal(StorageIntf *s) 00515 { 00516 marshalInt(s,(int)m_listType); 00517 marshalInt(s,m_varCnt); 00518 marshalInt(s,m_funcCnt); 00519 marshalInt(s,m_enumCnt); 00520 marshalInt(s,m_enumValCnt); 00521 marshalInt(s,m_typeCnt); 00522 marshalInt(s,m_protoCnt); 00523 marshalInt(s,m_defCnt); 00524 marshalInt(s,m_friendCnt); 00525 marshalInt(s,m_numDecMembers); 00526 marshalInt(s,m_numDocMembers); 00527 marshalBool(s,m_inGroup); 00528 marshalBool(s,m_inFile); 00529 if (memberGroupList==0) 00530 { 00531 marshalUInt(s,NULL_LIST); // null pointer representation 00532 } 00533 else 00534 { 00535 marshalUInt(s,memberGroupList->count()); 00536 QListIterator<MemberGroup> mgi(*memberGroupList); 00537 MemberGroup *mg=0; 00538 for (mgi.toFirst();(mg=mgi.current());++mgi) 00539 { 00540 mg->marshal(s); 00541 } 00542 } 00543 } 00544 00545 void MemberList::unmarshal(StorageIntf *s) 00546 { 00547 m_listType = (MemberList::ListType)unmarshalInt(s); 00548 m_varCnt = unmarshalInt(s); 00549 m_funcCnt = unmarshalInt(s); 00550 m_enumCnt = unmarshalInt(s); 00551 m_enumValCnt = unmarshalInt(s); 00552 m_typeCnt = unmarshalInt(s); 00553 m_protoCnt = unmarshalInt(s); 00554 m_defCnt = unmarshalInt(s); 00555 m_friendCnt = unmarshalInt(s); 00556 m_numDecMembers = unmarshalInt(s); 00557 m_numDocMembers = unmarshalInt(s); 00558 m_inGroup = unmarshalBool(s); 00559 m_inFile = unmarshalBool(s); 00560 uint i,count = unmarshalUInt(s); 00561 if (count==NULL_LIST) // empty list 00562 { 00563 memberGroupList = 0; 00564 } 00565 else // add member groups 00566 { 00567 memberGroupList = new MemberGroupList; 00568 for (i=0;i<count;i++) 00569 { 00570 MemberGroup *mg = new MemberGroup; 00571 mg->unmarshal(s); 00572 memberGroupList->append(mg); 00573 } 00574 } 00575 } 00576 00577 //-------------------------------------------------------------------------- 00578 00579 int MemberSDict::compareItems(GCI item1, GCI item2) 00580 { 00581 MemberDef *c1=(MemberDef *)item1; 00582 MemberDef *c2=(MemberDef *)item2; 00583 return stricmp(c1->name(),c2->name()); 00584 } 00585