1 /******************************************************************************
5 * Copyright (C) 1997-2015 by Dimitri van Heesch.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
18 #include "memberlist.h"
19 #include "classlist.h"
22 #include "memberdef.h"
24 #include "namespacedef.h"
27 #include "outputlist.h"
30 #include "docparser.h"
31 #include "searchindex.h"
33 #include "parserintf.h"
35 #include "vhdldocgen.h"
41 #include "membergroup.h"
44 #include "clangparser.h"
47 //---------------------------------------------------------------------------
49 /** Class implementing CodeOutputInterface by throwing away everything. */
50 class DevNullCodeDocInterface : public CodeOutputInterface
53 virtual void codify(const char *) {}
54 virtual void writeCodeLink(const char *,const char *,
55 const char *,const char *,
57 virtual void writeTooltip(const char *, const DocLinkInfo &, const char *,
58 const char *, const SourceLinkInfo &, const SourceLinkInfo &
60 virtual void writeLineNumber(const char *,const char *,
62 virtual void startCodeLine(bool) {}
63 virtual void endCodeLine() {}
64 virtual void startFontClass(const char *) {}
65 virtual void endFontClass() {}
66 virtual void writeCodeAnchor(const char *) {}
67 virtual void linkableSymbol(int, const char *,Definition *,Definition *) {}
68 virtual void setCurrentDoc(Definition *,const char *,bool) {}
69 virtual void addWord(const char *,bool) {}
72 //---------------------------------------------------------------------------
74 /*! create a new file definition, where \a p is the file path,
75 \a nm the file name, and \a lref is an HTML anchor name if the
76 file was read from a tag file or 0 otherwise
78 FileDef::FileDef(const char *p,const char *nm,
79 const char *lref,const char *dn)
80 : Definition((QCString)p+nm,1,1,nm)
86 setDiskName(dn?dn:nm);
98 m_isSource = guessSection(nm)==Entry::SOURCE_SEC;
101 if (Config_getBool(FULL_PATH_NAMES))
103 m_docname.prepend(stripFromPath(m_path.copy()));
105 setLanguage(getLanguageFromFileName(name()));
106 m_memberGroupSDict = 0;
107 acquireFileVersion();
108 m_subGrouping=Config_getBool(SUBGROUPING);
111 /*! destroy the file definition */
115 delete m_includeDict;
116 delete m_includeList;
117 delete m_includedByDict;
118 delete m_includedByList;
119 delete m_namespaceSDict;
121 delete m_srcMemberDict;
122 delete m_usingDirList;
123 delete m_usingDeclList;
124 delete m_memberGroupSDict;
127 void FileDef::setDiskName(const QCString &name)
131 m_outputDiskName = name;
132 m_inclDepFileName = name+"_incl";
133 m_inclByDepFileName = name+"_dep_incl";
137 m_outputDiskName = convertNameToFile(name);
138 m_inclDepFileName = convertNameToFile(name+"_incl");
139 m_inclByDepFileName = convertNameToFile(name+"_dep_incl");
143 /*! Compute the HTML anchor names for all members in the class */
144 void FileDef::computeAnchors()
146 MemberList *ml = getMemberList(MemberListType_allMembersList);
147 if (ml) setAnchors(ml);
150 void FileDef::distributeMemberGroupDocumentation()
152 //printf("FileDef::distributeMemberGroupDocumentation()\n");
153 if (m_memberGroupSDict)
155 MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
157 for (;(mg=mgli.current());++mgli)
159 mg->distributeMemberGroupDocumentation();
164 void FileDef::findSectionsInDocumentation()
166 docFindSections(documentation(),this,0,docFile());
167 if (m_memberGroupSDict)
169 MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
171 for (;(mg=mgli.current());++mgli)
173 mg->findSectionsInDocumentation();
177 QListIterator<MemberList> mli(m_memberLists);
179 for (mli.toFirst();(ml=mli.current());++mli)
181 if (ml->listType()&MemberListType_declarationLists)
183 ml->findSectionsInDocumentation();
188 bool FileDef::hasDetailedDescription() const
190 static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
191 static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
192 return ((!briefDescription().isEmpty() && repeatBrief) ||
193 !documentation().stripWhiteSpace().isEmpty() || // avail empty section
194 (sourceBrowser && getStartBodyLine()!=-1 && getBodyDef())
198 void FileDef::writeTagFile(FTextStream &tagFile)
200 tagFile << " <compound kind=\"file\">" << endl;
201 tagFile << " <name>" << convertToXML(name()) << "</name>" << endl;
202 tagFile << " <path>" << convertToXML(getPath()) << "</path>" << endl;
203 tagFile << " <filename>" << convertToXML(getOutputFileBase()) << "</filename>" << endl;
204 if (m_includeList && m_includeList->count()>0)
206 QListIterator<IncludeInfo> ili(*m_includeList);
208 for (;(ii=ili.current());++ili)
212 FileDef *fd=ii->fileDef;
213 if (fd && fd->isLinkable() && !fd->isReference())
215 bool isIDLorJava = FALSE;
216 SrcLangExt lang = fd->getLanguage();
217 isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
218 const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no";
219 const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no";
220 tagFile << " <includes id=\""
221 << convertToXML(fd->getOutputFileBase()) << "\" "
222 << "name=\"" << convertToXML(fd->name()) << "\" "
223 << "local=\"" << locStr << "\" "
224 << "imported=\"" << impStr << "\">"
225 << convertToXML(ii->includeName)
232 QListIterator<LayoutDocEntry> eli(
233 LayoutDocManager::instance().docEntries(LayoutDocManager::File));
235 for (eli.toFirst();(lde=eli.current());++eli)
239 case LayoutDocEntry::FileClasses:
243 SDict<ClassDef>::Iterator ci(*m_classSDict);
245 for (ci.toFirst();(cd=ci.current());++ci)
247 if (cd->isLinkableInProject())
249 tagFile << " <class kind=\"" << cd->compoundTypeString() <<
250 "\">" << convertToXML(cd->name()) << "</class>" << endl;
256 case LayoutDocEntry::FileNamespaces:
258 if (m_namespaceSDict)
260 SDict<NamespaceDef>::Iterator ni(*m_namespaceSDict);
262 for (ni.toFirst();(nd=ni.current());++ni)
264 if (nd->isLinkableInProject())
266 tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl;
272 case LayoutDocEntry::MemberDecl:
274 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
275 MemberList * ml = getMemberList(lmd->type);
278 ml->writeTagFile(tagFile);
282 case LayoutDocEntry::MemberGroups:
284 if (m_memberGroupSDict)
286 MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
288 for (;(mg=mgli.current());++mgli)
290 mg->writeTagFile(tagFile);
300 writeDocAnchorsToTagFile(tagFile);
301 tagFile << " </compound>" << endl;
304 void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title)
306 if (hasDetailedDescription())
308 ol.pushGeneratorState();
309 ol.disable(OutputGenerator::Html);
311 ol.popGeneratorState();
312 ol.pushGeneratorState();
313 ol.disableAllBut(OutputGenerator::Html);
314 ol.writeAnchor(0,"details");
315 ol.popGeneratorState();
316 ol.startGroupHeader();
321 if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
323 ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
325 if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) &&
326 !documentation().isEmpty())
328 ol.pushGeneratorState();
329 ol.disable(OutputGenerator::Man);
330 ol.disable(OutputGenerator::RTF);
331 // ol.newParagraph(); // FIXME:PARA
333 ol.disableAllBut(OutputGenerator::Man);
334 ol.enable(OutputGenerator::Latex);
335 ol.writeString("\n\n");
336 ol.popGeneratorState();
338 if (!documentation().isEmpty())
340 ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
342 //printf("Writing source ref for file %s\n",name().data());
343 if (Config_getBool(SOURCE_BROWSER))
345 //if Latex enabled and LATEX_SOURCE_CODE isn't -> skip, bug_738548
346 ol.pushGeneratorState();
347 if (ol.isEnabled(OutputGenerator::Latex) && !Config_getBool(LATEX_SOURCE_CODE))
349 ol.disable(OutputGenerator::Latex);
351 if (ol.isEnabled(OutputGenerator::RTF) && !Config_getBool(RTF_SOURCE_CODE))
353 ol.disable(OutputGenerator::RTF);
356 ol.startParagraph("definition");
357 QCString refText = theTranslator->trDefinedInSourceFile();
358 int fileMarkerPos = refText.find("@0");
359 if (fileMarkerPos!=-1) // should always pass this.
361 ol.parseText(refText.left(fileMarkerPos)); //text left from marker 1
362 ol.writeObjectLink(0,getSourceFileBase(),
364 ol.parseText(refText.right(
365 refText.length()-fileMarkerPos-2)); // text right from marker 2
369 err("translation error: invalid marker in trDefinedInSourceFile()\n");
372 //Restore settings, bug_738548
373 ol.popGeneratorState();
379 void FileDef::writeBriefDescription(OutputList &ol)
381 if (hasBriefDescription())
383 DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
384 briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
386 if (rootNode && !rootNode->isEmpty())
389 ol.pushGeneratorState();
390 ol.disableAllBut(OutputGenerator::Man);
391 ol.writeString(" - ");
392 ol.popGeneratorState();
393 ol.writeDoc(rootNode,this,0);
394 ol.pushGeneratorState();
395 ol.disable(OutputGenerator::RTF);
396 ol.writeString(" \n");
397 ol.enable(OutputGenerator::RTF);
399 if (Config_getBool(REPEAT_BRIEF) ||
400 !documentation().isEmpty()
403 ol.disableAllBut(OutputGenerator::Html);
404 ol.startTextLink(0,"details");
405 ol.parseText(theTranslator->trMore());
408 ol.popGeneratorState();
416 void FileDef::writeIncludeFiles(OutputList &ol)
418 if (m_includeList && m_includeList->count()>0)
420 ol.startTextBlock(TRUE);
421 QListIterator<IncludeInfo> ili(*m_includeList);
423 for (;(ii=ili.current());++ili)
427 FileDef *fd=ii->fileDef;
428 bool isIDLorJava = FALSE;
431 SrcLangExt lang = fd->getLanguage();
432 isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
434 ol.startTypewriter();
435 if (isIDLorJava) // IDL/Java include
437 ol.docify("import ");
439 else if (ii->imported) // Objective-C include
441 ol.docify("#import ");
443 else // C/C++ include
445 ol.docify("#include ");
447 if (ii->local || isIDLorJava)
451 ol.disable(OutputGenerator::Html);
452 ol.docify(ii->includeName);
454 ol.disableAllBut(OutputGenerator::Html);
456 // Here we use the include file name as it appears in the file.
457 // we could also we the name as it is used within doxygen,
458 // then we should have used fd->docName() instead of ii->includeName
459 if (fd && fd->isLinkable())
461 ol.writeObjectLink(fd->getReference(),
462 fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(),
467 ol.docify(ii->includeName);
471 if (ii->local || isIDLorJava)
485 void FileDef::writeIncludeGraph(OutputList &ol)
487 if (Config_getBool(HAVE_DOT) /*&& Config_getBool(INCLUDE_GRAPH)*/)
489 //printf("Graph for file %s\n",name().data());
490 DotInclDepGraph incDepGraph(this,FALSE);
491 if (incDepGraph.isTooBig())
493 warn_uncond("Include graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data());
495 else if (!incDepGraph.isTrivial())
498 ol.disable(OutputGenerator::Man);
499 ol.startInclDepGraph();
500 ol.parseText(theTranslator->trInclDepGraph(name()));
501 ol.endInclDepGraph(incDepGraph);
503 ol.endTextBlock(TRUE);
505 //incDepGraph.writeGraph(Config_getString(HTML_OUTPUT),fd->getOutputFileBase());
509 void FileDef::writeIncludedByGraph(OutputList &ol)
511 if (Config_getBool(HAVE_DOT) /*&& Config_getBool(INCLUDED_BY_GRAPH)*/)
513 //printf("Graph for file %s\n",name().data());
514 DotInclDepGraph incDepGraph(this,TRUE);
515 if (incDepGraph.isTooBig())
517 warn_uncond("Included by graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data());
519 else if (!incDepGraph.isTrivial())
522 ol.disable(OutputGenerator::Man);
523 ol.startInclDepGraph();
524 ol.parseText(theTranslator->trInclByDepGraph());
525 ol.endInclDepGraph(incDepGraph);
527 ol.endTextBlock(TRUE);
529 //incDepGraph.writeGraph(Config_getString(HTML_OUTPUT),fd->getOutputFileBase());
534 void FileDef::writeSourceLink(OutputList &ol)
536 //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile());
537 if (generateSourceFile())
539 ol.disableAllBut(OutputGenerator::Html);
541 ol.startTextLink(includeName(),0);
542 ol.parseText(theTranslator->trGotoSourceCode());
549 void FileDef::writeNamespaceDeclarations(OutputList &ol,const QCString &title,
550 bool const isConstantGroup)
552 // write list of namespaces
553 if (m_namespaceSDict) m_namespaceSDict->writeDeclaration(ol,title,isConstantGroup);
556 void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title)
558 // write list of classes
559 if (m_classSDict) m_classSDict->writeDeclaration(ol,0,title,FALSE);
562 void FileDef::writeInlineClasses(OutputList &ol)
564 // temporarily undo the disbling could be done by startMemberDocumentation()
565 // as a result of setting SEPARATE_MEMBER_PAGES to YES; see bug730512
566 bool isEnabled = ol.isEnabled(OutputGenerator::Html);
567 ol.enable(OutputGenerator::Html);
569 if (m_classSDict) m_classSDict->writeDocumentation(ol,this);
571 // restore the initial state if needed
572 if (!isEnabled) ol.disable(OutputGenerator::Html);
575 void FileDef::startMemberDeclarations(OutputList &ol)
577 ol.startMemberSections();
580 void FileDef::endMemberDeclarations(OutputList &ol)
582 ol.endMemberSections();
585 void FileDef::startMemberDocumentation(OutputList &ol)
587 if (Config_getBool(SEPARATE_MEMBER_PAGES))
589 ol.disable(OutputGenerator::Html);
590 Doxygen::suppressDocWarnings = TRUE;
594 void FileDef::endMemberDocumentation(OutputList &ol)
596 if (Config_getBool(SEPARATE_MEMBER_PAGES))
598 ol.enable(OutputGenerator::Html);
599 Doxygen::suppressDocWarnings = FALSE;
603 void FileDef::writeMemberGroups(OutputList &ol)
605 /* write user defined member groups */
606 if (m_memberGroupSDict)
608 m_memberGroupSDict->sort();
609 MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
611 for (;(mg=mgli.current());++mgli)
613 if ((!mg->allMembersInSameSection() || !m_subGrouping)
614 && mg->header()!="[NOHEADER]")
616 mg->writeDeclarations(ol,0,0,this,0);
622 void FileDef::writeAuthorSection(OutputList &ol)
624 // write Author section (Man only)
625 ol.pushGeneratorState();
626 ol.disableAllBut(OutputGenerator::Man);
627 ol.startGroupHeader();
628 ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
630 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString(PROJECT_NAME)));
631 ol.popGeneratorState();
634 void FileDef::writeSummaryLinks(OutputList &ol)
636 ol.pushGeneratorState();
637 ol.disableAllBut(OutputGenerator::Html);
638 QListIterator<LayoutDocEntry> eli(
639 LayoutDocManager::instance().docEntries(LayoutDocManager::File));
642 SrcLangExt lang=getLanguage();
643 for (eli.toFirst();(lde=eli.current());++eli)
645 if ((lde->kind()==LayoutDocEntry::FileClasses &&
646 m_classSDict && m_classSDict->declVisible()) ||
647 (lde->kind()==LayoutDocEntry::FileNamespaces &&
648 m_namespaceSDict && m_namespaceSDict->declVisible())
651 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
652 QCString label = lde->kind()==LayoutDocEntry::FileClasses ? "nested-classes" : "namespaces";
653 ol.writeSummaryLink(0,label,ls->title(lang),first);
656 else if (lde->kind()==LayoutDocEntry::MemberDecl)
658 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
659 MemberList * ml = getMemberList(lmd->type);
660 if (ml && ml->declVisible())
662 ol.writeSummaryLink(0,MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
669 ol.writeString(" </div>\n");
671 ol.popGeneratorState();
674 /*! Write the documentation page for this file to the file of output
677 void FileDef::writeDocumentation(OutputList &ol)
679 static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
680 //funcList->countDecMembers();
682 //QCString fn = name();
683 //if (Config_getBool(FULL_PATH_NAMES))
685 // fn.prepend(stripFromPath(getPath().copy()));
688 //printf("WriteDocumentation diskname=%s\n",diskname.data());
690 QCString versionTitle;
691 if (!m_fileVersion.isEmpty())
693 versionTitle=("("+m_fileVersion+")");
695 QCString title = m_docname+versionTitle;
696 QCString pageTitle=theTranslator->trFileReference(m_docname);
700 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,!generateTreeView);
701 if (!generateTreeView)
703 getDirDef()->writeNavigationPath(ol);
704 ol.endQuickIndices();
706 QCString pageTitleShort=theTranslator->trFileReference(name());
707 startTitle(ol,getOutputFileBase(),this);
708 ol.pushGeneratorState();
709 ol.disableAllBut(OutputGenerator::Html);
710 ol.parseText(pageTitleShort); // Html only
712 ol.disable(OutputGenerator::Html);
713 ol.parseText(pageTitle); // other output formats
714 ol.popGeneratorState();
715 addGroupListToTitle(ol,this);
716 endTitle(ol,getOutputFileBase(),title);
720 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,!generateTreeView);
721 if (!generateTreeView)
723 ol.endQuickIndices();
725 startTitle(ol,getOutputFileBase(),this);
726 ol.parseText(pageTitle);
727 addGroupListToTitle(ol,this);
728 endTitle(ol,getOutputFileBase(),title);
733 if (!m_fileVersion.isEmpty())
735 ol.disableAllBut(OutputGenerator::Html);
736 ol.startProjectNumber();
737 ol.docify(versionTitle);
738 ol.endProjectNumber();
742 if (Doxygen::searchIndex)
744 Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
745 Doxygen::searchIndex->addWord(localName(),TRUE);
749 //---------------------------------------- start flexible part -------------------------------
751 SrcLangExt lang = getLanguage();
752 QListIterator<LayoutDocEntry> eli(
753 LayoutDocManager::instance().docEntries(LayoutDocManager::File));
755 for (eli.toFirst();(lde=eli.current());++eli)
759 case LayoutDocEntry::BriefDesc:
760 writeBriefDescription(ol);
762 case LayoutDocEntry::MemberDeclStart:
763 startMemberDeclarations(ol);
765 case LayoutDocEntry::FileIncludes:
766 writeIncludeFiles(ol);
768 case LayoutDocEntry::FileIncludeGraph:
769 writeIncludeGraph(ol);
771 case LayoutDocEntry::FileIncludedByGraph:
772 writeIncludedByGraph(ol);
774 case LayoutDocEntry::FileSourceLink:
777 case LayoutDocEntry::FileClasses:
779 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
780 writeClassDeclarations(ol,ls->title(lang));
783 case LayoutDocEntry::FileNamespaces:
785 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
786 writeNamespaceDeclarations(ol,ls->title(lang),false);
789 case LayoutDocEntry::FileConstantGroups:
791 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
792 writeNamespaceDeclarations(ol,ls->title(lang),true);
795 case LayoutDocEntry::MemberGroups:
796 writeMemberGroups(ol);
798 case LayoutDocEntry::MemberDecl:
800 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
801 writeMemberDeclarations(ol,lmd->type,lmd->title(lang));
804 case LayoutDocEntry::MemberDeclEnd:
805 endMemberDeclarations(ol);
807 case LayoutDocEntry::DetailedDesc:
809 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
810 writeDetailedDescription(ol,ls->title(lang));
813 case LayoutDocEntry::MemberDefStart:
814 startMemberDocumentation(ol);
816 case LayoutDocEntry::FileInlineClasses:
817 writeInlineClasses(ol);
819 case LayoutDocEntry::MemberDef:
821 LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
822 writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
825 case LayoutDocEntry::MemberDefEnd:
826 endMemberDocumentation(ol);
828 case LayoutDocEntry::AuthorSection:
829 writeAuthorSection(ol);
831 case LayoutDocEntry::ClassIncludes:
832 case LayoutDocEntry::ClassInheritanceGraph:
833 case LayoutDocEntry::ClassNestedClasses:
834 case LayoutDocEntry::ClassCollaborationGraph:
835 case LayoutDocEntry::ClassAllMembersLink:
836 case LayoutDocEntry::ClassUsedFiles:
837 case LayoutDocEntry::ClassInlineClasses:
838 case LayoutDocEntry::NamespaceNestedNamespaces:
839 case LayoutDocEntry::NamespaceNestedConstantGroups:
840 case LayoutDocEntry::NamespaceClasses:
841 case LayoutDocEntry::NamespaceInlineClasses:
842 case LayoutDocEntry::GroupClasses:
843 case LayoutDocEntry::GroupInlineClasses:
844 case LayoutDocEntry::GroupNamespaces:
845 case LayoutDocEntry::GroupDirs:
846 case LayoutDocEntry::GroupNestedGroups:
847 case LayoutDocEntry::GroupFiles:
848 case LayoutDocEntry::GroupGraph:
849 case LayoutDocEntry::GroupPageDocs:
850 case LayoutDocEntry::DirSubDirs:
851 case LayoutDocEntry::DirFiles:
852 case LayoutDocEntry::DirGraph:
853 err("Internal inconsistency: member %d should not be part of "
854 "LayoutDocManager::File entry list\n",lde->kind());
859 //---------------------------------------- end flexible part -------------------------------
863 endFileWithNavPath(this,ol);
865 if (Config_getBool(SEPARATE_MEMBER_PAGES))
867 MemberList *ml = getMemberList(MemberListType_allMembersList);
869 writeMemberPages(ol);
873 void FileDef::writeMemberPages(OutputList &ol)
875 ol.pushGeneratorState();
876 ol.disableAllBut(OutputGenerator::Html);
878 QListIterator<MemberList> mli(m_memberLists);
880 for (mli.toFirst();(ml=mli.current());++mli)
882 if (ml->listType()&MemberListType_documentationLists)
884 ml->writeDocumentationPage(ol,name(),this);
888 ol.popGeneratorState();
891 void FileDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
893 static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
895 ol.writeString(" <div class=\"navtab\">\n");
896 ol.writeString(" <table>\n");
898 MemberList *allMemberList = getMemberList(MemberListType_allMembersList);
901 MemberListIterator mli(*allMemberList);
903 for (mli.toFirst();(md=mli.current());++mli)
905 if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable() && !md->isEnumValue())
907 ol.writeString(" <tr><td class=\"navtab\">");
908 if (md->isLinkableInProject())
910 if (md==currentMd) // selected item => highlight
912 ol.writeString("<a class=\"qindexHL\" ");
916 ol.writeString("<a class=\"qindex\" ");
918 ol.writeString("href=\"");
919 if (createSubDirs) ol.writeString("../../");
920 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
921 ol.writeString("\">");
922 ol.writeString(convertToHtml(md->localName()));
923 ol.writeString("</a>");
925 ol.writeString("</td></tr>\n");
930 ol.writeString(" </table>\n");
931 ol.writeString(" </div>\n");
934 /*! Write a source listing of this file to the output */
935 void FileDef::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu)
937 static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
938 static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
939 static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE);
940 static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE);
941 DevNullCodeDocInterface devNullIntf;
942 QCString title = m_docname;
943 if (!m_fileVersion.isEmpty())
945 title+=(" ("+m_fileVersion+")");
947 QCString pageTitle = theTranslator->trSourceFile(title);
948 ol.disable(OutputGenerator::Man);
949 if (!latexSourceCode) ol.disable(OutputGenerator::Latex);
950 if (!rtfSourceCode) ol.disable(OutputGenerator::RTF);
952 bool isDocFile = isDocumentationFile();
953 bool genSourceFile = !isDocFile && generateSourceFile();
956 startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,
958 !isDocFile && genSourceFile ? QCString() : getOutputFileBase());
959 if (!generateTreeView)
961 getDirDef()->writeNavigationPath(ol);
962 ol.endQuickIndices();
964 startTitle(ol,getSourceFileBase());
965 ol.parseText(name());
966 endTitle(ol,getSourceFileBase(),title);
970 startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,FALSE,
971 !isDocFile && genSourceFile ? QCString() : getOutputFileBase());
972 startTitle(ol,getSourceFileBase());
974 endTitle(ol,getSourceFileBase(),0);
981 if (latexSourceCode) ol.disable(OutputGenerator::Latex);
982 if (rtfSourceCode) ol.disable(OutputGenerator::RTF);
983 ol.startTextLink(getOutputFileBase(),0);
984 ol.parseText(theTranslator->trGotoDocumentation());
986 if (latexSourceCode) ol.enable(OutputGenerator::Latex);
987 if (rtfSourceCode) ol.enable(OutputGenerator::RTF);
993 static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
994 if (clangAssistedParsing &&
995 (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC))
997 ol.startCodeFragment();
1000 ClangParser::instance()->start(absFilePath(),filesInSameTu);
1004 ClangParser::instance()->switchToFile(absFilePath());
1006 ClangParser::instance()->writeSources(ol,this);
1007 ol.endCodeFragment();
1012 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
1013 pIntf->resetCodeParserState();
1014 ol.startCodeFragment();
1015 bool needs2PassParsing =
1016 Doxygen::parseSourcesNeeded && // we need to parse (filtered) sources for cross-references
1017 !filterSourceFiles && // but user wants to show sources as-is
1018 !getFileFilter(absFilePath(),TRUE).isEmpty(); // and there is a filter used while parsing
1020 if (needs2PassParsing)
1022 // parse code for cross-references only (see bug707641)
1023 pIntf->parseCode(devNullIntf,0,
1024 fileToString(absFilePath(),TRUE,TRUE),
1029 pIntf->parseCode(ol,0,
1030 fileToString(absFilePath(),filterSourceFiles,TRUE),
1031 getLanguage(), // lang
1032 FALSE, // isExampleBlock
1037 FALSE, // inlineFragment
1039 TRUE, // showLineNumbers
1041 !needs2PassParsing // collectXRefs
1043 ol.endCodeFragment();
1046 endFileWithNavPath(this,ol);
1050 void FileDef::parseSource(bool sameTu,QStrList &filesInSameTu)
1052 static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
1053 DevNullCodeDocInterface devNullIntf;
1055 (void)filesInSameTu;
1057 static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
1058 if (clangAssistedParsing &&
1059 (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC))
1063 ClangParser::instance()->start(absFilePath(),filesInSameTu);
1067 ClangParser::instance()->switchToFile(absFilePath());
1069 ClangParser::instance()->writeSources(devNullIntf,this);
1074 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
1075 pIntf->resetCodeParserState();
1078 fileToString(absFilePath(),filterSourceFiles,TRUE),
1085 void FileDef::startParsing()
1089 void FileDef::finishParsing()
1091 ClangParser::instance()->finish();
1094 void FileDef::addMembersToMemberGroup()
1096 QListIterator<MemberList> mli(m_memberLists);
1098 for (mli.toFirst();(ml=mli.current());++mli)
1100 if (ml->listType()&MemberListType_declarationLists)
1102 ::addMembersToMemberGroup(ml,&m_memberGroupSDict,this);
1106 // add members inside sections to their groups
1107 if (m_memberGroupSDict)
1109 MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
1111 for (;(mg=mgli.current());++mgli)
1113 if (mg->allMembersInSameSection() && m_subGrouping)
1115 //printf("----> addToDeclarationSection(%s)\n",mg->header().data());
1116 mg->addToDeclarationSection();
1122 /*! Adds member definition \a md to the list of all members of this file */
1123 void FileDef::insertMember(MemberDef *md)
1125 if (md->isHidden()) return;
1126 //printf("%s:FileDef::insertMember(%s (=%p) list has %d elements)\n",
1127 // name().data(),md->name().data(),md,allMemberList.count());
1128 MemberList *allMemberList = getMemberList(MemberListType_allMembersList);
1129 if (allMemberList && allMemberList->findRef(md)!=-1) // TODO optimize the findRef!
1134 if (allMemberList==0)
1136 allMemberList = new MemberList(MemberListType_allMembersList);
1137 m_memberLists.append(allMemberList);
1139 allMemberList->append(md);
1140 //::addFileMemberNameToIndex(md);
1141 switch (md->memberType())
1143 case MemberType_Variable:
1144 case MemberType_Property:
1145 addMemberToList(MemberListType_decVarMembers,md);
1146 addMemberToList(MemberListType_docVarMembers,md);
1148 case MemberType_Function:
1149 addMemberToList(MemberListType_decFuncMembers,md);
1150 addMemberToList(MemberListType_docFuncMembers,md);
1152 case MemberType_Typedef:
1153 addMemberToList(MemberListType_decTypedefMembers,md);
1154 addMemberToList(MemberListType_docTypedefMembers,md);
1156 case MemberType_Enumeration:
1157 addMemberToList(MemberListType_decEnumMembers,md);
1158 addMemberToList(MemberListType_docEnumMembers,md);
1160 case MemberType_EnumValue: // enum values are shown inside their enums
1162 case MemberType_Define:
1163 addMemberToList(MemberListType_decDefineMembers,md);
1164 addMemberToList(MemberListType_docDefineMembers,md);
1167 err("FileDef::insertMembers(): "
1168 "member `%s' with class scope `%s' inserted in file scope `%s'!\n",
1170 md->getClassDef() ? md->getClassDef()->name().data() : "<global>",
1173 //addMemberToGroup(md,groupId);
1176 /*! Adds compound definition \a cd to the list of all compounds of this file */
1177 void FileDef::insertClass(ClassDef *cd)
1179 if (cd->isHidden()) return;
1180 if (m_classSDict==0)
1182 m_classSDict = new ClassSDict(17);
1184 if (Config_getBool(SORT_BRIEF_DOCS))
1186 m_classSDict->inSort(cd->name(),cd);
1190 m_classSDict->append(cd->name(),cd);
1194 /*! Adds namespace definition \a nd to the list of all compounds of this file */
1195 void FileDef::insertNamespace(NamespaceDef *nd)
1197 if (nd->isHidden()) return;
1198 if (!nd->name().isEmpty() &&
1199 (m_namespaceSDict==0 || m_namespaceSDict->find(nd->name())==0))
1201 if (m_namespaceSDict==0)
1203 m_namespaceSDict = new NamespaceSDict;
1205 if (Config_getBool(SORT_BRIEF_DOCS))
1207 m_namespaceSDict->inSort(nd->name(),nd);
1211 m_namespaceSDict->append(nd->name(),nd);
1216 QCString FileDef::name() const
1218 if (Config_getBool(FULL_PATH_NAMES))
1221 return Definition::name();
1224 void FileDef::addSourceRef(int line,Definition *d,MemberDef *md)
1226 //printf("FileDef::addSourceDef(%d,%p,%p)\n",line,d,md);
1229 if (m_srcDefDict==0) m_srcDefDict = new QIntDict<Definition>(257);
1230 if (m_srcMemberDict==0) m_srcMemberDict = new QIntDict<MemberDef>(257);
1231 m_srcDefDict->insert(line,d);
1232 if (md) m_srcMemberDict->insert(line,md);
1233 //printf("Adding member %s with anchor %s at line %d to file %s\n",
1234 // md?md->name().data():"<none>",md?md->anchor().data():"<none>",line,name().data());
1238 Definition *FileDef::getSourceDefinition(int lineNr) const
1240 Definition *result=0;
1243 result = m_srcDefDict->find(lineNr);
1245 //printf("%s::getSourceDefinition(%d)=%s\n",name().data(),lineNr,result?result->name().data():"none");
1249 MemberDef *FileDef::getSourceMember(int lineNr) const
1251 MemberDef *result=0;
1252 if (m_srcMemberDict)
1254 result = m_srcMemberDict->find(lineNr);
1256 //printf("%s::getSourceMember(%d)=%s\n",name().data(),lineNr,result?result->name().data():"none");
1261 void FileDef::addUsingDirective(NamespaceDef *nd)
1263 if (m_usingDirList==0)
1265 m_usingDirList = new NamespaceSDict;
1267 if (m_usingDirList->find(nd->qualifiedName())==0)
1269 m_usingDirList->append(nd->qualifiedName(),nd);
1271 //printf("%p: FileDef::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count());
1274 NamespaceSDict *FileDef::getUsedNamespaces() const
1276 //printf("%p: FileDef::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0);
1277 return m_usingDirList;
1280 void FileDef::addUsingDeclaration(Definition *d)
1282 if (m_usingDeclList==0)
1284 m_usingDeclList = new SDict<Definition>(17);
1286 if (m_usingDeclList->find(d->qualifiedName())==0)
1288 m_usingDeclList->append(d->qualifiedName(),d);
1292 void FileDef::addIncludeDependency(FileDef *fd,const char *incName,bool local,
1293 bool imported,bool indirect)
1295 //printf("FileDef::addIncludeDependency(%p,%s,%d)\n",fd,incName,local);
1296 QCString iName = fd ? fd->absFilePath().data() : incName;
1297 if (!iName.isEmpty() && (!m_includeDict || m_includeDict->find(iName)==0))
1299 if (m_includeDict==0)
1301 m_includeDict = new QDict<IncludeInfo>(61);
1302 m_includeList = new QList<IncludeInfo>;
1303 m_includeList->setAutoDelete(TRUE);
1305 IncludeInfo *ii = new IncludeInfo;
1307 ii->includeName = incName;
1309 ii->imported = imported;
1310 ii->indirect = indirect;
1311 m_includeList->append(ii);
1312 m_includeDict->insert(iName,ii);
1316 void FileDef::addIncludedUsingDirectives()
1318 if (visited) return;
1320 //printf("( FileDef::addIncludedUsingDirectives for file %s\n",name().data());
1322 if (m_includeList) // file contains #includes
1325 QListIterator<IncludeInfo> iii(*m_includeList);
1327 for (iii.toFirst();(ii=iii.current());++iii) // foreach #include...
1329 if (ii->fileDef && !ii->fileDef->visited) // ...that is a known file
1331 // recurse into this file
1332 ii->fileDef->addIncludedUsingDirectives();
1337 QListIterator<IncludeInfo> iii(*m_includeList);
1339 // iterate through list from last to first
1340 for (iii.toLast();(ii=iii.current());--iii)
1342 if (ii->fileDef && ii->fileDef!=this)
1344 // add using directives
1345 NamespaceSDict *unl = ii->fileDef->m_usingDirList;
1348 NamespaceSDict::Iterator nli(*unl);
1350 for (nli.toLast();(nd=nli.current());--nli)
1352 // append each using directive found in a #include file
1353 if (m_usingDirList==0) m_usingDirList = new NamespaceSDict;
1354 //printf("Prepending used namespace %s to the list of file %s\n",
1355 // nd->name().data(),name().data());
1356 if (m_usingDirList->find(nd->qualifiedName())==0) // not yet added
1358 m_usingDirList->prepend(nd->qualifiedName(),nd);
1362 // add using declarations
1363 SDict<Definition> *udl = ii->fileDef->m_usingDeclList;
1366 SDict<Definition>::Iterator udi(*udl);
1368 for (udi.toLast();(d=udi.current());--udi)
1370 //printf("Adding using declaration %s\n",d->name().data());
1371 if (m_usingDeclList==0)
1373 m_usingDeclList = new SDict<Definition>(17);
1375 if (m_usingDeclList->find(d->qualifiedName())==0)
1377 m_usingDeclList->prepend(d->qualifiedName(),d);
1385 //printf(") end FileDef::addIncludedUsingDirectives for file %s\n",name().data());
1389 void FileDef::addIncludedByDependency(FileDef *fd,const char *incName,
1390 bool local,bool imported)
1392 //printf("FileDef::addIncludedByDependency(%p,%s,%d)\n",fd,incName,local);
1393 QCString iName = fd ? fd->absFilePath().data() : incName;
1394 if (!iName.isEmpty() && (m_includedByDict==0 || m_includedByDict->find(iName)==0))
1396 if (m_includedByDict==0)
1398 m_includedByDict = new QDict<IncludeInfo>(61);
1399 m_includedByList = new QList<IncludeInfo>;
1400 m_includedByList->setAutoDelete(TRUE);
1402 IncludeInfo *ii = new IncludeInfo;
1404 ii->includeName = incName;
1406 ii->imported = imported;
1407 ii->indirect = FALSE;
1408 m_includedByList->append(ii);
1409 m_includedByDict->insert(iName,ii);
1413 bool FileDef::isIncluded(const QCString &name) const
1415 if (name.isEmpty()) return FALSE;
1416 return m_includeDict!=0 && m_includeDict->find(name)!=0;
1419 bool FileDef::generateSourceFile() const
1421 static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1422 static bool verbatimHeaders = Config_getBool(VERBATIM_HEADERS);
1423 QCString extension = name().right(4);
1424 return !isReference() &&
1426 (verbatimHeaders && guessSection(name())==Entry::HEADER_SEC)
1428 extension!=".doc" && extension!=".txt" && extension!=".dox" &&
1429 extension!=".md" && name().right(9)!=".markdown";
1433 void FileDef::addListReferences()
1436 QList<ListItemInfo> *xrefItems = xrefListItems();
1437 addRefItem(xrefItems,
1438 getOutputFileBase(),
1439 theTranslator->trFile(TRUE,TRUE),
1440 getOutputFileBase(),name(),
1445 if (m_memberGroupSDict)
1447 MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
1449 for (;(mg=mgli.current());++mgli)
1451 mg->addListReferences(this);
1454 QListIterator<MemberList> mli(m_memberLists);
1456 for (mli.toFirst();(ml=mli.current());++mli)
1458 if (ml->listType()&MemberListType_documentationLists)
1460 ml->addListReferences(this);
1465 //-------------------------------------------------------------------
1467 static int findMatchingPart(const QCString &path,const QCString dir)
1471 while ((si1=path.find('/',pos1))!=-1)
1473 int si2=dir.find('/',pos2);
1474 //printf(" found slash at pos %d in path %d: %s<->%s\n",si1,si2,
1475 // path.mid(pos1,si1-pos2).data(),dir.mid(pos2).data());
1476 if (si2==-1 && path.mid(pos1,si1-pos2)==dir.mid(pos2)) // match at end
1478 return dir.length();
1480 if (si1!=si2 || path.mid(pos1,si1-pos2)!=dir.mid(pos2,si2-pos2)) // no match in middle
1482 return QMAX(pos1-1,0);
1490 static Directory *findDirNode(Directory *root,const QCString &name)
1492 QListIterator<DirEntry> dli(root->children());
1494 for (dli.toFirst();(de=dli.current());++dli)
1496 if (de->kind()==DirEntry::Dir)
1498 Directory *dir = (Directory *)de;
1499 QCString dirName=dir->name();
1500 int sp=findMatchingPart(name,dirName);
1501 //printf("findMatchingPart(%s,%s)=%d\n",name.data(),dirName.data(),sp);
1502 if (sp>0) // match found
1504 if ((uint)sp==dirName.length()) // whole directory matches
1506 // recurse into the directory
1507 return findDirNode(dir,name.mid(dirName.length()+1));
1509 else // partial match => we need to split the path into three parts
1511 QCString baseName =dirName.left(sp);
1512 QCString oldBranchName=dirName.mid(sp+1);
1513 QCString newBranchName=name.mid(sp+1);
1514 // strip file name from path
1515 int newIndex=newBranchName.findRev('/');
1516 if (newIndex>0) newBranchName=newBranchName.left(newIndex);
1518 //printf("Splitting off part in new branch \n"
1519 // "base=%s old=%s new=%s\n",
1521 // oldBranchName.data(),
1522 // newBranchName.data()
1524 Directory *base = new Directory(root,baseName);
1525 Directory *newBranch = new Directory(base,newBranchName);
1526 dir->reParent(base);
1527 dir->rename(oldBranchName);
1528 base->addChild(dir);
1529 base->addChild(newBranch);
1530 dir->setLast(FALSE);
1531 // remove DirEntry container from list (without deleting it)
1532 root->children().setAutoDelete(FALSE);
1533 root->children().removeRef(dir);
1534 root->children().setAutoDelete(TRUE);
1535 // add new branch to the root
1536 if (!root->children().isEmpty())
1538 root->children().getLast()->setLast(FALSE);
1540 root->addChild(base);
1546 int si=name.findRev('/');
1547 if (si==-1) // no subdir
1549 return root; // put the file under the root node.
1551 else // need to create a subdir
1553 QCString baseName = name.left(si);
1554 //printf("new subdir %s\n",baseName.data());
1555 Directory *newBranch = new Directory(root,baseName);
1556 if (!root->children().isEmpty())
1558 root->children().getLast()->setLast(FALSE);
1560 root->addChild(newBranch);
1565 static void mergeFileDef(Directory *root,FileDef *fd)
1567 QCString filePath = fd->absFilePath();
1568 //printf("merging %s\n",filePath.data());
1569 Directory *dirNode = findDirNode(root,filePath);
1570 if (!dirNode->children().isEmpty())
1572 dirNode->children().getLast()->setLast(FALSE);
1574 DirEntry *e=new DirEntry(dirNode,fd);
1575 dirNode->addChild(e);
1579 static void generateIndent(QTextStream &t,DirEntry *de,int level)
1583 generateIndent(t,de->parent(),level+1);
1585 // from the root up to node n do...
1586 if (level==0) // item before a dir or document
1590 if (de->kind()==DirEntry::Dir)
1592 t << "<img " << FTV_IMGATTRIBS(plastnode) << "/>";
1596 t << "<img " << FTV_IMGATTRIBS(lastnode) << "/>";
1601 if (de->kind()==DirEntry::Dir)
1603 t << "<img " << FTV_IMGATTRIBS(pnode) << "/>";
1607 t << "<img " << FTV_IMGATTRIBS(node) << "/>";
1611 else // item at another level
1615 t << "<img " << FTV_IMGATTRIBS(blank) << "/>";
1619 t << "<img " << FTV_IMGATTRIBS(vertline) << "/>";
1624 static void writeDirTreeNode(QTextStream &t,Directory *root,int level)
1627 indent.fill(' ',level*2);
1628 QListIterator<DirEntry> dli(root->children());
1630 for (dli.toFirst();(de=dli.current());++dli)
1632 t << indent << "<p>";
1633 generateIndent(t,de,0);
1634 if (de->kind()==DirEntry::Dir)
1636 Directory *dir=(Directory *)de;
1637 //printf("%s [dir]: %s (last=%d,dir=%d)\n",indent.data(),dir->name().data(),dir->isLast(),dir->kind()==DirEntry::Dir);
1638 t << "<img " << FTV_IMGATTRIBS(folderclosed) << "/>";
1641 t << indent << "<div>\n";
1642 writeDirTreeNode(t,dir,level+1);
1643 t << indent << "</div>\n";
1647 //printf("%s [file]: %s (last=%d,dir=%d)\n",indent.data(),de->file()->name().data(),de->isLast(),de->kind()==DirEntry::Dir);
1648 t << "<img " << FTV_IMGATTRIBS(doc) << "/>";
1649 t << de->file()->name();
1656 static void addDirsAsGroups(Directory *root,GroupDef *parent,int level)
1659 if (root->kind()==DirEntry::Dir)
1661 gd = new GroupDef("[generated]",
1663 root->path(), // name
1664 root->name() // title
1668 parent->addGroup(gd);
1669 gd->makePartOfGroup(parent);
1673 Doxygen::groupSDict->append(root->path(),gd);
1676 QListIterator<DirEntry> dli(root->children());
1678 for (dli.toFirst();(de=dli.current());++dli)
1680 if (de->kind()==DirEntry::Dir)
1682 addDirsAsGroups((Directory *)de,gd,level+1);
1687 void generateFileTree()
1689 Directory *root=new Directory(0,"root");
1690 root->setLast(TRUE);
1691 FileNameListIterator fnli(*Doxygen::inputNameList);
1693 for (fnli.toFirst();(fn=fnli.current());++fnli)
1695 FileNameIterator fni(*fn);
1697 for (;(fd=fni.current());++fni)
1699 mergeFileDef(root,fd);
1702 //t << "<div class=\"directory\">\n";
1703 //writeDirTreeNode(t,root,0);
1705 addDirsAsGroups(root,0,0);
1709 //-------------------------------------------------------------------
1711 void FileDef::combineUsingRelations()
1713 if (visited) return; // already done
1717 NamespaceSDict::Iterator nli(*m_usingDirList);
1719 for (nli.toFirst();(nd=nli.current());++nli)
1721 nd->combineUsingRelations();
1723 for (nli.toFirst();(nd=nli.current());++nli)
1725 // add used namespaces of namespace nd to this namespace
1726 if (nd->getUsedNamespaces())
1728 NamespaceSDict::Iterator unli(*nd->getUsedNamespaces());
1730 for (unli.toFirst();(und=unli.current());++unli)
1732 //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data());
1733 addUsingDirective(und);
1736 // add used classes of namespace nd to this namespace
1737 if (nd->getUsedClasses())
1739 SDict<Definition>::Iterator cli(*nd->getUsedClasses());
1741 for (cli.toFirst();(ucd=cli.current());++cli)
1743 //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data());
1744 addUsingDeclaration(ucd);
1751 bool FileDef::isDocumentationFile() const
1753 return name().right(4)==".doc" ||
1754 name().right(4)==".txt" ||
1755 name().right(4)==".dox" ||
1756 name().right(3)==".md" ||
1757 name().right(9)==".markdown";
1760 void FileDef::acquireFileVersion()
1762 QCString vercmd = Config_getString(FILE_VERSION_FILTER);
1763 if (!vercmd.isEmpty() && !m_filePath.isEmpty() &&
1764 m_filePath!="generated" && m_filePath!="graph_legend")
1766 msg("Version of %s : ",m_filePath.data());
1767 QCString cmd = vercmd+" \""+m_filePath+"\"";
1768 Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd));
1769 FILE *f=portable_popen(cmd,"r");
1772 err("could not execute %s\n",vercmd.data());
1775 const int bufSize=1024;
1777 int numRead = (int)fread(buf,1,bufSize-1,f);
1779 if (numRead>0 && numRead<bufSize)
1782 m_fileVersion=QCString(buf,numRead).stripWhiteSpace();
1783 if (!m_fileVersion.isEmpty())
1785 msg("%s\n",m_fileVersion.data());
1789 msg("no version available\n");
1794 QCString FileDef::getSourceFileBase() const
1796 if (Htags::useHtags)
1798 return Htags::path2URL(m_filePath);
1802 return m_outputDiskName+"_source";
1806 QCString FileDef::getOutputFileBase() const
1808 return m_outputDiskName;
1811 /*! Returns the name of the verbatim copy of this file (if any). */
1812 QCString FileDef::includeName() const
1814 return getSourceFileBase();
1817 MemberList *FileDef::createMemberList(MemberListType lt)
1819 m_memberLists.setAutoDelete(TRUE);
1820 QListIterator<MemberList> mli(m_memberLists);
1822 for (mli.toFirst();(ml=mli.current());++mli)
1824 if (ml->listType()==lt)
1829 // not found, create a new member list
1830 ml = new MemberList(lt);
1831 m_memberLists.append(ml);
1835 void FileDef::addMemberToList(MemberListType lt,MemberDef *md)
1837 static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
1838 static bool sortMemberDocs = Config_getBool(SORT_MEMBER_DOCS);
1839 MemberList *ml = createMemberList(lt);
1840 ml->setNeedsSorting(
1841 ((ml->listType()&MemberListType_declarationLists) && sortBriefDocs) ||
1842 ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs));
1845 if (ml->needsSorting())
1850 if (lt&MemberListType_documentationLists)
1852 ml->setInFile(TRUE);
1854 if (ml->listType()&MemberListType_declarationLists) md->setSectionList(this,ml);
1857 void FileDef::sortMemberLists()
1859 QListIterator<MemberList> mli(m_memberLists);
1861 for (;(ml=mli.current());++mli)
1863 if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
1867 MemberList *FileDef::getMemberList(MemberListType lt) const
1869 QListIterator<MemberList> mli(m_memberLists);
1871 for (;(ml=mli.current());++mli)
1873 if (ml->listType()==lt)
1881 void FileDef::writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title)
1883 static bool optVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
1884 MemberList * ml = getMemberList(lt);
1887 if (optVhdl) // use specific declarations function
1890 VhdlDocGen::writeVhdlDeclarations(ml,ol,0,0,this,0);
1894 ml->writeDeclarations(ol,0,0,this,0,title,0);
1899 void FileDef::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title)
1901 MemberList * ml = getMemberList(lt);
1902 if (ml) ml->writeDocumentation(ol,name(),this,title);
1905 bool FileDef::isLinkableInProject() const
1907 static bool showFiles = Config_getBool(SHOW_FILES);
1908 return hasDocumentation() && !isReference() && (showFiles || isLinkableViaGroup());
1911 static void getAllIncludeFilesRecursively(
1912 QDict<void> *filesVisited,const FileDef *fd,QStrList &incFiles)
1914 if (fd->includeFileList())
1916 QListIterator<IncludeInfo> iii(*fd->includeFileList());
1918 for (iii.toFirst();(ii=iii.current());++iii)
1920 if (ii->fileDef && !ii->fileDef->isReference() &&
1921 !filesVisited->find(ii->fileDef->absFilePath()))
1923 //printf("FileDef::addIncludeDependency(%s)\n",ii->fileDef->absFilePath().data());
1924 incFiles.append(ii->fileDef->absFilePath());
1925 filesVisited->insert(ii->fileDef->absFilePath(),(void*)0x8);
1926 getAllIncludeFilesRecursively(filesVisited,ii->fileDef,incFiles);
1932 void FileDef::getAllIncludeFilesRecursively(QStrList &incFiles) const
1934 QDict<void> includes(257);
1935 ::getAllIncludeFilesRecursively(&includes,this,incFiles);
1938 QCString FileDef::title() const
1940 return theTranslator->trFileReference(name());
1943 QCString FileDef::fileVersion() const
1945 return m_fileVersion;
1948 QCString FileDef::includeDependencyGraphFileName() const
1950 return m_inclDepFileName;
1953 QCString FileDef::includedByDependencyGraphFileName() const
1955 return m_inclByDepFileName;