After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 494521 - PATCH INCLUDED : Doxygen unable to process files generated by EDoc++
PATCH INCLUDED : Doxygen unable to process files generated by EDoc++
Status: RESOLVED DUPLICATE of bug 494519
Product: doxygen
Classification: Other
Component: general
unspecified
Other All
: Normal enhancement
: ---
Assigned To: Dimitri van Heesch
Dimitri van Heesch
Depends on:
Blocks:
 
 
Reported: 2007-11-07 10:07 UTC by Brendon Costa
Modified: 2012-11-18 11:13 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Brendon Costa 2007-11-07 10:07:53 UTC
The above summary is not as concise as it could be. This is because in the one patch I have included fixes for a few smaller problems which is easier to attach to a single report than submitting a report for each problem and breaking the patch up.


===============================================
* Function prototypes fail to match with template types

In the example below Doxygen is unable to determine that the "\fn ..." identifies the provided function prototype declared previously. 

template <typename T, typename U = float>
class Test {};
void ExatcMatchWithDefaults(Test<int> one);

/** \fn ExatcMatchWithDefaults(Test<int, float>)
*
* \brief ExatcMatchWithDefaults Brief.
*
* ExatcMatchWithDefaults Detailed.
*/


===============================================
* Order of processing for files can not be easily modified by user

If the user wishes to process source files in a particular order there is no way to achieve it except by renaming the files as doxygen currently processes in alphabetical order. This was not a problem in earlier versions but now when doxygen encounters multiple document blocks for a single entity it will append the documentation of the second encountered block after the first. By allowing the user to modify the order of files being processed, the order of the documentation blocks seen can also be controlled.
Example:

Create three files:
--- file.h ---
void FirstBriefDualDetail();

--- filea.cpp ---
/** \fn FirstBriefDualDetail()
 *
 * \brief FirstBriefDualDetail brief a.
 *
 * FirstBriefDualDetail detailed a.
 */


--- fileb.cpp ---
/** \fn FirstBriefDualDetail()
 *
 * \brief FirstBriefDualDetail brief b.
 *
 * FirstBriefDualDetail detailed b.
 */


Now create two doxygen configuration files setting the input field as shown below
--- ab.dox ---
INPUT                  = file.h filea.cpp fileb.cpp

--- ba.dox ---
INPUT                  = file.h fileb.cpp filea.cpp

If you run doxygen with ab.dox and then again with ba.dox the documentation in the two is the same. This gives the user less control over thedocumentation that is generated (and in the case of EDoc++ causesissues with the order of information presented).


===============================================
* Patch also includes a few lines that provide DESTDIR installs which are helpful for generating packages. I.e.

./configure --prefix=/usr/local && make && make DESTDIR=$HOME/staging

will build for /usr/local but install to $HOME/staging


===============================================
===============================================
Patch below was generated using svn head revision: 593 using:
svn diff >../edoc.patch

This should produce a unified diff and there are no new files.



---- Snip: edoc.patch ----
Index: configure
===================================================================
--- configure	(revision 593)
+++ configure	(working copy)
@@ -435,6 +435,7 @@
 configPWD=`pwd`
 
 cat > .makeconfig <<EOF
+DESTDIR   =
 DOXYGEN   = $configPWD
 TMAKEPATH = $configPWD/tmake/lib/$f_platform
 ENV       = env TMAKEPATH=\$(TMAKEPATH)
@@ -444,7 +445,7 @@
 RM        = rm -f
 CP        = cp
 VERSION   = `cat VERSION`
-INSTALL   = $f_prefix
+INSTALL   = \$(DESTDIR)$f_prefix
 INSTTOOL  = $f_insttool
 DOXYDOCS  = ..
 DOCDIR    = $f_docdir
Index: src/util.cpp
===================================================================
--- src/util.cpp	(revision 593)
+++ src/util.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include <qdir.h>
 #include <qdatetime.h>
 #include <qcache.h>
+#include <qvaluelist.h>
 
 #include "util.h"
 #include "message.h"
@@ -3183,6 +3184,156 @@
   return extractCanonicalType(d,fs,type);
 }
 
+static bool BreakUpType(QString type, QString& prefix, QValueList<QString>& params, QString& suffix)
+{
+   //printf("Breaking up type: %s\n", type.data());
+   params.clear();
+
+   size_t depth = 0;
+   size_t start_param = -1;
+   for (size_t i = 0; i < type.length(); i++)
+   {
+      if (type[i] == '<')
+      {
+         //printf("< index: %d, depth: %d\n", i, depth);
+         depth++;
+         if (depth == 1)
+         {
+            // Then we have a prefix.
+            prefix = type.left(i).stripWhiteSpace();
+            //printf("Prefix: %s, index: %d\n", prefix.data(), i);
+            start_param = i + 1;
+         }
+      }
+      else if (type[i] == '>')
+      {
+         //printf("> index: %d, depth: %d\n", i, depth);
+         depth--;
+         if (depth == 0)
+         {
+            if (start_param != (size_t)-1)
+            {
+               params.append(type.mid(start_param, i - start_param).stripWhiteSpace());
+               //printf("Added param: %s, index: %d, start_param: %d\n", params.last().data(), i, start_param);
+            }
+            // Then we have finished parsing template params, lets obtain the suffix and return.
+            suffix = type.mid(i + 1).stripWhiteSpace();
+            //printf("Suffix: %s, index: %d\n", suffix.data(), i);
+            return true;
+         }
+      }
+      else if (type[i] == ',')
+      {
+         // If inside top level template then we have a new parameter.
+         if (depth == 1)
+         {
+            params.append(type.mid(start_param, i - start_param).stripWhiteSpace());
+            //printf("Added param: %s, index: %d, start_param: %d\n", params.last().data(), i, start_param);
+            start_param = i + 1;
+         }
+      }
+   }
+   
+   prefix = type.stripWhiteSpace();
+   //printf("No template info found. Returning prefix: %s\n", prefix.data());
+   return false;
+}
+
+// This function will return true if the two types are considered the same.
+// It differs from comparison of canonical names in that it breaks the 
+// canonical names into various parts for template types and will match types
+// where default template parameters have been specified explicitly with those
+// that have not been.
+static bool sameType(const QString& left, const QString& right)
+{
+   QString left_prefix;
+   QString left_suffix;
+   QValueList<QString> left_params;
+
+   QString right_prefix;
+   QString right_suffix;
+   QValueList<QString> right_params;
+   
+   BreakUpType(left, left_prefix, left_params, left_suffix);
+   BreakUpType(right, right_prefix, right_params, right_suffix);
+
+   // @@@It seems doxygen has trouble determining the namespace of 
+   // items inside template parameters. In order to get some sembelance of 
+   // correct matching i will use the shortest of the two strings as a 
+   // reference, and if the longer ends with the same contents then there is 
+   // a GOOD chance that it is a match. This will fail if for example in two 
+   // different namespaces there is a class defined called Blah. This method 
+   // may be unable to determine the difference between the two types of Blah, 
+   // but only when used in an overloaded function prototype.
+   
+   
+   
+   // Note: We will consider reference and value types as the same too.
+   // This is due to the way EDoc++ emits funciton names. If the compiler has
+   // decided that the function can have the value passed as a const reference
+   // then EDoc++ will not know that the user requested a pass by value, but 
+   // will just see a pass by reference instead. In the end by considering 
+   // reference types the same as value types for this purpose there is little
+   // difference.
+   
+   // So first we remove trailing " &" from the prefix.
+   if (left_prefix.length() >= 1 && left_prefix.mid(left_prefix.length() - 1) == "&")
+   {
+      left_prefix = left_prefix.mid(0, left_prefix.length() - 1).stripWhiteSpace();
+   }
+   if (right_prefix.length() >= 1 && right_prefix.mid(right_prefix.length() - 1) == "&")
+   {
+      right_prefix = right_prefix.mid(0, right_prefix.length() - 1).stripWhiteSpace();
+   }
+   
+   //printf("Obtaining min size of prefixes.\n");
+   size_t min = left_prefix.length();
+   min = (right_prefix.length() < min ? right_prefix.length() : min);
+   
+   // Check for zero length prefixes. If one is 0 and the other is not then 
+   // assume a failed match in case we are comparing a type ending in & with
+   // a compound type.
+   if (!min && left_prefix.length() != right_prefix.length())
+   {
+      return false;
+   }
+   
+   //printf("Finally getting proper values.\n");
+   left_prefix = left_prefix.mid(left_prefix.length() - min).stripWhiteSpace();
+   right_prefix = right_prefix.mid(right_prefix.length() - min).stripWhiteSpace();
+   
+   // If the prefixes differ then the types do not match.
+   if (left_prefix != right_prefix)
+   {
+      return false;
+   }
+
+   
+   QValueList<QString>::Iterator lt = left_params.begin();
+   QValueList<QString>::Iterator rt = right_params.begin();
+   for (; lt != left_params.end() && rt != right_params.end(); lt++, rt++)
+   {
+      // if the template parameter types are not considered the same then there is a failed match.
+      if (!sameType((*lt), QString(*rt)))
+      {
+         return false;
+      }
+   }
+   
+   // If the suffix types differ then the types do not match.
+   if (right_suffix != left_suffix)
+   {
+      if (!sameType(left_suffix, right_suffix))
+      {
+         return false;
+      }
+   }
+
+   // otherwise the two types are considered the same.
+   return true;
+}
+
+
 static bool matchArgument2(
     Definition *srcScope,FileDef *srcFileScope,Argument *srcA,
     Definition *dstScope,FileDef *dstFileScope,Argument *dstA
@@ -3229,7 +3380,10 @@
     dstA->canType = extractCanonicalArgType(dstScope,dstFileScope,dstA);
   }
 
-  if (srcA->canType==dstA->canType)
+  // Changed from comparison of canonical type names to a more 
+  // complex comparison of types to allow template types with specified default
+  // params to match "more correctly"
+  if (sameType(srcA->canType, dstA->canType))
   {
     MATCH
     return TRUE;
Index: src/doxygen.cpp
===================================================================
--- src/doxygen.cpp	(revision 593)
+++ src/doxygen.cpp	(working copy)
@@ -6899,28 +6899,26 @@
 static void generateFileSources()
 {
   if (documentedHtmlFiles==0) return;
-  if (Doxygen::inputNameList->count()>0)
+  // Ensure that sources are parsed in the order they are specified in the
+  // configuration file and not alphabetical order as was done in the past.
+  for (size_t i = 0; i < Doxygen::inputNameList->count(); i++)
   {
-    FileNameListIterator fnli(*Doxygen::inputNameList); 
-    FileName *fn;
-    for (;(fn=fnli.current());++fnli)
+    FileName *fn = Doxygen::inputNameList->at(i);
+    FileNameIterator fni(*fn);
+    FileDef *fd;
+    for (;(fd=fni.current());++fni)
     {
-      FileNameIterator fni(*fn);
-      FileDef *fd;
-      for (;(fd=fni.current());++fni)
+      if (fd->generateSourceFile()) // sources need to be shown in the output
       {
-        if (fd->generateSourceFile()) // sources need to be shown in the output
-        {
-          msg("Generating code for file %s...\n",fd->docName().data());
-          fd->writeSource(*outputList);
-        }
-        else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
-          // we needed to parse the sources even if we do not show them
-        {
-          msg("Parsing code for file %s...\n",fd->docName().data());
-          fd->parseSource();
-        }
+        msg("Generating code for file %s...\n",fd->docName().data());
+        fd->writeSource(*outputList);
       }
+      else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
+        // we needed to parse the sources even if we do not show them
+      {
+        msg("Parsing code for file %s...\n",fd->docName().data());
+        fd->parseSource();
+      }
     }
   }
 }
@@ -8391,9 +8389,11 @@
     }
   }
 
-  QCString *s=inputFiles.first();
-  while (s)
+  // Process files in order specified in the configuration 
+  // file, not just based on the iterator order.
+  for (size_t i = 0; i < inputFiles.count(); i++)
   {
+    QCString* s = inputFiles.at(i);
     QCString fileName=*s;
     QCString extension;
     int ei = fileName.findRev('.');
@@ -8438,8 +8438,6 @@
     FileDef *fd=findFileDef(Doxygen::inputNameDict,fileName,ambig);
     ASSERT(fd!=0);
     root->createNavigationIndex(rootNav,g_storage,fd);
-
-    s=inputFiles.next();
   }
 }
 
@@ -8598,7 +8596,7 @@
               {
                 fn = new FileName(fi.absFilePath(),name);
                 fn->append(fd);
-                if (fnList) fnList->inSort(fn);
+                if (fnList) fnList->append(fn);
                 fnDict->insert(name,fn);
               }
             }

---- Snip: edoc.patch ----
Comment 1 Brendon Costa 2007-11-07 10:30:56 UTC

*** This bug has been marked as a duplicate of 494519 ***