00001 /****************************************************************************** 00002 * 00003 * $Id: classdef.cpp,v 1.54 2001/03/19 19:27:39 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 <stdio.h> 00019 #include <qfile.h> 00020 #include <qregexp.h> 00021 #include "classdef.h" 00022 #include "classlist.h" 00023 #include "entry.h" 00024 #include "doxygen.h" 00025 #include "membername.h" 00026 #include "message.h" 00027 #include "config.h" 00028 #include "util.h" 00029 #include "diagram.h" 00030 #include "language.h" 00031 #include "htmlhelp.h" 00032 #include "example.h" 00033 #include "outputlist.h" 00034 #include "dot.h" 00035 #include "defargs.h" 00036 #include "debug.h" 00037 #include "docparser.h" 00038 #include "searchindex.h" 00039 #include "vhdldocgen.h" 00040 00041 //static inline MemberList *createNewMemberList(MemberList::ListType lt) 00042 //{ 00043 // MemberList *result = new MemberList(lt); 00044 // return result; 00045 //} 00046 00047 class ClassDefImpl 00048 { 00049 public: 00050 ClassDefImpl(); 00051 ~ClassDefImpl(); 00052 void init(const char *defFileName, const char *name, 00053 const QCString &ctStr, const char *fName); 00054 00059 QCString fileName; 00060 00064 IncludeInfo *incInfo; 00065 00069 BaseClassList *inherits; 00070 00073 BaseClassList *inheritedBy; 00074 00078 NamespaceDef *nspace; 00079 00081 FileDef *fileDef; 00082 00084 MemberNameInfoSDict *allMemberNameInfoSDict; 00085 00087 ArgumentList *tempArgs; 00088 00090 ArgumentList *typeConstraints; 00091 00093 QStrList files; 00094 00096 ExampleSDict *exampleSDict; 00097 00099 ClassDef::CompoundType compType; 00100 00105 Protection prot; 00106 00110 ClassSDict *innerClasses; 00111 00112 /* classes for the collaboration diagram */ 00113 UsesClassDict *usesImplClassDict; 00114 UsesClassDict *usedByImplClassDict; 00115 UsesClassDict *usesIntfClassDict; 00116 00120 QDict<ClassDef> *templateInstances; 00121 00126 QDict<ClassDef> *variableInstances; 00127 00128 QDict<int> *templBaseClassNames; 00129 00131 ClassDef *templateMaster; 00132 00134 QCString className; 00135 00139 ClassDef *categoryOf; 00140 00141 QList<MemberList> memberLists; 00142 00143 /* user defined member groups */ 00144 MemberGroupSDict *memberGroupSDict; 00145 00147 bool isAbstract; 00148 00150 bool isStatic; 00151 00153 bool isObjC; 00154 00156 bool membersMerged; 00157 00159 bool isLocal; 00160 00161 bool isTemplArg; 00162 00167 bool subGrouping; 00168 00169 bool usedOnly; 00170 }; 00171 00172 void ClassDefImpl::init(const char *defFileName, const char *name, 00173 const QCString &ctStr, const char *fName) 00174 { 00175 if (fName) 00176 { 00177 fileName=stripExtension(fName); 00178 } 00179 else 00180 { 00181 fileName=ctStr+name; 00182 } 00183 exampleSDict = 0; 00184 inherits = 0; 00185 inheritedBy = 0; 00186 allMemberNameInfoSDict = 0; 00187 incInfo=0; 00188 tempArgs=0; 00189 typeConstraints=0; 00190 prot=Public; 00191 nspace=0; 00192 fileDef=0; 00193 usesImplClassDict=0; 00194 usedByImplClassDict=0; 00195 usesIntfClassDict=0; 00196 memberGroupSDict = 0; 00197 innerClasses = 0; 00198 subGrouping=Config_getBool("SUBGROUPING"); 00199 templateInstances = 0; 00200 variableInstances = 0; 00201 templateMaster =0; 00202 templBaseClassNames = 0; 00203 isAbstract = FALSE; 00204 isStatic = FALSE; 00205 isTemplArg = FALSE; 00206 membersMerged = FALSE; 00207 categoryOf = 0; 00208 usedOnly = FALSE; 00209 QCString ns; 00210 extractNamespaceName(name,className,ns); 00211 //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data()); 00212 00213 if (((QCString)defFileName).right(5)!=".java" && 00214 guessSection(defFileName)==Entry::SOURCE_SEC) 00215 { 00216 isLocal=TRUE; 00217 } 00218 else 00219 { 00220 isLocal=FALSE; 00221 } 00222 } 00223 00224 ClassDefImpl::ClassDefImpl() 00225 { 00226 } 00227 00228 ClassDefImpl::~ClassDefImpl() 00229 { 00230 delete inherits; 00231 delete inheritedBy; 00232 delete allMemberNameInfoSDict; 00233 delete exampleSDict; 00234 delete usesImplClassDict; 00235 delete usedByImplClassDict; 00236 delete usesIntfClassDict; 00237 delete incInfo; 00238 delete memberGroupSDict; 00239 delete innerClasses; 00240 delete templateInstances; 00241 delete variableInstances; 00242 delete templBaseClassNames; 00243 delete tempArgs; 00244 delete typeConstraints; 00245 } 00246 00247 // constructs a new class definition 00248 ClassDef::ClassDef( 00249 const char *defFileName,int defLine, 00250 const char *nm,CompoundType ct, 00251 const char *lref,const char *fName, 00252 bool isSymbol) 00253 : Definition(defFileName,defLine,removeRedundantWhiteSpace(nm),0,0,isSymbol) 00254 { 00255 visited=FALSE; 00256 setReference(lref); 00257 m_impl = new ClassDefImpl; 00258 m_impl->compType = ct; 00259 m_impl->isObjC = FALSE; 00260 m_impl->init(defFileName,name(),compoundTypeString(),fName); 00261 00262 } 00263 00264 // destroy the class definition 00265 ClassDef::~ClassDef() 00266 { 00267 delete m_impl; 00268 } 00269 00270 QCString ClassDef::getMemberListFileName() const 00271 { 00272 return convertNameToFile(compoundTypeString()+name()+"-members"); 00273 } 00274 00275 QCString ClassDef::displayName() const 00276 { 00277 static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES"); 00278 static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); 00279 static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 00280 QCString n; 00281 if (vhdlOpt) 00282 { 00283 n = VhdlDocGen::getClassName(this); 00284 } 00285 else if (hideScopeNames) 00286 { 00287 n=m_impl->className; 00288 } 00289 else 00290 { 00291 n=qualifiedNameWithTemplateParameters(); 00292 } 00293 if (optimizeOutputForJava) 00294 { 00295 n=substitute(n,"::","."); 00296 } 00297 if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p") 00298 { 00299 n="< "+n.left(n.length()-2)+" >"; 00300 } 00301 return n; 00302 } 00303 00304 // inserts a base class in the inheritance list 00305 void ClassDef::insertBaseClass(ClassDef *cd,const char *n,Protection p, 00306 Specifier s,const char *t) 00307 { 00308 //printf("*** insert base class %s into %s\n",cd->name().data(),name().data()); 00309 //inherits->inSort(new BaseClassDef(cd,p,s,t)); 00310 if (m_impl->inherits==0) 00311 { 00312 m_impl->inherits = new BaseClassList; 00313 m_impl->inherits->setAutoDelete(TRUE); 00314 } 00315 m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t)); 00316 } 00317 00318 // inserts a sub class in the inherited list 00319 void ClassDef::insertSubClass(ClassDef *cd,Protection p, 00320 Specifier s,const char *t) 00321 { 00322 //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data()); 00323 if (m_impl->inheritedBy==0) 00324 { 00325 m_impl->inheritedBy = new BaseClassList; 00326 m_impl->inheritedBy->setAutoDelete(TRUE); 00327 } 00328 m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); 00329 } 00330 00331 void ClassDef::addMembersToMemberGroup() 00332 { 00333 QListIterator<MemberList> mli(m_impl->memberLists); 00334 MemberList *ml; 00335 for (mli.toFirst();(ml=mli.current());++mli) 00336 { 00337 if ((ml->listType()&MemberList::detailedLists)==0) 00338 { 00339 ::addMembersToMemberGroup(ml,&m_impl->memberGroupSDict,this); 00340 } 00341 } 00342 00343 // add members inside sections to their groups 00344 if (m_impl->memberGroupSDict) 00345 { 00346 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 00347 MemberGroup *mg; 00348 for (;(mg=mgli.current());++mgli) 00349 { 00350 if (mg->allMembersInSameSection() && m_impl->subGrouping) 00351 { 00352 //printf("addToDeclarationSection(%s)\n",mg->header().data()); 00353 mg->addToDeclarationSection(); 00354 } 00355 } 00356 } 00357 } 00358 00359 // adds new member definition to the class 00360 void ClassDef::internalInsertMember(MemberDef *md, 00361 Protection prot, 00362 bool addToAllList 00363 ) 00364 { 00365 //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden()); 00366 if (md->isHidden()) return; 00367 00368 if (!isReference()) 00369 { 00370 static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); 00371 00372 /********************************************/ 00373 /* insert member in the declaration section */ 00374 /********************************************/ 00375 if (md->isRelated() && (extractPrivate || prot!=Private)) 00376 { 00377 addMemberToList(MemberList::related,md); 00378 } 00379 else if (md->isFriend()) 00380 { 00381 addMemberToList(MemberList::friends,md); 00382 } 00383 else 00384 { 00385 switch (md->memberType()) 00386 { 00387 case MemberDef::Signal: // Qt specific 00388 addMemberToList(MemberList::signals,md); 00389 break; 00390 case MemberDef::DCOP: // KDE2 specific 00391 addMemberToList(MemberList::dcopMethods,md); 00392 break; 00393 case MemberDef::Property: 00394 addMemberToList(MemberList::properties,md); 00395 break; 00396 case MemberDef::Event: 00397 addMemberToList(MemberList::events,md); 00398 break; 00399 case MemberDef::Slot: // Qt specific 00400 switch (prot) 00401 { 00402 case Protected: 00403 case Package: // slots in packages are not possible! 00404 addMemberToList(MemberList::proSlots,md); 00405 break; 00406 case Public: 00407 addMemberToList(MemberList::pubSlots,md); 00408 break; 00409 case Private: 00410 addMemberToList(MemberList::priSlots,md); 00411 break; 00412 } 00413 break; 00414 default: // any of the other members 00415 if (md->isStatic()) 00416 { 00417 if (md->isVariable()) 00418 { 00419 switch (prot) 00420 { 00421 case Protected: 00422 addMemberToList(MemberList::proStaticAttribs,md); 00423 break; 00424 case Package: 00425 addMemberToList(MemberList::pacStaticAttribs,md); 00426 break; 00427 case Public: 00428 addMemberToList(MemberList::pubStaticAttribs,md); 00429 break; 00430 case Private: 00431 addMemberToList(MemberList::priStaticAttribs,md); 00432 break; 00433 } 00434 } 00435 else // function 00436 { 00437 switch (prot) 00438 { 00439 case Protected: 00440 addMemberToList(MemberList::proStaticMethods,md); 00441 break; 00442 case Package: 00443 addMemberToList(MemberList::pacStaticMethods,md); 00444 break; 00445 case Public: 00446 addMemberToList(MemberList::pubStaticMethods,md); 00447 break; 00448 case Private: 00449 addMemberToList(MemberList::priStaticMethods,md); 00450 break; 00451 } 00452 } 00453 } 00454 else // not static 00455 { 00456 if (md->isVariable()) 00457 { 00458 switch (prot) 00459 { 00460 case Protected: 00461 addMemberToList(MemberList::proAttribs,md); 00462 break; 00463 case Package: 00464 addMemberToList(MemberList::pacAttribs,md); 00465 break; 00466 case Public: 00467 addMemberToList(MemberList::pubAttribs,md); 00468 break; 00469 case Private: 00470 addMemberToList(MemberList::priAttribs,md); 00471 break; 00472 } 00473 } 00474 else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue()) 00475 { 00476 switch (prot) 00477 { 00478 case Protected: 00479 addMemberToList(MemberList::proTypes,md); 00480 break; 00481 case Package: 00482 addMemberToList(MemberList::pacTypes,md); 00483 break; 00484 case Public: 00485 addMemberToList(MemberList::pubTypes,md); 00486 break; 00487 case Private: 00488 addMemberToList(MemberList::priTypes,md); 00489 break; 00490 } 00491 } 00492 else // member function 00493 { 00494 switch (prot) 00495 { 00496 case Protected: 00497 addMemberToList(MemberList::proMethods,md); 00498 break; 00499 case Package: 00500 addMemberToList(MemberList::pacMethods,md); 00501 break; 00502 case Public: 00503 addMemberToList(MemberList::pubMethods,md); 00504 break; 00505 case Private: 00506 addMemberToList(MemberList::priMethods,md); 00507 break; 00508 } 00509 } 00510 } 00511 break; 00512 } 00513 } 00514 00515 /*******************************************************/ 00516 /* insert member in the detailed documentation section */ 00517 /*******************************************************/ 00518 if ((md->isRelated() && (extractPrivate || prot!=Private)) || md->isFriend()) 00519 { 00520 addMemberToList(MemberList::relatedMembers,md); 00521 } 00522 else 00523 { 00524 switch (md->memberType()) 00525 { 00526 case MemberDef::Property: 00527 addMemberToList(MemberList::propertyMembers,md); 00528 break; 00529 case MemberDef::Event: 00530 addMemberToList(MemberList::eventMembers,md); 00531 break; 00532 case MemberDef::Signal: // fall through 00533 case MemberDef::DCOP: 00534 addMemberToList(MemberList::functionMembers,md); 00535 break; 00536 case MemberDef::Slot: 00537 switch (prot) 00538 { 00539 case Protected: 00540 case Package: 00541 case Public: 00542 addMemberToList(MemberList::functionMembers,md); 00543 break; 00544 case Private: 00545 if (extractPrivate) 00546 { 00547 addMemberToList(MemberList::functionMembers,md); 00548 } 00549 break; 00550 } 00551 break; 00552 default: // any of the other members 00553 if (prot!=Private || extractPrivate) 00554 { 00555 switch (md->memberType()) 00556 { 00557 case MemberDef::Typedef: 00558 addMemberToList(MemberList::typedefMembers,md); 00559 break; 00560 case MemberDef::Enumeration: 00561 addMemberToList(MemberList::enumMembers,md); 00562 break; 00563 case MemberDef::EnumValue: 00564 addMemberToList(MemberList::enumValMembers,md); 00565 break; 00566 case MemberDef::Function: 00567 if (md->isConstructor() || md->isDestructor()) 00568 { 00569 MemberList *ml = createMemberList(MemberList::constructors); 00570 ml->append(md); 00571 } 00572 else 00573 { 00574 addMemberToList(MemberList::functionMembers,md); 00575 } 00576 break; 00577 case MemberDef::Variable: 00578 addMemberToList(MemberList::variableMembers,md); 00579 break; 00580 default: 00581 err("Unexpected member type %d found!\n",md->memberType()); 00582 } 00583 } 00584 break; 00585 } 00586 } 00587 00588 /*************************************************/ 00589 /* insert member in the appropriate member group */ 00590 /*************************************************/ 00591 // Note: this must be done AFTER inserting the member in the 00592 // regular groups 00593 //addMemberToGroup(md,groupId); 00594 00595 } 00596 00597 if (md->virtualness()==Pure) 00598 { 00599 m_impl->isAbstract=TRUE; 00600 } 00601 00602 //::addClassMemberNameToIndex(md); 00603 if (addToAllList && 00604 !(Config_getBool("HIDE_FRIEND_COMPOUNDS") && 00605 md->isFriend() && 00606 (QCString(md->typeString())=="friend class" || 00607 QCString(md->typeString())=="friend struct" || 00608 QCString(md->typeString())=="friend union"))) 00609 { 00610 //printf("=======> adding member %s to class %s\n",md->name().data(),name().data()); 00611 MemberInfo *mi = new MemberInfo((MemberDef *)md, 00612 prot,md->virtualness(),FALSE); 00613 MemberNameInfo *mni=0; 00614 if (m_impl->allMemberNameInfoSDict==0) 00615 { 00616 m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17); 00617 m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE); 00618 } 00619 if ((mni=m_impl->allMemberNameInfoSDict->find(md->name()))) 00620 { 00621 mni->append(mi); 00622 } 00623 else 00624 { 00625 mni = new MemberNameInfo(md->name()); 00626 mni->append(mi); 00627 m_impl->allMemberNameInfoSDict->append(mni->memberName(),mni); 00628 } 00629 } 00630 } 00631 00632 void ClassDef::insertMember(MemberDef *md) 00633 { 00634 internalInsertMember(md,md->protection(),TRUE); 00635 } 00636 00637 // compute the anchors for all members 00638 void ClassDef::computeAnchors() 00639 { 00640 ClassDef *context = Config_getBool("INLINE_INHERITED_MEMB") ? this : 0; 00641 const char *letters = "abcdefghijklmnopqrstuvwxyz0123456789"; 00642 QListIterator<MemberList> mli(m_impl->memberLists); 00643 MemberList *ml; 00644 int index = 0; 00645 for (mli.toFirst();(ml=mli.current());++mli) 00646 { 00647 if ((ml->listType()&MemberList::detailedLists)==0) 00648 { 00649 setAnchors(context,letters[index++],ml); 00650 } 00651 } 00652 00653 if (m_impl->memberGroupSDict) 00654 { 00655 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 00656 MemberGroup *mg; 00657 for (;(mg=mgli.current());++mgli) 00658 { 00659 mg->setAnchors(context); 00660 } 00661 } 00662 } 00663 00664 void ClassDef::distributeMemberGroupDocumentation() 00665 { 00666 if (m_impl->memberGroupSDict) 00667 { 00668 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 00669 MemberGroup *mg; 00670 for (;(mg=mgli.current());++mgli) 00671 { 00672 mg->distributeMemberGroupDocumentation(); 00673 } 00674 } 00675 } 00676 00677 void ClassDef::findSectionsInDocumentation() 00678 { 00679 docFindSections(documentation(),this,0,docFile()); 00680 if (m_impl->memberGroupSDict) 00681 { 00682 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 00683 MemberGroup *mg; 00684 for (;(mg=mgli.current());++mgli) 00685 { 00686 mg->findSectionsInDocumentation(); 00687 } 00688 } 00689 QListIterator<MemberList> mli(m_impl->memberLists); 00690 MemberList *ml; 00691 for (mli.toFirst();(ml=mli.current());++mli) 00692 { 00693 if ((ml->listType()&MemberList::detailedLists)==0) 00694 { 00695 ml->findSectionsInDocumentation(); 00696 } 00697 } 00698 } 00699 00700 00701 // add a file name to the used files set 00702 void ClassDef::insertUsedFile(const char *f) 00703 { 00704 if (m_impl->files.find(f)==-1) m_impl->files.append(f); 00705 if (m_impl->templateInstances) 00706 { 00707 QDictIterator<ClassDef> qdi(*m_impl->templateInstances); 00708 ClassDef *cd; 00709 for (qdi.toFirst();(cd=qdi.current());++qdi) 00710 { 00711 cd->insertUsedFile(f); 00712 } 00713 } 00714 } 00715 00716 static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) 00717 { 00718 if (bcd->prot!=Public || bcd->virt!=Normal) 00719 { 00720 ol.startTypewriter(); 00721 ol.docify(" ["); 00722 QStrList sl; 00723 if (bcd->prot==Protected) sl.append("protected"); 00724 else if (bcd->prot==Private) sl.append("private"); 00725 if (bcd->virt==Virtual) sl.append("virtual"); 00726 const char *s=sl.first(); 00727 while (s) 00728 { 00729 ol.docify(s); 00730 s=sl.next(); 00731 if (s) ol.docify(", "); 00732 } 00733 ol.docify("]"); 00734 ol.endTypewriter(); 00735 } 00736 } 00737 00738 void ClassDef::setIncludeFile(FileDef *fd, 00739 const char *includeName,bool local, bool force) 00740 { 00741 //printf("ClassDef::setIncludeFile(%p,%s,%d,%d)\n",fd,includeName,local,force); 00742 if (!m_impl->incInfo) m_impl->incInfo=new IncludeInfo; 00743 if ((includeName && m_impl->incInfo->includeName.isEmpty()) || 00744 (fd!=0 && m_impl->incInfo->fileDef==0) 00745 ) 00746 { 00747 //printf("Setting file info\n"); 00748 m_impl->incInfo->fileDef = fd; 00749 m_impl->incInfo->includeName = includeName; 00750 m_impl->incInfo->local = local; 00751 } 00752 if (force && includeName) m_impl->incInfo->includeName = includeName; 00753 } 00754 00755 // TODO: fix this: a nested template class can have multiple outer templates 00756 //ArgumentList *ClassDef::outerTemplateArguments() const 00757 //{ 00758 // int ti; 00759 // ClassDef *pcd=0; 00760 // int pi=0; 00761 // if (m_impl->tempArgs) return m_impl->tempArgs; 00762 // // find the outer most class scope 00763 // while ((ti=name().find("::",pi))!=-1 && 00764 // (pcd=getClass(name().left(ti)))==0 00765 // ) pi=ti+2; 00766 // if (pcd) 00767 // { 00768 // return pcd->templateArguments(); 00769 // } 00770 // return 0; 00771 //} 00772 00773 static void searchTemplateSpecs(/*in*/ Definition *d, 00774 /*out*/ QList<ArgumentList> &result, 00775 /*out*/ QCString &name) 00776 { 00777 if (d->definitionType()==Definition::TypeClass) 00778 { 00779 if (d->getOuterScope()) 00780 { 00781 searchTemplateSpecs(d->getOuterScope(),result,name); 00782 } 00783 ClassDef *cd=(ClassDef *)d; 00784 if (!name.isEmpty()) name+="::"; 00785 name+=d->localName(); 00786 bool isSpecialization = d->localName().find('<')!=-1; 00787 if (cd->templateArguments()) 00788 { 00789 result.append(cd->templateArguments()); 00790 if (!isSpecialization) 00791 { 00792 name+=tempArgListToString(cd->templateArguments()); 00793 } 00794 } 00795 } 00796 else 00797 { 00798 name+=d->qualifiedName(); 00799 } 00800 } 00801 00802 static void writeTemplateSpec(OutputList &ol,Definition *d, 00803 const QCString &type) 00804 { 00805 QList<ArgumentList> specs; 00806 QCString name; 00807 searchTemplateSpecs(d,specs,name); 00808 if (specs.count()>0) // class has template scope specifiers 00809 { 00810 ol.startSubsubsection(); 00811 QListIterator<ArgumentList> spi(specs); 00812 ArgumentList *al; 00813 for (spi.toFirst();(al=spi.current());++spi) 00814 { 00815 ol.docify("template<"); 00816 Argument *a=al->first(); 00817 while (a) 00818 { 00819 ol.docify(a->type); 00820 if (!a->name.isEmpty()) 00821 { 00822 ol.docify(" "); 00823 ol.docify(a->name); 00824 } 00825 if (a->defval.length()!=0) 00826 { 00827 ol.docify(" = "); 00828 ol.docify(a->defval); 00829 } 00830 a=al->next(); 00831 if (a) ol.docify(", "); 00832 } 00833 ol.docify(">"); 00834 ol.pushGeneratorState(); 00835 ol.disableAllBut(OutputGenerator::Html); 00836 ol.lineBreak(); 00837 ol.popGeneratorState(); 00838 } 00839 ol.docify(type.lower()+" "+name); 00840 ol.endSubsubsection(); 00841 ol.writeString("\n"); 00842 } 00843 } 00844 00845 // write the detailed description for this class 00846 void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &pageType, bool exampleFlag) 00847 { 00848 if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || 00849 !documentation().isEmpty() || 00850 (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef()) || 00851 exampleFlag) 00852 { 00853 ol.writeRuler(); 00854 ol.pushGeneratorState(); 00855 ol.disable(OutputGenerator::Latex); 00856 ol.disable(OutputGenerator::RTF); 00857 ol.writeAnchor(0,"_details"); 00858 ol.popGeneratorState(); 00859 ol.startGroupHeader(); 00860 ol.parseText(theTranslator->trDetailedDescription()); 00861 ol.endGroupHeader(); 00862 ol.startTextBlock(); 00863 00864 writeTemplateSpec(ol,this,pageType); 00865 00866 // repeat brief description 00867 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) 00868 { 00869 ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); 00870 } 00871 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && 00872 !documentation().isEmpty()) 00873 { 00874 ol.pushGeneratorState(); 00875 ol.disable(OutputGenerator::Man); 00876 ol.disable(OutputGenerator::RTF); 00877 ol.newParagraph(); 00878 ol.enableAll(); 00879 ol.disableAllBut(OutputGenerator::Man); 00880 ol.writeString("\n\n"); 00881 ol.popGeneratorState(); 00882 } 00883 // write documentation 00884 if (!documentation().isEmpty()) 00885 { 00886 //ol.newParagraph(); 00887 ol.parseDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE); 00888 } 00889 // write type constraints 00890 writeTypeConstraints(ol,this,m_impl->typeConstraints); 00891 00892 // write examples 00893 if (exampleFlag && m_impl->exampleSDict) 00894 { 00895 ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": "); 00896 ol.writeDescItem(); 00897 ol.newParagraph(); 00898 writeExample(ol,m_impl->exampleSDict); 00899 ol.endSimpleSect(); 00900 } 00901 //ol.newParagraph(); 00902 writeSourceDef(ol,name()); 00903 ol.endTextBlock(); 00904 } 00905 else 00906 { 00907 writeTemplateSpec(ol,this,pageType); 00908 } 00909 } 00910 00911 void ClassDef::showUsedFiles(OutputList &ol) 00912 { 00913 bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); 00914 if (Config_getBool("SHOW_USED_FILES")) 00915 { 00916 ol.writeRuler(); 00917 if (fortranOpt) 00918 { 00919 ol.parseText(theTranslator->trGeneratedFromFilesFortran( 00920 m_impl->isObjC && m_impl->compType==Interface ? Class : m_impl->compType, 00921 m_impl->files.count()==1)); 00922 } 00923 else 00924 { 00925 ol.parseText(theTranslator->trGeneratedFromFiles( 00926 m_impl->isObjC && m_impl->compType==Interface ? Class : m_impl->compType, 00927 m_impl->files.count()==1)); 00928 } 00929 00930 00931 bool first=TRUE; 00932 const char *file = m_impl->files.first(); 00933 while (file) 00934 { 00935 bool ambig; 00936 FileDef *fd=findFileDef(Doxygen::inputNameDict,file,ambig); 00937 if (fd) 00938 { 00939 if (first) 00940 { 00941 first=FALSE; 00942 ol.startItemList(); 00943 } 00944 00945 ol.writeListItem(); 00946 QCString path=fd->getPath().copy(); 00947 if (Config_getBool("FULL_PATH_NAMES")) 00948 { 00949 ol.docify(stripFromPath(path)); 00950 } 00951 00952 QCString fname = fd->name(); 00953 if (!fd->getVersion().isEmpty()) // append version if available 00954 { 00955 fname += " (" + fd->getVersion() + ")"; 00956 } 00957 00958 // for HTML 00959 ol.pushGeneratorState(); 00960 ol.disableAllBut(OutputGenerator::Html); 00961 if (fd->generateSourceFile()) 00962 { 00963 ol.writeObjectLink(0,fd->getSourceFileBase(),0,fname); 00964 } 00965 else if (fd->isLinkable()) 00966 { 00967 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0, 00968 fname); 00969 } 00970 else 00971 { 00972 ol.docify(fname); 00973 } 00974 ol.popGeneratorState(); 00975 00976 // for other output formats 00977 ol.pushGeneratorState(); 00978 ol.disable(OutputGenerator::Html); 00979 if (fd->isLinkable()) 00980 { 00981 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0, 00982 fname); 00983 } 00984 else 00985 { 00986 ol.docify(fname); 00987 } 00988 00989 ol.popGeneratorState(); 00990 00991 00992 } 00993 file=m_impl->files.next(); 00994 } 00995 if (!first) ol.endItemList(); 00996 } 00997 } 00998 00999 01000 void ClassDef::writeClassDiagrams(OutputList &ol) 01001 { 01002 // count direct inheritance relations 01003 int count=0; 01004 BaseClassDef *ibcd; 01005 if (m_impl->inheritedBy) 01006 { 01007 ibcd=m_impl->inheritedBy->first(); 01008 while (ibcd) 01009 { 01010 ClassDef *icd=ibcd->classDef; 01011 if ( icd->isVisibleInHierarchy()) count++; 01012 ibcd=m_impl->inheritedBy->next(); 01013 } 01014 } 01015 if (m_impl->inherits) 01016 { 01017 ibcd=m_impl->inherits->first(); 01018 while (ibcd) 01019 { 01020 ClassDef *icd=ibcd->classDef; 01021 if ( icd->isVisibleInHierarchy()) count++; 01022 ibcd=m_impl->inherits->next(); 01023 } 01024 } 01025 01026 01027 bool renderDiagram = FALSE; 01028 if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_GRAPH")) 01029 // write class diagram using dot 01030 { 01031 DotClassGraph inheritanceGraph(this,DotNode::Inheritance); 01032 if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig()) 01033 { 01034 ol.pushGeneratorState(); 01035 ol.disable(OutputGenerator::Man); 01036 ol.startDotGraph(); 01037 ol.parseText(theTranslator->trClassDiagram(displayName())); 01038 ol.endDotGraph(inheritanceGraph); 01039 ol.popGeneratorState(); 01040 renderDiagram = TRUE; 01041 } 01042 } 01043 else if (Config_getBool("CLASS_DIAGRAMS") && count>0) 01044 // write class diagram using build-in generator 01045 { 01046 ClassDiagram diagram(this); // create a diagram of this class. 01047 ol.startClassDiagram(); 01048 ol.disable(OutputGenerator::Man); 01049 ol.parseText(theTranslator->trClassDiagram(displayName())); 01050 ol.enable(OutputGenerator::Man); 01051 ol.endClassDiagram(diagram,getOutputFileBase(),displayName()); 01052 renderDiagram = TRUE; 01053 } 01054 01055 if (renderDiagram) // if we already show the inheritance relations graphically, 01056 // then hide the text version 01057 { 01058 ol.disableAllBut(OutputGenerator::Man); 01059 } 01060 01061 if (m_impl->inherits && (count=m_impl->inherits->count())>0) 01062 { 01063 //parseText(ol,theTranslator->trInherits()+" "); 01064 01065 QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); 01066 QRegExp marker("@[0-9]+"); 01067 int index=0,newIndex,matchLen; 01068 // now replace all markers in inheritLine with links to the classes 01069 while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) 01070 { 01071 ol.parseText(inheritLine.mid(index,newIndex-index)); 01072 bool ok; 01073 uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); 01074 BaseClassDef *bcd=m_impl->inherits->at(entryIndex); 01075 if (ok && bcd) 01076 { 01077 ClassDef *cd=bcd->classDef; 01078 if (cd->isLinkable()) 01079 { 01080 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 01081 { 01082 Doxygen::tagFile << " <base"; 01083 if (bcd->prot==Protected) 01084 { 01085 Doxygen::tagFile << " protection=\"protected\""; 01086 } 01087 else if (bcd->prot==Private) 01088 { 01089 Doxygen::tagFile << " protection=\"private\""; 01090 } 01091 if (bcd->virt==Virtual) 01092 { 01093 Doxygen::tagFile << " virtualness=\"virtual\""; 01094 } 01095 Doxygen::tagFile << ">" << convertToXML(cd->name()) 01096 << "</base>" << endl; 01097 } 01098 ol.writeObjectLink(cd->getReference(), 01099 cd->getOutputFileBase(), 01100 0, 01101 cd->displayName()+bcd->templSpecifiers); 01102 } 01103 else 01104 { 01105 ol.docify(cd->displayName()); 01106 } 01107 } 01108 else 01109 { 01110 err("Error: invalid marker %d in inherits list!\n",entryIndex); 01111 } 01112 index=newIndex+matchLen; 01113 } 01114 ol.parseText(inheritLine.right(inheritLine.length()-index)); 01115 ol.newParagraph(); 01116 } 01117 01118 // write subclasses 01119 if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0) 01120 { 01121 QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); 01122 QRegExp marker("@[0-9]+"); 01123 int index=0,newIndex,matchLen; 01124 // now replace all markers in inheritLine with links to the classes 01125 while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) 01126 { 01127 ol.parseText(inheritLine.mid(index,newIndex-index)); 01128 bool ok; 01129 uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); 01130 BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); 01131 if (ok && bcd) 01132 { 01133 ClassDef *cd=bcd->classDef; 01134 if (cd->isLinkable()) 01135 { 01136 ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()); 01137 } 01138 else 01139 { 01140 ol.docify(cd->displayName()); 01141 } 01142 writeInheritanceSpecifier(ol,bcd); 01143 } 01144 index=newIndex+matchLen; 01145 } 01146 ol.parseText(inheritLine.right(inheritLine.length()-index)); 01147 ol.newParagraph(); 01148 } 01149 01150 if (renderDiagram) 01151 { 01152 ol.enableAll(); 01153 } 01154 01155 if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) 01156 { 01157 DotClassGraph usageImplGraph(this,DotNode::Collaboration); 01158 if (!usageImplGraph.isTrivial()) 01159 { 01160 ol.pushGeneratorState(); 01161 ol.disable(OutputGenerator::Man); 01162 ol.startDotGraph(); 01163 ol.parseText(theTranslator->trCollaborationDiagram(displayName())); 01164 ol.endDotGraph(usageImplGraph); 01165 ol.popGeneratorState(); 01166 } 01167 } 01168 01169 } 01170 01171 // write all documentation for this class 01172 void ClassDef::writeDocumentation(OutputList &ol) 01173 { 01174 static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); 01175 static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 01176 QCString pageType = " "; 01177 QCString pageTitle = " "; 01178 01179 pageType += compoundTypeString(); 01180 toupper(pageType.at(1)); 01181 if (fortranOpt) 01182 { 01183 pageTitle = theTranslator->trCompoundReferenceFortran(displayName(), 01184 m_impl->compType, 01185 m_impl->tempArgs != 0); 01186 } 01187 else if (vhdlOpt) 01188 { 01189 // TODO: translate 01190 pageTitle = VhdlDocGen::getClassTitle(this)+" Reference"; 01191 } 01192 else 01193 { 01194 pageTitle = theTranslator->trCompoundReference(displayName(), 01195 m_impl->compType == Interface && m_impl->isObjC ? Class : m_impl->compType, 01196 m_impl->tempArgs != 0); 01197 } 01198 01199 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ClassVisible,TRUE); 01200 if (getOuterScope()!=Doxygen::globalScope) 01201 { 01202 writeNavigationPath(ol); 01203 } 01204 ol.endQuickIndices(); 01205 ol.startContents(); 01206 startTitle(ol,getOutputFileBase()); 01207 ol.parseText(pageTitle); 01208 addGroupListToTitle(ol,this); 01209 endTitle(ol,getOutputFileBase(),name()); 01210 01211 { 01212 ol.pushGeneratorState(); 01213 ol.disableAllBut(OutputGenerator::Html); 01214 ol.writeString("<!-- doxytag: class=\""); 01215 ol.docify(name()); 01216 ol.writeString("\" -->"); 01217 if (m_impl->inherits && m_impl->inherits->count()>0) 01218 { 01219 BaseClassListIterator bli(*m_impl->inherits); 01220 ol.writeString("<!-- doxytag: inherits=\""); 01221 BaseClassDef *bcd=0; 01222 bool first=TRUE; 01223 for (bli.toFirst();(bcd=bli.current());++bli) 01224 { 01225 if (!first) ol.writeString(","); 01226 ol.docify(bcd->classDef->name()); 01227 first=FALSE; 01228 } 01229 ol.writeString("\" -->"); 01230 } 01231 ol.popGeneratorState(); 01232 } 01233 01234 01235 if (Config_getBool("SEARCHENGINE")) 01236 { 01237 Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase()); 01238 Doxygen::searchIndex->addWord(localName(),TRUE); 01239 } 01240 01241 ol.startTextBlock(); 01242 01243 //printf("Class %s brief=`%s' doc=`%s'\n",name().data(),briefDescription().data(),documentation().data()); 01244 01245 bool exampleFlag=hasExamples(); 01246 // write brief description 01247 if (!briefDescription().isEmpty()) 01248 { 01249 if (!Config_getBool("DETAILS_AT_TOP")) 01250 { 01251 ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE); 01252 ol.pushGeneratorState(); 01253 ol.disable(OutputGenerator::RTF); 01254 ol.writeString(" \n"); 01255 ol.enable(OutputGenerator::RTF); 01256 ol.disableAllBut(OutputGenerator::Html); 01257 ol.startTextLink(0,"_details"); 01258 01259 if (Config_getBool("REPEAT_BRIEF") || 01260 !documentation().isEmpty() || 01261 exampleFlag 01262 ) 01263 { 01264 ol.parseText(theTranslator->trMore()); 01265 } 01266 ol.endTextLink(); 01267 ol.popGeneratorState(); 01268 01269 ol.pushGeneratorState(); 01270 ol.disable(OutputGenerator::RTF); 01271 ol.newParagraph(); 01272 ol.popGeneratorState(); 01273 } 01274 } 01275 ol.writeSynopsis(); 01276 01277 if (m_impl->incInfo && Config_getBool("SHOW_INCLUDE_FILES")) 01278 { 01279 QCString nm=m_impl->incInfo->includeName.isEmpty() ? 01280 (m_impl->incInfo->fileDef ? 01281 m_impl->incInfo->fileDef->docName().data() : "" 01282 ) : 01283 m_impl->incInfo->includeName.data(); 01284 if (!nm.isEmpty()) 01285 { 01286 ol.startTypewriter(); 01287 bool isIDLorJava = nm.right(4)==".idl" || 01288 nm.right(5)==".pidl" || 01289 nm.right(5)==".java"; 01290 if (isIDLorJava) 01291 { 01292 ol.docify("import "); 01293 } 01294 else if (isObjectiveC()) 01295 { 01296 ol.docify("#import "); 01297 } 01298 else 01299 { 01300 ol.docify("#include "); 01301 } 01302 if (m_impl->incInfo->local || isIDLorJava) 01303 ol.docify("\""); 01304 else 01305 ol.docify("<"); 01306 ol.pushGeneratorState(); 01307 ol.disable(OutputGenerator::Html); 01308 ol.docify(nm); 01309 ol.disableAllBut(OutputGenerator::Html); 01310 ol.enable(OutputGenerator::Html); 01311 if (m_impl->incInfo->fileDef) 01312 { 01313 ol.writeObjectLink(0,m_impl->incInfo->fileDef->includeName(),0,nm); 01314 } 01315 else 01316 { 01317 ol.docify(nm); 01318 } 01319 ol.popGeneratorState(); 01320 if (m_impl->incInfo->local || isIDLorJava) 01321 ol.docify("\""); 01322 else 01323 ol.docify(">"); 01324 if (isIDLorJava) 01325 ol.docify(";"); 01326 ol.endTypewriter(); 01327 ol.newParagraph(); 01328 } 01329 } 01330 01331 01332 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 01333 { 01334 Doxygen::tagFile << " <compound kind=\"" << compoundTypeString(); 01335 Doxygen::tagFile << "\""; 01336 if (isObjectiveC()) { Doxygen::tagFile << " objc=\"yes\""; } 01337 Doxygen::tagFile << ">" << endl; 01338 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; 01339 Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl; 01340 if (m_impl->tempArgs) 01341 { 01342 ArgumentListIterator ali(*m_impl->tempArgs); 01343 Argument *a; 01344 for (;(a=ali.current());++ali) 01345 { 01346 Doxygen::tagFile << " <templarg>" << convertToXML(a->name) << "</templarg>" << endl; 01347 } 01348 } 01349 } 01350 01351 writeClassDiagrams(ol); 01352 01353 // write link to list of all members (HTML only) 01354 if (m_impl->allMemberNameInfoSDict && 01355 !Config_getBool("OPTIMIZE_OUTPUT_FOR_C") 01356 ) 01357 { 01358 ol.pushGeneratorState(); 01359 ol.disableAllBut(OutputGenerator::Html); 01360 ol.newParagraph(); 01361 ol.startTextLink(getMemberListFileName(),0); 01362 ol.parseText(theTranslator->trListOfAllMembers()); 01363 ol.endTextLink(); 01364 ol.enableAll(); 01365 ol.popGeneratorState(); 01366 } 01367 01368 ol.endTextBlock(); 01369 01370 // write detailed description if the user wants it near the top 01371 if (Config_getBool("DETAILS_AT_TOP")) 01372 { 01373 writeDetailedDescription(ol,pageType,exampleFlag); 01374 } 01375 01379 01380 // write member groups 01381 ol.startMemberSections(); 01382 01383 // write user defined member groups 01384 if (m_impl->memberGroupSDict) 01385 { 01386 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 01387 MemberGroup *mg; 01388 for (;(mg=mgli.current());++mgli) 01389 { 01390 if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section 01391 { 01392 mg->writeDeclarations(ol,this,0,0,0); 01393 } 01394 else // add this group to the corresponding member section 01395 { 01396 //printf("addToDeclarationSection(%s)\n",mg->header().data()); 01397 //mg->addToDeclarationSection(); 01398 } 01399 } 01400 } 01401 01402 // public types 01403 writeMemberDeclarations(ol,MemberList::pubTypes,theTranslator->trPublicTypes()); 01404 01405 // public methods 01406 writeMemberDeclarations(ol,MemberList::pubSlots,theTranslator->trPublicSlots()); 01407 writeMemberDeclarations(ol,MemberList::signals,theTranslator->trSignals()); 01408 writeMemberDeclarations(ol,MemberList::dcopMethods,theTranslator->trDCOPMethods()); 01409 writeMemberDeclarations(ol,MemberList::pubMethods,theTranslator->trPublicMembers()); 01410 writeMemberDeclarations(ol,MemberList::pubStaticMethods,theTranslator->trStaticPublicMembers()); 01411 01412 // public attribs 01413 writeMemberDeclarations(ol,MemberList::pubAttribs,theTranslator->trPublicAttribs()); 01414 writeMemberDeclarations(ol,MemberList::pubStaticAttribs,theTranslator->trStaticPublicAttribs()); 01415 01416 // protected types 01417 writeMemberDeclarations(ol,MemberList::proTypes,theTranslator->trProtectedTypes()); 01418 01419 // protected methods 01420 writeMemberDeclarations(ol,MemberList::proSlots,theTranslator->trProtectedSlots()); 01421 writeMemberDeclarations(ol,MemberList::proMethods,theTranslator->trProtectedMembers()); 01422 writeMemberDeclarations(ol,MemberList::proStaticMethods,theTranslator->trStaticProtectedMembers()); 01423 01424 // protected attribs 01425 writeMemberDeclarations(ol,MemberList::proAttribs,theTranslator->trProtectedAttribs()); 01426 writeMemberDeclarations(ol,MemberList::proStaticAttribs,theTranslator->trStaticProtectedAttribs()); 01427 01428 // package types 01429 writeMemberDeclarations(ol,MemberList::pacTypes,theTranslator->trPackageTypes()); 01430 01431 // package methods 01432 writeMemberDeclarations(ol,MemberList::pacMethods,theTranslator->trPackageMembers()); 01433 writeMemberDeclarations(ol,MemberList::pacStaticMethods,theTranslator->trStaticPackageMembers()); 01434 01435 // package attribs 01436 writeMemberDeclarations(ol,MemberList::pacAttribs,theTranslator->trPackageAttribs()); 01437 writeMemberDeclarations(ol,MemberList::pacStaticAttribs,theTranslator->trStaticPackageAttribs()); 01438 01439 // package 01440 writeMemberDeclarations(ol,MemberList::properties,theTranslator->trProperties()); 01441 01442 // events 01443 writeMemberDeclarations(ol,MemberList::events,theTranslator->trEvents()); 01444 01445 if (Config_getBool("EXTRACT_PRIVATE")) 01446 { 01447 // private types 01448 writeMemberDeclarations(ol,MemberList::priTypes,theTranslator->trPrivateTypes()); 01449 01450 // private members 01451 writeMemberDeclarations(ol,MemberList::priSlots,theTranslator->trPrivateSlots()); 01452 writeMemberDeclarations(ol,MemberList::priMethods,theTranslator->trPrivateMembers()); 01453 writeMemberDeclarations(ol,MemberList::priStaticMethods,theTranslator->trStaticPrivateMembers()); 01454 01455 // private attribs 01456 writeMemberDeclarations(ol,MemberList::priAttribs,theTranslator->trPrivateAttribs()); 01457 writeMemberDeclarations(ol,MemberList::priStaticAttribs,theTranslator->trStaticPrivateAttribs()); 01458 } 01459 01460 // friends 01461 writeMemberDeclarations(ol,MemberList::friends,theTranslator->trFriends()); 01462 01463 // related functions 01464 writeMemberDeclarations(ol,MemberList::related,theTranslator->trRelatedFunctions(), 01465 theTranslator->trRelatedSubscript() 01466 ); 01467 //if (related) related->writeDeclarations(ol,this,0,0,0, 01468 // theTranslator->trRelatedFunctions(), 01469 // theTranslator->trRelatedSubscript() 01470 // ); 01471 01472 // nested classes 01473 if (m_impl->innerClasses) 01474 { 01475 m_impl->innerClasses->writeDeclaration(ol,0,0,TRUE); 01476 } 01477 01478 ol.endMemberSections(); 01479 01480 // write detailed description 01481 if (!Config_getBool("DETAILS_AT_TOP")) 01482 { 01483 writeDetailedDescription(ol,pageType,exampleFlag); 01484 } 01485 01486 writeMemberDocumentation(ol); 01487 01489 ol.startTextBlock(); 01490 01491 // write the list of used files (not for man pages) 01492 ol.pushGeneratorState(); 01493 ol.disable(OutputGenerator::Man); 01494 01495 showUsedFiles(ol); 01496 01497 // write Author section (Man only) 01498 ol.enable(OutputGenerator::Man); 01499 ol.disableAllBut(OutputGenerator::Man); 01500 ol.writeString("\n"); 01501 ol.startGroupHeader(); 01502 ol.parseText(theTranslator->trAuthor(TRUE,TRUE)); 01503 ol.endGroupHeader(); 01504 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME"))); 01505 ol.popGeneratorState(); 01506 01507 ol.endTextBlock(); 01509 01510 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 01511 { 01512 writeDocAnchorsToTagFile(); 01513 Doxygen::tagFile << " </compound>" << endl; 01514 } 01515 01516 endFile(ol); 01517 01518 if (Config_getBool("SEPARATE_MEMBER_PAGES")) 01519 { 01520 writeMemberPages(ol); 01521 } 01522 } 01523 01524 void ClassDef::writeMemberDocumentation(OutputList &ol) 01525 { 01529 bool fortranOpt=Config_getBool("OPTIMIZE_FOR_FORTRAN"); 01530 01531 if (Config_getBool("SEPARATE_MEMBER_PAGES")) 01532 { 01533 ol.disable(OutputGenerator::Html); 01534 Doxygen::suppressDocWarnings = TRUE; 01535 } 01536 01537 writeMemberDocumentation(ol,MemberList::typedefMembers,theTranslator->trMemberTypedefDocumentation()); 01538 writeMemberDocumentation(ol,MemberList::enumMembers,theTranslator->trMemberEnumerationDocumentation()); 01539 writeMemberDocumentation(ol,MemberList::constructors,theTranslator->trConstructorDocumentation()); 01540 if (fortranOpt) 01541 { 01542 writeMemberDocumentation(ol,MemberList::functionMembers,theTranslator->trMemberFunctionDocumentationFortran()); 01543 } 01544 else 01545 { 01546 writeMemberDocumentation(ol,MemberList::functionMembers,theTranslator->trMemberFunctionDocumentation()); 01547 } 01548 writeMemberDocumentation(ol,MemberList::relatedMembers,theTranslator->trRelatedFunctionDocumentation()); 01549 writeMemberDocumentation(ol,MemberList::variableMembers,theTranslator->trMemberDataDocumentation()); 01550 writeMemberDocumentation(ol,MemberList::propertyMembers,theTranslator->trPropertyDocumentation()); 01551 writeMemberDocumentation(ol,MemberList::eventMembers,theTranslator->trEventDocumentation()); 01552 01553 if (Config_getBool("SEPARATE_MEMBER_PAGES")) 01554 { 01555 ol.enable(OutputGenerator::Html); 01556 Doxygen::suppressDocWarnings = FALSE; 01557 } 01558 } 01559 01560 void ClassDef::writeMemberPages(OutputList &ol) 01561 { 01565 01566 ol.pushGeneratorState(); 01567 ol.disableAllBut(OutputGenerator::Html); 01568 01569 QListIterator<MemberList> mli(m_impl->memberLists); 01570 MemberList *ml; 01571 for (mli.toFirst();(ml=mli.current());++mli) 01572 { 01573 if (ml->listType()&MemberList::detailedLists) 01574 { 01575 ml->writeDocumentationPage(ol,name(),this); 01576 } 01577 } 01578 01579 ol.popGeneratorState(); 01580 } 01581 01582 void ClassDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const 01583 { 01584 static bool createSubDirs=Config_getBool("CREATE_SUBDIRS"); 01585 01586 ol.writeString(" <div class=\"navtab\">\n"); 01587 ol.writeString(" <table>\n"); 01588 01589 if (m_impl->allMemberNameInfoSDict) 01590 { 01591 MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); 01592 MemberNameInfo *mni; 01593 for (;(mni=mnili.current());++mnili) 01594 { 01595 MemberNameInfoIterator mnii(*mni); 01596 MemberInfo *mi; 01597 for (mnii.toFirst();(mi=mnii.current());++mnii) 01598 { 01599 MemberDef *md=mi->memberDef; 01600 if (md->getClassDef()==this && md->isLinkable()) 01601 { 01602 ol.writeString(" <tr><td class=\"navtab\">"); 01603 if (md->isLinkableInProject()) 01604 { 01605 if (md==currentMd) // selected item => highlight 01606 { 01607 ol.writeString("<a class=\"qindexHL\" "); 01608 } 01609 else 01610 { 01611 ol.writeString("<a class=\"qindex\" "); 01612 } 01613 ol.writeString("href=\""); 01614 if (createSubDirs) ol.writeString("../../"); 01615 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); 01616 ol.writeString("\">"); 01617 ol.writeString(md->name()); 01618 ol.writeString("</a>"); 01619 } 01620 ol.writeString("</td></tr>\n"); 01621 } 01622 } 01623 } 01624 } 01625 01626 ol.writeString(" </table>\n"); 01627 ol.writeString(" </div>\n"); 01628 } 01629 01630 01631 01632 void ClassDef::writeDocumentationForInnerClasses(OutputList &ol) 01633 { 01634 // write inner classes after the parent, so the tag files contain 01635 // the definition in proper order! 01636 if (m_impl->innerClasses) 01637 { 01638 ClassSDict::Iterator cli(*m_impl->innerClasses); 01639 ClassDef *innerCd; 01640 for (cli.toFirst();(innerCd=cli.current());++cli) 01641 { 01642 if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && 01643 (innerCd->protection()!=Private || Config_getBool("EXTRACT_PRIVATE")) 01644 ) 01645 { 01646 msg("Generating docs for nested compound %s...\n",innerCd->name().data()); 01647 innerCd->writeDocumentation(ol); 01648 innerCd->writeMemberList(ol); 01649 } 01650 innerCd->writeDocumentationForInnerClasses(ol); 01651 } 01652 } 01653 } 01654 01655 // write the list of all (inherited) members for this class 01656 void ClassDef::writeMemberList(OutputList &ol) 01657 { 01658 static bool cOpt = Config_getBool("OPTIMIZE_OUTPUT_FOR_C"); 01659 static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 01660 if (m_impl->allMemberNameInfoSDict==0 || cOpt) return; 01661 // only for HTML 01662 ol.pushGeneratorState(); 01663 ol.disableAllBut(OutputGenerator::Html); 01664 01665 QCString memListFile = getMemberListFileName(); 01666 startFile(ol,memListFile,memListFile, 01667 theTranslator->trMemberList(),HLI_ClassVisible); 01668 startTitle(ol,0); 01669 ol.parseText(displayName()+" "+theTranslator->trMemberList()); 01670 endTitle(ol,0,0); 01671 ol.parseText(theTranslator->trThisIsTheListOfAllMembers()); 01672 ol.writeObjectLink(getReference(),getOutputFileBase(),0,displayName()); 01673 ol.parseText(theTranslator->trIncludingInheritedMembers()); 01674 01675 //ol.startItemList(); 01676 ol.writeString("<p><table>\n"); 01677 01678 //MemberNameInfo *mni=m_impl->allMemberNameInfoList->first(); 01679 MemberNameInfoSDict::Iterator mnii(*m_impl->allMemberNameInfoSDict); 01680 MemberNameInfo *mni; 01681 for (mnii.toFirst();(mni=mnii.current());++mnii) 01682 { 01683 MemberInfo *mi=mni->first(); 01684 while (mi) 01685 { 01686 MemberDef *md=mi->memberDef; 01687 ClassDef *cd=md->getClassDef(); 01688 Protection prot = mi->prot; 01689 Specifier virt=md->virtualness(); 01690 01691 //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n", 01692 // name().data(),md->name().data(),cd->name().data(),md->protection(),mi->prot,prot,mi->inherited); 01693 01694 01695 if (cd && !md->name().isEmpty() && md->name()[0]!='@') 01696 { 01697 bool memberWritten=FALSE; 01698 if (cd->isLinkable() && md->isLinkable()) 01699 // create a link to the documentation 01700 { 01701 QCString name=mi->ambiguityResolutionScope+md->name(); 01702 //ol.writeListItem(); 01703 ol.writeString(" <tr class=\"memlist\"><td>"); 01704 if (cd->isObjectiveC()) 01705 { 01706 if (md->isObjCMethod()) 01707 { 01708 if (md->isStatic()) 01709 ol.writeString("+ </td><td>"); 01710 else 01711 ol.writeString("- </td><td>"); 01712 } 01713 else 01714 ol.writeString("</td><td>"); 01715 } 01716 if (md->isObjCMethod()) 01717 { 01718 ol.writeObjectLink(md->getReference(), 01719 md->getOutputFileBase(), 01720 md->anchor(),md->name()); 01721 } 01722 else 01723 { 01724 //Definition *bd = md->getGroupDef(); 01725 //if (bd==0) bd=cd; 01726 ol.writeObjectLink(md->getReference(), 01727 md->getOutputFileBase(), 01728 md->anchor(),name); 01729 01730 if ( md->isFunction() || md->isSignal() || md->isSlot() || 01731 (md->isFriend() && md->argsString())) 01732 ol.docify(md->argsString()); 01733 else if (md->isEnumerate()) 01734 ol.parseText(" "+theTranslator->trEnumName()); 01735 else if (md->isEnumValue()) 01736 ol.parseText(" "+theTranslator->trEnumValue()); 01737 else if (md->isTypedef()) 01738 ol.docify(" typedef"); 01739 else if (md->isFriend() && !strcmp(md->typeString(),"friend class")) 01740 ol.docify(" class"); 01741 //ol.writeString("\n"); 01742 } 01743 ol.writeString("</td>"); 01744 memberWritten=TRUE; 01745 } 01746 else if (!Config_getBool("HIDE_UNDOC_MEMBERS") && 01747 (md->protection()!=Private || Config_getBool("EXTRACT_PRIVATE") || md->isFriend()) 01748 ) // no documentation, 01749 // generate link to the class instead. 01750 { 01751 //ol.writeListItem(); 01752 ol.writeString(" <tr bgcolor=\"#f0f0f0\"><td>"); 01753 if (cd->isObjectiveC()) 01754 { 01755 if (md->isObjCMethod()) 01756 { 01757 if (md->isStatic()) 01758 ol.writeString("+ </td><td>"); 01759 else 01760 ol.writeString("- </td><td>"); 01761 } 01762 else 01763 ol.writeString("</td><td>"); 01764 } 01765 ol.startBold(); 01766 ol.docify(md->name()); 01767 ol.endBold(); 01768 if (!md->isObjCMethod()) 01769 { 01770 if ( md->isFunction() || md->isSignal() || md->isSlot() ) 01771 ol.docify(md->argsString()); 01772 else if (md->isEnumerate()) 01773 ol.parseText(" "+theTranslator->trEnumName()); 01774 else if (md->isEnumValue()) 01775 ol.parseText(" "+theTranslator->trEnumValue()); 01776 else if (md->isTypedef()) 01777 ol.docify(" typedef"); 01778 } 01779 ol.writeString(" ("); 01780 ol.parseText(theTranslator->trDefinedIn()+" "); 01781 if (cd->isLinkable()) 01782 { 01783 ol.writeObjectLink( 01784 cd->getReference(), 01785 cd->getOutputFileBase(), 01786 0, 01787 cd->displayName()); 01788 } 01789 else 01790 { 01791 ol.startBold(); 01792 ol.docify(cd->displayName()); 01793 ol.endBold(); 01794 } 01795 ol.writeString(")"); 01796 ol.writeString("</td>"); 01797 memberWritten=TRUE; 01798 } 01799 if (memberWritten) 01800 { 01801 ol.writeString("<td>"); 01802 ol.writeObjectLink(cd->getReference(), 01803 cd->getOutputFileBase(), 01804 0, 01805 cd->displayName()); 01806 ol.writeString("</td>"); 01807 ol.writeString("<td>"); 01808 } 01809 if ( 01810 (prot!=Public || (virt!=Normal && !m_impl->isObjC) || 01811 md->isFriend() || md->isRelated() || md->isExplicit() || 01812 md->isMutable() || (md->isInline() && Config_getBool("INLINE_INFO")) || 01813 md->isSignal() || md->isSlot() || 01814 md->isStatic() || vhdlOpt 01815 ) 01816 && memberWritten) 01817 { 01818 ol.startTypewriter(); 01819 ol.docify(" ["); 01820 QStrList sl; 01821 if (vhdlOpt) sl.append(VhdlDocGen::trVhdlType( 01822 md->getMemberSpecifiers())); //append vhdl type 01823 else if (md->isFriend()) sl.append("friend"); 01824 else if (md->isRelated()) sl.append("related"); 01825 else 01826 { 01827 if (Config_getBool("INLINE_INFO") && md->isInline()) 01828 sl.append("inline"); 01829 if (md->isExplicit()) sl.append("explicit"); 01830 if (md->isMutable()) sl.append("mutable"); 01831 if (prot==Protected) sl.append("protected"); 01832 else if (prot==Private) sl.append("private"); 01833 else if (prot==Package) sl.append("package"); 01834 if (virt==Virtual && 01835 !m_impl->isObjC) sl.append("virtual"); 01836 else if (virt==Pure) sl.append("pure virtual"); 01837 if (md->isStatic()) sl.append("static"); 01838 if (md->isSignal()) sl.append("signal"); 01839 if (md->isSlot()) sl.append("slot"); 01840 } 01841 const char *s=sl.first(); 01842 while (s) 01843 { 01844 ol.docify(s); 01845 s=sl.next(); 01846 if (s) ol.docify(", "); 01847 } 01848 ol.docify("]"); 01849 ol.endTypewriter(); 01850 } 01851 if (memberWritten) 01852 { 01853 ol.writeString("</td>"); 01854 ol.writeString("</tr>\n"); 01855 } 01856 } 01857 mi=mni->next(); 01858 } 01859 } 01860 //ol.endItemList(); 01861 01862 ol.writeString("</table>"); 01863 01864 endFile(ol); 01865 ol.popGeneratorState(); 01866 } 01867 01868 01869 // add a reference to an example 01870 bool ClassDef::addExample(const char *anchor,const char *nameStr, 01871 const char *file) 01872 { 01873 if (m_impl->exampleSDict==0) 01874 { 01875 m_impl->exampleSDict = new ExampleSDict; 01876 m_impl->exampleSDict->setAutoDelete(TRUE); 01877 } 01878 if (!m_impl->exampleSDict->find(nameStr)) 01879 { 01880 Example *e=new Example; 01881 e->anchor=anchor; 01882 e->name=nameStr; 01883 e->file=file; 01884 m_impl->exampleSDict->inSort(nameStr,e); 01885 return TRUE; 01886 } 01887 return FALSE; 01888 } 01889 01890 // returns TRUE if this class is used in an example 01891 bool ClassDef::hasExamples() 01892 { 01893 if (m_impl->exampleSDict==0) 01894 return FALSE; 01895 else 01896 return m_impl->exampleSDict->count()>0; 01897 } 01898 01899 01900 void ClassDef::setTemplateArguments(ArgumentList *al) 01901 { 01902 if (al==0) return; 01903 if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed 01904 m_impl->tempArgs=new ArgumentList; 01905 ArgumentListIterator ali(*al); 01906 Argument *a; 01907 for (;(a=ali.current());++ali) 01908 { 01909 m_impl->tempArgs->append(new Argument(*a)); 01910 } 01911 } 01912 01913 void ClassDef::setTypeConstraints(ArgumentList *al) 01914 { 01915 if (al==0) return; 01916 if (!m_impl->typeConstraints) delete m_impl->typeConstraints; 01917 m_impl->typeConstraints = new ArgumentList; 01918 ArgumentListIterator ali(*al); 01919 Argument *a; 01920 for (;(a=ali.current());++ali) 01921 { 01922 m_impl->typeConstraints->append(new Argument(*a)); 01923 } 01924 } 01925 01929 bool ClassDef::hasNonReferenceSuperClass() 01930 { 01931 bool found=!isReference() && isLinkableInProject() && !isHidden(); 01932 if (found) 01933 { 01934 return TRUE; // we're done if this class is not a reference 01935 } 01936 if (m_impl->inheritedBy) 01937 { 01938 BaseClassListIterator bcli(*m_impl->inheritedBy); 01939 for ( ; bcli.current() && !found ; ++bcli ) // for each super class 01940 { 01941 ClassDef *bcd=bcli.current()->classDef; 01942 // recurse into the super class branch 01943 found = found || bcd->hasNonReferenceSuperClass(); 01944 if (!found) 01945 { 01946 // look for template instances that might have non-reference super classes 01947 QDict<ClassDef> *cil = bcd->getTemplateInstances(); 01948 if (cil) 01949 { 01950 QDictIterator<ClassDef> tidi(*cil); 01951 for ( ; tidi.current() && !found ; ++tidi) // for each template instance 01952 { 01953 // recurse into the template instance branch 01954 found = found || tidi.current()->hasNonReferenceSuperClass(); 01955 } 01956 } 01957 } 01958 } 01959 } 01960 return found; 01961 } 01962 01966 void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup) 01967 { 01968 //ol.insertMemberAlign(); 01969 //printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup); 01970 01971 //if (inGroup && md && md->getClassDef()==this) return; 01972 01973 ol.docify(compoundTypeString()); 01974 int ri=name().findRev("::"); 01975 if (ri==-1) ri=name().length(); 01976 QCString cn=name().right(name().length()-ri-2); 01977 if (!cn.isEmpty() && cn.at(0)!='@' && md) 01978 { 01979 ol.docify(" "); 01980 if (isLinkable()) 01981 { 01982 ol.writeObjectLink(0,0,md->anchor(),cn); 01983 } 01984 else 01985 { 01986 ol.startBold(); 01987 ol.docify(cn); 01988 ol.endBold(); 01989 } 01990 } 01991 ol.docify(" {"); 01992 ol.endMemberItem(); 01993 01994 // write user defined member groups 01995 if (m_impl->memberGroupSDict) 01996 { 01997 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 01998 MemberGroup *mg; 01999 for (;(mg=mgli.current());++mgli) 02000 { 02001 mg->setInGroup(inGroup); 02002 mg->writePlainDeclarations(ol,this,0,0,0); 02003 } 02004 } 02005 02006 writePlainMemberDeclaration(ol,MemberList::pubTypes,inGroup); 02007 writePlainMemberDeclaration(ol,MemberList::pubMethods,inGroup); 02008 writePlainMemberDeclaration(ol,MemberList::pubAttribs,inGroup); 02009 writePlainMemberDeclaration(ol,MemberList::pubSlots,inGroup); 02010 writePlainMemberDeclaration(ol,MemberList::signals,inGroup); 02011 writePlainMemberDeclaration(ol,MemberList::dcopMethods,inGroup); 02012 writePlainMemberDeclaration(ol,MemberList::properties,inGroup); 02013 writePlainMemberDeclaration(ol,MemberList::events,inGroup); 02014 writePlainMemberDeclaration(ol,MemberList::pubStaticMethods,inGroup); 02015 writePlainMemberDeclaration(ol,MemberList::pubStaticAttribs,inGroup); 02016 writePlainMemberDeclaration(ol,MemberList::proTypes,inGroup); 02017 writePlainMemberDeclaration(ol,MemberList::proMethods,inGroup); 02018 writePlainMemberDeclaration(ol,MemberList::proAttribs,inGroup); 02019 writePlainMemberDeclaration(ol,MemberList::proSlots,inGroup); 02020 writePlainMemberDeclaration(ol,MemberList::proStaticMethods,inGroup); 02021 writePlainMemberDeclaration(ol,MemberList::proStaticAttribs,inGroup); 02022 writePlainMemberDeclaration(ol,MemberList::pacTypes,inGroup); 02023 writePlainMemberDeclaration(ol,MemberList::pacMethods,inGroup); 02024 writePlainMemberDeclaration(ol,MemberList::pacAttribs,inGroup); 02025 writePlainMemberDeclaration(ol,MemberList::pacStaticMethods,inGroup); 02026 writePlainMemberDeclaration(ol,MemberList::pacStaticAttribs,inGroup); 02027 if (Config_getBool("EXTRACT_PRIVATE")) 02028 { 02029 writePlainMemberDeclaration(ol,MemberList::priTypes,inGroup); 02030 writePlainMemberDeclaration(ol,MemberList::priMethods,inGroup); 02031 writePlainMemberDeclaration(ol,MemberList::priAttribs,inGroup); 02032 writePlainMemberDeclaration(ol,MemberList::priSlots,inGroup); 02033 writePlainMemberDeclaration(ol,MemberList::priStaticMethods,inGroup); 02034 writePlainMemberDeclaration(ol,MemberList::priStaticAttribs,inGroup); 02035 } 02036 writePlainMemberDeclaration(ol,MemberList::friends,inGroup); 02037 writePlainMemberDeclaration(ol,MemberList::related,inGroup); 02038 } 02039 02041 bool ClassDef::isLinkableInProject() const 02042 { 02043 if (m_impl->templateMaster) 02044 { 02045 return m_impl->templateMaster->isLinkableInProject(); 02046 } 02047 else 02048 { 02049 return !name().isEmpty() && /* no name */ 02050 !isArtificial() && !isHidden() && 02051 name().find('@')==-1 && /* anonymous compound */ 02052 (m_impl->prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && /* private */ 02053 (!m_impl->isLocal || Config_getBool("EXTRACT_LOCAL_CLASSES")) && /* local */ 02054 hasDocumentation() && /* documented */ 02055 !isReference() && /* not an external reference */ 02056 (!m_impl->isStatic || Config_getBool("EXTRACT_STATIC")); 02057 } 02058 } 02059 02060 bool ClassDef::isLinkable() const 02061 { 02062 if (m_impl->templateMaster) 02063 { 02064 return m_impl->templateMaster->isLinkable(); 02065 } 02066 else 02067 { 02068 return isLinkableInProject() || isReference(); 02069 } 02070 } 02071 02072 02074 bool ClassDef::isVisibleInHierarchy() 02075 { 02076 static bool allExternals = Config_getBool("ALLEXTERNALS"); 02077 static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); 02078 static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES"); 02079 static bool extractStatic = Config_getBool("EXTRACT_STATIC"); 02080 02081 return // show all classes or a subclass is visible 02082 (allExternals || hasNonReferenceSuperClass()) && 02083 // and not an annonymous compound 02084 name().find('@')==-1 && 02085 // not an artifically introduced class 02086 !isArtificial() && 02087 // and not privately inherited 02088 (m_impl->prot!=Private || extractPrivate) && 02089 // documented or shown anyway or documentation is external 02090 (hasDocumentation() || 02091 !hideUndocClasses || 02092 (m_impl->templateMaster && m_impl->templateMaster->hasDocumentation()) || 02093 isReference() 02094 ) && 02095 // is not part of an unnamed namespace or shown anyway 02096 (!m_impl->isStatic || extractStatic); 02097 } 02098 02099 bool ClassDef::hasDocumentation() const 02100 { 02101 return Definition::hasDocumentation(); 02102 } 02103 02104 //---------------------------------------------------------------------- 02105 // recursive function: 02106 // returns TRUE iff class definition `bcd' represents an (in)direct base 02107 // class of class definition `cd'. 02108 02109 bool ClassDef::isBaseClass(ClassDef *bcd, bool followInstances,int level) 02110 { 02111 bool found=FALSE; 02112 //printf("isBaseClass(cd=%s) looking for %s\n",cd->name().data(),bcd->name().data()); 02113 if (level>256) 02114 { 02115 err("Possible recursive class relation while inside %s and looking for %s\n",name().data(),bcd->name().data()); 02116 abort(); 02117 return FALSE; 02118 } 02119 if (baseClasses()) 02120 { 02121 BaseClassListIterator bcli(*baseClasses()); 02122 for ( ; bcli.current() && !found ; ++bcli) 02123 { 02124 ClassDef *ccd=bcli.current()->classDef; 02125 if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); 02126 //printf("isBaseClass() baseclass %s\n",ccd->name().data()); 02127 if (ccd==bcd) 02128 found=TRUE; 02129 else 02130 found=ccd->isBaseClass(bcd,followInstances,level+1); 02131 } 02132 } 02133 return found; 02134 } 02135 02136 //---------------------------------------------------------------------------- 02137 02138 static bool isStandardFunc(MemberDef *md) 02139 { 02140 return md->name()=="operator=" || // assignment operator 02141 md->isConstructor() || // constructor 02142 md->isDestructor(); // destructor 02143 } 02144 02151 void ClassDef::mergeMembers() 02152 { 02153 if (m_impl->membersMerged) return; 02154 02155 static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); 02156 static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 02157 QCString sep="::"; 02158 if (optimizeOutputForJava || vhdlOpt) sep="."; 02159 int sepLen = sep.length(); 02160 02161 m_impl->membersMerged=TRUE; 02162 //printf(" mergeMembers for %s\n",name().data()); 02163 bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB" ); 02164 if (baseClasses()) 02165 { 02166 //printf(" => has base classes!\n"); 02167 BaseClassListIterator bcli(*baseClasses()); 02168 BaseClassDef *bcd; 02169 for ( ; (bcd=bcli.current()) ; ++bcli ) 02170 { 02171 ClassDef *bClass=bcd->classDef; 02172 02173 // merge the members in the base class of this inheritance branch first 02174 bClass->mergeMembers(); 02175 02176 MemberNameInfoSDict *srcMnd = bClass->memberNameInfoSDict(); 02177 MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; 02178 02179 if (srcMnd) 02180 { 02181 MemberNameInfoSDict::Iterator srcMnili(*srcMnd); 02182 MemberNameInfo *srcMni; 02183 for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) 02184 { 02185 //printf(" Base member name %s\n",srcMni->memberName()); 02186 MemberNameInfo *dstMni; 02187 if (dstMnd!=0 && (dstMni=dstMnd->find(srcMni->memberName()))) 02188 // a member with that name is already in the class. 02189 // the member may hide or reimplement the one in the sub class 02190 // or there may be another path to the base class that is already 02191 // visited via another branch in the class hierarchy. 02192 { 02193 MemberNameInfoIterator srcMnii(*srcMni); 02194 MemberInfo *srcMi; 02195 for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) 02196 { 02197 MemberDef *srcMd = srcMi->memberDef; 02198 bool found=FALSE; 02199 bool ambigue=FALSE; 02200 bool hidden=FALSE; 02201 MemberNameInfoIterator dstMnii(*dstMni); 02202 MemberInfo *dstMi; 02203 ClassDef *srcCd = srcMd->getClassDef(); 02204 for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii ) 02205 { 02206 MemberDef *dstMd = dstMi->memberDef; 02207 if (srcMd!=dstMd) // different members 02208 { 02209 ClassDef *dstCd = dstMd->getClassDef(); 02210 //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); 02211 if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) 02212 // member is in the same or a base class 02213 { 02214 LockingPtr<ArgumentList> srcAl = srcMd->argumentList(); 02215 LockingPtr<ArgumentList> dstAl = dstMd->argumentList(); 02216 found=matchArguments2( 02217 srcMd->getOuterScope(),srcMd->getFileDef(),srcAl.pointer(), 02218 dstMd->getOuterScope(),dstMd->getFileDef(),dstAl.pointer(), 02219 TRUE 02220 ); 02221 //printf(" Yes, matching (%s<->%s): %d\n", 02222 // argListToString(srcMd->argumentList()).data(), 02223 // argListToString(dstMd->argumentList()).data(), 02224 // found); 02225 hidden = hidden || !found; 02226 } 02227 else // member is in a non base class => multiple inheritance 02228 // using the same base class. 02229 { 02230 //printf("$$ Existing member %s %s add scope %s\n", 02231 // dstMi->ambiguityResolutionScope.data(), 02232 // dstMd->name().data(), 02233 // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); 02234 02235 QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen); 02236 if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) 02237 dstMi->ambiguityResolutionScope.prepend(scope); 02238 ambigue=TRUE; 02239 } 02240 } 02241 else // same members 02242 { 02243 // do not add if base class is virtual or 02244 // if scope paths are equal or 02245 // if base class is an interface (and thus implicitly virtual). 02246 //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt); 02247 if ((srcMi->virt!=Normal && dstMi->virt!=Normal) || 02248 bClass->name()+sep+srcMi->scopePath == dstMi->scopePath || 02249 dstMd->getClassDef()->compoundType()==Interface 02250 ) 02251 { 02252 found=TRUE; 02253 } 02254 else // member can be reached via multiple paths in the 02255 // inheritance tree 02256 { 02257 //printf("$$ Existing member %s %s add scope %s\n", 02258 // dstMi->ambiguityResolutionScope.data(), 02259 // dstMd->name().data(), 02260 // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); 02261 02262 QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen); 02263 if (scope!=dstMi->ambiguityResolutionScope.left(scope.length())) 02264 { 02265 dstMi->ambiguityResolutionScope.prepend(scope); 02266 } 02267 ambigue=TRUE; 02268 } 02269 } 02270 } 02271 //printf("member %s::%s hidden %d ambigue %d srcMi->ambigClass=%p\n", 02272 // srcCd->name().data(),srcMd->name().data(),hidden,ambigue,srcMi->ambigClass); 02273 02274 // TODO: fix the case where a member is hidden by inheritance 02275 // of a member with the same name but with another prototype, 02276 // while there is more than one path to the member in the 02277 // base class due to multiple inheritance. In this case 02278 // it seems that the member is not reachable by prefixing a 02279 // scope name either (according to my compiler). Currently, 02280 // this case is shown anyway. 02281 if (!found && srcMd->protection()!=Private) 02282 { 02283 Protection prot=srcMd->protection(); 02284 if (bcd->prot==Protected && prot==Public) prot=bcd->prot; 02285 else if (bcd->prot==Private) prot=bcd->prot; 02286 02287 if (inlineInheritedMembers) 02288 { 02289 if (!isStandardFunc(srcMd)) 02290 { 02291 //printf(" insertMember `%s'\n",srcMd->name().data()); 02292 internalInsertMember(srcMd,prot,FALSE); 02293 } 02294 } 02295 02296 Specifier virt=srcMi->virt; 02297 if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; 02298 02299 MemberInfo *newMi = new MemberInfo(srcMd,prot,virt,TRUE); 02300 newMi->scopePath=bClass->name()+sep+srcMi->scopePath; 02301 if (ambigue) 02302 { 02303 //printf("$$ New member %s %s add scope %s::\n", 02304 // srcMi->ambiguityResolutionScope.data(), 02305 // srcMd->name().data(), 02306 // bClass->name().data()); 02307 02308 QCString scope=bClass->name()+sep; 02309 if (scope!=srcMi->ambiguityResolutionScope.left(scope.length())) 02310 { 02311 newMi->ambiguityResolutionScope= 02312 scope+srcMi->ambiguityResolutionScope.copy(); 02313 } 02314 } 02315 if (hidden) 02316 { 02317 if (srcMi->ambigClass==0) 02318 { 02319 newMi->ambigClass=bClass; 02320 newMi->ambiguityResolutionScope=bClass->name()+sep; 02321 } 02322 else 02323 { 02324 newMi->ambigClass=srcMi->ambigClass; 02325 newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+sep; 02326 } 02327 } 02328 dstMni->append(newMi); 02329 } 02330 } 02331 } 02332 else // base class has a member that is not in the sub class => copy 02333 { 02334 // create a deep copy of the list (only the MemberInfo's will be 02335 // copied, not the actual MemberDef's) 02336 MemberNameInfo *newMni = 0; 02337 newMni = new MemberNameInfo(srcMni->memberName()); 02338 02339 // copy the member(s) from the base to the sub class 02340 MemberNameInfoIterator mnii(*srcMni); 02341 MemberInfo *mi; 02342 for (;(mi=mnii.current());++mnii) 02343 { 02344 Protection prot = mi->prot; 02345 if (bcd->prot==Protected) 02346 { 02347 if (prot==Public) prot=Protected; 02348 } 02349 else if (bcd->prot==Private) 02350 { 02351 prot=Private; 02352 } 02353 //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", 02354 // name().data(),mi->memberDef->name().data(),mi->prot, 02355 // bcd->prot,prot); 02356 02357 if (mi->prot!=Private) 02358 { 02359 Specifier virt=mi->virt; 02360 if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; 02361 02362 if (inlineInheritedMembers) 02363 { 02364 if (!isStandardFunc(mi->memberDef)) 02365 { 02366 //printf(" insertMember `%s'\n",mi->memberDef->name().data()); 02367 internalInsertMember(mi->memberDef,prot,FALSE); 02368 } 02369 } 02370 //printf("Adding!\n"); 02371 MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE); 02372 newMi->scopePath=bClass->name()+sep+mi->scopePath; 02373 newMi->ambigClass=mi->ambigClass; 02374 newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy(); 02375 newMni->append(newMi); 02376 } 02377 } 02378 02379 if (dstMnd==0) 02380 { 02381 m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17); 02382 m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE); 02383 dstMnd = m_impl->allMemberNameInfoSDict; 02384 } 02385 // add it to the dictionary 02386 dstMnd->append(newMni->memberName(),newMni); 02387 } 02388 } 02389 } 02390 } 02391 } 02392 //printf(" end mergeMembers\n"); 02393 } 02394 02395 //---------------------------------------------------------------------------- 02396 02399 void ClassDef::mergeCategory(ClassDef *category) 02400 { 02401 category->setCategoryOf(this); 02402 02403 MemberNameInfoSDict *srcMnd = category->memberNameInfoSDict(); 02404 MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; 02405 02406 if (srcMnd && dstMnd) 02407 { 02408 MemberNameInfoSDict::Iterator srcMnili(*srcMnd); 02409 MemberNameInfo *srcMni; 02410 for ( ; (srcMni=srcMnili.current()) ; ++srcMnili) 02411 { 02412 MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName()); 02413 if (dstMni) // method is already defined in the class 02414 { 02415 // TODO: we should remove the other member and insert this one. 02416 } 02417 else // new method name 02418 { 02419 // create a deep copy of the list (only the MemberInfo's will be 02420 // copied, not the actual MemberDef's) 02421 MemberNameInfo *newMni = 0; 02422 newMni = new MemberNameInfo(srcMni->memberName()); 02423 02424 // copy the member(s) from the category to this class 02425 MemberNameInfoIterator mnii(*srcMni); 02426 MemberInfo *mi; 02427 for (;(mi=mnii.current());++mnii) 02428 { 02429 //printf("Adding!\n"); 02430 MemberInfo *newMi=new MemberInfo(mi->memberDef,mi->prot,mi->virt,mi->inherited); 02431 newMi->scopePath=mi->scopePath; 02432 newMi->ambigClass=mi->ambigClass; 02433 newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy(); 02434 newMni->append(newMi); 02435 } 02436 02437 // add it to the dictionary 02438 dstMnd->append(newMni->memberName(),newMni); 02439 } 02440 } 02441 } 02442 } 02443 02444 //---------------------------------------------------------------------------- 02445 02446 void ClassDef::addUsedClass(ClassDef *cd,const char *accessName) 02447 { 02448 //printf("%s::addUsedClass(%s,%s)\n",name().data(),cd->name().data(),accessName); 02449 if (m_impl->usesImplClassDict==0) 02450 { 02451 m_impl->usesImplClassDict = new UsesClassDict(17); 02452 m_impl->usesImplClassDict->setAutoDelete(TRUE); 02453 } 02454 UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name()); 02455 if (ucd==0) 02456 { 02457 ucd = new UsesClassDef(cd); 02458 m_impl->usesImplClassDict->insert(cd->name(),ucd); 02459 //printf("Adding used class %s to class %s\n", 02460 // cd->name().data(),name().data()); 02461 } 02462 ucd->addAccessor(accessName); 02463 } 02464 02465 void ClassDef::addUsedByClass(ClassDef *cd,const char *accessName) 02466 { 02467 if (m_impl->usedByImplClassDict==0) 02468 { 02469 m_impl->usedByImplClassDict = new UsesClassDict(17); 02470 m_impl->usedByImplClassDict->setAutoDelete(TRUE); 02471 } 02472 UsesClassDef *ucd=m_impl->usedByImplClassDict->find(cd->name()); 02473 if (ucd==0) 02474 { 02475 ucd = new UsesClassDef(cd); 02476 m_impl->usedByImplClassDict->insert(cd->name(),ucd); 02477 //printf("Adding used by class %s to class %s\n", 02478 // cd->name().data(),name().data()); 02479 } 02480 ucd->addAccessor(accessName); 02481 } 02482 02483 02484 #if 0 02485 02490 void ClassDef::determineImplUsageRelation() 02491 { 02492 MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); 02493 MemberNameInfo *mni; 02494 for (;(mni=mnili.current());++mnili) 02495 { 02496 MemberNameInfoIterator mnii(*mni); 02497 MemberInfo *mi; 02498 for (mnii.toFirst();(mi=mnii.current());++mnii) 02499 { 02500 MemberDef *md=mi->memberDef; 02501 if (md->isVariable()) // for each member variable in this class 02502 { 02503 QCString type=removeRedundantWhiteSpace(md->typeString()); 02504 //printf("in class %s found var type=`%s' name=`%s'\n", 02505 // name().data(),type.data(),md->name().data()); 02506 int pos=0; 02507 QCString usedClassName; 02508 QCString templSpec; 02509 bool found=FALSE; 02510 while (extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1 && !found) 02511 { 02512 //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data()); 02513 // check if usedClassName is a template argument of its class 02514 ClassDef *cd=md->getClassDef(); 02515 if (cd && cd->templateArguments()) 02516 { 02517 ArgumentListIterator ali(*cd->templateArguments()); 02518 Argument *arg; 02519 int count=0; 02520 for (ali.toFirst();(arg=ali.current());++ali,++count) 02521 { 02522 if (arg->name==usedClassName) // type is a template argument 02523 { 02524 found=TRUE; 02525 if (m_impl->usesImplClassDict==0) m_impl->usesImplClassDict = new UsesClassDict(257); 02526 cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(), 02527 usedClassName,ClassDef::Class); 02528 cd->setIsTemplateBaseClass(count); 02529 UsesClassDef *ucd = new UsesClassDef(cd); 02530 m_impl->usesImplClassDict->insert(cd->name(),ucd); 02531 ucd->templSpecifiers = templSpec; 02532 ucd->addAccessor(md->name()); 02533 Doxygen::hiddenClasses.append(cd); 02534 //printf("Adding used template argument %s to class %s\n", 02535 // cd->name().data(),name().data()); 02536 //printf("Adding accessor %s to class %s\n", 02537 // md->name().data(),ucd->classDef->name().data()); 02538 } 02539 } 02540 } 02541 02542 if (!found) 02543 { 02544 cd=0; 02545 if (getNamespaceDef()!=0) 02546 { 02547 cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec); 02548 } 02549 if (cd==0) cd=getResolvedClass(name()+"::"+usedClassName,0,&templSpec); 02550 if (cd==0) cd=getResolvedClass(usedClassName,0,&templSpec); // TODO: also try inbetween scopes! 02551 //printf("Search for class %s result=%p\n",usedClassName.data(),cd); 02552 if (cd) // class exists 02553 { 02554 found=TRUE; 02555 if (m_impl->usesImplClassDict==0) 02556 { 02557 m_impl->usesImplClassDict = new UsesClassDict(257); 02558 m_impl->usesImplClassDict->setAutoDelete(TRUE); 02559 } 02560 UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name()); 02561 if (ucd==0 || ucd->templSpecifiers!=templSpec) 02562 { 02563 ucd = new UsesClassDef(cd); 02564 m_impl->usesImplClassDict->insert(cd->name(),ucd); 02565 ucd->templSpecifiers = templSpec; 02566 //printf("Adding used class %s to class %s\n", 02567 // cd->name().data(),name().data()); 02568 } 02569 ucd->addAccessor(md->name()); 02570 //printf("Adding accessor %s to class %s\n", 02571 // md->name().data(),ucd->classDef->name().data()); 02572 } 02573 } 02574 } 02575 } 02576 } 02577 } 02578 #ifdef DUMP 02579 if (m_impl->usesClassDict) 02580 { 02581 msg("Class %s uses the following classes:\n",name().data()); 02582 UsesClassDictIterator ucdi(*m_impl->usesClassDict); 02583 UsesClassDef *ucd; 02584 for (;(ucd=ucdi.current());++ucdi) 02585 { 02586 msg(" %s via ",ucd->classDef->name().data()); 02587 QDictIterator<void> dvi(*ucd->accessors); 02588 const char *s; 02589 for (;(s=dvi.currentKey());++dvi) 02590 { 02591 msg("%s ",s); 02592 } 02593 msg("\n"); 02594 } 02595 } 02596 #endif 02597 } 02598 02599 //---------------------------------------------------------------------------- 02600 02601 // I have disabled this code because the graphs it renders quickly become 02602 // too large to be of practical use. 02603 02604 void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr) 02605 { 02606 QCString type = typeStr; 02607 static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*"); 02608 int p=0,i,l; 02609 while ((i=re.match(type,p,&l))!=-1) // for each class name in the type 02610 { 02611 ClassDef *cd=getClass(name()+"::"+type.mid(i,l)); 02612 if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try inbetween scopes! 02613 if (cd && cd!=this && !isBaseClass(cd)) 02614 { 02615 if (m_impl->usesIntfClassDict==0) 02616 { 02617 m_impl->usesIntfClassDict = new UsesClassDict(257); 02618 } 02619 UsesClassDef *ucd=m_impl->usesIntfClassDict->find(cd->name()); 02620 if (ucd==0) 02621 { 02622 ucd = new UsesClassDef(cd); 02623 m_impl->usesIntfClassDict->insert(cd->name(),ucd); 02624 //printf("in class `%s' adding used intf class `%s'\n", 02625 // name().data(),cd->name().data()); 02626 } 02627 ucd->addAccessor(md->name()); 02628 //printf("in class `%s' adding accessor `%s' to class `%s'\n", 02629 // name().data(),md->name().data(),ucd->classDef->name().data()); 02630 } 02631 p=i+l; 02632 } 02633 } 02634 02635 void ClassDef::determineIntfUsageRelation() 02636 { 02637 MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoList); 02638 MemberNameInfo *mni; 02639 for (;(mni=mnili.current());++mnili) 02640 { 02641 MemberNameInfoIterator mnii(*mni); 02642 MemberInfo *mi; 02643 for (mnii.toFirst();(mi=mnii.current());++mnii) 02644 { 02645 MemberDef *md=mi->memberDef; 02646 02647 // compute the protection level for this member 02648 Protection protect=md->protection(); 02649 if (mi->prot==Protected) // inherited protection 02650 { 02651 if (protect==Public) protect=Protected; 02652 else if (protect==Protected) protect=Private; 02653 } 02654 02655 if (!md->name().isEmpty() && md->name()[0]!='@' && 02656 (mi->prot!=Private && protect!=Private) 02657 ) 02658 { 02659 // add classes found in the return type 02660 addUsedInterfaceClasses(md,md->typeString()); 02661 ArgumentList *al = md->argumentList(); 02662 if (al) // member has arguments 02663 { 02664 // add classes found in the types of the argument list 02665 ArgumentListIterator ali(*al); 02666 Argument *a; 02667 for (;(a=ali.current());++ali) 02668 { 02669 if (!a->type.isEmpty() && a->type.at(0)!='@') 02670 { 02671 addUsedInterfaceClasses(md,a->type); 02672 } 02673 } 02674 } 02675 } 02676 } 02677 } 02678 } 02679 #endif 02680 02681 QCString ClassDef::compoundTypeString() const 02682 { 02683 if (m_impl->compType==Interface && m_impl->isObjC) return "class"; 02684 if (Config_getBool("OPTIMIZE_FOR_FORTRAN")) 02685 { 02686 switch (m_impl->compType) 02687 { 02688 case Class: return "module"; 02689 case Struct: return "type"; 02690 case Union: return "union"; 02691 case Interface: return "interface"; 02692 case Protocol: return "protocol"; 02693 case Category: return "category"; 02694 case Exception: return "exception"; 02695 default: return "unknown"; 02696 } 02697 } 02698 else 02699 { 02700 switch (m_impl->compType) 02701 { 02702 case Class: return "class"; 02703 case Struct: return "struct"; 02704 case Union: return "union"; 02705 case Interface: return "interface"; 02706 case Protocol: return "protocol"; 02707 case Category: return "category"; 02708 case Exception: return "exception"; 02709 default: return "unknown"; 02710 } 02711 } 02712 } 02713 02714 QCString ClassDef::getOutputFileBase() const 02715 { 02716 if (m_impl->templateMaster) 02717 { 02718 return m_impl->templateMaster->getOutputFileBase(); 02719 } 02720 else if (isReference()) 02721 { 02722 return m_impl->fileName; 02723 } 02724 else 02725 { 02726 return convertNameToFile(m_impl->fileName); 02727 } 02728 } 02729 02730 QCString ClassDef::getInstanceOutputFileBase() const 02731 { 02732 if (isReference()) 02733 { 02734 return m_impl->fileName; 02735 } 02736 else 02737 { 02738 return convertNameToFile(m_impl->fileName); 02739 } 02740 } 02741 02742 QCString ClassDef::getFileBase() const 02743 { 02744 if (m_impl->templateMaster) 02745 { 02746 return m_impl->templateMaster->getFileBase(); 02747 } 02748 else 02749 { 02750 return m_impl->fileName; 02751 } 02752 } 02753 02754 QCString ClassDef::getSourceFileBase() const 02755 { 02756 if (m_impl->templateMaster) 02757 { 02758 return m_impl->templateMaster->getSourceFileBase(); 02759 } 02760 else 02761 { 02762 return convertNameToFile(m_impl->fileName+"-source"); 02763 } 02764 } 02765 02766 void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) 02767 { 02768 gd->addClass(this); 02769 //printf("ClassDef::setGroupDefForAllMembers(%s)\n",gd->name().data()); 02770 if (m_impl->allMemberNameInfoSDict==0) return; 02771 MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict); 02772 MemberNameInfo *mni; 02773 for (;(mni=mnili.current());++mnili) 02774 { 02775 MemberNameInfoIterator mnii(*mni); 02776 MemberInfo *mi; 02777 for (mnii.toFirst();(mi=mnii.current());++mnii) 02778 { 02779 MemberDef *md=mi->memberDef; 02780 md->setGroupDef(gd,pri,fileName,startLine,hasDocs); 02781 gd->insertMember(md,TRUE); 02782 ClassDef *innerClass = md->getClassDefOfAnonymousType(); 02783 if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs); 02784 } 02785 } 02786 } 02787 02788 void ClassDef::addInnerCompound(Definition *d) 02789 { 02790 //printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data()); 02791 if (d->definitionType()==Definition::TypeClass) // only classes can be 02792 // nested in classes. 02793 { 02794 if (m_impl->innerClasses==0) 02795 { 02796 m_impl->innerClasses = new ClassSDict(17); 02797 } 02798 m_impl->innerClasses->inSort(d->localName(),(ClassDef *)d); 02799 } 02800 } 02801 02802 Definition *ClassDef::findInnerCompound(const char *name) 02803 { 02804 Definition *result=0; 02805 if (name==0) return 0; 02806 if (m_impl->innerClasses) 02807 { 02808 result = m_impl->innerClasses->find(name); 02809 } 02810 return result; 02811 } 02812 02813 //void ClassDef::initTemplateMapping() 02814 //{ 02815 // m_impl->templateMapping->clear(); 02816 // ArgumentList *al = templateArguments(); 02817 // if (al) 02818 // { 02819 // ArgumentListIterator ali(*al); 02820 // Argument *arg; 02821 // for (ali.toFirst();(arg=ali.current());++ali) 02822 // { 02823 // setTemplateArgumentMapping(arg->name,arg->defval); 02824 // } 02825 // } 02826 //} 02827 //void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual) 02828 //{ 02829 // //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual); 02830 // if (m_impl->templateMapping && formal) 02831 // { 02832 // if (m_impl->templateMapping->find(formal)) 02833 // { 02834 // m_impl->templateMapping->remove(formal); 02835 // } 02836 // m_impl->templateMapping->insert(formal,new QCString(actual)); 02837 // } 02838 //} 02839 // 02840 //QCString ClassDef::getTemplateArgumentMapping(const char *formal) const 02841 //{ 02842 // if (m_impl->templateMapping && formal) 02843 // { 02844 // QCString *s = m_impl->templateMapping->find(formal); 02845 // if (s) 02846 // { 02847 // return *s; 02848 // } 02849 // } 02850 // return ""; 02851 //} 02852 02853 ClassDef *ClassDef::insertTemplateInstance(const QCString &fileName, 02854 int startLine, const QCString &templSpec,bool &freshInstance) 02855 { 02856 freshInstance = FALSE; 02857 if (m_impl->templateInstances==0) 02858 { 02859 m_impl->templateInstances = new QDict<ClassDef>(17); 02860 } 02861 ClassDef *templateClass=m_impl->templateInstances->find(templSpec); 02862 if (templateClass==0) 02863 { 02864 Debug::print(Debug::Classes,0," New template instance class `%s'`%s'\n",name().data(),templSpec.data()); 02865 templateClass = new ClassDef( 02866 fileName,startLine,localName()+templSpec,ClassDef::Class); 02867 templateClass->setTemplateMaster(this); 02868 templateClass->setOuterScope(getOuterScope()); 02869 templateClass->setHidden(isHidden()); 02870 m_impl->templateInstances->insert(templSpec,templateClass); 02871 freshInstance=TRUE; 02872 } 02873 return templateClass; 02874 } 02875 02876 ClassDef *ClassDef::getVariableInstance(const char *templSpec) 02877 { 02878 if (m_impl->variableInstances==0) 02879 { 02880 m_impl->variableInstances = new QDict<ClassDef>(17); 02881 m_impl->variableInstances->setAutoDelete(TRUE); 02882 } 02883 ClassDef *templateClass=m_impl->variableInstances->find(templSpec); 02884 if (templateClass==0) 02885 { 02886 Debug::print(Debug::Classes,0," New template variable instance class `%s'`%s'\n",name().data(),templSpec); 02887 templateClass = new ClassDef("<code>",1,name()+templSpec, 02888 ClassDef::Class,0,0,FALSE); 02889 templateClass->addMembersToTemplateInstance( this, templSpec ); 02890 templateClass->setTemplateMaster(this); 02891 m_impl->variableInstances->insert(templSpec,templateClass); 02892 } 02893 return templateClass; 02894 } 02895 02896 void ClassDef::setTemplateBaseClassNames(QDict<int> *templateNames) 02897 { 02898 if (templateNames==0) return; 02899 if (m_impl->templBaseClassNames==0) 02900 { 02901 m_impl->templBaseClassNames = new QDict<int>(17); 02902 m_impl->templBaseClassNames->setAutoDelete(TRUE); 02903 } 02904 // make a deep copy of the dictionary. 02905 QDictIterator<int> qdi(*templateNames); 02906 for (;qdi.current();++qdi) 02907 { 02908 if (m_impl->templBaseClassNames->find(qdi.currentKey())==0) 02909 { 02910 m_impl->templBaseClassNames->insert(qdi.currentKey(),new int(*qdi.current())); 02911 } 02912 } 02913 } 02914 02915 QDict<int> *ClassDef::getTemplateBaseClassNames() const 02916 { 02917 return m_impl->templBaseClassNames; 02918 } 02919 02920 void ClassDef::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec) 02921 { 02922 //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec); 02923 if (cd->memberNameInfoSDict()==0) return; 02924 MemberNameInfoSDict::Iterator mnili(*cd->memberNameInfoSDict()); 02925 MemberNameInfo *mni; 02926 for (;(mni=mnili.current());++mnili) 02927 { 02928 MemberNameInfoIterator mnii(*mni); 02929 MemberInfo *mi; 02930 for (mnii.toFirst();(mi=mnii.current());++mnii) 02931 { 02932 ArgumentList *actualArguments = new ArgumentList; 02933 stringToArgumentList(templSpec,actualArguments); 02934 MemberDef *md = mi->memberDef; 02935 MemberDef *imd = md->createTemplateInstanceMember( 02936 cd->templateArguments(),actualArguments); 02937 delete actualArguments; 02938 //printf("%s->setMemberClass(%p)\n",imd->name().data(),this); 02939 imd->setMemberClass(this); 02940 imd->setTemplateMaster(md); 02941 imd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); 02942 imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); 02943 imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); 02944 imd->setMemberSpecifiers(md->getMemberSpecifiers()); 02945 imd->setMemberGroupId(md->getMemberGroupId()); 02946 insertMember(imd); 02947 //printf("Adding member=%s %s%s to class %s templSpec %s\n", 02948 // imd->typeString(),imd->name().data(),imd->argsString(), 02949 // imd->getClassDef()->name().data(),templSpec); 02950 // insert imd in the list of all members 02951 //printf("Adding member=%s class=%s\n",imd->name().data(),name().data()); 02952 MemberName *mn = Doxygen::memberNameSDict->find(imd->name()); 02953 if (mn==0) 02954 { 02955 mn = new MemberName(imd->name()); 02956 Doxygen::memberNameSDict->append(imd->name(),mn); 02957 } 02958 mn->append(imd); 02959 } 02960 } 02961 } 02962 02963 QCString ClassDef::getReference() const 02964 { 02965 if (m_impl->templateMaster) 02966 { 02967 return m_impl->templateMaster->getReference(); 02968 } 02969 else 02970 { 02971 return Definition::getReference(); 02972 } 02973 } 02974 02975 bool ClassDef::isReference() const 02976 { 02977 if (m_impl->templateMaster) 02978 { 02979 return m_impl->templateMaster->isReference(); 02980 } 02981 else 02982 { 02983 return Definition::isReference(); 02984 } 02985 } 02986 02987 void ClassDef::getTemplateParameterLists(QList<ArgumentList> &lists) const 02988 { 02989 Definition *d=getOuterScope(); 02990 if (d) 02991 { 02992 if (d->definitionType()==Definition::TypeClass) 02993 { 02994 ClassDef *cd=(ClassDef *)d; 02995 cd->getTemplateParameterLists(lists); 02996 } 02997 } 02998 if (templateArguments()) 02999 { 03000 lists.append(templateArguments()); 03001 } 03002 } 03003 03004 QCString ClassDef::qualifiedNameWithTemplateParameters( 03005 QList<ArgumentList> *actualParams) const 03006 { 03007 static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); 03008 //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); 03009 QCString scName; 03010 Definition *d=getOuterScope(); 03011 if (d) 03012 { 03013 if (d->definitionType()==Definition::TypeClass) 03014 { 03015 ClassDef *cd=(ClassDef *)d; 03016 scName = cd->qualifiedNameWithTemplateParameters(actualParams); 03017 } 03018 else 03019 { 03020 scName = d->qualifiedName(); 03021 } 03022 } 03023 03024 QCString scopeSeparator; 03025 if (optimizeOutputJava) 03026 scopeSeparator="."; 03027 else 03028 scopeSeparator="::"; 03029 03030 if (!scName.isEmpty()) scName+=scopeSeparator; 03031 scName+=localName(); 03032 ArgumentList *al=0; 03033 bool isSpecialization = localName().find('<')!=-1; 03034 if (templateArguments()) 03035 { 03036 if (actualParams && (al=actualParams->current())) 03037 { 03038 if (!isSpecialization) 03039 { 03040 scName+=tempArgListToString(al); 03041 } 03042 actualParams->next(); 03043 } 03044 else 03045 { 03046 if (!isSpecialization) 03047 { 03048 scName+=tempArgListToString(templateArguments()); 03049 } 03050 } 03051 } 03052 //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data()); 03053 return scName; 03054 } 03055 03056 QCString ClassDef::className() const 03057 { 03058 return m_impl->className; 03059 }; 03060 03061 void ClassDef::setClassName(const char *name) 03062 { 03063 m_impl->className = name; 03064 } 03065 03066 void ClassDef::addListReferences() 03067 { 03068 bool fortranOpt=Config_getBool("OPTIMIZE_FOR_FORTRAN"); 03069 if (!isLinkableInProject()) return; 03070 //printf("ClassDef(%s)::addListReferences()\n",name().data()); 03071 { 03072 LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); 03073 addRefItem(xrefItems.pointer(), 03074 fortranOpt?theTranslator->trType(TRUE,TRUE):theTranslator->trClass(TRUE,TRUE), 03075 getOutputFileBase(),displayName() 03076 ); 03077 } 03078 if (m_impl->memberGroupSDict) 03079 { 03080 MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); 03081 MemberGroup *mg; 03082 for (;(mg=mgli.current());++mgli) 03083 { 03084 mg->addListReferences(this); 03085 } 03086 } 03087 QListIterator<MemberList> mli(m_impl->memberLists); 03088 MemberList *ml; 03089 for (mli.toFirst();(ml=mli.current());++mli) 03090 { 03091 if (ml->listType()&MemberList::detailedLists) 03092 { 03093 ml->addListReferences(this); 03094 } 03095 } 03096 } 03097 03098 MemberDef *ClassDef::getMemberByName(const QCString &name) const 03099 { 03100 MemberDef *xmd = 0; 03101 if (m_impl->allMemberNameInfoSDict) 03102 { 03103 MemberNameInfo *mni = m_impl->allMemberNameInfoSDict->find(name); 03104 if (mni) 03105 { 03106 const int maxInheritanceDepth = 100000; 03107 int mdist=maxInheritanceDepth; 03108 MemberNameInfoIterator mnii(*mni); 03109 MemberInfo *mi; 03110 for (mnii.toFirst();(mi=mnii.current());++mnii) 03111 { 03112 ClassDef *mcd=mi->memberDef->getClassDef(); 03113 int m=minClassDistance(this,mcd); 03114 //printf("found member in %s linkable=%d m=%d\n", 03115 // mcd->name().data(),mcd->isLinkable(),m); 03116 if (m<mdist && mcd->isLinkable()) 03117 { 03118 mdist=m; 03119 xmd=mi->memberDef; 03120 } 03121 } 03122 } 03123 } 03124 //printf("getMemberByName(%s)=%p\n",name.data(),xmd); 03125 return xmd; 03126 } 03127 03128 bool ClassDef::isAccessibleMember(MemberDef *md) 03129 { 03130 return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE); 03131 } 03132 03133 MemberList *ClassDef::createMemberList(MemberList::ListType lt) 03134 { 03135 m_impl->memberLists.setAutoDelete(TRUE); 03136 QListIterator<MemberList> mli(m_impl->memberLists); 03137 MemberList *ml; 03138 for (mli.toFirst();(ml=mli.current());++mli) 03139 { 03140 if (ml->listType()==lt) 03141 { 03142 return ml; 03143 } 03144 } 03145 // not found, create a new member list 03146 ml = new MemberList(lt); 03147 m_impl->memberLists.append(ml); 03148 return ml; 03149 } 03150 03151 MemberList *ClassDef::getMemberList(MemberList::ListType lt) 03152 { 03153 MemberList *ml = m_impl->memberLists.first(); 03154 while (ml) 03155 { 03156 if (ml->listType()==lt) 03157 { 03158 return ml; 03159 } 03160 ml = m_impl->memberLists.next(); 03161 } 03162 return 0; 03163 } 03164 03165 void ClassDef::addMemberToList(MemberList::ListType lt,MemberDef *md) 03166 { 03167 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); 03168 MemberList *ml = createMemberList(lt); 03169 if (sortBriefDocs) 03170 ml->inSort(md); 03171 else 03172 ml->append(md); 03173 03174 // for members in the declaration lists we set the section, needed for member grouping 03175 if ((ml->listType()&MemberList::detailedLists)==0) md->setSectionList(this,ml); 03176 } 03177 03178 void ClassDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title, 03179 const char *subTitle) 03180 { 03181 static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 03182 MemberList * ml = getMemberList(lt); 03183 if (ml) 03184 { 03185 if (optimizeVhdl) // use specific declarations function 03186 { 03187 VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this); 03188 } 03189 else // ise generic declaration function 03190 { 03191 ml->writeDeclarations(ol,this,0,0,0,title,subTitle); 03192 } 03193 } 03194 } 03195 03196 void ClassDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title) 03197 { 03198 MemberList * ml = getMemberList(lt); 03199 if (ml) ml->writeDocumentation(ol,name(),this,title); 03200 } 03201 03202 void ClassDef::writePlainMemberDeclaration(OutputList &ol,MemberList::ListType lt,bool inGroup) 03203 { 03204 MemberList * ml = getMemberList(lt); 03205 if (ml) 03206 { 03207 ml->setInGroup(inGroup); 03208 ml->writePlainDeclarations(ol,this,0,0,0); 03209 } 03210 } 03211 03212 bool ClassDef::isLocal() const 03213 { 03214 return m_impl->isLocal; 03215 } 03216 03217 ClassSDict *ClassDef::getInnerClasses() 03218 { 03219 return m_impl->innerClasses; 03220 } 03221 03222 ClassDef::CompoundType ClassDef::compoundType() const 03223 { 03224 return m_impl->compType; 03225 } 03226 03227 BaseClassList *ClassDef::baseClasses() const 03228 { 03229 return m_impl->inherits; 03230 } 03231 03232 BaseClassList *ClassDef::subClasses() const 03233 { 03234 return m_impl->inheritedBy; 03235 } 03236 03237 MemberNameInfoSDict *ClassDef::memberNameInfoSDict() const 03238 { 03239 return m_impl->allMemberNameInfoSDict; 03240 } 03241 03242 Protection ClassDef::protection() const 03243 { 03244 return m_impl->prot; 03245 } 03246 03247 ArgumentList *ClassDef::templateArguments() const 03248 { 03249 return m_impl->tempArgs; 03250 } 03251 03252 NamespaceDef *ClassDef::getNamespaceDef() const 03253 { 03254 return m_impl->nspace; 03255 } 03256 03257 FileDef *ClassDef::getFileDef() const 03258 { 03259 return m_impl->fileDef; 03260 } 03261 03262 QDict<ClassDef> *ClassDef::getTemplateInstances() const 03263 { 03264 return m_impl->templateInstances; 03265 } 03266 03267 ClassDef *ClassDef::templateMaster() const 03268 { 03269 return m_impl->templateMaster; 03270 } 03271 03272 bool ClassDef::isTemplate() const 03273 { 03274 return m_impl->tempArgs!=0; 03275 } 03276 03277 IncludeInfo *ClassDef::includeInfo() const 03278 { 03279 return m_impl->incInfo; 03280 } 03281 03282 UsesClassDict *ClassDef::usedImplementationClasses() const 03283 { 03284 return m_impl->usesImplClassDict; 03285 } 03286 03287 UsesClassDict *ClassDef::usedByImplementationClasses() const 03288 { 03289 return m_impl->usedByImplClassDict; 03290 } 03291 03292 UsesClassDict *ClassDef::usedInterfaceClasses() const 03293 { 03294 return m_impl->usesIntfClassDict; 03295 } 03296 03297 bool ClassDef::isTemplateArgument() const 03298 { 03299 return m_impl->isTemplArg; 03300 } 03301 03302 bool ClassDef::isAbstract() const 03303 { 03304 return m_impl->isAbstract; 03305 } 03306 03307 bool ClassDef::isObjectiveC() const 03308 { 03309 return m_impl->isObjC; 03310 } 03311 03312 ClassDef *ClassDef::categoryOf() const 03313 { 03314 return m_impl->categoryOf; 03315 } 03316 03317 const QList<MemberList> &ClassDef::getMemberLists() const 03318 { 03319 return m_impl->memberLists; 03320 } 03321 03322 MemberGroupSDict *ClassDef::getMemberGroupSDict() const 03323 { 03324 return m_impl->memberGroupSDict; 03325 } 03326 03327 void ClassDef::setNamespace(NamespaceDef *nd) 03328 { 03329 m_impl->nspace = nd; 03330 } 03331 03332 void ClassDef::setFileDef(FileDef *fd) 03333 { 03334 m_impl->fileDef=fd; 03335 } 03336 03337 void ClassDef::setSubGrouping(bool enabled) 03338 { 03339 m_impl->subGrouping = enabled; 03340 } 03341 03342 void ClassDef::setProtection(Protection p) 03343 { 03344 m_impl->prot=p; 03345 } 03346 03347 void ClassDef::setIsStatic(bool b) 03348 { 03349 m_impl->isStatic=b; 03350 } 03351 03352 void ClassDef::setIsObjectiveC(bool b) 03353 { 03354 m_impl->isObjC=b; 03355 } 03356 03357 void ClassDef::setCompoundType(CompoundType t) 03358 { 03359 m_impl->compType = t; 03360 } 03361 03362 void ClassDef::setTemplateMaster(ClassDef *tm) 03363 { 03364 m_impl->templateMaster=tm; 03365 } 03366 03367 void ClassDef::makeTemplateArgument(bool b) 03368 { 03369 m_impl->isTemplArg = b; 03370 } 03371 03372 void ClassDef::setCategoryOf(ClassDef *cd) 03373 { 03374 m_impl->categoryOf = cd; 03375 } 03376 03377 void ClassDef::setUsedOnly(bool b) 03378 { 03379 m_impl->usedOnly = b; 03380 } 03381 03382 bool ClassDef::isUsedOnly() const 03383 { 03384 return m_impl->usedOnly; 03385 } 03386