tools/qdoc3/javadocgenerator.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the tools applications of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "javadocgenerator.h"
       
    43 
       
    44 QT_BEGIN_NAMESPACE
       
    45 
       
    46 enum JavaSignatureSyntax {
       
    47     GeneratedJdocFile,
       
    48     JavadocRef,
       
    49     SlotSignature
       
    50 };
       
    51 
       
    52 static QString javaSignature(const FunctionNode *func, JavaSignatureSyntax syntax,
       
    53                              int maxParams = 65535)
       
    54 {
       
    55     maxParams = qMin(maxParams, func->parameters().count());
       
    56 
       
    57     QString result;
       
    58 
       
    59     if (syntax == GeneratedJdocFile) {
       
    60         if (func->access() == Node::Public) {
       
    61             result += "public ";
       
    62         } else if (func->access() == Node::Protected) {
       
    63             result += "protected ";
       
    64         } else {
       
    65             result += "private ";
       
    66         }
       
    67 
       
    68         if (func->metaness() == FunctionNode::Native)
       
    69             result += "native ";
       
    70 
       
    71         if (func->isConst())
       
    72             result += "final ";
       
    73 
       
    74         // ### func->metaness() == FunctionNode::Abstract
       
    75 
       
    76         if (func->isStatic())
       
    77             result += "static ";
       
    78 
       
    79         if (!func->returnType().isEmpty()) {
       
    80             result += func->returnType();
       
    81             result += ' ';
       
    82         }
       
    83     }
       
    84 
       
    85     if (syntax == SlotSignature) {
       
    86         result += "void mySlot";
       
    87     } else {
       
    88         result += func->name();
       
    89     }
       
    90     result += '(';
       
    91     for (int i = 0; i < maxParams; ++i) {
       
    92         if (i != 0)
       
    93             result += ", ";
       
    94         result += func->parameters().at(i).leftType();
       
    95         if (syntax != JavadocRef) {
       
    96             result += ' ';
       
    97             result += func->parameters().at(i).name();
       
    98         }
       
    99     }
       
   100     result += ')';
       
   101 
       
   102     return result;
       
   103 }
       
   104 
       
   105 static QString packageName(const Node *node)
       
   106 {
       
   107     while (node && node->type() != Node::Class && node->type() != Node::Fake)
       
   108         node = node->parent();
       
   109     if (!node)
       
   110         return QString();
       
   111     return node->moduleName();
       
   112 }
       
   113 
       
   114 JavadocGenerator::JavadocGenerator()
       
   115     : oldDevice(0), currentDepth(0)
       
   116 {
       
   117 }
       
   118 
       
   119 JavadocGenerator::~JavadocGenerator()
       
   120 {
       
   121 }
       
   122 
       
   123 void JavadocGenerator::initializeGenerator(const Config &config)
       
   124 {
       
   125     HtmlGenerator::initializeGenerator(config);
       
   126 
       
   127     formattingLeftMap().insert(ATOM_FORMATTING_PARAMETER,
       
   128                                formattingLeftMap().value(ATOM_FORMATTING_TELETYPE));
       
   129     formattingRightMap().insert(ATOM_FORMATTING_PARAMETER,
       
   130                                 formattingRightMap().value(ATOM_FORMATTING_TELETYPE));
       
   131 }
       
   132 
       
   133 void JavadocGenerator::terminateGenerator()
       
   134 {
       
   135     HtmlGenerator::terminateGenerator();
       
   136 }
       
   137 
       
   138 QString JavadocGenerator::format()
       
   139 {
       
   140     return "javadoc";
       
   141 }
       
   142 
       
   143 void JavadocGenerator::generateTree(const Tree *tree, CodeMarker *marker)
       
   144 {
       
   145     HtmlGenerator::generateTree(tree, marker);
       
   146 }
       
   147 
       
   148 QString JavadocGenerator::fileExtension(const Node *node)
       
   149 {
       
   150     if (node->type() == Node::Fake) {
       
   151         return "html";
       
   152     } else {
       
   153         return "jdoc";
       
   154     }
       
   155 }
       
   156 
       
   157 QString JavadocGenerator::typeString(const Node *node)
       
   158 {
       
   159     if (node->type() == Node::Function) {
       
   160         const FunctionNode *func = static_cast<const FunctionNode *>(node);
       
   161         return func->metaness() == FunctionNode::Signal ? "signal" : "method";
       
   162     } else {
       
   163         return HtmlGenerator::typeString(node);
       
   164     }
       
   165 }
       
   166 
       
   167 QString JavadocGenerator::imageFileName(const Node *relative, const QString& fileBase)
       
   168 {
       
   169     QString result = HtmlGenerator::imageFileName(relative, fileBase);
       
   170     if (!result.isEmpty()) {
       
   171         QString package = packageName(relative);
       
   172         int numSubPackages = package.count('.') - 2;
       
   173         while (numSubPackages > 0) {
       
   174             result.prepend("%2E%2E/");  // javadoc 1.5.0_06 chokes on '../'
       
   175             --numSubPackages;
       
   176         }
       
   177     }
       
   178     return result;
       
   179 }
       
   180 
       
   181 static int textDepth = 0;
       
   182 
       
   183 void JavadocGenerator::startText(const Node *relative, CodeMarker *marker)
       
   184 {
       
   185     if (textDepth++ == 0 && relative->type() != Node::Fake) {
       
   186         Q_ASSERT(!oldDevice);
       
   187         oldDevice = out().device();
       
   188         Q_ASSERT(oldDevice);
       
   189         out().setString(&buffer);
       
   190     }
       
   191     HtmlGenerator::startText(relative, marker);
       
   192 }
       
   193 
       
   194 void JavadocGenerator::endText(const Node *relative, CodeMarker *marker)
       
   195 {
       
   196     HtmlGenerator::endText(relative, marker);
       
   197     if (--textDepth == 0 && relative->type() != Node::Fake) {
       
   198         Q_ASSERT(oldDevice);
       
   199         out().setDevice(oldDevice);
       
   200         oldDevice = 0;
       
   201 
       
   202         /*
       
   203             Need to escape XML metacharacters in .jdoc files.
       
   204         */
       
   205         buffer.replace("*/", "*&lt;!-- noop --&gt;/");
       
   206         buffer.replace("&", "&amp;");
       
   207         buffer.replace("\"", "&quot;");
       
   208         buffer.replace("<", "&lt;");
       
   209         buffer.replace(">", "&gt;");
       
   210         out() << buffer;
       
   211         buffer.clear();
       
   212     }
       
   213 }
       
   214 
       
   215 int JavadocGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker)
       
   216 {
       
   217     return HtmlGenerator::generateAtom(atom, relative, marker);
       
   218 }
       
   219 
       
   220 void JavadocGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker)
       
   221 {
       
   222     generateIndent();
       
   223     out() << "<class name=\"" << protect(inner->name()) << "\"";
       
   224     generateDoc(inner, marker);
       
   225     out() << ">\n";
       
   226 
       
   227     ++currentDepth;
       
   228     foreach (Node *node, inner->childNodes()) {
       
   229         if (node->isInnerNode()) {
       
   230             generateClassLikeNode(static_cast<InnerNode *>(node), marker);
       
   231         } else {
       
   232             if (node->type() == Node::Enum) {
       
   233                 EnumNode *enume = static_cast<EnumNode *>(node);
       
   234 
       
   235                 generateIndent();
       
   236                 out() << "<enum name=\"" << protect(node->name()) << "\"";
       
   237                 generateDoc(node, marker);
       
   238                 out() << ">\n";
       
   239 
       
   240                 ++currentDepth;
       
   241                 const QList<EnumItem> &items = enume->items();
       
   242                 for (int i = 0; i < items.count(); ++i) {
       
   243                     const EnumItem &item = items.at(i);
       
   244                     generateIndent();
       
   245                     out() << "<enum-value name=\"" << protect(item.name()) << "\"";
       
   246                     generateEnumItemDoc(item.text(), enume, marker);
       
   247                     out() << "/>\n";
       
   248                 }
       
   249                 --currentDepth;
       
   250 
       
   251                 out() << "</enum>\n";
       
   252             } else if (node->type() == Node::Function) {
       
   253                 FunctionNode *func = static_cast<FunctionNode *>(node);
       
   254                 generateIndent();
       
   255                 out() << (func->metaness() == FunctionNode::Signal ? "<signal" : "<method")
       
   256                       << " name=\""
       
   257                       << protect(javaSignature(func, GeneratedJdocFile))
       
   258                       << "\"";
       
   259                 generateDoc(node, marker);
       
   260                 out() << "/>\n";
       
   261             }
       
   262         }
       
   263     }
       
   264     --currentDepth;
       
   265 
       
   266     generateIndent();
       
   267     out() << "</class>\n";
       
   268 }
       
   269 
       
   270 void JavadocGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
       
   271 {
       
   272     HtmlGenerator::generateFakeNode(fake, marker);
       
   273 }
       
   274 
       
   275 bool JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker)
       
   276 {
       
   277     HtmlGenerator::generateText(text, relative, marker);
       
   278     return true;
       
   279 }
       
   280 
       
   281 void JavadocGenerator::generateBody(const Node *node, CodeMarker *marker)
       
   282 {
       
   283     generateText(node->doc().body(), node, marker);
       
   284 }
       
   285 
       
   286 void JavadocGenerator::generateAlsoList( const Node *node, CodeMarker *marker )
       
   287 {
       
   288     QList<Text> alsoList = node->doc().alsoList();
       
   289     supplementAlsoList(node, alsoList);
       
   290 
       
   291     if (node->type() == Node::Fake
       
   292             || (node->type() == Node::Function
       
   293                 && static_cast<const FunctionNode *>(node)->metaness() == FunctionNode::Signal)) {
       
   294         Text text;
       
   295 
       
   296         if (!alsoList.isEmpty()) {
       
   297             text << Atom(Atom::ListLeft, ATOM_LIST_TAG)
       
   298                  << Atom(Atom::ListTagLeft, ATOM_LIST_TAG)
       
   299                  << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
       
   300                  << "See Also:"
       
   301                  << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
       
   302                  << Atom(Atom::ListTagRight, ATOM_LIST_TAG)
       
   303                  << Atom(Atom::ListItemLeft, ATOM_LIST_TAG);
       
   304 
       
   305             for (int i = 0; i < alsoList.count(); ++i) {
       
   306                 if (i != 0)
       
   307                     text << ", ";
       
   308                 text << alsoList.at(i);
       
   309             }
       
   310             text << Atom(Atom::ListItemRight, ATOM_LIST_TAG)
       
   311                  << Atom(Atom::ListRight, ATOM_LIST_TAG);
       
   312         }
       
   313 
       
   314         generateText(text, node, marker);
       
   315     } else {
       
   316         foreach (const Text &text, alsoList) {
       
   317             out() << "\n@see ";
       
   318             generateText(text, node, marker);
       
   319         }
       
   320     }
       
   321 }
       
   322 
       
   323 QString JavadocGenerator::refForNode( const Node *node )
       
   324 {
       
   325     if (node->type() == Node::Function)
       
   326         return javaSignature(static_cast<const FunctionNode *>(node), JavadocRef);
       
   327 
       
   328     return HtmlGenerator::refForNode(node);
       
   329 }
       
   330 
       
   331 QString JavadocGenerator::linkForNode( const Node *node, const Node *relative )
       
   332 {
       
   333     // ### EVIL, relative should never be null
       
   334     if (!relative)
       
   335         relative = node;
       
   336 
       
   337     if (packageName(node).isEmpty()) {
       
   338         // ### jasmin: Fixme
       
   339         return QString();
       
   340     }
       
   341 
       
   342     QString result;
       
   343     if (node->type() == Node::Fake) {
       
   344         result = node->name();
       
   345     } else {
       
   346         if (!node->isInnerNode()) {
       
   347             result = linkForNode(node->parent(), relative) + "#" + refForNode(node);
       
   348         } else {
       
   349             result = node->name() + ".html";
       
   350         }
       
   351     }
       
   352 
       
   353     QStringList nodePackage = packageName(node).split(".");
       
   354     QStringList relativePackage = packageName(relative).split(".");
       
   355     if (nodePackage == QStringList(QString()) || relativePackage == QStringList(QString())) {
       
   356         qWarning("I'm in trouble [%s][%s]", qPrintable(node->name()), qPrintable(relative->name()));
       
   357         return QString();
       
   358     }
       
   359 
       
   360     int i = nodePackage.count() - 1;
       
   361     while (nodePackage.value(i) != relativePackage.value(i)) {
       
   362         result.prepend(nodePackage.at(i) + "/");
       
   363         --i;
       
   364     }
       
   365 
       
   366     ++i;
       
   367     while (i < relativePackage.count()) {
       
   368         result.prepend("%2E%2E/");      // javadoc 1.5.0_06 chokes on '../'
       
   369         ++i;
       
   370     }
       
   371 
       
   372     return result;
       
   373 }
       
   374 
       
   375 QString JavadocGenerator::refForAtom(Atom *atom, const Node *node)
       
   376 {
       
   377     return HtmlGenerator::refForAtom(atom, node);
       
   378 }
       
   379 
       
   380 /*
       
   381     Neutralize dumb functions called from HtmlGenerator.
       
   382 */
       
   383 void JavadocGenerator::generateDcf(const QString & /* fileBase */, const QString & /* startPage */,
       
   384                                    const QString & /* title */, DcfSection & /* dcfRoot */)
       
   385 {
       
   386 }
       
   387 
       
   388 void JavadocGenerator::generateIndex(const QString & /* fileBase */, const QString & /* url */,
       
   389                                      const QString & /* title */)
       
   390 {
       
   391 }
       
   392 
       
   393 void JavadocGenerator::generateIndent()
       
   394 {
       
   395     for (int i = 0; i < currentDepth; ++i)
       
   396         out() << "    ";
       
   397 }
       
   398 
       
   399 void JavadocGenerator::generateDoc(const Node *node, CodeMarker *marker)
       
   400 {
       
   401     const Text &text = node->doc().body();
       
   402     if (!text.isEmpty()) {
       
   403         out() << " doc=\"/**\n";
       
   404         Generator::generateStatus(node, marker);
       
   405         generateText(text, node, marker);
       
   406         if (node && node->type() == Node::Function) {
       
   407             const FunctionNode *func = static_cast<const FunctionNode *>(node);
       
   408             if (func->metaness() == FunctionNode::Signal) {
       
   409                 QStringList slotSignatures;
       
   410                 for (int i = func->parameters().count(); i >= 0; --i)
       
   411                     slotSignatures += javaSignature(func, SlotSignature, i);
       
   412 
       
   413                 Text text;
       
   414 
       
   415                 text << Atom(Atom::ListLeft, ATOM_LIST_TAG)
       
   416                      << Atom(Atom::ListTagLeft, ATOM_LIST_TAG)
       
   417                      << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
       
   418 
       
   419                 if (slotSignatures.count() == 1) {
       
   420                     text << "Compatible Slot Signature:";
       
   421                 } else {
       
   422                     text << "Compatible Slot Signatures:";
       
   423                 }
       
   424 
       
   425                 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
       
   426                      << Atom(Atom::ListTagRight, ATOM_LIST_TAG);
       
   427 
       
   428                 for (int i = 0; i < slotSignatures.count(); ++i) {
       
   429                     text << Atom(Atom::ListItemLeft, ATOM_LIST_TAG)
       
   430                          << Atom(Atom::C, marker->markedUpCode(slotSignatures.at(i), 0, ""))
       
   431                          << Atom(Atom::ListItemRight, ATOM_LIST_TAG);
       
   432                 }
       
   433                 text << Atom(Atom::ListRight, ATOM_LIST_TAG);
       
   434                 generateText(text, node, marker);
       
   435             }
       
   436         }
       
   437         if (node)
       
   438             generateAlsoList(node, marker);
       
   439         out() << " */\"";
       
   440     }
       
   441 }
       
   442 
       
   443 void JavadocGenerator::generateEnumItemDoc(const Text &text, const Node *node, CodeMarker *marker)
       
   444 {
       
   445     out() << " doc=\"/**\n";
       
   446     if (text.isEmpty()) {
       
   447         out() << "Internal.";
       
   448     } else {
       
   449         generateText(text, node, marker);
       
   450     }
       
   451     out() << " */\"";
       
   452 }
       
   453 
       
   454 QT_END_NAMESPACE