tools/qdoc3/generator.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 37 758a864f9613
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 /*
    42 /*
    43   generator.cpp
    43   generator.cpp
    44 */
    44 */
    45 #include <QtCore>
       
    46 #include <qdir.h>
    45 #include <qdir.h>
    47 #include <qdebug.h>
    46 #include <qdebug.h>
    48 #include "codemarker.h"
    47 #include "codemarker.h"
    49 #include "config.h"
    48 #include "config.h"
    50 #include "doc.h"
    49 #include "doc.h"
    65 QSet<QString> Generator::outputFormats;
    64 QSet<QString> Generator::outputFormats;
    66 QStringList Generator::imageFiles;
    65 QStringList Generator::imageFiles;
    67 QStringList Generator::imageDirs;
    66 QStringList Generator::imageDirs;
    68 QStringList Generator::exampleDirs;
    67 QStringList Generator::exampleDirs;
    69 QStringList Generator::exampleImgExts;
    68 QStringList Generator::exampleImgExts;
       
    69 QStringList Generator::scriptFiles;
       
    70 QStringList Generator::scriptDirs;
       
    71 QStringList Generator::styleFiles;
       
    72 QStringList Generator::styleDirs;
    70 QString Generator::outDir;
    73 QString Generator::outDir;
    71 QString Generator::project;
    74 QString Generator::project;
    72 
    75 
    73 static void singularPlural(Text& text, const NodeList& nodes)
    76 static void singularPlural(Text& text, const NodeList& nodes)
    74 {
    77 {
   123             config.lastLocation().fatal(tr("Cannot create output directory '%1'")
   126             config.lastLocation().fatal(tr("Cannot create output directory '%1'")
   124                                         .arg(outDir + "/images"));
   127                                         .arg(outDir + "/images"));
   125         if (!dirInfo.mkdir(outDir + "/images/used-in-examples"))
   128         if (!dirInfo.mkdir(outDir + "/images/used-in-examples"))
   126             config.lastLocation().fatal(tr("Cannot create output directory '%1'")
   129             config.lastLocation().fatal(tr("Cannot create output directory '%1'")
   127                                         .arg(outDir + "/images/used-in-examples"));
   130                                         .arg(outDir + "/images/used-in-examples"));
       
   131         if (!dirInfo.mkdir(outDir + "/scripts"))
       
   132             config.lastLocation().fatal(tr("Cannot create output directory '%1'")
       
   133                                         .arg(outDir + "/scripts"));
       
   134         if (!dirInfo.mkdir(outDir + "/style"))
       
   135             config.lastLocation().fatal(tr("Cannot create output directory '%1'")
       
   136                                         .arg(outDir + "/style"));
   128     }
   137     }
   129 
   138 
   130     imageFiles = config.getStringList(CONFIG_IMAGES);
   139     imageFiles = config.getStringList(CONFIG_IMAGES);
   131     imageDirs = config.getStringList(CONFIG_IMAGEDIRS);
   140     imageDirs = config.getStringList(CONFIG_IMAGEDIRS);
       
   141     scriptFiles = config.getStringList(CONFIG_SCRIPTS);
       
   142     scriptDirs = config.getStringList(CONFIG_SCRIPTDIRS);
       
   143     styleFiles = config.getStringList(CONFIG_STYLES);
       
   144     styleDirs = config.getStringList(CONFIG_STYLEDIRS);
   132     exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
   145     exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
   133     exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
   146     exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
   134                                           CONFIG_IMAGEEXTENSIONS);
   147                                           CONFIG_IMAGEEXTENSIONS);
   135 
   148 
   136     QString imagesDotFileExtensions =
   149     QString imagesDotFileExtensions =
   164                                      userFriendlyFilePath,
   177                                      userFriendlyFilePath,
   165                                      (*g)->outputDir() +
   178                                      (*g)->outputDir() +
   166                                      "/images");
   179                                      "/images");
   167                 ++e;
   180                 ++e;
   168             }
   181             }
       
   182 
       
   183             QStringList noExts;
       
   184             QStringList scripts =
       
   185                 config.getStringList(CONFIG_SCRIPTS+Config::dot+(*g)->format());
       
   186             e = scripts.begin();
       
   187             while (e != scripts.end()) {
       
   188                 QString userFriendlyFilePath;
       
   189                 QString filePath = Config::findFile(config.lastLocation(),
       
   190                                                     scriptFiles,
       
   191                                                     scriptDirs,
       
   192                                                     *e,
       
   193                                                     noExts,
       
   194                                                     userFriendlyFilePath);
       
   195                 if (!filePath.isEmpty())
       
   196                     Config::copyFile(config.lastLocation(),
       
   197                                      filePath,
       
   198                                      userFriendlyFilePath,
       
   199                                      (*g)->outputDir() +
       
   200                                      "/scripts");
       
   201                 ++e;
       
   202             }
       
   203 
       
   204             QStringList styles =
       
   205                 config.getStringList(CONFIG_STYLES+Config::dot+(*g)->format());
       
   206             e = styles.begin();
       
   207             while (e != styles.end()) {
       
   208                 QString userFriendlyFilePath;
       
   209                 QString filePath = Config::findFile(config.lastLocation(),
       
   210                                                     styleFiles,
       
   211                                                     styleDirs,
       
   212                                                     *e,
       
   213                                                     noExts,
       
   214                                                     userFriendlyFilePath);
       
   215                 if (!filePath.isEmpty())
       
   216                     Config::copyFile(config.lastLocation(),
       
   217                                      filePath,
       
   218                                      userFriendlyFilePath,
       
   219                                      (*g)->outputDir() +
       
   220                                      "/style");
       
   221                 ++e;
       
   222             }
   169         }
   223         }
   170         ++g;
   224         ++g;
   171     }
   225     }
   172 
   226 
   173     QRegExp secondParamAndAbove("[\2-\7]");
   227     QRegExp secondParamAndAbove("[\2-\7]");
   225     fmtRightMaps.clear();
   279     fmtRightMaps.clear();
   226     imgFileExts.clear();
   280     imgFileExts.clear();
   227     imageFiles.clear();
   281     imageFiles.clear();
   228     imageDirs.clear();
   282     imageDirs.clear();
   229     outDir = "";
   283     outDir = "";
       
   284     QmlClassNode::clear();
   230 }
   285 }
   231 
   286 
   232 Generator *Generator::generatorForFormat(const QString& format)
   287 Generator *Generator::generatorForFormat(const QString& format)
   233 {
   288 {
   234     QList<Generator *>::ConstIterator g = generators.begin();
   289     QList<Generator *>::ConstIterator g = generators.begin();
   320 void Generator::generateBody(const Node *node, CodeMarker *marker)
   375 void Generator::generateBody(const Node *node, CodeMarker *marker)
   321 {
   376 {
   322     bool quiet = false;
   377     bool quiet = false;
   323 
   378 
   324     if (node->type() == Node::Function) {
   379     if (node->type() == Node::Function) {
   325 #if 0        
   380 #if 0
   326         const FunctionNode *func = (const FunctionNode *) node;
   381         const FunctionNode *func = (const FunctionNode *) node;
   327         if (func->isOverload() && func->metaness() != FunctionNode::Ctor)
   382         if (func->isOverload() && func->metaness() != FunctionNode::Ctor)
   328             generateOverload(node, marker);
   383             generateOverload(node, marker);
   329 #endif        
   384 #endif
   330     }
   385     }
   331     else if (node->type() == Node::Fake) {
   386     else if (node->type() == Node::Fake) {
   332         const FakeNode *fake = static_cast<const FakeNode *>(node);
   387         const FakeNode *fake = static_cast<const FakeNode *>(node);
   333         if (fake->subType() == Node::Example)
   388         if (fake->subType() == Node::Example)
   334             generateExampleFiles(fake, marker);
   389             generateExampleFiles(fake, marker);
   345         if (node->type() == Node::Function) {
   400         if (node->type() == Node::Function) {
   346             const FunctionNode *func = static_cast<const FunctionNode *>(node);
   401             const FunctionNode *func = static_cast<const FunctionNode *>(node);
   347             if (func->reimplementedFrom() != 0)
   402             if (func->reimplementedFrom() != 0)
   348                 generateReimplementedFrom(func, marker);
   403                 generateReimplementedFrom(func, marker);
   349         }
   404         }
   350         
   405 
   351         if (!generateText(node->doc().body(), node, marker))
   406         if (!generateText(node->doc().body(), node, marker))
   352             if (node->isReimp())
   407             if (node->isReimp())
   353                 return;
   408                 return;
   354 
   409 
   355         if (node->type() == Node::Enum) {
   410         if (node->type() == Node::Enum) {
   450             }
   505             }
   451 #if 0
   506 #if 0
   452             // Now we put this at the top, before the other text.
   507             // Now we put this at the top, before the other text.
   453             if (func->reimplementedFrom() != 0)
   508             if (func->reimplementedFrom() != 0)
   454                 generateReimplementedFrom(func, marker);
   509                 generateReimplementedFrom(func, marker);
   455 #endif            
   510 #endif
   456         }
   511         }
   457     }
   512     }
   458 
   513 
   459     if (node->type() == Node::Fake) {
   514     if (node->type() == Node::Fake) {
   460         const FakeNode *fake = static_cast<const FakeNode *>(node);
   515         const FakeNode *fake = static_cast<const FakeNode *>(node);
   542 /*!
   597 /*!
   543   This function is called when the documentation for an
   598   This function is called when the documentation for an
   544   example is being formatted. It outputs the list of source
   599   example is being formatted. It outputs the list of source
   545   files comprising the example, and the list of images used
   600   files comprising the example, and the list of images used
   546   by the example. The images are copied into a subtree of
   601   by the example. The images are copied into a subtree of
   547   \c{...doc/html/images/used-in-examples/...} 
   602   \c{...doc/html/images/used-in-examples/...}
   548  */
   603  */
   549 void Generator::generateFileList(const FakeNode* fake,
   604 void Generator::generateFileList(const FakeNode* fake,
   550                                  CodeMarker* marker,
   605                                  CodeMarker* marker,
   551                                  Node::SubType subtype,
   606                                  Node::SubType subtype,
   552                                  const QString& tag)
   607                                  const QString& tag)
   638             }
   693             }
   639         }
   694         }
   640         ++g;
   695         ++g;
   641     }
   696     }
   642 #endif
   697 #endif
   643 
       
   644 void Generator::generateModuleWarning(const ClassNode *classe,
       
   645                                       CodeMarker *marker)
       
   646 {
       
   647     QString module = classe->moduleName();
       
   648     if (!module.isEmpty()) {
       
   649         Text text;
       
   650         if (!editionModuleMap["DesktopLight"].contains(module)) {
       
   651             text << Atom::ParaLeft
       
   652                  << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
       
   653                  << "This class is not part of the Qt GUI Framework Edition."
       
   654                  << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
       
   655                  << Atom::ParaRight;
       
   656         }
       
   657         else if (module == "Qt3Support") {
       
   658             text << Atom::ParaLeft
       
   659                  << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
       
   660                  << "Note to Qt GUI Framework Edition users:"
       
   661                  << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
       
   662                  << " This class is only available in the "
       
   663                  << Atom(Atom::AutoLink, "Qt Full Framework Edition")
       
   664                  << "." << Atom::ParaRight;
       
   665         }
       
   666 
       
   667         generateText(text, classe, marker);
       
   668     }
       
   669 }
       
   670 
   698 
   671 QString Generator::indent(int level, const QString& markedCode)
   699 QString Generator::indent(int level, const QString& markedCode)
   672 {
   700 {
   673     if (level == 0)
   701     if (level == 0)
   674         return markedCode;
   702         return markedCode;
   971                 default:
   999                 default:
   972                     break;
  1000                     break;
   973                 }
  1001                 }
   974                 ++c;
  1002                 ++c;
   975             }
  1003             }
   976             if (!exceptions) 
  1004             if (!exceptions)
   977                 text << ".";
  1005                 text << ".";
   978             else if (threadSafeness == Node::Reentrant) {
  1006             else if (threadSafeness == Node::Reentrant) {
   979                 if (nonreentrant.isEmpty()) {
  1007                 if (nonreentrant.isEmpty()) {
   980                     if (!threadsafe.isEmpty()) {
  1008                     if (!threadsafe.isEmpty()) {
   981                         text << ", but ";
  1009                         text << ", but ";
  1058 {
  1086 {
  1059     Text text;
  1087     Text text;
  1060     text << Atom::ParaLeft
  1088     text << Atom::ParaLeft
  1061          << "This function overloads ";
  1089          << "This function overloads ";
  1062     QString t = node->name() + "()";
  1090     QString t = node->name() + "()";
  1063     text << Atom::AutoLink << t 
  1091     text << Atom::AutoLink << t
  1064          << Atom::ParaRight;
  1092          << Atom::ParaRight;
  1065     generateText(text, node, marker);
  1093     generateText(text, node, marker);
  1066 }
  1094 }
  1067 
  1095 
  1068 void Generator::generateReimplementedFrom(const FunctionNode *func,
  1096 void Generator::generateReimplementedFrom(const FunctionNode *func,
  1211         text << classMap[className];
  1239         text << classMap[className];
  1212         text << separator(index++, classNames.count());
  1240         text << separator(index++, classNames.count());
  1213     }
  1241     }
  1214 }
  1242 }
  1215 
  1243 
       
  1244 void Generator::appendSortedQmlNames(Text& text,
       
  1245                                      const Node* base,
       
  1246                                      const NodeList& subs,
       
  1247                                      CodeMarker *marker)
       
  1248 {
       
  1249     QMap<QString,Text> classMap;
       
  1250     int index = 0;
       
  1251 
       
  1252 #ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
       
  1253     qDebug() << "Generator::appendSortedQmlNames():" << base->name() << "is inherited by...";
       
  1254 #endif
       
  1255     for (int i = 0; i < subs.size(); ++i) {
       
  1256         Text t;
       
  1257 #ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
       
  1258         qDebug() << "    " << subs[i]->name();
       
  1259 #endif
       
  1260         appendFullName(t, subs[i], base, marker);
       
  1261         classMap[t.toString().toLower()] = t;
       
  1262     }
       
  1263 
       
  1264     QStringList names = classMap.keys();
       
  1265     names.sort();
       
  1266 
       
  1267     foreach (const QString &name, names) {
       
  1268         text << classMap[name];
       
  1269         text << separator(index++, names.count());
       
  1270     }
       
  1271 }
       
  1272 
  1216 int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
  1273 int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
  1217 {
  1274 {
  1218     int skipAhead = 0;
  1275     int skipAhead = 0;
  1219     atom = atom->next();
  1276     atom = atom->next();
  1220     while (atom != 0 && atom->type() != type) {
  1277     while (atom != 0 && atom->type() != type) {