diff options
author | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2007-07-19 13:04:41 (GMT) |
---|---|---|
committer | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2007-07-19 13:04:41 (GMT) |
commit | 687fe7a1487c68f0c6b4ef7d169b23ff274ab9ca (patch) | |
tree | 7c115c97f09109f537a6eb50b9baa3c0cd91d07d | |
parent | 34ca582041237fd0b2c91b58afd2a39dc91cf0a8 (diff) | |
download | Doxygen-687fe7a1487c68f0c6b4ef7d169b23ff274ab9ca.zip Doxygen-687fe7a1487c68f0c6b4ef7d169b23ff274ab9ca.tar.gz Doxygen-687fe7a1487c68f0c6b4ef7d169b23ff274ab9ca.tar.bz2 |
Release-1.5.2-20070719
43 files changed, 1205 insertions, 440 deletions
@@ -1,7 +1,7 @@ -DOXYGEN Version 1.5.2-20070610 +DOXYGEN Version 1.5.2-20070719 Please read the installation section of the manual (http://www.doxygen.org/install.html) for instructions. -------- -Dimitri van Heesch (10 June 2007) +Dimitri van Heesch (19 July 2007) diff --git a/Makefile.in b/Makefile.in index 55ac74a..233e57b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -54,15 +54,15 @@ install: doxywizard_install $(INSTTOOL) -m 755 bin/doxygen $(INSTALL)/bin $(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin $(INSTTOOL) -d $(INSTALL)/$(MAN1DIR) - cat doc/doxygen.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxygen.1 + cat doc/doxygen.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > doxygen.1 $(INSTTOOL) -m 644 doxygen.1 $(INSTALL)/$(MAN1DIR)/doxygen.1 rm doxygen.1 - cat doc/doxytag.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxytag.1 + cat doc/doxytag.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > doxytag.1 $(INSTTOOL) -m 644 doxytag.1 $(INSTALL)/$(MAN1DIR)/doxytag.1 rm doxytag.1 - cat doc/doxywizard.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxywizard.1 + cat doc/doxywizard.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > doxywizard.1 $(INSTTOOL) -m 644 doxywizard.1 $(INSTALL)/$(MAN1DIR)/doxywizard.1 - rm doxywizard + rm doxywizard.1 install_docs: $(INSTTOOL) -d $(DOCDIR) @@ -1,4 +1,4 @@ -DOXYGEN Version 1.5.2_20070610 +DOXYGEN Version 1.5.2_20070719 Please read INSTALL for compilation instructions. @@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives. Enjoy, -Dimitri van Heesch (dimitri@stack.nl) (10 June 2007) +Dimitri van Heesch (dimitri@stack.nl) (19 July 2007) diff --git a/addon/doxyapp/doxyapp.cpp b/addon/doxyapp/doxyapp.cpp index 501303a..bd44b18 100644 --- a/addon/doxyapp/doxyapp.cpp +++ b/addon/doxyapp/doxyapp.cpp @@ -22,10 +22,11 @@ * * This example shows how to use to code parser to get cross-references information * and it also shows how to look up symbols in a program parsed by doxygen and - * show some information about it. + * show some information about them. */ #include <stdlib.h> +#include <unistd.h> #include "doxygen.h" #include "outputgen.h" #include "parserintf.h" @@ -20,7 +20,7 @@ doxygen_version_minor=5 doxygen_version_revision=2 #NOTE: Setting version_mmn to "NO" will omit mmn info from the package. -doxygen_version_mmn=20070610 +doxygen_version_mmn=20070719 bin_dirs=`echo $PATH | sed -e "s/:/ /g"` @@ -238,7 +238,7 @@ if test -z "$f_platform"; then fi if test -z "$f_docdir"; then - f_docdir=$f_prefix/share/doc/packages/doxygen + f_docdir='$(INSTALL)/share/doc/packages/doxygen' fi if test "$f_plf_auto" = NO; then diff --git a/doc/custcmd.doc b/doc/custcmd.doc new file mode 100644 index 0000000..15b7d06 --- /dev/null +++ b/doc/custcmd.doc @@ -0,0 +1,123 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2007 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ +/*! \page custcmd Custom Commands + +Doxygen provides a large number of \ref commands "special commands", +\ref xmlcmds "XML commands", and \ref htmlcmds "HTML commands". +that can be used to enhance or structure the documentation inside a comment block. +If you for some reason have a need to define new commands you can do +so by means of an \e alias definition. + +The definition of an alias should be specified in the configuration file using +the \ref cfg_aliases "ALIASES" configuration tag. + +\section custcmd_simple Simple aliases +The simplest form of an alias is a simple substitution of the form +\verbatim + name=value +\endverbatim + For example defining the following alias: +\verbatim + ALIASES += sideeffect="\par Side Effects:\n" +\endverbatim + will allow you to + put the command \\sideeffect (or \@sideeffect) in the documentation, which + will result in a user-defined paragraph with heading <b>Side Effects:</b>. + +Note that you can put \\n's in the value part of an alias to insert newlines. + +Also note that you can redefine existing special commands if you wish. + +Some commands, such as \ref cmdxrefitem "\\xrefitem" are designed to be used in +combination with aliases. + +\section custcmd_complex Aliases with arguments +Aliases can also have one or more arguments. In the alias definition you then need +to specify the number of arguments between curly braces. In the value part of the +definition you can place \\x markers, where 'x' represents the argument number starting +with 1. + +Here is an example of an alias definition with a single argument: +\verbatim +ALIASES += l{1}="\ref \1" +\endverbatim + +Inside a comment block you can use it as follows +\verbatim +/** See \l{SomeClass} for more information. */ +\endverbatim +which would be the same as writing +\verbatim +/** See \ref SomeClass for more information. */ +\endverbatim + +Note that you can overload an alias by a version with multiple arguments, for instance: +\verbatim +ALIASES += l{1}="\ref \1" +ALIASES += l{2}="\ref \1 \"\2\"" +\endverbatim +Note that the quotes inside the alias definition have to be escaped with a backslash. + +With these alias definitions, we can write +\verbatim +/** See \l{SomeClass,Some Text} for more information. */ +\endverbatim +inside the comment block and it will expand to +\verbatim +/** See \ref SomeClass "Some Text" for more information. */ +\endverbatim +where the command with a single argument would still work as shown before. + +Aliases can also be expressed in terms of other aliases, e.g. a new command +\\reminder can be expressed as a \\xrefitem via an intermediate \\xreflist command +as follows: +\verbatim +ALIASES += xreflist{3}="\xrefitem \1 \"\2\" \"\3\" " \ +ALIASES += reminder="\xreflist{reminders,Reminder,Reminders}" \ +\endverbatim + +Note that if for aliases with more than one argument a comma is used as a separator, +if you want to put a comma inside the command, you will need to escape it with a backslash, +i.e. +\verbatim +\l{SomeClass,Some text\, with an escaped comma} +\endverbatim +given the alias definition of \\l in the example above. + +\section custcmd_nesting Nesting custom command + +You can use commands as arguments of aliases, including commands +defined using aliases. + +As an example consider the following alias definitions + +\verbatim +ALIASES += Bold{1}="<b>\1</b>" +ALIASES += Emph{1}="<em>\1</em>" +\endverbatim + +Inside a comment block you can now use: +\verbatim +/** This is a \Bold{bold \Emph{and} Emphasized} text fragment. */ +\endverbatim +which will expand to +\verbatim +/** This is a <b>bold <em>and</em> Emphasized</b> text fragment. */ +\endverbatim + + +*/ diff --git a/doc/index.doc b/doc/index.doc index faed772..3c4eae3 100644 --- a/doc/index.doc +++ b/doc/index.doc @@ -192,8 +192,6 @@ Thanks go to: <li>Talin for adding support for C# style comments with XML markup. <li>Petr Prikryl for coordinating the internationalisation support. All language maintainers for providing translations into many languages. -<li>Gerald Steffens of <a href="http://www.e-trend.de">E-trend</a> - for financial support. <li>The band <a href="http://www.porcupinetree.com">Porcupine Tree</a> for providing hours of great music to listen to while coding. <li>many, many others for suggestions, patches and bug reports. diff --git a/doc/install.doc b/doc/install.doc index 3c75386..b8cb8ff 100644 --- a/doc/install.doc +++ b/doc/install.doc @@ -366,40 +366,61 @@ before running make. \section install_src_windows Compiling from source on Windows From version 1.5.0 onwards, build files are provided for Visual Studio 2005. -Also the free "Express" version of Developer Studio can be used to compile doxygen. -Alternatively, you can compile doxygen \ref install_src_unix "the Unix way" using +Also the free (as in beer) "Express" version of Developer Studio can be used to +compile doxygen. Alternatively, you can compile doxygen +\ref install_src_unix "the Unix way" using <a href="http://en.wikipedia.org/wiki/Cygwin">Cygwin</a> or <a href="http://www.mingw.org/">MinGW</a>. Before you can compile doxygen you need to download and install the C++ compiler of Visual Studio. Since Microsoft apparently wants to lure everyone into using their -.NET stuff, you need to +.NET stuff, they made things somewhat difficult when you use the Express version. +You need to <a href="http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/"> do some manual steps</a> in order to setup a proper working environment for building -native win32 applications. - -Once your environment is setup, you -can <a href="http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc">download</a> -the source distribution of doxygen and unpack it. -If you don't have a tool like WinZip, then I suggest to download -<a href="http://sourceforge.net/projects/unxutils/">unxutils</a> -and untar the archive from within a command box using +native win32 applications such as Doxygen. + +The next step is to install unxutils (see http://sourceforge.net/projects/unxutils). +This packages contains the tools \c flex and \c bison which are needed during the +compilation process if you use a CVS snapshot of doxygen (the official source releases +come with pre-generated sources). +Download the zip extract it to e.g. <code>c:\\tools\\unxutils</code>. + +Now you need to add/adjust the following environment variables +(via Control Panel/System/Advanced/Environment Variables): +- add <code>c:\\tools\\unxutils\\usr\\local\\wbin;</code> to the start of <code>PATH</code> +- set <code>BISON_SIMPLE</code> to <code>c:\\tools\\unxutils\\usr\\share\\bison.simple</code> + +Download doxygen's source tarball and put it somewhere (e.g use <code>c:\\tools</code>) + +Now start a new command shell and type \verbatim - tar zxvf doxygen-version.src.tar.gz +cd c:\tools +gunzip doxygen-x.y.z.src.tar.gz +tar xvf doxygen-x.y.z.src.tar \endverbatim -Inside the archive you will find a \c winbuild directory containing a \c Doxygen.sln -file. Just open this file in Visual Studio. You can now build the Doxygen, Doxytag, -and Doxywizard projects for Release or Debug to compile the executables. +to unpack the sources. + +Now your environment is setup to build \c doxygen and \c doxytag. + +Inside the \c doxygen-x.y.z directory you will find a \c winbuild directory +containing a \c Doxygen.sln file. Open this file in Visual Studio. +You can now build the Release or Debug flavor of Doxygen and Doxytag by right-clicking +the project in the solutions explorer, and selecting Build. -Note that compiling Doxywizard currently requires a <a href="http://www.trolltech.com/products/qt/qt3"> -commercial license for Qt 3</a>. +Note that compiling Doxywizard currently requires Qt version 3 +(see http://www.trolltech.com/products/qt/qt3). +If you do not have a commercial license, you can build Doxywizard with the open +source version (see http://qtwin.sourceforge.net/qt3-win32/compile-msvc-2005.php), +but I have not tried this myself. -Also read the next section for additional tools you may need to install. +Also read the next section for additional tools you may need to install to run +doxygen with certain features enabled. <!-- Currently, I have only compiled doxygen for Windows using Microsoft's -Visual C++ (version 6.0). For other compilers you may need to edit the +Visual C++ (). For other compilers you may need to edit the perl script in <code>wintools/make.pl</code> a bit. Let me know what you had to change if you got Doxygen working with another compiler. If you have Visual Studio you can also use the .dsw file found in diff --git a/src/classdef.cpp b/src/classdef.cpp index bbfe3e8..1991a4a 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -85,6 +85,9 @@ class ClassDefImpl /*! Template arguments of this class */ ArgumentList *tempArgs; + /*! Type constraints for template parameters */ + ArgumentList *typeConstraints; + /*! Files that were used for generating the class documentation. */ QStrList files; @@ -189,6 +192,7 @@ void ClassDefImpl::init(const char *defFileName, const char *name, allMemberNameInfoSDict = 0; incInfo=0; tempArgs=0; + typeConstraints=0; prot=Public; nspace=0; fileDef=0; @@ -244,6 +248,7 @@ ClassDefImpl::~ClassDefImpl() delete variableInstances; delete templBaseClassNames; delete tempArgs; + delete typeConstraints; } // constructs a new class definition @@ -870,6 +875,7 @@ void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &pageType { ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::RTF); ol.newParagraph(); ol.enableAll(); ol.disableAllBut(OutputGenerator::Man); @@ -879,12 +885,12 @@ void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &pageType // write documentation if (!documentation().isEmpty()) { - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::RTF); - ol.newParagraph(); - ol.popGeneratorState(); - ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); + //ol.newParagraph(); + ol.parseDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE); } + // write type constraints + writeTypeConstraints(ol,this,m_impl->typeConstraints); + // write examples if (exampleFlag && m_impl->exampleSDict) { @@ -894,7 +900,7 @@ void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &pageType writeExample(ol,m_impl->exampleSDict); ol.endSimpleSect(); } - ol.newParagraph(); + //ol.newParagraph(); writeSourceDef(ol,name()); ol.endTextBlock(); } @@ -1021,17 +1027,6 @@ void ClassDef::writeClassDiagrams(OutputList &ol) ol.startDotGraph(); ol.parseText(theTranslator->trClassDiagram(displayName())); ol.endDotGraph(inheritanceGraph); - if (Config_getBool("GENERATE_LEGEND")) - { - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - ol.writeString("<center><font size=\"2\">["); - ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); - ol.docify(theTranslator->trLegend()); - ol.endHtmlLink(); - ol.writeString("]</font></center>"); - ol.popGeneratorState(); - } ol.popGeneratorState(); renderDiagram = TRUE; } @@ -1048,7 +1043,8 @@ void ClassDef::writeClassDiagrams(OutputList &ol) renderDiagram = TRUE; } - if (Config_getBool("CLASS_DIAGRAMS") && renderDiagram) + if (renderDiagram) // if we already show the inheritance relations graphically, + // then hide the text version { ol.disableAllBut(OutputGenerator::Man); } @@ -1138,7 +1134,7 @@ void ClassDef::writeClassDiagrams(OutputList &ol) ol.newParagraph(); } - if (Config_getBool("CLASS_DIAGRAMS") && renderDiagram) + if (renderDiagram) { ol.enableAll(); } @@ -1153,15 +1149,6 @@ void ClassDef::writeClassDiagrams(OutputList &ol) ol.startDotGraph(); ol.parseText(theTranslator->trCollaborationDiagram(displayName())); ol.endDotGraph(usageImplGraph); - if (Config_getBool("GENERATE_LEGEND")) - { - ol.disableAllBut(OutputGenerator::Html); - ol.writeString("<center><font size=\"2\">["); - ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); - ol.docify(theTranslator->trLegend()); - ol.endHtmlLink(); - ol.writeString("]</font></center>"); - } ol.popGeneratorState(); } } @@ -1229,8 +1216,10 @@ void ClassDef::writeDocumentation(OutputList &ol) if (!Config_getBool("DETAILS_AT_TOP")) { ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE); - ol.writeString(" \n"); ol.pushGeneratorState(); + ol.disable(OutputGenerator::RTF); + ol.writeString(" \n"); + ol.enable(OutputGenerator::RTF); ol.disableAllBut(OutputGenerator::Html); ol.startTextLink(0,"_details"); @@ -1329,12 +1318,13 @@ void ClassDef::writeDocumentation(OutputList &ol) writeClassDiagrams(ol); // write link to list of all members (HTML only) - if (m_impl->allMemberNameInfoSDict && + if (m_impl->allMemberNameInfoSDict && !Config_getBool("OPTIMIZE_OUTPUT_FOR_C") ) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); + ol.newParagraph(); ol.startTextLink(getMemberListFileName(),0); ol.parseText(theTranslator->trListOfAllMembers()); ol.endTextLink(); @@ -1345,11 +1335,11 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.endTextBlock(); // write detailed description if the user wants it near the top - if (Config_getBool("DETAILS_AT_TOP")) { + if (Config_getBool("DETAILS_AT_TOP")) + { writeDetailedDescription(ol,pageType,exampleFlag); } - /////////////////////////////////////////////////////////////////////////// //// Member declarations + brief descriptions /////////////////////////////////////////////////////////////////////////// @@ -1866,6 +1856,19 @@ void ClassDef::setTemplateArguments(ArgumentList *al) } } +void ClassDef::setTypeConstraints(ArgumentList *al) +{ + if (al==0) return; + if (!m_impl->typeConstraints) delete m_impl->typeConstraints; + m_impl->typeConstraints = new ArgumentList; + ArgumentListIterator ali(*al); + Argument *a; + for (;(a=ali.current());++ali) + { + m_impl->typeConstraints->append(new Argument(*a)); + } +} + /*! Returns \c TRUE iff this class or a class inheriting from this class * is \e not defined in an external tag file. */ diff --git a/src/classdef.h b/src/classdef.h index b03ae52..1cfccc2 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -294,6 +294,7 @@ class ClassDef : public Definition void setTemplateArguments(ArgumentList *al); void setTemplateBaseClassNames(QDict<int> *templateNames); void setTemplateMaster(ClassDef *tm); + void setTypeConstraints(ArgumentList *al); void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec); void makeTemplateArgument(bool b=TRUE); void setCategoryOf(ClassDef *cd); diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index c4469c7..e6f74f0 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -26,6 +26,7 @@ CommandMap cmdMap[] = { "arg", CMD_LI }, { "attention", CMD_ATTENTION }, { "author", CMD_AUTHOR }, + { "authors", CMD_AUTHORS }, { "b", CMD_BOLD }, { "c", CMD_CODE }, { "code", CMD_STARTCODE }, @@ -89,8 +90,6 @@ CommandMap cmdMap[] = { "verbinclude", CMD_VERBINCLUDE }, { "version", CMD_VERSION }, { "warning", CMD_WARNING }, - { "author", CMD_AUTHOR }, - { "authors", CMD_AUTHORS }, { "throws", CMD_EXCEPTION }, { "\\", CMD_BSLASH }, { "@", CMD_AT }, diff --git a/src/commentcnv.l b/src/commentcnv.l index b12d9d8..465c951 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -168,6 +168,7 @@ static void endCondSection() } } +#if 0 /** remove and executes cond and endcond commands in \a s */ static QCString handleCondCmdInAliases(const QCString &s) { @@ -223,6 +224,7 @@ static QCString handleCondCmdInAliases(const QCString &s) result+=s.right(s.length()-p); return result; } +#endif /** copies string \a s with length \a len to the output, while * replacing any alias commands found in the string. diff --git a/src/commentscan.l b/src/commentscan.l index 553b93a..9a7f698 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -198,6 +198,7 @@ static DocCmdMap docCmdMap[] = { "arg", 0, TRUE }, { "attention", 0, TRUE }, { "author", 0, TRUE }, + { "authors", 0, TRUE }, { "date", 0, TRUE }, { "dotfile", 0, TRUE }, { "htmlinclude", 0, TRUE }, @@ -212,7 +213,9 @@ static DocCmdMap docCmdMap[] = { "param", 0, TRUE }, { "post", 0, TRUE }, { "pre", 0, TRUE }, + { "remark", 0, TRUE }, { "remarks", 0, TRUE }, + { "result", 0, TRUE }, { "return", 0, TRUE }, { "returns", 0, TRUE }, { "retval", 0, TRUE }, @@ -220,6 +223,7 @@ static DocCmdMap docCmdMap[] = { "see", 0, TRUE }, { "since", 0, TRUE }, { "throw", 0, TRUE }, + { "throws", 0, TRUE }, { "until", 0, TRUE }, { "verbinclude", 0, TRUE }, { "version", 0, TRUE }, diff --git a/src/config.l b/src/config.l index e3faf84..cb73dfb 100644 --- a/src/config.l +++ b/src/config.l @@ -2222,6 +2222,16 @@ void Config::create() FALSE ); cb->addDependency("GENERATE_HTML"); + cb = addBool( + "HTML_DYNAMIC_SECTIONS", + "If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML \n" + "documentation will contain sections that can be hidden and shown after the \n" + "page has loaded. For this to work a browser that supports \n" + "JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox \n" + "Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). \n", + FALSE + ); + cb->addDependency("GENERATE_HTML"); cs = addString( "CHM_FILE", "If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can \n" diff --git a/src/definition.cpp b/src/definition.cpp index bfcfbad..668e566 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -551,7 +551,7 @@ void Definition::writeSourceDef(OutputList &ol,const char *) QCString lineStr,anchorStr; lineStr.sprintf("%d",m_impl->body->startLine); anchorStr.sprintf(Htags::useHtags ? "L%d" : "l%05d",m_impl->body->startLine); - ol.newParagraph(); + ol.startParagraph(); if (lineMarkerPos<fileMarkerPos) // line marker before file marker { // write text left from linePos marker @@ -616,6 +616,7 @@ void Definition::writeSourceDef(OutputList &ol,const char *) ol.parseText(refText.right( refText.length()-lineMarkerPos-2)); } + ol.endParagraph(); } else { @@ -691,7 +692,7 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, ol.pushGeneratorState(); if (Config_getBool("SOURCE_BROWSER") && members) { - ol.newParagraph(); + ol.startParagraph(); ol.parseText(text); ol.docify(" "); @@ -772,6 +773,7 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, } ol.parseText(ldefLine.right(ldefLine.length()-index)); ol.writeString("."); + ol.endParagraph(); } ol.popGeneratorState(); } diff --git a/src/docparser.cpp b/src/docparser.cpp index 01d88ae..e9d16af 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -368,11 +368,15 @@ static void checkUndocumentedParams() } if (g_memberDef->inheritsDocsFrom()) { - warn_doc_error(g_memberDef->getDefFileName(),g_memberDef->getDefLine(),errMsg); + warn_doc_error(g_memberDef->getDefFileName(), + g_memberDef->getDefLine(), + substitute(errMsg,"%","%%")); } else { - warn_doc_error(g_memberDef->docFile(),g_memberDef->docLine(),errMsg); + warn_doc_error(g_memberDef->docFile(), + g_memberDef->docLine(), + substitute(errMsg,"%","%%")); } } } diff --git a/src/dot.cpp b/src/dot.cpp index 603fc38..412eeda 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -242,7 +242,7 @@ static bool readBoundingBoxEPS(const char *fileName,int *width,int *height) { int numBytes = f.readLine(buf,maxLineLen-1); // read line buf[numBytes]='\0'; - if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundBox string + if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundingBox string { int x,y; if (sscanf(buf+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4) @@ -543,7 +543,6 @@ static QCString escapeTooltip(const QCString &tooltip) switch(c) { case '\\': result+="\\\\"; break; - case '"': result+="\\\""; break; default: result+=c; break; } } @@ -1398,44 +1397,98 @@ void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includePa } } -void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue, - int &maxNodes,bool includeParents) +bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, + int maxNodes,bool includeParents) { - while (queue.count()>0 && maxNodes>0) + QList<DotNode> childQueue; + QList<DotNode> parentQueue; + QArray<int> childTreeWidth; + QArray<int> parentTreeWidth; + childQueue.append(rootNode); + if (includeParents) parentQueue.append(rootNode); + bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop + // despite being marked visible in the child loop + while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0) { static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH"); - DotNode *n = queue.take(0); - //printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p " - // "m_parents=%p distance=%d maxDistance=%d\n", - // n,queue.count(),maxNodes,n->m_children,n->m_parents,n->distance(), - // maxDistance); - if (!n->isVisible() && n->distance()<maxDistance) // not yet processed + if (childQueue.count()>0) { - //printf(" Marked as visible!\n"); - n->markAsVisible(); - maxNodes--; - // add direct children - if (n->m_children) + DotNode *n = childQueue.take(0); + int distance = n->distance(); + if (!n->isVisible() && distance<maxDistance) // not yet processed { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) + if (distance>0) { - queue.append(dn); + int oldSize=(int)childTreeWidth.size(); + if (distance>oldSize) + { + childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance)); + int i; for (i=oldSize;i<distance;i++) childTreeWidth[i]=0; + } + childTreeWidth[distance-1]+=n->label().length(); + } + n->markAsVisible(); + maxNodes--; + // add direct children + if (n->m_children) + { + QListIterator<DotNode> li(*n->m_children); + DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + childQueue.append(dn); + } } } - // add direct parents - if (n->m_parents && includeParents) + } + if (includeParents && parentQueue.count()>0) + { + DotNode *n = parentQueue.take(0); + if ((!n->isVisible() || firstNode) && n->distance()<maxDistance) // not yet processed { - QListIterator<DotNode> li(*n->m_parents); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) + firstNode=FALSE; + int distance = n->distance(); + if (distance>0) { - queue.append(dn); + int oldSize = (int)parentTreeWidth.size(); + if (distance>oldSize) + { + parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance)); + int i; for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0; + } + parentTreeWidth[distance-1]+=n->label().length(); + } + n->markAsVisible(); + maxNodes--; + // add direct parents + if (n->m_parents) + { + QListIterator<DotNode> li(*n->m_parents); + DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + parentQueue.append(dn); + } } } } } + int maxWidth=0; + int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size()); + uint i; + for (i=0;i<childTreeWidth.size();i++) + { + if (childTreeWidth[i]>maxWidth) maxWidth=childTreeWidth[i]; + } + for (i=0;i<parentTreeWidth.size();i++) + { + if (parentTreeWidth[i]>maxWidth) maxWidth=parentTreeWidth[i]; + } + //printf("max tree width=%d, max tree height=%d\n",maxWidth,maxHeight); + return maxWidth>80 && maxHeight<12; // used metric to decide to render the tree + // from left to right instead of top to bottom, + // with the idea to render very wide trees in + // left to right order. } void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base,int distance) @@ -1564,19 +1617,17 @@ DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t) if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE,1); //} - static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int maxNodes = nodes; + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); //int directChildNodes = 1; //if (m_startNode->m_children!=0) // directChildNodes+=m_startNode->m_children->count(); //if (t==DotNode::Inheritance && m_startNode->m_parents!=0) // directChildNodes+=m_startNode->m_parents->count(); //if (directChildNodes>maxNodes) maxNodes=directChildNodes; + //openNodeQueue.append(m_startNode); + m_lrRank = determineVisibleNodes(m_startNode,maxNodes,t==DotNode::Inheritance); QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); - determineVisibleNodes(openNodeQueue,maxNodes,t==DotNode::Inheritance); - openNodeQueue.clear(); - openNodeQueue.append(m_startNode); determineTruncatedNodes(openNodeQueue,t==DotNode::Inheritance); m_diskName = cd->getFileBase().copy(); @@ -1733,7 +1784,7 @@ QCString DotClassGraph::writeGraph(QTextStream &out, GraphOutputFormat format, const char *path, const char *relPath, - bool isTBRank, + bool /*isTBRank*/, bool generateImageMap) { QDir d(path); @@ -1772,7 +1823,7 @@ QCString DotClassGraph::writeGraph(QTextStream &out, m_graphType, baseName, format, - !isTBRank, + m_lrRank, //!isTBRank, m_graphType==DotNode::Inheritance, TRUE ) @@ -1853,20 +1904,33 @@ QCString DotClassGraph::writeGraph(QTextStream &out, } else if (format==EPS) // produce tex to include the .eps image { - int width,height; + int width=420,height=600; if (!readBoundingBoxEPS(baseName+".eps",&width,&height)) { err("Error: Could not extract bounding box from .eps!\n"); QDir::setCurrent(oldDir); return baseName; } - int maxWidth = 420; /* approx. page width in points */ + //printf("Got EPS size %d,%d\n",width,height); + int maxWidth = 400; /* approx. page width in points, excl. margins */ + int maxHeight = 400; /* approx. page height in points, excl. margins */ out << "\\nopagebreak\n" "\\begin{figure}[H]\n" "\\begin{center}\n" - "\\leavevmode\n" - "\\includegraphics[width=" << QMIN(width/2,maxWidth) - << "pt]{" << baseName << "}\n" + "\\leavevmode\n"; + if (width>maxWidth) + { + out << "\\includegraphics[width=" << maxWidth << "pt]"; + } + else if (height>maxHeight) + { + out << "\\includegraphics[height=" << maxHeight << "pt]"; + } + else + { + out << "\\includegraphics[width=" << width/2 << "pt]"; + } + out << "{" << baseName << "}\n" "\\end{center}\n" "\\end{figure}\n"; } @@ -2204,7 +2268,7 @@ void DotInclDepGraph::writeXML(QTextStream &t) int DotCallGraph::m_curNodeNumber = 0; -void DotCallGraph::buildGraph(DotNode *n,MemberDef *md) +void DotCallGraph::buildGraph(DotNode *n,MemberDef *md,int distance) { LockingPtr<MemberSDict> refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); if (!refs.isNull()) @@ -2223,6 +2287,7 @@ void DotCallGraph::buildGraph(DotNode *n,MemberDef *md) { n->addChild(bn,0,0,0); bn->addParent(n); + bn->setDistance(distance); } else { @@ -2246,9 +2311,10 @@ void DotCallGraph::buildGraph(DotNode *n,MemberDef *md) ); n->addChild(bn,0,0,0); bn->addParent(n); + bn->setDistance(distance); m_usedNodes->insert(uniqueId,bn); - buildGraph(bn,rmd); + buildGraph(bn,rmd,distance+1); } } } @@ -2259,8 +2325,9 @@ void DotCallGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes) { while (queue.count()>0 && maxNodes>0) { + static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH"); DotNode *n = queue.take(0); - if (!n->isVisible()) // not yet processed + if (!n->isVisible() && n->distance()<maxDistance) // not yet processed { n->markAsVisible(); maxNodes--; @@ -2329,9 +2396,10 @@ DotCallGraph::DotCallGraph(MemberDef *md,bool inverse) uniqueId.data(), TRUE // root node ); + m_startNode->setDistance(0); m_usedNodes = new QDict<DotNode>(1009); m_usedNodes->insert(uniqueId,m_startNode); - buildGraph(m_startNode,md); + buildGraph(m_startNode,md,1); static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); int maxNodes = nodes; @@ -168,7 +168,7 @@ class DotClassGraph private: void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance); - void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes,bool includeParents); + bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents); void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, const char *usedName,const char *templSpec, @@ -179,6 +179,7 @@ class DotClassGraph static int m_curNodeNumber; DotNode::GraphType m_graphType; QCString m_diskName; + bool m_lrRank; }; /** @brief Representation of an include dependency graph */ @@ -216,7 +217,7 @@ class DotCallGraph ~DotCallGraph(); QCString writeGraph(QTextStream &t, GraphOutputFormat f, const char *path,const char *relPath,bool writeImageMap=TRUE); - void buildGraph(DotNode *n,MemberDef *md); + void buildGraph(DotNode *n,MemberDef *md,int distance); bool isTrivial() const; bool isTooBig() const; void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 3042aa0..54ace8a 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -1164,6 +1164,7 @@ static void addClassToContext(EntryNav *rootNav) cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); cd->setIsObjectiveC(root->objc); cd->setHidden(root->hidden); + cd->setTypeConstraints(root->typeConstr); //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data()); ArgumentList *tArgList = @@ -1357,6 +1358,8 @@ static void buildNamespaceList(EntryNav *rootNav) rootNav->loadEntry(g_storage); Entry *root = rootNav->entry(); + //printf("** buildNamespaceList(%s)\n",root->name.data()); + QCString fullName = root->name; if (root->section==Entry::PACKAGEDOC_SEC) { @@ -1422,6 +1425,7 @@ static void buildNamespaceList(EntryNav *rootNav) nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); nd->addSectionsToDefinition(root->anchors); + nd->setHidden(root->hidden); //printf("Adding namespace to group\n"); addNamespaceToGroups(root,nd); @@ -2577,6 +2581,7 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd, const QCString &rname,bool isFriend) { Entry *root = rootNav->entry(); + FileDef *fd=rootNav->fileDef(); int l,i; static QRegExp re("([a-z_A-Z0-9: ]*[ *]*[ ]*"); @@ -2598,7 +2603,8 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd, else mtype=MemberDef::Function; // strip redundant template specifier for constructors - if ((i=name.find('<'))!=-1 && name.find('>')!=-1) + if ((fd==0 || getLanguageFromFileName(fd->name())==SrcLangExt_Cpp) && + (i=name.find('<')!=-1) && name.find('>')!=-1) { name=name.left(i); } @@ -2622,7 +2628,7 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd, md->setBodySegment(root->bodyLine,root->endBodyLine); md->setMemberSpecifiers(root->spec); md->setMemberGroupId(root->mGrpId); - FileDef *fd=rootNav->fileDef(); + md->setTypeConstraints(root->typeConstr); md->setBodyDef(fd); md->setFileDef(fd); //md->setScopeTemplateArguments(root->tArgList); @@ -2964,6 +2970,7 @@ static void buildFunctionList(EntryNav *rootNav) md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); md->setPrototype(root->proto); md->setDocsForDefinition(!root->proto); + md->setTypeConstraints(root->typeConstr); //md->setBody(root->body); md->setBodySegment(root->bodyLine,root->endBodyLine); FileDef *fd=rootNav->fileDef(); @@ -5539,6 +5546,7 @@ static void findMember(EntryNav *rootNav, md->setTagInfo(rootNav->tagInfo()); md->setMemberClass(cd); md->setTemplateSpecialization(TRUE); + md->setTypeConstraints(root->typeConstr); md->setDefinition(funcDecl); md->enableCallGraph(root->callGraph); md->enableCallerGraph(root->callerGraph); @@ -5599,6 +5607,7 @@ static void findMember(EntryNav *rootNav, root->protection,root->virt,root->stat,TRUE, mtype,tArgList,root->argList); md->setTagInfo(rootNav->tagInfo()); + md->setTypeConstraints(root->typeConstr); md->setMemberClass(cd); md->setDefinition(funcDecl); md->enableCallGraph(root->callGraph); @@ -9288,7 +9297,7 @@ void parseInput() cleanUpDoxygen(); exit(1); } - + QCString &xmlOutput = Config_getString("XML_OUTPUT"); bool &generateXml = Config_getBool("GENERATE_XML"); if (xmlOutput.isEmpty() && generateXml) @@ -9709,6 +9718,21 @@ void parseInput() msg("Computing dependencies between directories...\n"); computeDirDependencies(); } + + msg("Counting data structures...\n"); + countDataStructures(); + + msg("Resolving user defined references...\n"); + resolveUserReferences(); + + msg("Finding anchors and sections in the documentation...\n"); + findSectionsInDocumentation(); + + transferFunctionReferences(); + + msg("Combining using relations...\n"); + combineUsingRelations(); + } void generateOutput() @@ -9734,31 +9758,6 @@ void generateOutput() initDocParser(); - //{ - // QCString fileName = Config_getString("HTML_OUTPUT")+"/filetree.html"; - // QFile f(fileName); - // if (f.open(IO_WriteOnly)) - // { - // QTextStream t(&f); - // t << "<html>\n"; - // t << " <head>\n"; - // t << " <style type=\"text/css\">\n"; - // t << " <!--\n"; - // t << " .directory { font-size: 10pt; font-weight: bold; }\n"; - // t << " .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }\n"; - // t << " .directory p { margin: 0px; white-space: nowrap; }\n"; - // t << " .directory div { display: visible; margin: 0px; }\n"; - // t << " .directory img { vertical-align: middle; }\n"; - // t << " -->\n"; - // t << " </style>\n"; - // t << " </head>\n"; - // t << " <body>\n"; - // generateFileTree(t); - // t << " </body>\n"; - // t << "</html>\n"; - // } - //} - outputList = new OutputList(TRUE); if (Config_getBool("GENERATE_HTML")) { @@ -9766,6 +9765,7 @@ void generateOutput() HtmlGenerator::init(); if (Config_getBool("GENERATE_HTMLHELP")) HtmlHelp::getInstance()->initialize(); if (Config_getBool("GENERATE_TREEVIEW")) FTVHelp::getInstance()->initialize(); + if (Config_getBool("HTML_DYNAMIC_SECTIONS")) HtmlGenerator::generateSectionImages(); copyStyleSheet(); } if (Config_getBool("GENERATE_LATEX")) @@ -9842,18 +9842,6 @@ void generateOutput() // count the number of documented elements in the lists we have built. // If the result is 0 we do not generate the lists and omit the // corresponding links in the index. - msg("Counting data structures...\n"); - countDataStructures(); - - msg("Resolving user defined references...\n"); - resolveUserReferences(); - - msg("Combining using relations...\n"); - combineUsingRelations(); - - msg("Finding anchors and sections in the documentation...\n"); - findSectionsInDocumentation(); - msg("Generating index page...\n"); writeIndex(*outputList); @@ -9865,7 +9853,6 @@ void generateOutput() { generateFileSources(); } - transferFunctionReferences(); msg("Generating file documentation...\n"); generateFileDocs(); @@ -9958,6 +9945,7 @@ void generateOutput() if (Config_getBool("GENERATE_HTML") && Config_getBool("DOT_CLEANUP")) removeDoxFont(Config_getString("HTML_OUTPUT")); if (Config_getBool("GENERATE_RTF") && Config_getBool("DOT_CLEANUP")) removeDoxFont(Config_getString("RTF_OUTPUT")); + if (Config_getBool("GENERATE_XML")) { msg("Generating XML output...\n"); diff --git a/src/entry.cpp b/src/entry.cpp index 77830c0..edb54c1 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -27,122 +27,6 @@ #define HEADER ('D'<<24)+('O'<<16)+('X'<<8)+'!' -#if 0 -static bool saveEntry(Entry *e,StorageIntf *f) -{ - marshalUInt(f,HEADER); - marshalInt(f,(int)e->protection); - marshalInt(f,(int)e->mtype); - marshalInt(f,e->spec); - marshalInt(f,e->initLines); - marshalBool(f,e->stat); - marshalBool(f,e->explicitExternal); - marshalBool(f,e->proto); - marshalBool(f,e->subGrouping); - marshalBool(f,e->callGraph); - marshalBool(f,e->callerGraph); - marshalInt(f,(int)e->virt); - marshalQCString(f,e->args); - marshalQCString(f,e->bitfields); - marshalArgumentList(f,e->argList); - marshalArgumentLists(f,e->tArgLists); - marshalQGString(f,e->program); - marshalQGString(f,e->initializer); - marshalQCString(f,e->includeFile); - marshalQCString(f,e->includeName); - marshalQCString(f,e->doc); - marshalInt(f,e->docLine); - marshalQCString(f,e->docFile); - marshalQCString(f,e->brief); - marshalInt(f,e->briefLine); - marshalQCString(f,e->briefFile); - marshalQCString(f,e->inbodyDocs); - marshalInt(f,e->inbodyLine); - marshalQCString(f,e->inbodyFile); - marshalQCString(f,e->relates); - marshalBool(f,e->relatesDup); - marshalQCString(f,e->read); - marshalQCString(f,e->write); - marshalQCString(f,e->inside); - marshalQCString(f,e->exception); - marshalInt(f,e->bodyLine); - marshalInt(f,e->endBodyLine); - marshalInt(f,e->mGrpId); - marshalBaseInfoList(f,e->extends); - marshalGroupingList(f,e->groups); - marshalSectionInfoList(f,e->anchors); - marshalQCString(f,e->fileName); - marshalInt(f,e->startLine); - marshalItemInfoList(f,e->sli); - marshalBool(f,e->objc); - marshalBool(f,e->hidden); - marshalInt(f,(int)e->groupDocType); - return TRUE; -} - -static bool loadEntry(Entry *e,StorageIntf *f) -{ - uint header=unmarshalUInt(f); - if (header!=HEADER) - { - printf("Internal error: Invalid header %x for entry in storage file %s\n", - header,Doxygen::entryDBFileName.data()); - exit(1); - } - e->protection = (Protection)unmarshalInt(f); - e->mtype = (MethodTypes)unmarshalInt(f); - e->spec = unmarshalInt(f); - e->initLines = unmarshalInt(f); - e->stat = unmarshalBool(f); - e->explicitExternal = unmarshalBool(f); - e->proto = unmarshalBool(f); - e->subGrouping = unmarshalBool(f); - e->callGraph = unmarshalBool(f); - e->callerGraph = unmarshalBool(f); - e->virt = (Specifier)unmarshalInt(f); - e->args = unmarshalQCString(f); - e->bitfields = unmarshalQCString(f); - delete e->argList; - e->argList = unmarshalArgumentList(f); - e->tArgLists = unmarshalArgumentLists(f); - e->program = unmarshalQGString(f); - e->initializer = unmarshalQGString(f); - e->includeFile = unmarshalQCString(f); - e->includeName = unmarshalQCString(f); - e->doc = unmarshalQCString(f); - e->docLine = unmarshalInt(f); - e->docFile = unmarshalQCString(f); - e->brief = unmarshalQCString(f); - e->briefLine = unmarshalInt(f); - e->briefFile = unmarshalQCString(f); - e->inbodyDocs = unmarshalQCString(f); - e->inbodyLine = unmarshalInt(f); - e->inbodyFile = unmarshalQCString(f); - e->relates = unmarshalQCString(f); - e->relatesDup = unmarshalBool(f); - e->read = unmarshalQCString(f); - e->write = unmarshalQCString(f); - e->inside = unmarshalQCString(f); - e->exception = unmarshalQCString(f); - e->bodyLine = unmarshalInt(f); - e->endBodyLine = unmarshalInt(f); - e->mGrpId = unmarshalInt(f); - delete e->extends; - e->extends = unmarshalBaseInfoList(f); - delete e->groups; - e->groups = unmarshalGroupingList(f); - delete e->anchors; - e->anchors = unmarshalSectionInfoList(f); - e->fileName = unmarshalQCString(f); - e->startLine = unmarshalInt(f); - e->sli = unmarshalItemInfoList(f); - e->objc = unmarshalBool(f); - e->hidden = unmarshalBool(f); - e->groupDocType = (Entry::GroupDocType)unmarshalInt(f); - return TRUE; -} -#endif - //------------------------------------------------------------------ /*! the argument list is documented if one of its @@ -181,6 +65,7 @@ Entry::Entry() argList->setAutoDelete(TRUE); //printf("Entry::Entry() tArgList=0\n"); tArgLists = 0; + typeConstr = 0; mGrpId = -1; tagInfo = 0; sli = 0; @@ -245,6 +130,8 @@ Entry::Entry(const Entry &e) anchors = new QList<SectionInfo>; argList = new ArgumentList; argList->setAutoDelete(TRUE); + typeConstr = new ArgumentList; + typeConstr->setAutoDelete(TRUE); tArgLists = 0; groupDocType = e.groupDocType; @@ -290,6 +177,16 @@ Entry::Entry(const Entry &e) argList->volatileSpecifier = e.argList->volatileSpecifier; argList->pureSpecifier = e.argList->pureSpecifier; + // deep copy type contraint list + if (e.typeConstr) + { + QListIterator<Argument> tcli(*e.typeConstr); + for (;(a=tcli.current());++tcli) + { + typeConstr->append(new Argument(*a)); + } + } + // deep copy template argument lists if (e.tArgLists) { @@ -391,9 +288,10 @@ void Entry::reset() groups->clear(); anchors->clear(); argList->clear(); - if (tagInfo) { delete tagInfo; tagInfo=0; } - if (tArgLists) { delete tArgLists; tArgLists=0; } - if (sli) { delete sli; sli=0; } + if (tagInfo) { delete tagInfo; tagInfo=0; } + if (tArgLists) { delete tArgLists; tArgLists=0; } + if (sli) { delete sli; sli=0; } + if (typeConstr) { delete typeConstr; typeConstr=0; } //if (mtArgList) { delete mtArgList; mtArgList=0; } } diff --git a/src/entry.h b/src/entry.h index ede809c..1a51944 100644 --- a/src/entry.h +++ b/src/entry.h @@ -349,6 +349,7 @@ class Entry QCString write; //!< property write accessor QCString inside; //!< name of the class in which documents are found QCString exception; //!< throw specification + ArgumentList *typeConstr; //!< where clause (C#) for type constraints int bodyLine; //!< line number of the definition in the source int endBodyLine; //!< line number where the definition ends int mGrpId; //!< member group id diff --git a/src/filedef.cpp b/src/filedef.cpp index 45b7ea6..3588a45 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -168,6 +168,7 @@ void FileDef::writeDetailedDocumentation(OutputList &ol) ol.startGroupHeader(); ol.parseText(theTranslator->trDetailedDescription()); ol.endGroupHeader(); + ol.startTextBlock(); if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) { ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); @@ -192,7 +193,7 @@ void FileDef::writeDetailedDocumentation(OutputList &ol) //printf("Writing source ref for file %s\n",name().data()); if (Config_getBool("SOURCE_BROWSER")) { - ol.newParagraph(); + ol.startParagraph(); QCString refText = theTranslator->trDefinedInSourceFile(); int fileMarkerPos = refText.find("@0"); if (fileMarkerPos!=-1) // should always pass this. @@ -203,7 +204,9 @@ void FileDef::writeDetailedDocumentation(OutputList &ol) ol.parseText(refText.right( refText.length()-fileMarkerPos-2)); // text right from marker 2 } + ol.endParagraph(); } + ol.endTextBlock(); } } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index d923186..5442ed7 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -46,7 +46,7 @@ static const char defaultStyleSheet[] = #include "doxygen_css.h" ; -const char search_script[]= +static const char search_script[]= #include "search_php.h" ; @@ -488,7 +488,29 @@ static void writeTabData(const char *dir) } } -//----------------------------------------------------------------------- +//------------------------------------------------------------------------ + +unsigned char open_gif[] = { + 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x09, 0x00, 0x09, 0x00, 0xf0, 0x00, + 0x00, 0x8e, 0xaf, 0xc4, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x00, 0x02, 0x0d, 0x8c, 0x8f, 0xa9, 0xcb, 0xe0, 0xff, 0x02, 0x8c, 0x66, + 0x26, 0x7a, 0x51, 0x01, 0x00, 0x3b +}; +unsigned int open_gif_len = 54; + +unsigned char closed_gif[] = { + 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x09, 0x00, 0x09, 0x00, 0xf0, 0x00, + 0x00, 0x8e, 0xaf, 0xc4, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x00, 0x02, 0x10, 0x8c, 0x03, 0xa7, 0x98, 0xcb, 0xad, 0x80, 0x84, 0x66, + 0xca, 0x38, 0x57, 0xd6, 0xf4, 0xd0, 0x02, 0x00, 0x3b +}; +unsigned int closed_gif_len = 57; + + + +//------------------------- Pictures for the Tabs ------------------------ HtmlGenerator::HtmlGenerator() : OutputGenerator() { @@ -598,6 +620,54 @@ void HtmlGenerator::writeFooterFile(QFile &file) << "</html>\n"; } +static void generateDynamicSections(QTextStream &t,const QCString &relPath) +{ + if (Config_getBool("HTML_DYNAMIC_SECTIONS")) + { + t << + "<script type=\"text/javascript\">\n" + "<!--\n" + "function changeDisplayState (e){\n" + " var num=this.id.replace(/[^[0-9]/g,'');\n" + " var button=this.firstChild;\n" + " var sectionDiv=document.getElementById('dynsection'+num);\n" + " if (sectionDiv.style.display=='none'||sectionDiv.style.display==''){\n" + " sectionDiv.style.display='block';\n" + " button.src='" << relPath << "open.gif';\n" + " }else{\n" + " sectionDiv.style.display='none';\n" + " button.src='" << relPath << "closed.gif';\n" + " }\n" + "}\n" + "function initDynSections(){\n" + " var divs=document.getElementsByTagName('div');\n" + " var sectionCounter=1;\n" + " for(var i=0;i<divs.length-1;i++){\n" + " if(divs[i].className=='dynheader'&&divs[i+1].className=='dynsection'){\n" + " var header=divs[i];\n" + " var section=divs[i+1];\n" + " var button=header.firstChild;\n" + " if (button!='IMG'){\n" + " divs[i].insertBefore(document.createTextNode(' '),divs[i].firstChild);\n" + " button=document.createElement('img');\n" + " divs[i].insertBefore(button,divs[i].firstChild);\n" + " }\n" + " header.style.cursor='pointer';\n" + " header.onclick=changeDisplayState;\n" + " header.id='dynheader'+sectionCounter;\n" + " button.src='" << relPath << "closed.gif';\n" + " section.id='dynsection'+sectionCounter;\n" + " section.style.display='none';\n" + " sectionCounter++;\n" + " }\n" + " }\n" + "}\n" + "window.onload = initDynSections;\n" + "-->\n" + "</script>\n"; + } +} + void HtmlGenerator::startFile(const char *name,const char *, const char *title) @@ -635,9 +705,9 @@ void HtmlGenerator::startFile(const char *name,const char *, } t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " << versionString << " -->" << endl; + generateDynamicSections(t,relPath); } - static void writePageFooter(QTextStream &t,const QCString &lastTitle, const QCString relPath) { @@ -751,6 +821,16 @@ void HtmlGenerator::newParagraph() t << endl << "<p>" << endl; } +void HtmlGenerator::startParagraph() +{ + t << endl << "<p>"; +} + +void HtmlGenerator::endParagraph() +{ + t << "</p>" << endl; +} + void HtmlGenerator::writeString(const char *text) { t << text; @@ -1033,18 +1113,22 @@ void HtmlGenerator::writeChar(char c) void HtmlGenerator::startClassDiagram() { - t << "<p>"; + //t << "<p>"; + t << "<div class=\"dynheader\">" << endl; } void HtmlGenerator::endClassDiagram(ClassDiagram &d, const char *fileName,const char *name) { + t << "</div>" << endl; + t << "<div class=\"dynsection\">" << endl; t << "\n<p><center><img src=\"" << relPath << fileName << ".png\" usemap=\"#" << name << "_map\"" << " border=\"0\" alt=\"\"></center>" << endl << "<map name=\"" << name << "_map\">" << endl; d.writeImage(t,dir,relPath,fileName); + t << "</div>" << endl; } @@ -1402,49 +1486,75 @@ void HtmlGenerator::endMemberDoc(bool hasArgs) void HtmlGenerator::startDotGraph() { + t << "<div class=\"dynheader\">" << endl; } void HtmlGenerator::endDotGraph(DotClassGraph &g) { + t << "</div>" << endl; + t << "<div class=\"dynsection\">" << endl; g.writeGraph(t,BITMAP,dir,relPath); + if (Config_getBool("GENERATE_LEGEND")) + { + t << "<center><font size=\"2\">["; + startHtmlLink(relPath+"graph_legend"+Doxygen::htmlFileExtension); + t << theTranslator->trLegend(); + endHtmlLink(); + t << "]</font></center>"; + } + t << "</div>" << endl; } void HtmlGenerator::startInclDepGraph() { + t << "<div class=\"dynheader\">" << endl; } void HtmlGenerator::endInclDepGraph(DotInclDepGraph &g) { + t << "</div>" << endl; + t << "<div class=\"dynsection\">" << endl; g.writeGraph(t,BITMAP,dir,relPath); + t << "</div>" << endl; } - void HtmlGenerator::startGroupCollaboration() { + t << "<div class=\"dynheader\">" << endl; } void HtmlGenerator::endGroupCollaboration(DotGroupCollaboration &g) { + t << "</div>" << endl; + t << "<div class=\"dynsection\">" << endl; g.writeGraph(t,BITMAP,dir,relPath); + t << "</div>" << endl; } - void HtmlGenerator::startCallGraph() { + t << "<div class=\"dynheader\">" << endl; } void HtmlGenerator::endCallGraph(DotCallGraph &g) { + t << "</div>" << endl; + t << "<div class=\"dynsection\">" << endl; g.writeGraph(t,BITMAP,dir,relPath); + t << "</div>" << endl; } void HtmlGenerator::startDirDepGraph() { + t << "<div class=\"dynheader\">" << endl; } void HtmlGenerator::endDirDepGraph(DotDirDeps &g) { + t << "</div>" << endl; + t << "<div class=\"dynsection\">" << endl; g.writeGraph(t,BITMAP,dir,relPath); + t << "</div>" << endl; } void HtmlGenerator::writeGraphicalHierarchy(DotGfxHierarchyTable &g) @@ -1966,3 +2076,68 @@ void HtmlGenerator::writeSearchPage() } } +void HtmlGenerator::generateSectionImages() +{ + { + QCString fileName = Config_getString("HTML_OUTPUT")+"/open.gif"; + QFile f(fileName); + if (f.open(IO_WriteOnly)) + { + f.writeBlock((char*)open_gif,open_gif_len); + } + } + { + QCString fileName = Config_getString("HTML_OUTPUT")+"/closed.gif"; + QFile f(fileName); + if (f.open(IO_WriteOnly)) + { + f.writeBlock((char*)closed_gif,closed_gif_len); + } + } +} + +void HtmlGenerator::startConstraintList(const char *header) +{ + t << "<div class=\"typeconstraint\">" << endl; + t << "<dl compact><dt><b>" << header << "</b><dt><dd>" << endl; + t << "<table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">" << endl; +} + +void HtmlGenerator::startConstraintParam() +{ + t << "<tr><td valign=\"top\"><em>"; +} + +void HtmlGenerator::endConstraintParam() +{ + t << "</em></td>"; +} + +void HtmlGenerator::startConstraintType() +{ + t << "<td> :</td><td valign=\"top\"><em>"; +} + +void HtmlGenerator::endConstraintType() +{ + t << "</em></td>"; +} + +void HtmlGenerator::startConstraintDocs() +{ + t << "<td> "; +} + +void HtmlGenerator::endConstraintDocs() +{ + t << "</td></tr>" << endl; +} + +void HtmlGenerator::endConstraintList() +{ + t << "</table>" << endl; + t << "</dl>" << endl; + t << "</div>" << endl; +} + + diff --git a/src/htmlgen.h b/src/htmlgen.h index 8ca87d0..5c318be 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -63,6 +63,8 @@ class HtmlGenerator : public OutputGenerator void endTitle() { t << "</h1>"; } void newParagraph(); + void startParagraph(); + void endParagraph(); void writeString(const char *text); void startIndexList(); void endIndexList(); @@ -219,6 +221,15 @@ class HtmlGenerator : public OutputGenerator void startParameterList(bool); void endParameterList(); + void startConstraintList(const char *); + void startConstraintParam(); + void endConstraintParam(); + void startConstraintType(); + void endConstraintType(); + void startConstraintDocs(); + void endConstraintDocs(); + void endConstraintList(); + void startFontClass(const char *s) { t << "<span class=\"" << s << "\">"; } void endFontClass() { t << "</span>"; } @@ -227,6 +238,7 @@ class HtmlGenerator : public OutputGenerator void linkableSymbol(int,const char *,Definition *,Definition *) {} static void writeSearchPage(); + static void generateSectionImages(); private: QCString lastTitle; diff --git a/src/latexgen.cpp b/src/latexgen.cpp index ab06be0..356c7b4 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -873,6 +873,15 @@ void LatexGenerator::newParagraph() t << endl << endl; } +void LatexGenerator::startParagraph() +{ + t << endl << endl; +} + +void LatexGenerator::endParagraph() +{ +} + void LatexGenerator::writeString(const char *text) { t << text; @@ -1598,3 +1607,46 @@ void LatexGenerator::printDoc(DocNode *n,const char *langExt) delete visitor; } +void LatexGenerator::startConstraintList(const char *header) +{ + t << "\\begin{Desc}\n\\item["; + docify(header); + t << "]"; + t << "\\begin{description}" << endl; +} + +void LatexGenerator::startConstraintParam() +{ + t << "\\item[{\\em "; +} + +void LatexGenerator::endConstraintParam() +{ +} + +void LatexGenerator::startConstraintType() +{ + t << "} : {\\em "; +} + +void LatexGenerator::endConstraintType() +{ + t << "}]"; +} + +void LatexGenerator::startConstraintDocs() +{ +} + +void LatexGenerator::endConstraintDocs() +{ +} + +void LatexGenerator::endConstraintList() +{ + t << "\\end{description}" << endl; + t << "\\end{Desc}" << endl; +} + + + diff --git a/src/latexgen.h b/src/latexgen.h index 214256f..c130d75 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -61,6 +61,8 @@ class LatexGenerator : public OutputGenerator void endTitle() { t << "}"; } void newParagraph(); + void startParagraph(); + void endParagraph(); void writeString(const char *text); void startIndexList() { t << "\\begin{CompactList}" << endl; } void endIndexList() { t << "\\end{CompactList}" << endl; } @@ -210,6 +212,15 @@ class LatexGenerator : public OutputGenerator void startParameterList(bool) {} void endParameterList() {} + void startConstraintList(const char *); + void startConstraintParam(); + void endConstraintParam(); + void startConstraintType(); + void endConstraintType(); + void startConstraintDocs(); + void endConstraintDocs(); + void endConstraintList(); + void startFontClass(const char *) {} void endFontClass() {} diff --git a/src/mangen.cpp b/src/mangen.cpp index f8bfb57..220dee2 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -179,6 +179,21 @@ void ManGenerator::newParagraph() paragraph=TRUE; } +void ManGenerator::startParagraph() +{ + if (!paragraph) + { + if (!firstCol) t << endl; + t << ".PP" << endl; + firstCol=TRUE; + } + paragraph=TRUE; +} + +void ManGenerator::endParagraph() +{ +} + void ManGenerator::writeString(const char *text) { docify(text); @@ -640,3 +655,54 @@ void ManGenerator::printDoc(DocNode *n,const char *langExt) paragraph = FALSE; } +void ManGenerator::startConstraintList(const char *header) +{ + if (!firstCol) + { t << endl << ".PP" << endl; + firstCol=TRUE; paragraph=TRUE; + col=0; + } + paragraph=FALSE; + startBold(); + docify(header); + endBold(); + paragraph=TRUE; +} + +void ManGenerator::startConstraintParam() +{ + writeListItem(); + startEmphasis(); +} + +void ManGenerator::endConstraintParam() +{ + endEmphasis(); + t << " : "; +} + +void ManGenerator::startConstraintType() +{ + startEmphasis(); +} + +void ManGenerator::endConstraintType() +{ + endEmphasis(); +} + +void ManGenerator::startConstraintDocs() +{ +} + +void ManGenerator::endConstraintDocs() +{ + t << endl; firstCol=TRUE; +} + +void ManGenerator::endConstraintList() +{ +} + + + diff --git a/src/mangen.h b/src/mangen.h index 38b566a..45ef306 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -60,6 +60,8 @@ class ManGenerator : public OutputGenerator void endTitle(); void newParagraph(); + void startParagraph(); + void endParagraph(); void writeString(const char *text); void startIndexList() {} void endIndexList() { newParagraph(); } @@ -268,6 +270,15 @@ class ManGenerator : public OutputGenerator //void startSectionRefList() {} //void endSectionRefList() {} + void startConstraintList(const char *); + void startConstraintParam(); + void endConstraintParam(); + void startConstraintType(); + void endConstraintType(); + void startConstraintDocs(); + void endConstraintDocs(); + void endConstraintList(); + void writeCodeAnchor(const char *) {} void linkableSymbol(int,const char *,Definition *,Definition *) {} diff --git a/src/marshal.cpp b/src/marshal.cpp index a08c20a..a11a25f 100644 --- a/src/marshal.cpp +++ b/src/marshal.cpp @@ -390,6 +390,7 @@ void marshalEntry(StorageIntf *s,Entry *e) marshalQCString(s,e->write); marshalQCString(s,e->inside); marshalQCString(s,e->exception); + marshalArgumentList(s,e->typeConstr); marshalInt(s,e->bodyLine); marshalInt(s,e->endBodyLine); marshalInt(s,e->mGrpId); @@ -774,6 +775,7 @@ Entry * unmarshalEntry(StorageIntf *s) e->write = unmarshalQCString(s); e->inside = unmarshalQCString(s); e->exception = unmarshalQCString(s); + e->typeConstr = unmarshalArgumentList(s); e->bodyLine = unmarshalInt(s); e->endBodyLine = unmarshalInt(s); e->mGrpId = unmarshalInt(s); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index dffbb82..bc8c76e 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -346,6 +346,7 @@ class MemberDefImpl ArgumentList *declArgList; // argument list of this member declaration ArgumentList *tArgList; // template argument list of function template + ArgumentList *typeConstraints; // type constraints for template parameters MemberDef *templateMaster; QList<ArgumentList> *defTmpArgLists; // lists of template argument lists // (for template functions in nested template classes) @@ -410,6 +411,7 @@ MemberDefImpl::MemberDefImpl() : defArgList(0), declArgList(0), tArgList(0), + typeConstraints(0), defTmpArgLists(0), classSectionSDict(0) { @@ -422,6 +424,7 @@ MemberDefImpl::~MemberDefImpl() delete enumFields; delete defArgList; delete tArgList; + delete typeConstraints; delete defTmpArgLists; delete classSectionSDict; delete declArgList; @@ -2014,10 +2017,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, // write class that contains a member that is reimplemented by this one if (bcd->isLinkable()) { - ol.disable(OutputGenerator::RTF); - ol.newParagraph(); - ol.enableAll(); - + ol.startParagraph(); QCString reimplFromLine; if (bmd->virtualness()!=Pure && bcd->compoundType()!=ClassDef::Interface) { @@ -2062,6 +2062,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, { err("Error: translation error: no marker in trReimplementsFromList()\n"); } + ol.endParagraph(); } //ol.writeString("."); @@ -2087,9 +2088,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, { mli.toFirst(); // write the list of classes that overwrite this member - ol.disable(OutputGenerator::RTF); - ol.newParagraph(); - ol.enable(OutputGenerator::RTF); + ol.startParagraph(); QCString reimplInLine; if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface)) @@ -2137,6 +2136,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, index=newIndex+matchLen; } ol.parseText(reimplInLine.right(reimplInLine.length()-index)); + ol.endParagraph(); } } @@ -2150,6 +2150,11 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, ol.endSimpleSect(); } + if (m_impl->typeConstraints) + { + writeTypeConstraints(ol,this,m_impl->typeConstraints); + } + // write reference to the source writeSourceDef(ol,cname); writeSourceRefs(ol,cname); @@ -2635,7 +2640,8 @@ bool MemberDef::isDestructor() const } else // other languages { - return name().find('~')!=-1 && name().find("operator")==-1; + return (name().find('~')!=-1 || name().find('!')!=-1) // The ! is for C++/CLI + && name().find("operator")==-1; } } @@ -2780,6 +2786,21 @@ void MemberDef::setDeclArgumentList(ArgumentList *al) m_impl->declArgList = al; } +void MemberDef::setTypeConstraints(ArgumentList *al) +{ + if (al==0) return; + makeResident(); + if (m_impl->typeConstraints) delete m_impl->typeConstraints; + m_impl->typeConstraints = new ArgumentList; + m_impl->typeConstraints->setAutoDelete(TRUE); + ArgumentListIterator ali(*al); + Argument *a; + for (;(a=ali.current());++ali) + { + m_impl->typeConstraints->append(new Argument(*a)); + } +} + void MemberDef::findSectionsInDocumentation() { makeResident(); @@ -3648,6 +3669,7 @@ void MemberDef::flushToDisk() const marshalArgumentList (Doxygen::symbolStorage,m_impl->defArgList); marshalArgumentList (Doxygen::symbolStorage,m_impl->declArgList); marshalArgumentList (Doxygen::symbolStorage,m_impl->tArgList); + marshalArgumentList (Doxygen::symbolStorage,m_impl->typeConstraints); marshalObjPointer (Doxygen::symbolStorage,m_impl->templateMaster); marshalArgumentLists(Doxygen::symbolStorage,m_impl->defTmpArgLists); marshalObjPointer (Doxygen::symbolStorage,m_impl->cachedAnonymousType); @@ -3746,6 +3768,7 @@ void MemberDef::loadFromDisk() const m_impl->defArgList = unmarshalArgumentList (Doxygen::symbolStorage); m_impl->declArgList = unmarshalArgumentList (Doxygen::symbolStorage); m_impl->tArgList = unmarshalArgumentList (Doxygen::symbolStorage); + m_impl->typeConstraints = unmarshalArgumentList (Doxygen::symbolStorage); m_impl->templateMaster = (MemberDef*)unmarshalObjPointer (Doxygen::symbolStorage); m_impl->defTmpArgLists = unmarshalArgumentLists(Doxygen::symbolStorage); m_impl->cachedAnonymousType = (ClassDef*)unmarshalObjPointer (Doxygen::symbolStorage); diff --git a/src/memberdef.h b/src/memberdef.h index c396346..385b353 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -281,6 +281,7 @@ class MemberDef : public Definition void setArgumentList(ArgumentList *al); void setDeclArgumentList(ArgumentList *al); void setDefinitionTemplateParameterLists(QList<ArgumentList> *lists); + void setTypeConstraints(ArgumentList *al); // namespace related members void setNamespace(NamespaceDef *nd); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index fe69505..d021764 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -259,7 +259,7 @@ void NamespaceDef::writeDetailedDocumentation(OutputList &ol) if (!documentation().isEmpty()) { ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); - ol.newParagraph(); + //ol.newParagraph(); } ol.endTextBlock(); } @@ -321,8 +321,10 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.popGeneratorState(); } ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::RTF); ol.newParagraph(); ol.enable(OutputGenerator::Man); + ol.enable(OutputGenerator::RTF); ol.writeSynopsis(); ol.endTextBlock(); diff --git a/src/outputgen.h b/src/outputgen.h index 0a7c06c..9118ef4 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -132,6 +132,11 @@ class BaseOutputDocInterface : public CodeOutputInterface /*! Starts a new paragraph */ virtual void newParagraph() = 0; + /*! Starts a new paragraph */ + virtual void startParagraph() = 0; + /*! End a paragraph */ + virtual void endParagraph() = 0; + /*! Writes a link to an object in the documentation. * \param ref If this is non-zero, the object is to be found in * an external documentation file. @@ -376,6 +381,15 @@ class OutputGenerator : public BaseOutputDocInterface virtual void startParameterList(bool) = 0; virtual void endParameterList() = 0; + virtual void startConstraintList(const char *) = 0; + virtual void startConstraintParam() = 0; + virtual void endConstraintParam() = 0; + virtual void startConstraintType() = 0; + virtual void endConstraintType() = 0; + virtual void startConstraintDocs() = 0; + virtual void endConstraintDocs() = 0; + virtual void endConstraintList() = 0; + protected: QTextStream fs; QByteArray a; diff --git a/src/outputlist.h b/src/outputlist.h index 4a8a0d7..30f8e64 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -97,6 +97,10 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::endTitle); } void newParagraph() { forall(&OutputGenerator::newParagraph); } + void startParagraph() + { forall(&OutputGenerator::startParagraph); } + void endParagraph() + { forall(&OutputGenerator::endParagraph); } void writeString(const char *text) { forall(&OutputGenerator::writeString,text); } void startIndexList() @@ -370,6 +374,25 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::startParameterList,openBracket); } void endParameterList() { forall(&OutputGenerator::endParameterList); } + + void startConstraintList(const char *header) + { forall(&OutputGenerator::startConstraintList,header); } + void startConstraintParam() + { forall(&OutputGenerator::startConstraintParam); } + void endConstraintParam() + { forall(&OutputGenerator::endConstraintParam); } + void startConstraintType() + { forall(&OutputGenerator::startConstraintType); } + void endConstraintType() + { forall(&OutputGenerator::endConstraintType); } + void startConstraintDocs() + { forall(&OutputGenerator::startConstraintDocs); } + void endConstraintDocs() + { forall(&OutputGenerator::endConstraintDocs); } + void endConstraintList() + { forall(&OutputGenerator::endConstraintList); } + + void startFontClass(const char *c) { forall(&OutputGenerator::startFontClass,c); } void endFontClass() @@ -396,6 +419,8 @@ class OutputList : public OutputDocInterface } void linkableSymbol(int,const char *,Definition *,Definition *) {} + + private: void debug(); void clear(); diff --git a/src/pyscanner.l b/src/pyscanner.l index 913f88e..ed3f10b 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -1000,6 +1000,7 @@ STARTDOCSYMS ^{B}"##"/[^#] // prepend scope in case of nested classes if (current_root->section&Entry::SCOPE_MASK) { + printf("*** Prepending scope %s to class %s\n",current_root->name.data(),current->name.data()); current->name.prepend(current_root->name+"::"); } @@ -1476,11 +1477,15 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) QFileInfo fi(fileName); g_moduleScope = findPackageScope(fileName); - if (!g_moduleScope.isEmpty()) + QString baseName=fi.baseName(); + if (baseName!="__init__") // package initializer file is not a package itself { - g_moduleScope+="::"; + if (!g_moduleScope.isEmpty()) + { + g_moduleScope+="::"; + } + g_moduleScope+=baseName; } - g_moduleScope+=fi.baseName(); current = new Entry; current->name = g_moduleScope; diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index 05fe40d..e835811 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -259,7 +259,7 @@ void RTFDocVisitor::visit(DocLineBreak *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n"); - m_t << "\\par\n"; + m_t << "\\par"; m_lastIsPara=TRUE; } @@ -310,7 +310,7 @@ void RTFDocVisitor::visit(DocStyleChange *s) else { m_insidePre=FALSE; - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; } m_lastIsPara=TRUE; @@ -442,7 +442,7 @@ void RTFDocVisitor::visit(DocInclude *inc) inc->text().latin1(), inc->isExample(), inc->exampleFile(), &fd); - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; } break; @@ -454,7 +454,7 @@ void RTFDocVisitor::visit(DocInclude *inc) ->parseCode(m_ci,inc->context(), inc->text().latin1(),inc->isExample(), inc->exampleFile()); - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; break; case DocInclude::DontInclude: @@ -466,7 +466,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); filter(inc->text()); - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; break; } @@ -506,7 +506,7 @@ void RTFDocVisitor::visit(DocIncOperator *op) popEnabled(); if (!m_hide) { - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; } m_lastIsPara=TRUE; @@ -553,7 +553,7 @@ void RTFDocVisitor::visitPost(DocAutoList *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoList)}\n"); - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; m_lastIsPara=TRUE; } @@ -593,7 +593,8 @@ void RTFDocVisitor::visitPost(DocPara *p) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n"); - if (!p->isLast() && // omit <p> for last paragraph + if (!m_lastIsPara && + !p->isLast() && // omit <p> for last paragraph !(p->parent() && // and for parameters & sections p->parent()->kind()==DocNode::Kind_ParamSect ) @@ -669,7 +670,7 @@ void RTFDocVisitor::visitPre(DocSimpleSect *s) if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) { m_t << ":"; - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}"; // end bold incIndentLevel(); m_t << rtf_Style_Reset << getStyle("DescContinue"); @@ -779,7 +780,7 @@ void RTFDocVisitor::visitPost(DocHtmlList *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlList)}\n"); - m_t << "\\par" << endl << "}" << endl; + m_t << "\\par" << "}" << endl; m_lastIsPara=TRUE; } @@ -858,7 +859,7 @@ void RTFDocVisitor::visitPost(DocHtmlDescData *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescData)}\n"); - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; decIndentLevel(); m_lastIsPara=TRUE; @@ -959,7 +960,7 @@ void RTFDocVisitor::visitPost(DocInternal *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternal)}\n"); - m_t << "\\par" << endl; + m_t << "\\par"; decIndentLevel(); m_t << "}"; // end desc m_lastIsPara=TRUE; @@ -1025,7 +1026,7 @@ void RTFDocVisitor::visitPost(DocHtmlHeader *) { if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlHeader)}\n"); - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; // end section m_lastIsPara=TRUE; } @@ -1131,8 +1132,8 @@ void RTFDocVisitor::visitPost(DocSecRefList *) if (m_hide) return; DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefList)}\n"); decIndentLevel(); - m_t << "\\par" << endl; - m_t << "}"; + m_t << "\\par"; + m_t << "}" << endl; m_lastIsPara=TRUE; } @@ -1177,7 +1178,7 @@ void RTFDocVisitor::visitPre(DocParamSect *s) ASSERT(0); } m_t << ":"; - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}" << endl; incIndentLevel(); m_t << rtf_Style_Reset << getStyle("DescContinue"); @@ -1268,7 +1269,7 @@ void RTFDocVisitor::visitPre(DocXRefItem *x) filter(x->title()); } m_t << ":"; - m_t << "\\par" << endl; + m_t << "\\par"; m_t << "}"; // end bold incIndentLevel(); m_t << rtf_Style_Reset << getStyle("DescContinue"); diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index f6fb8af..37e2ddd 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -852,6 +852,7 @@ void RTFGenerator::lineBreak() { DBG_RTF(t << "{\\comment (lineBreak)}" << endl) t << "\\par" << endl; + m_omitParagraph = TRUE; } void RTFGenerator::writeString(const char *text) @@ -863,16 +864,16 @@ void RTFGenerator::startIndexList() { DBG_RTF(t << "{\\comment (startIndexList)}" << endl) t << "{" << endl; + t << "\\par" << endl; incrementIndentLevel(); t << rtf_Style_Reset << rtf_LCList_DepthStyle() << endl; - newParagraph(); m_omitParagraph = TRUE; } void RTFGenerator::endIndexList() { DBG_RTF(t << "{\\comment (endIndexList)}" << endl) - newParagraph(); + t << "\\par"; t << "}"; decrementIndentLevel(); m_omitParagraph = TRUE; @@ -881,6 +882,7 @@ void RTFGenerator::endIndexList() /*! start bullet list */ void RTFGenerator::startItemList() { + newParagraph(); DBG_RTF(t << "{\\comment (startItemList level=" << m_listLevel << ") }" << endl) t << "{"; incrementIndentLevel(); @@ -954,8 +956,8 @@ void RTFGenerator::endIndexItem(const char *ref,const char *fn) { t << endl; } - newParagraph(); m_omitParagraph = TRUE; + newParagraph(); } //void RTFGenerator::writeIndexFileItem(const char *,const char *text) @@ -1048,17 +1050,19 @@ void RTFGenerator::startIndexKey() void RTFGenerator::endIndexKey() { + DBG_RTF(t << "{\\comment (endIndexKey)}" << endl) } void RTFGenerator::startIndexValue(bool hasBrief) { + DBG_RTF(t << "{\\comment (startIndexValue)}" << endl) t << " "; if (hasBrief) t << "("; } void RTFGenerator::endIndexValue(const char *name,bool hasBrief) { - DBG_RTF(t << "{\\comment (endIndexKey)}" << endl) + DBG_RTF(t << "{\\comment (endIndexValue)}" << endl) if (hasBrief) t << ")"; t << "} "; if (name) @@ -1071,6 +1075,7 @@ void RTFGenerator::endIndexValue(const char *name,bool hasBrief) { t << endl; } + m_omitParagraph=FALSE; newParagraph(); } @@ -1353,7 +1358,7 @@ void RTFGenerator::startGroupHeader() void RTFGenerator::endGroupHeader() { DBG_RTF(t <<"{\\comment endGroupHeader}" << endl) - newParagraph(); + t << "\\par" << endl; t << rtf_Style_Reset << endl; } @@ -1496,7 +1501,9 @@ void RTFGenerator::endMemberDescription() endEmphasis(); newParagraph(); decrementIndentLevel(); - t << "\\par}" << endl; + //t << "\\par"; + t << "}" << endl; + //m_omitParagraph = TRUE; } void RTFGenerator::startDescList(SectionTypes) @@ -1714,6 +1721,7 @@ void RTFGenerator::writeChar(char c) void RTFGenerator::startClassDiagram() { + DBG_RTF(t <<"{\\comment startClassDiagram }" << endl) } void RTFGenerator::endClassDiagram(ClassDiagram &d, @@ -1987,9 +1995,9 @@ void RTFGenerator::startTextBlock(bool dense) } } -void RTFGenerator::endTextBlock(bool paraBreak) +void RTFGenerator::endTextBlock(bool /*paraBreak*/) { - if (paraBreak) newParagraph(); + newParagraph(); DBG_RTF(t << "{\\comment endTextBlock}" << endl) t << "}" << endl; //m_omitParagraph = TRUE; @@ -1999,12 +2007,26 @@ void RTFGenerator::newParagraph() { if (!m_omitParagraph) { - DBG_RTF(t << "{\\comment (newParagraph)}" << endl) + DBG_RTF(t << "{\\comment (newParagraph)}" << endl) t << "\\par" << endl; } m_omitParagraph = FALSE; } +void RTFGenerator::startParagraph() +{ + DBG_RTF(t << "{\\comment startParagraph}" << endl) + newParagraph(); + t << "{" << endl; +} + +void RTFGenerator::endParagraph() +{ + DBG_RTF(t << "{\\comment endParagraph}" << endl) + t << "}\\par" << endl; + m_omitParagraph = TRUE; +} + void RTFGenerator::startMemberSubtitle() { DBG_RTF(t << "{\\comment startMemberSubtitle}" << endl) @@ -2496,6 +2518,7 @@ void RTFGenerator::printDoc(DocNode *n,const char *langExt) RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,langExt); n->accept(visitor); delete visitor; + m_omitParagraph = TRUE; } void RTFGenerator::rtfwriteRuler_doubleline() @@ -2545,3 +2568,68 @@ void RTFGenerator::postProcess(QByteArray &a) enc.resize(off); a = enc; } + +void RTFGenerator::startConstraintList(const char *header) +{ + DBG_RTF(t << "{\\comment (startConstraintList)}" << endl) + t << "{"; // ends at endConstraintList + t << "{"; + startBold(); + newParagraph(); + docify(header); + endBold(); + t << "}"; + newParagraph(); + incrementIndentLevel(); + t << rtf_Style_Reset << rtf_DList_DepthStyle(); +} + +void RTFGenerator::startConstraintParam() +{ + DBG_RTF(t << "{\\comment (startConstraintParam)}" << endl) + startEmphasis(); +} + +void RTFGenerator::endConstraintParam() +{ + DBG_RTF(t << "{\\comment (endConstraintParam)}" << endl) + endEmphasis(); + t << " : "; +} + +void RTFGenerator::startConstraintType() +{ + DBG_RTF(t << "{\\comment (startConstraintType)}" << endl) + startEmphasis(); +} + +void RTFGenerator::endConstraintType() +{ + DBG_RTF(t << "{\\comment (endConstraintType)}" << endl) + endEmphasis(); + t << " "; +} + +void RTFGenerator::startConstraintDocs() +{ + DBG_RTF(t << "{\\comment (startConstraintDocs)}" << endl) +} + +void RTFGenerator::endConstraintDocs() +{ + DBG_RTF(t << "{\\comment (endConstraintDocs)}" << endl) + newParagraph(); +} + +void RTFGenerator::endConstraintList() +{ + DBG_RTF(t << "{\\comment (endConstraintList)}" << endl) + newParagraph(); + decrementIndentLevel(); + m_omitParagraph = TRUE; + t << "}"; +} + + + + diff --git a/src/rtfgen.h b/src/rtfgen.h index 2183237..577cc40 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -64,6 +64,8 @@ class RTFGenerator : public OutputGenerator void endTitle() {} void newParagraph(); + void startParagraph(); + void endParagraph(); void writeString(const char *text); void startIndexList(); void endIndexList(); @@ -255,6 +257,16 @@ class RTFGenerator : public OutputGenerator void startParameterList(bool) {} void endParameterList() {} + void startConstraintList(const char *); + void startConstraintParam(); + void endConstraintParam(); + void startConstraintType(); + void endConstraintType(); + void startConstraintDocs(); + void endConstraintDocs(); + void endConstraintList(); + + void startFontClass(const char *) {} void endFontClass() {} diff --git a/src/scanner.l b/src/scanner.l index 8fd1672..09c52fb 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -68,6 +68,7 @@ static int lastClassTemplSpecContext; static int lastPreLineCtrlContext; static int lastSkipVerbStringContext; static int lastCommentInArgContext; +static int lastCSConstraint; static Protection protection; static Protection baseProt; static int sharpCount = 0 ; @@ -82,6 +83,7 @@ static Entry* current = 0 ; static Entry* previous = 0 ; static Entry* tempEntry = 0 ; static Entry* firstTypedefEntry = 0 ; +static Entry* memspecEntry = 0 ; static int yyLineNr = 1 ; static int anonCount = 0 ; static int anonNSCount = 0 ; @@ -303,7 +305,7 @@ static QCString stripQuotes(const char *s) static void startCommentBlock(bool); static void handleCommentBlock(const QCString &doc,bool brief); -static void handleParametersCommentBlocks(); +static void handleParametersCommentBlocks(ArgumentList *al); //----------------------------------------------------------------- @@ -359,7 +361,6 @@ static void prependScope() for (talsi.toLast();(srcAl=talsi.current());--talsi) { ArgumentList *dstAl = new ArgumentList; - dstAl->setAutoDelete(TRUE); QListIterator<Argument> tali(*srcAl); Argument *a; for (;(a=tali.current());++tali) @@ -544,7 +545,7 @@ FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]+ ID "$"?[a-z_A-Z][a-z_A-Z0-9]* LABELID [a-z_A-Z][a-z_A-Z0-9\-]* SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) -SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID}) +SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID}) TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&,]*">")? FTSCOPE {ID}("<"[a-z_A-Z0-9\*\&,]*">")? CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID}) @@ -572,7 +573,8 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) %x DefineEnd %x CompoundName %x ClassVar -%x CSConstraint +%x CSConstraintName +%x CSConstraintType %x ClassCategory %x ClassTemplSpec %x CliPropertyType @@ -1477,7 +1479,6 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) current->tArgLists->setAutoDelete(TRUE); } ArgumentList *al = new ArgumentList; - al->setAutoDelete(TRUE); current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template; current->tArgLists->append(al); currentArgumentList = al; @@ -2052,11 +2053,6 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) } <FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") { - //Entry *tmp = current; - //if (previous) - //{ - // current = previous; - //} //handleGroupStartCommand(current->name); if (previous && previous->section==Entry::GROUPDOC_SEC) { @@ -2866,6 +2862,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) else { current_root->addSubEntry( current ) ; + memspecEntry = current; current = new Entry(*current); if (current->section==Entry::NAMESPACE_SEC || (current->spec==Entry::Interface) || @@ -2874,6 +2871,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) { // namespaces and interfaces and java classes ends with a closing bracket without semicolon current->reset(); initEntry(); + memspecEntry = 0; BEGIN( FindMembers ) ; } else @@ -2934,6 +2932,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) current->args = current->args.simplifyWhiteSpace(); current->type = current->type.simplifyWhiteSpace(); current_root->addSubEntry( current ) ; + memspecEntry = current; current = new Entry(*current); unput(';'); BEGIN( MemberSpec ) ; @@ -3004,60 +3003,73 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) //printf("msName=%s current->name=%s\n",msName.data(),current->name.data()); if (!msName.isEmpty() && msName!=current->name) // skip typedef T {} T; { - Entry *varEntry=new Entry; - varEntry->protection = current->protection ; - varEntry->mtype = current->mtype; - varEntry->virt = current->virt; - varEntry->stat = current->stat; - varEntry->section = Entry::VARIABLE_SEC; - varEntry->name = msName.stripWhiteSpace(); - varEntry->type = current->type.simplifyWhiteSpace()+" "; - varEntry->args = msArgs; //current->args.simplifyWhiteSpace(); - //if (!current->name.isEmpty() && current->name[0]!='@' && - // current->parent->section & Entry::COMPOUND_MASK) - // varEntry->type+=current->parent->name+"::"; - if (isTypedef) + static bool optimizeForC = Config_getBool("OPTIMIZE_OUTPUT_FOR_C"); + // case 1: typedef struct _S { ... } S_t; + // -> omit typedef and use S_t as the struct name + if (optimizeForC && + isTypedef && + (current->spec&(Entry::Struct|Entry::Union)) && + msType.stripWhiteSpace().isEmpty() && + memspecEntry) { - varEntry->type.prepend("typedef "); - // //printf("current->name = %s %s\n",current->name.data(),msName.data()); - // if (!current->name.isEmpty() && current->name.at(0)!='@') - // { - // //printf("2>>>>>>>>>> adding %s->%s\n",msName.data(),current->name.data()); - // QCString scope; - // if (current_root->section & Entry::SCOPE_MASK) scope=current_root->name; - // Doxygen::typedefDict.insert(msName,new TypedefInfo(current->name,scope)); - // } + memspecEntry->name=msName; } - varEntry->type+=current->name+msType; - varEntry->fileName = yyFileName; - varEntry->startLine = yyLineNr; - varEntry->doc = current->doc.copy(); - varEntry->brief = current->brief.copy(); - varEntry->mGrpId = current->mGrpId; - - // deep copy group list - QListIterator<Grouping> gli(*current->groups); - Grouping *g; - for (;(g=gli.current());++gli) - { - varEntry->groups->append(new Grouping(*g)); - } - if (current->sli) // copy special list items + else // case 2: create a typedef field { - QListIterator<ListItemInfo> li(*current->sli); - ListItemInfo *lii; - for (li.toFirst();(lii=li.current());++li) + Entry *varEntry=new Entry; + varEntry->protection = current->protection ; + varEntry->mtype = current->mtype; + varEntry->virt = current->virt; + varEntry->stat = current->stat; + varEntry->section = Entry::VARIABLE_SEC; + varEntry->name = msName.stripWhiteSpace(); + varEntry->type = current->type.simplifyWhiteSpace()+" "; + varEntry->args = msArgs; + if (isTypedef) { - varEntry->addSpecialListItem(lii->type,lii->itemId); + varEntry->type.prepend("typedef "); + // //printf("current->name = %s %s\n",current->name.data(),msName.data()); + } + if (optimizeForC && + isTypedef && + (current->spec&(Entry::Struct|Entry::Union)) && + memspecEntry + ) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;" + { + varEntry->type+=memspecEntry->name+msType; + } + else // case 2: use _S as type for for pS_t + { + varEntry->type+=current->name+msType; + } + varEntry->fileName = yyFileName; + varEntry->startLine = yyLineNr; + varEntry->doc = current->doc.copy(); + varEntry->brief = current->brief.copy(); + varEntry->mGrpId = current->mGrpId; + + // deep copy group list + QListIterator<Grouping> gli(*current->groups); + Grouping *g; + for (;(g=gli.current());++gli) + { + varEntry->groups->append(new Grouping(*g)); + } + if (current->sli) // copy special list items + { + QListIterator<ListItemInfo> li(*current->sli); + ListItemInfo *lii; + for (li.toFirst();(lii=li.current());++li) + { + varEntry->addSpecialListItem(lii->type,lii->itemId); + } } - //delete current->sli; - //current->sli = 0; - } - //printf("Add: type=`%s',name=`%s',args=`%s' brief=%s doc=%s\n", - // varEntry->type.data(),varEntry->name.data(), - // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data()); - current_root->addSubEntry(varEntry); + //printf("Add: type=`%s',name=`%s',args=`%s' brief=%s doc=%s\n", + // varEntry->type.data(),varEntry->name.data(), + // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data()); + current_root->addSubEntry(varEntry); + } } if (*yytext==';') { @@ -3066,6 +3078,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) msArgs.resize(0); isTypedef=FALSE; firstTypedefEntry=0; + memspecEntry=0; current->reset(); initEntry(); BEGIN( FindMembers ); @@ -3272,7 +3285,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) *copyArgString+=*yytext; fullArgString+=*yytext; stringToArgumentList(fullArgString,current->argList); - handleParametersCommentBlocks(); + handleParametersCommentBlocks(current->argList); /* remember the current documentation block, since we could overwrite it with the documentation of @@ -3295,7 +3308,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) unput(yytext[i]); } stringToArgumentList(fullArgString,current->argList); - handleParametersCommentBlocks(); + handleParametersCommentBlocks(current->argList); BEGIN( currentArgumentContext ); } else // not a define @@ -3347,7 +3360,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) *copyArgString+=*yytext; fullArgString+=*yytext; stringToArgumentList(fullArgString,current->argList); - handleParametersCommentBlocks(); + handleParametersCommentBlocks(current->argList); BEGIN( currentArgumentContext ); } else @@ -3657,7 +3670,16 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) yyLineNr++; } <FuncQual>{ID} { // typically a K&R style C function - if (checkForKnRstyleC()) + if (insideCS && strcmp(yytext,"where")==0) + { + // type contraint for a method + delete current->typeConstr; + current->typeConstr = new ArgumentList; + current->typeConstr->append(new Argument); + lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else if (checkForKnRstyleC()) { //fprintf(stderr,"===> got a K&R style function\n"); current->args = yytext; @@ -4181,7 +4203,11 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) } else if (insideCS && strcmp(yytext,"where")==0) // C# type contraint { - BEGIN( CSConstraint ); + delete current->typeConstr; + current->typeConstr = new ArgumentList; + current->typeConstr->append(new Argument); + lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); } else { @@ -4216,14 +4242,53 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) BEGIN( FindMembers ); } } -<CSConstraint>"{" { +<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment + fullArgString.resize(0); + lastCopyArgChar='#'; // end marker + lastCommentInArgContext=YY_START; + if (yytext[1]=='/') + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } +<CSConstraintType,CSConstraintName>"#" { // artifically inserted token to signal end of comment block + current->typeConstr->last()->docs = fullArgString; + } +<CSConstraintType>"{" { // end of type constraint reached + // parse documentation of the constraints + handleParametersCommentBlocks(current->typeConstr); unput('{'); - BEGIN( ClassVar ); + BEGIN( lastCSConstraint ); } -<CSConstraint>\n { +<CSConstraintName>":" { + BEGIN( CSConstraintType ); + } +<CSConstraintName>{ID} { + // parameter name + current->typeConstr->last()->name=yytext; + } +<CSConstraintType>"where" { // another constraint for a different param + current->typeConstr->append(new Argument); + BEGIN( CSConstraintName ); + } +<CSConstraintType>({ID}".")*{ID}("<"{ID}">")?("()")? { + if (current->typeConstr->last()->type.isEmpty()) + // first type constraint for this parameter + { + current->typeConstr->last()->type=yytext; + } + else // new type constraint for same parameter + { + QCString name = current->typeConstr->last()->name; + current->typeConstr->append(new Argument); + current->typeConstr->last()->name=name; + current->typeConstr->last()->type=yytext; + } + } +<CSConstraintName,CSConstraintType>\n { yyLineNr++; } -<CSConstraint>. { +<CSConstraintName,CSConstraintType>. { } <ClassCategory>{ID} { current->name+=yytext; @@ -5000,10 +5065,10 @@ static void handleCommentBlock(const QCString &doc,bool brief) } } -static void handleParametersCommentBlocks() +static void handleParametersCommentBlocks(ArgumentList *al) { //printf(">>>>>>> handleParametersCommentBlocks()\n"); - ArgumentListIterator ali(*current->argList); + ArgumentListIterator ali(*al); Argument *a; for (ali.toFirst();(a=ali.current());++ali) { diff --git a/src/textdocvisitor.cpp b/src/textdocvisitor.cpp index fe5573b..9e5cd21 100644 --- a/src/textdocvisitor.cpp +++ b/src/textdocvisitor.cpp @@ -71,8 +71,13 @@ void TextDocVisitor::filter(const char *str) c=*p++; switch(c) { - case '\n': m_t << " "; break; - default: m_t << c; + case '\n': m_t << " "; break; + case '"': m_t << """; break; + case '\'': m_t << "'"; break; + case '<': m_t << "<"; break; + case '>': m_t << ">"; break; + case '&': m_t << "&"; break; + default: m_t << c; } } } diff --git a/src/textdocvisitor.h b/src/textdocvisitor.h index cf7788a..8e70da9 100644 --- a/src/textdocvisitor.h +++ b/src/textdocvisitor.h @@ -36,11 +36,11 @@ class TextDocVisitor : public DocVisitor // visitor functions for leaf nodes //-------------------------------------- - void visit(DocWord *w) { m_t << w->word(); } - void visit(DocLinkedWord *w) { m_t << w->word(); } + void visit(DocWord *w) { filter(w->word()); } + void visit(DocLinkedWord *w) { filter(w->word()); } void visit(DocWhiteSpace *) { m_t << " "; } void visit(DocSymbol *); - void visit(DocURL *u) { m_t << u->url(); } + void visit(DocURL *u) { filter(u->url()); } void visit(DocLineBreak *) { m_t << " "; } void visit(DocHorRuler *) {} void visit(DocStyleChange *) {} diff --git a/src/util.cpp b/src/util.cpp index 0723ae4..fde2dab 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -500,10 +500,11 @@ ClassDef *newResolveTypedef(FileDef *fileScope,MemberDef *md, ip--; } type=type.left(ip+1); + type.stripPrefix("const "); // strip leading "const" + type.stripPrefix("struct "); // strip leading "struct" + type.stripPrefix("union "); // strip leading "union" int sp=0; - if (type.stripPrefix("const ")) sp+=6; // strip leading "const" - if (type.stripPrefix("struct ")) sp+=7; // strip leading "struct" - if (type.stripPrefix("union ")) sp+=6; // strip leading "union" + tl=type.length(); // length may have been changed while (sp<tl && type.at(sp)==' ') sp++; MemberDef *memTypeDef = 0; ClassDef *result = getResolvedClassRec(md->getOuterScope(), @@ -697,9 +698,13 @@ static Definition *followPath(Definition *start,FileDef *fileScope,const QCStrin } } Definition *next = current->findInnerCompound(qualScopePart); - //printf("++ Looking for %s inside %s result %p\n",qualScopePart.data(),current->name().data(),next?next->name().data():"<null>"); + //printf("++ Looking for %s inside %s result %s\n", + // qualScopePart.data(), + // current->name().data(), + // next?next->name().data():"<null>"); if (next==0) // failed to follow the path { + //printf("==> next==0!\n"); if (current->definitionType()==Definition::TypeNamespace) { current = endOfPathIsUsedClass( @@ -715,6 +720,7 @@ static Definition *followPath(Definition *start,FileDef *fileScope,const QCStrin else // continue to follow scope { current = next; + //printf("==> current = %p\n",current); } ps=is+l; } @@ -1295,6 +1301,7 @@ ClassDef *getResolvedClassRec(Definition *scope, if (di->definitionType()==DefinitionIntf::TypeSymbolList) // not a unique name { + //printf(" name is not unique\n"); DefinitionListIterator dli(*(DefinitionList*)di); Definition *d; int count=0; @@ -1307,6 +1314,7 @@ ClassDef *getResolvedClassRec(Definition *scope, } else // unique name { + //printf(" name is unique\n"); Definition *d = (Definition *)di; getResolvedSymbol(scope,fileScope,d,explicitScopePart, minDistance,bestMatch,bestTypedef,bestTemplSpec, @@ -1426,12 +1434,29 @@ QCString removeRedundantWhiteSpace(const QCString &s) { nextChar: char c=s.at(i); - if ((csp==0 && (i==0 || !isId(constScope[i-1])) || (csp>0 && csp<6)) && - c==constScope[csp] - ) csp++; else csp=0; - if ((vsp==0 && (i==0 || !isId(virtualScope[i-1])) || (vsp>0 && vsp<8)) && - c==virtualScope[vsp] - ) vsp++; else vsp=0; + + // search for "const" + if (csp<6 && c==constScope[csp] && // character matches substring "const" + (csp>0 || // if it is the first character + i==0 || // the previous may not be a digit + !isId(s.at(i-1)) + ) + ) + csp++; + else // reset counter + csp=0; + + // search for "virtual" + if (vsp<8 && c==virtualScope[vsp] && // character matches substring "virtual" + (vsp>0 || // if it is the first character + i==0 || // the previous may not be a digit + !isId(s.at(i-1)) + ) + ) + vsp++; + else // reset counter + vsp=0; + if (c=='"') // quoted string { i++; @@ -1478,30 +1503,40 @@ nextChar: result+=' '; result+=s.at(i); } - else if (c=='t' && csp==5 && (i<5 || !isId(s.at(i-5))) && - !(isId(s.at(i+1)) /*|| s.at(i+1)==' '*/ || s.at(i+1)==')' || - s.at(i+1)==',' || s.at(i+1)=='\0')) + else if (c=='t' && csp==5 /*&& (i<5 || !isId(s.at(i-5)))*/ && + !(isId(s.at(i+1)) /*|| s.at(i+1)==' '*/ || + s.at(i+1)==')' || + s.at(i+1)==',' || + s.at(i+1)=='\0' + ) + ) // prevent const ::A from being converted to const::A { result+="t "; if (s.at(i+1)==' ') i++; csp=0; } - else if (c==':' && csp==6 && (i<6 || !isId(s.at(i-6)))) // replace const::A by const ::A + else if (c==':' && csp==6 /*&& (i<6 || !isId(s.at(i-6)))*/) + // replace const::A by const ::A { result+=" :"; csp=0; } - else if (c=='l' && vsp==7 && (i<7 || !isId(s.at(i-7))) && - !(isId(s.at(i+1)) /*|| s.at(i+1)==' '*/ || s.at(i+1)==')' || - s.at(i+1)==',' || s.at(i+1)=='\0')) + else if (c=='l' && vsp==7 /*&& (i<7 || !isId(s.at(i-7)))*/ && + !(isId(s.at(i+1)) /*|| s.at(i+1)==' '*/ || + s.at(i+1)==')' || + s.at(i+1)==',' || + s.at(i+1)=='\0' + ) + ) // prevent virtual ::A from being converted to virtual::A { result+="l "; if (s.at(i+1)==' ') i++; vsp=0; } - else if (c==':' && vsp==8 && (i<8 || !isId(s.at(i-8)))) // replace virtual::A by virtual ::A + else if (c==':' && vsp==8 /*&& (i<8 || !isId(s.at(i-8)))*/) + // replace virtual::A by virtual ::A { result+=" :"; vsp=0; @@ -1552,7 +1587,7 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope, bool keepSpaces) { //printf("`%s'\n",text); - static QRegExp regExp("[a-z_A-Z][~a-z_A-Z0-9.:]*"); + static QRegExp regExp("[a-z_A-Z][~!a-z_A-Z0-9.:]*"); QCString txtStr=text; int strLen = txtStr.length(); //printf("linkifyText scope=%s fileScope=%s strtxt=%s strlen=%d\n", @@ -1571,7 +1606,7 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope, ) { // add non-word part to the result - floatingIndex+=newIndex-skipIndex; + floatingIndex+=newIndex-skipIndex+matchLen; bool insideString=FALSE; int i; for (i=index;i<newIndex;i++) @@ -1579,24 +1614,28 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope, if (txtStr.at(i)=='"') insideString=!insideString; } - if (strLen>30 && floatingIndex>25 && autoBreak) // try to insert a split point + //printf("floatingIndex=%d strlen=%d autoBreak=%d\n",floatingIndex,strLen,autoBreak); + if (strLen>25 && floatingIndex>20 && autoBreak) // try to insert a split point { QCString splitText = txtStr.mid(skipIndex,newIndex-skipIndex); int splitLength = splitText.length(); - int i=splitText.find('<'); - if (i==-1) i=splitText.find(','); + int offset=1; + i=splitText.find(','); + if (i==-1) { i=splitText.find('<'); if (i!=-1) offset=0; } + if (i==-1) i=splitText.find('>'); if (i==-1) i=splitText.find(' '); + //printf("splitText=[%s] len=%d i=%d offset=%d\n",splitText.data(),splitLength,i,offset); if (i!=-1) // add a link-break at i in case of Html output { - out.writeString(splitText.left(i+1),keepSpaces); + out.writeString(splitText.left(i+offset),keepSpaces); out.writeBreak(); - out.writeString(splitText.right(splitLength-i-1),keepSpaces); + out.writeString(splitText.right(splitLength-i-offset),keepSpaces); + floatingIndex=splitLength-i-offset+matchLen; } else { out.writeString(splitText,keepSpaces); } - floatingIndex=splitLength-i-1; } else { @@ -1686,7 +1725,6 @@ void linkifyText(const TextGeneratorIntf &out,Definition *scope, // set next start point in the string //printf("index=%d/%d\n",index,txtStr.length()); skipIndex=index=newIndex+matchLen; - floatingIndex+=matchLen; } // add last part of the string to the result. //ol.docify(txtStr.right(txtStr.length()-skipIndex)); @@ -2893,14 +2931,17 @@ static QCString stripDeclKeywords(const QCString &s) // forward decl for circular dependencies static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type); -QCString getCanonicalTemplateSpec(Definition *d,FileDef *,const QCString& spec) +QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec) { + QCString templSpec = spec.stripWhiteSpace(); - //if (!templSpec.isEmpty() && templSpec.at(0) == '<') - //{ - // templSpec = "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace()); - //} - QCString resolvedType = resolveTypeDef(d,spec); + // this part had been commented out before... but it is needed to match for instance + // std::list<std::string> against list<string> so it is now back again! + if (!templSpec.isEmpty() && templSpec.at(0) == '<') + { + templSpec = "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace()); + } + QCString resolvedType = resolveTypeDef(d,templSpec); if (!resolvedType.isEmpty()) // not known as a typedef either { templSpec = resolvedType; @@ -2926,6 +2967,8 @@ static QCString getCanonicalTypeForIdentifier( { symName=word; } + //printf("getCanonicalTypeForIdentifier(%s,[%s->%s]) start\n", + // word.data(),tSpec?tSpec->data():"<none>",templSpec.data()); ClassDef *cd = 0; MemberDef *mType = 0; @@ -2942,7 +2985,7 @@ static QCString getCanonicalTypeForIdentifier( } if (cd && cd->isUsedOnly()) cd=0; // ignore types introduced by usage relations - //printf(" symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n", + //printf(" getCanonicalTypeForIdentifer: symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n", // symName.data(), // word.data(), // cd?cd->name().data():"<none>", @@ -3020,6 +3063,7 @@ static QCString getCanonicalTypeForIdentifier( result = resolvedType; } } + //printf("getCanonicalTypeForIdentifier [%s]->[%s]\n",word.data(),result.data()); return result; } @@ -3038,7 +3082,7 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type) type.stripPrefix("typename "); type = removeRedundantWhiteSpace(type); - //printf("extractCanonicalType(type=%s) def=%s file=%s\n",type.data(), + //printf("extractCanonicalType(type=%s) start: def=%s file=%s\n",type.data(), // d ? d->name().data() : "<null>",fs ? fs->name().data() : "<null>"); static QRegExp id("[a-z_A-Z][:a-z_A-Z0-9]*"); @@ -3112,7 +3156,7 @@ static bool matchArgument2( if (srcA->array!=dstA->array) // nomatch for char[] against char { NOMATCH - return FALSE; + return FALSE; } QCString sSrcName = " "+srcA->name; QCString sDstName = " "+dstA->name; @@ -3147,14 +3191,14 @@ static bool matchArgument2( if (srcA->canType==dstA->canType) { MATCH - return TRUE; + return TRUE; } else { //printf(" Canonical types do not match [%s]<->[%s]\n", // srcA->canType.data(),dstA->canType.data()); NOMATCH - return FALSE; + return FALSE; } } @@ -3173,12 +3217,12 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr if (match) { MATCH - return TRUE; + return TRUE; } else { NOMATCH - return FALSE; + return FALSE; } } @@ -3190,7 +3234,7 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr a->type = "void"; srcAl->append(a); MATCH - return TRUE; + return TRUE; } if ( dstAl->count()==0 && srcAl->count()==1 && srcAl->getFirst()->type=="void" ) @@ -3199,13 +3243,13 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr a->type = "void"; dstAl->append(a); MATCH - return TRUE; + return TRUE; } if (srcAl->count() != dstAl->count()) { NOMATCH - return FALSE; // different number of arguments -> no match + return FALSE; // different number of arguments -> no match } if (checkCV) @@ -3213,12 +3257,12 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr if (srcAl->constSpecifier != dstAl->constSpecifier) { NOMATCH - return FALSE; // one member is const, the other not -> no match + return FALSE; // one member is const, the other not -> no match } if (srcAl->volatileSpecifier != dstAl->volatileSpecifier) { NOMATCH - return FALSE; // one member is volatile, the other not -> no match + return FALSE; // one member is volatile, the other not -> no match } } @@ -3233,11 +3277,11 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr ) { NOMATCH - return FALSE; + return FALSE; } } MATCH - return TRUE; // all arguments match + return TRUE; // all arguments match } @@ -5953,6 +5997,7 @@ SrcLangExt getLanguageFromFileName(const QCString fileName) extLookup.insert(".idl", new int(SrcLangExt_IDL)); extLookup.insert(".ddl", new int(SrcLangExt_IDL)); extLookup.insert(".odl", new int(SrcLangExt_IDL)); + extLookup.insert(".ddl", new int(SrcLangExt_IDL)); extLookup.insert(".java", new int(SrcLangExt_Java)); extLookup.insert(".jsl", new int(SrcLangExt_Java)); extLookup.insert(".as", new int(SrcLangExt_Java)); @@ -6243,4 +6288,24 @@ QCString expandAlias(const QCString &aliasName,const QCString &aliasValue) return result; } +void writeTypeConstraints(OutputList &ol,Definition *d,ArgumentList *al) +{ + if (al==0) return; + ol.startConstraintList("Type constraints"); // TODO: add to translator! + ArgumentListIterator ali(*al); + Argument *a; + for (;(a=ali.current());++ali) + { + ol.startConstraintParam(); + ol.parseText(a->name); + ol.endConstraintParam(); + ol.startConstraintType(); + linkifyText(TextGeneratorOLImpl(ol),d,0,0,a->type); + ol.endConstraintType(); + ol.startConstraintDocs(); + ol.parseDoc(d->docFile(),d->docLine(),d,0,a->docs,TRUE,FALSE); + ol.endConstraintDocs(); + } + ol.endConstraintList(); +} @@ -343,5 +343,8 @@ QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argLis QCString resolveAliasCmd(const QCString aliasCmd); QCString expandAlias(const QCString &aliasName,const QCString &aliasValue); +void writeTypeConstraints(OutputList &ol,Definition *d,ArgumentList *al); + + #endif |