Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/tools/qdoc3/cppcodeparser.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the tools applications of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     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.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848
    4949#include <stdio.h>
     50#include <errno.h>
    5051
    5152#include "codechunk.h"
     
    8889#define COMMAND_QMLCLASS                Doc::alias("qmlclass")
    8990#define COMMAND_QMLPROPERTY             Doc::alias("qmlproperty")
     91#define COMMAND_QMLATTACHEDPROPERTY     Doc::alias("qmlattachedproperty")
     92#define COMMAND_QMLINHERITS             Doc::alias("inherits")
     93#define COMMAND_QMLSIGNAL               Doc::alias("qmlsignal")
     94#define COMMAND_QMLATTACHEDSIGNAL       Doc::alias("qmlattachedsignal")
     95#define COMMAND_QMLMETHOD               Doc::alias("qmlmethod")
     96#define COMMAND_QMLATTACHEDMETHOD       Doc::alias("qmlattachedmethod")
     97#define COMMAND_QMLDEFAULT              Doc::alias("default")
    9098#endif
    9199
     
    110118            *link = arg.left(spaceAt).trimmed();
    111119            *desc = arg.mid(spaceAt).trimmed();
    112         } else {
     120        }
     121        else {
    113122            *link = arg;
    114123            *desc = arg;
     
    189198CppCodeParser::~CppCodeParser()
    190199{
    191 }
    192 
     200    // nothing.
     201}
     202
     203/*!
     204  The constructor initializes a map of special node types
     205  for identifying important nodes. And it initializes
     206  some filters for identifying certain kinds of files.
     207 */
    193208void CppCodeParser::initializeParser(const Config &config)
    194209{
     
    203218    nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable);
    204219
    205 #ifdef QDOC_QML
    206     //    nodeTypeMap.insert(COMMAND_QMLCLASS, Node::Class);
    207     nodeTypeMap.insert(COMMAND_QMLPROPERTY, Node::Property);
    208 #endif   
    209    
    210220    exampleFiles = config.getStringList(CONFIG_EXAMPLES);
    211221    exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
     
    217227    else
    218228        exampleNameFilter = "*.cpp *.h *.js *.xq *.svg *.xml *.ui";
    219 }
    220 
     229
     230    QStringList exampleImagePatterns = config.getStringList(
     231        CONFIG_EXAMPLES + Config::dot + CONFIG_IMAGEEXTENSIONS);
     232
     233    if (!exampleImagePatterns.isEmpty())
     234        exampleImageFilter = exampleImagePatterns.join(" ");
     235    else
     236        exampleImageFilter = "*.png";
     237}
     238
     239/*!
     240  Clear the map of common node types and call
     241  the same function in the base class.
     242 */
    221243void CppCodeParser::terminateParser()
    222244{
     
    225247}
    226248
     249/*!
     250  Returns "Cpp".
     251 */
    227252QString CppCodeParser::language()
    228253{
     
    230255}
    231256
     257/*!
     258  Returns a list of extensions for header files.
     259 */
    232260QString CppCodeParser::headerFileNameFilter()
    233261{
     
    235263}
    236264
     265/*!
     266  Returns a list of extensions for source files, i.e. not
     267  header files.
     268 */
    237269QString CppCodeParser::sourceFileNameFilter()
    238270{
     
    282314    FILE *in = fopen(QFile::encodeName(filePath), "r");
    283315    if (!in) {
    284         location.error(tr("Cannot open C++ source file '%1'").arg(filePath));
     316        location.error(tr("Cannot open C++ source file '%1' (%2)").arg(filePath).arg(strerror(errno)));
    285317        return;
    286318    }
     
    296328}
    297329
     330/*!
     331  This is called after all the header files have been parsed.
     332  I think the most important thing it does is resolve class
     333  inheritance links in the tree. But it also initializes a
     334  bunch of stuff.
     335 */
    298336void CppCodeParser::doneParsingHeaderFiles(Tree *tree)
    299337{
     
    342380}
    343381
     382/*!
     383  This is called after all the source files (i.e., not the
     384  header files) have been parsed. It traverses the tree to
     385  resolve property links, normalize overload signatures, and
     386  do other housekeeping of the tree.
     387 */
    344388void CppCodeParser::doneParsingSourceFiles(Tree *tree)
    345389{
     
    350394}
    351395
     396/*!
     397  This function searches the \a tree to find a FunctionNode
     398  for a function with the signature \a synopsis. If the
     399  \a relative node is provided, the search begins there. If
     400  \a fuzzy is true, base classes are searched. The function
     401  node is returned, if found.
     402 */
    352403const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis,
    353404                                                    Tree *tree,
     
    478529                           << COMMAND_SERVICE
    479530                           << COMMAND_TYPEDEF
    480 #ifdef QDOC_QML       
     531#ifdef QDOC_QML
    481532                           << COMMAND_VARIABLE
    482533                           << COMMAND_QMLCLASS
    483                            << COMMAND_QMLPROPERTY;
    484 #else   
     534                           << COMMAND_QMLPROPERTY
     535                           << COMMAND_QMLATTACHEDPROPERTY
     536                           << COMMAND_QMLSIGNAL
     537                           << COMMAND_QMLATTACHEDSIGNAL
     538                           << COMMAND_QMLMETHOD
     539                           << COMMAND_QMLATTACHEDMETHOD;
     540#else
    485541                           << COMMAND_VARIABLE;
    486 #endif   
     542#endif
    487543}
    488544
     
    539595                lastPath = parentPath;
    540596            }
    541 
    542             if (func)
     597            if (func) {
    543598                func->borrowParameterNames(clone);
     599                func->setParentPath(clone->parentPath());
     600            }
    544601            delete clone;
    545602        }
     
    588645         */
    589646        // ### split(" ") hack is there to support header file syntax
    590         QStringList paths = arg.split(" "); 
     647        QStringList paths = arg.split(" ");
    591648        QStringList path = paths[0].split("::");
    592        
    593 #if QDOC2DOX       
    594         // qdoc -> doxygen.
    595         if (Doc::isDoxPass(1)) {
    596             if (command == COMMAND_PROPERTY) {
    597                 Doc::insertProperty(path);
    598             }
    599             else if (command == COMMAND_VARIABLE) {
    600                 Doc::insertVariable(path);
    601             }
    602             else if (command == COMMAND_ENUM) {
    603                 // zzz
    604             }
    605         }
    606 #endif
    607 
    608649        Node *node = 0;
    609650        if (!usedNamespaces.isEmpty()) {
     
    644685        }
    645686
     687        if (command == COMMAND_CLASS) {
     688            if (paths.size() > 1) {
     689                if (!paths[1].endsWith(".h")) {
     690                    ClassNode*cnode = static_cast<ClassNode*>(node);
     691                    cnode->setQmlElement(paths[1]);
     692                }
     693            }
     694        }
    646695        return node;
    647696    }
    648697    else if (command == COMMAND_EXAMPLE) {
    649         FakeNode *fake = new FakeNode(tre->root(), arg, FakeNode::Example);
     698        FakeNode *fake = new FakeNode(tre->root(), arg, Node::Example);
    650699        createExampleFileNodes(fake);
    651700        return fake;
    652701    }
    653702    else if (command == COMMAND_EXTERNALPAGE) {
    654         return new FakeNode(tre->root(), arg, FakeNode::ExternalPage);
     703        return new FakeNode(tre->root(), arg, Node::ExternalPage);
    655704    }
    656705    else if (command == COMMAND_FILE) {
    657         return new FakeNode(tre->root(), arg, FakeNode::File);
     706        return new FakeNode(tre->root(), arg, Node::File);
    658707    }
    659708    else if (command == COMMAND_GROUP) {
    660         return new FakeNode(tre->root(), arg, FakeNode::Group);
     709        return new FakeNode(tre->root(), arg, Node::Group);
    661710    }
    662711    else if (command == COMMAND_HEADERFILE) {
    663         return new FakeNode(tre->root(), arg, FakeNode::HeaderFile);
     712        return new FakeNode(tre->root(), arg, Node::HeaderFile);
    664713    }
    665714    else if (command == COMMAND_MODULE) {
    666         return new FakeNode(tre->root(), arg, FakeNode::Module);
     715        return new FakeNode(tre->root(), arg, Node::Module);
    667716    }
    668717    else if (command == COMMAND_PAGE) {
    669         return new FakeNode(tre->root(), arg, FakeNode::Page);
    670     }
    671 #ifdef QDOC_QML   
     718        return new FakeNode(tre->root(), arg, Node::Page);
     719    }
     720#ifdef QDOC_QML
    672721    else if (command == COMMAND_QMLCLASS) {
    673722        const ClassNode* classNode = 0;
    674         QStringList names = arg.split(" ");
    675         //qDebug() << "QMLCLASS" << names;
     723        QStringList names = arg.split(" ");
    676724        if (names.size() > 1) {
    677725            Node* n = tre->findNode(names[1].split("::"),Node::Class);
    678             if (n) {
     726            if (n)
    679727                classNode = static_cast<const ClassNode*>(n);
    680                 //qDebug() << "FOUND IT!" << classNode->name();
    681             }
    682         }
    683         return new QmlNode(tre->root(), names[0], classNode);
    684     }
    685 #endif   
     728        }
     729        return new QmlClassNode(tre->root(), names[0], classNode);
     730    }
     731    else if ((command == COMMAND_QMLSIGNAL) ||
     732             (command == COMMAND_QMLMETHOD) ||
     733             (command == COMMAND_QMLATTACHEDSIGNAL) ||
     734             (command == COMMAND_QMLATTACHEDMETHOD)) {
     735        QString element;
     736        QString type;
     737        QmlClassNode* qmlClass = 0;
     738        if (splitQmlMethodArg(doc,arg,type,element)) {
     739            Node* n = tre->findNode(QStringList(element),Node::Fake);
     740            if (n && n->subType() == Node::QmlClass) {
     741                qmlClass = static_cast<QmlClassNode*>(n);
     742                if (command == COMMAND_QMLSIGNAL)
     743                    return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,false,COMMAND_QMLSIGNAL);
     744                else if (command == COMMAND_QMLATTACHEDSIGNAL)
     745                    return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,true,COMMAND_QMLATTACHEDSIGNAL);
     746                else if (command == COMMAND_QMLMETHOD)
     747                    return makeFunctionNode(doc,arg,qmlClass,Node::QmlMethod,false,COMMAND_QMLMETHOD);
     748                else if (command == COMMAND_QMLATTACHEDMETHOD)
     749                    return makeFunctionNode(doc,arg,qmlClass,Node::QmlMethod,true,COMMAND_QMLATTACHEDMETHOD);
     750                else
     751                    return 0; // never get here.
     752            }
     753        }
     754    }
     755#endif
    686756    return 0;
    687757}
     758
     759#ifdef QDOC_QML
     760
     761/*!
     762  A QML property argument has the form...
     763
     764  <type> <element>::<name>
     765
     766  This function splits the argument into those three
     767  parts, sets \a type, \a element, and \a name,
     768  and returns true. If any of the parts isn't found,
     769  a qdoc warning is output and false is returned.
     770 */
     771bool CppCodeParser::splitQmlPropertyArg(const Doc& doc,
     772                                        const QString& arg,
     773                                        QString& type,
     774                                        QString& element,
     775                                        QString& name)
     776{
     777    QStringList blankSplit = arg.split(" ");
     778    if (blankSplit.size() > 1) {
     779        type = blankSplit[0];
     780        QStringList colonSplit(blankSplit[1].split("::"));
     781        if (colonSplit.size() > 1) {
     782            element = colonSplit[0];
     783            name = colonSplit[1];
     784            return true;
     785        }
     786        else
     787            doc.location().warning(tr("Missing parent QML element name"));
     788    }
     789    else
     790        doc.location().warning(tr("Missing property type"));
     791    return false;
     792}
     793
     794/*!
     795  A QML signal or method argument has the form...
     796
     797  <type> <element>::<name>(<param>, <param>, ...)
     798
     799  This function splits the argument into those two
     800  parts, sets \a element, and \a name, and returns
     801  true. If either of the parts isn't found, a debug
     802  message is output and false is returned.
     803 */
     804bool CppCodeParser::splitQmlMethodArg(const Doc& doc,
     805                                      const QString& arg,
     806                                      QString& type,
     807                                      QString& element)
     808{
     809    QStringList colonSplit(arg.split("::"));
     810    if (colonSplit.size() > 1) {
     811        QStringList blankSplit = colonSplit[0].split(" ");
     812        if (blankSplit.size() > 1) {
     813            type = blankSplit[0];
     814            element = blankSplit[1];
     815        }
     816        else {
     817            type = QString("");
     818            element = colonSplit[0];
     819        }
     820        return true;
     821    }
     822    else
     823        doc.location().warning(tr("Missing parent QML element or method signature"));
     824    return false;
     825}
     826
     827/*!
     828  Process the topic \a command group with arguments \a args.
     829
     830  Currently, this function is called only for \e{qmlproperty}
     831  and \e{qmlattachedproperty}.
     832 */
     833Node *CppCodeParser::processTopicCommandGroup(const Doc& doc,
     834                                              const QString& command,
     835                                              const QStringList& args)
     836{
     837    QmlPropGroupNode* qmlPropGroup = 0;
     838    if ((command == COMMAND_QMLPROPERTY) ||
     839        (command == COMMAND_QMLATTACHEDPROPERTY)) {
     840        QString type;
     841        QString element;
     842        QString property;
     843        bool attached = (command == COMMAND_QMLATTACHEDPROPERTY);
     844        QStringList::ConstIterator arg = args.begin();
     845        if (splitQmlPropertyArg(doc,(*arg),type,element,property)) {
     846            Node* n = tre->findNode(QStringList(element),Node::Fake);
     847            if (n && n->subType() == Node::QmlClass) {
     848                QmlClassNode* qmlClass = static_cast<QmlClassNode*>(n);
     849                if (qmlClass)
     850                    qmlPropGroup = new QmlPropGroupNode(qmlClass,
     851                                                        property,
     852                                                        attached);
     853            }
     854        }
     855        if (qmlPropGroup) {
     856            const ClassNode *correspondingClass = static_cast<const QmlClassNode*>(qmlPropGroup->parent())->classNode();
     857            PropertyNode *correspondingProperty = 0;
     858            if (correspondingClass)
     859                correspondingProperty = static_cast<PropertyNode*>((Node*)correspondingClass->findNode(property, Node::Property));
     860            QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached);
     861            if (correspondingProperty) {
     862                bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
     863                qmlPropNode->setWritable(writableList || correspondingProperty->isWritable());
     864            }
     865            ++arg;
     866            while (arg != args.end()) {
     867                if (splitQmlPropertyArg(doc,(*arg),type,element,property)) {
     868                    QmlPropertyNode* qmlPropNode = new QmlPropertyNode(qmlPropGroup,
     869                                                                       property,
     870                                                                       type,
     871                                                                       attached);
     872                    if (correspondingProperty) {
     873                        bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
     874                        qmlPropNode->setWritable(writableList || correspondingProperty->isWritable());
     875                    }
     876                }
     877                ++arg;
     878            }
     879        }
     880    }
     881    return qmlPropGroup;
     882}
     883#endif
    688884
    689885/*!
     
    701897                                << COMMAND_PREVIOUSPAGE
    702898                                << COMMAND_INDEXPAGE
     899#ifdef QDOC_QML       
     900                                << COMMAND_STARTPAGE
     901                                << COMMAND_QMLINHERITS
     902                                << COMMAND_QMLDEFAULT;
     903#else   
    703904                                << COMMAND_STARTPAGE;
     905#endif   
    704906}
    705907
     
    743945                       "with the same signature or it exists but isn't virtual."));
    744946            }
    745 #if 0 // Ideally, we would enable this check to warn whenever \reimp is used
    746       // incorrectly, and only make the node internal if the function is a
    747       // reimplementation of another function in a base class.
     947            /*
     948              Ideally, we would enable this check to warn whenever
     949              \reimp is used incorrectly, and only make the node
     950              internal if the function is a reimplementation of
     951              another function in a base class.
     952            */
    748953            else if (from->access() == Node::Private
    749954                     || from->parent()->access() == Node::Private) {
    750                 doc.location().warning(
    751                     tr("Base function for '\\%1' in %2() is private or internal")
     955                doc.location().warning(tr("'\\%1' in %2() should be '\\internal' because its base function is private or internal")
    752956                    .arg(COMMAND_REIMP).arg(node->name()));
    753957            }
    754 #endif
    755             // Note: Setting the access to Private hides the documentation,
    756             // but setting the status to Internal makes the node available
    757             // in the XML output when the WebXMLGenerator is used.
     958
     959#if 0
     960            // Reimplemented functions now reported in separate sections.
     961            /*
     962              Note: Setting the access to Private hides the documentation,
     963              but setting the status to Internal makes the node available
     964              in the XML output when the WebXMLGenerator is used.
     965            */
    758966            func->setAccess(Node::Private);
    759967            func->setStatus(Node::Internal);
     968#endif
     969            func->setReimp(true);
    760970        }
    761971        else {
     
    768978        InnerNode *pseudoParent;
    769979        if (arg.startsWith("<") || arg.startsWith("\"")) {
    770             pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(arg), Node::Fake));
     980            pseudoParent =
     981                static_cast<InnerNode *>(tre->findNode(QStringList(arg),
     982                                                       Node::Fake));
    771983        }
    772984        else {
    773985            QStringList newPath = arg.split("::");
    774             pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath), Node::Class));
     986            pseudoParent =
     987                static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
     988                                                      Node::Class));
    775989            if (!pseudoParent)
    776                 pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath),
    777                                                         Node::Namespace));
     990                pseudoParent =
     991                    static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
     992                                                          Node::Namespace));
    778993        }
    779994        if (!pseudoParent) {
     
    8001015        setLink(node, Node::StartLink, arg);
    8011016    }
     1017#ifdef QDOC_QML
     1018    else if (command == COMMAND_QMLINHERITS) {
     1019        setLink(node, Node::InheritsLink, arg);
     1020    }
     1021    else if (command == COMMAND_QMLDEFAULT) {
     1022        QmlPropGroupNode* qpgn = static_cast<QmlPropGroupNode*>(node);
     1023        qpgn->setDefault();
     1024    }
     1025#endif
    8021026    else {
    8031027        processCommonMetaCommand(doc.location(),command,arg,node,tre);
     
    8791103        return true;
    8801104    }
    881     else {
     1105    else
    8821106        return false;
    883     }
    8841107}
    8851108
     
    9161139            if (tok == Tok_LeftAngle) {
    9171140                leftAngleDepth++;
    918             } else if (tok == Tok_RightAngle) {
     1141            }
     1142            else if (tok == Tok_RightAngle) {
    9191143                leftAngleDepth--;
    920             } else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) {
     1144            }
     1145            else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) {
    9211146                ++parenAndBraceDepth;
    922             } else if (tok == Tok_RightParen || tok == Tok_RightBrace) {
     1147            }
     1148            else if (tok == Tok_RightParen || tok == Tok_RightBrace) {
    9231149                if (--parenAndBraceDepth < 0)
    9241150                    return false;
     
    9831209            else
    9841210                return false;
    985         } else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) {
     1211        }
     1212        else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) {
    9861213            dataType->append(previousLexeme());
    9871214        }
     
    10831310        }
    10841311    }
    1085     func->addParameter(Parameter(dataType.toString(), "", name,
    1086                                   defaultValue.toString())); // ###
     1312    func->addParameter(Parameter(dataType.toString(),
     1313                                 "",
     1314                                 name,
     1315                                 defaultValue.toString())); // ###
    10871316    return true;
    10881317}
     
    10911320                                      QStringList *parentPathPtr,
    10921321                                      FunctionNode **funcPtr,
    1093                                       const QString &templateStuff)
     1322                                      const QString &templateStuff,
     1323                                      Node::Type type,
     1324                                      bool attached)
    10941325{
    10951326    CodeChunk returnType;
     
    11211352                && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY)))
    11221353            returnType = CodeChunk(previousLexeme());
    1123         else
     1354        else {
    11241355            return false;
     1356        }
    11251357    }
    11261358
     
    11321364
    11331365    if (tok == Tok_operator &&
    1134          (returnType.toString().isEmpty() || returnType.toString().endsWith("::"))) {
     1366         (returnType.toString().isEmpty() ||
     1367          returnType.toString().endsWith("::"))) {
    11351368        // 'QString::operator const char *()'
    11361369        parentPath = returnType.toString().split(sep);
     
    11511384            }
    11521385        }
    1153         if (tok != Tok_LeftParen)
     1386        if (tok != Tok_LeftParen) {
    11541387            return false;
     1388        }
    11551389    }
    11561390    else if (tok == Tok_LeftParen) {
     
    11681402            matchTemplateAngles();
    11691403
    1170             if (match(Tok_Gulbrandsen)) {
     1404            if (match(Tok_Gulbrandsen))
    11711405                parentPath.append(name);
    1172             } else {
     1406            else
    11731407                break;
    1174             }
    11751408        }
    11761409
     
    11851418            }
    11861419        }
    1187         if (parent && (tok == Tok_Semicolon || tok == Tok_LeftBracket || tok == Tok_Colon)
     1420        if (parent && (tok == Tok_Semicolon ||
     1421                       tok == Tok_LeftBracket ||
     1422                       tok == Tok_Colon)
    11881423                && access != Node::Private) {
    11891424            if (tok == Tok_LeftBracket) {
     
    11971432                    readToken();
    11981433                }
    1199                 if (tok != Tok_Semicolon)
     1434                if (tok != Tok_Semicolon) {
    12001435                    return false;
    1201             } else if (tok == Tok_Colon) {
     1436                }
     1437            }
     1438            else if (tok == Tok_Colon) {
    12021439                returnType.appendHotspot();
    12031440
     
    12061443                    readToken();
    12071444                }
    1208                 if (tok != Tok_Semicolon)
     1445                if (tok != Tok_Semicolon) {
    12091446                    return false;
     1447                }
    12101448            }
    12111449
     
    12201458            return false;
    12211459        }
    1222         if (tok != Tok_LeftParen)
     1460        if (tok != Tok_LeftParen) {
    12231461            return false;
     1462        }
    12241463    }
    12251464    readToken();
    12261465
    1227     FunctionNode *func = new FunctionNode(parent, name);
     1466    FunctionNode *func = new FunctionNode(type, parent, name, attached);
    12281467    func->setAccess(access);
    12291468    func->setLocation(location());
    12301469    func->setReturnType(returnType.toString());
     1470    func->setParentPath(parentPath);
    12311471    func->setTemplateStuff(templateStuff);
    12321472    if (compat)
     
    12451485    if (tok != Tok_RightParen) {
    12461486        do {
    1247             if (!matchParameter(func))
     1487            if (!matchParameter(func)) {
    12481488                return false;
     1489            }
    12491490        } while (match(Tok_Comma));
    12501491    }
    1251     if (!match(Tok_RightParen))
     1492    if (!match(Tok_RightParen)) {
    12521493        return false;
     1494    }
    12531495
    12541496    func->setConst(match(Tok_const));
     
    12661508        int braceDepth0 = tokenizer->braceDepth();
    12671509
    1268         if (!match(Tok_LeftBrace))
     1510        if (!match(Tok_LeftBrace)) {
    12691511            return false;
     1512        }
    12701513        while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi)
    12711514            readToken();
     
    13911634    NamespaceNode *namespasse = 0;
    13921635    if (parent)
    1393         namespasse = static_cast<NamespaceNode *>(parent->findNode(namespaceName, Node::Namespace));
     1636        namespasse = static_cast<NamespaceNode*>(parent->findNode(namespaceName, Node::Namespace));
    13941637    if (!namespasse) {
    13951638        namespasse = new NamespaceNode(parent, namespaceName);
     
    14571700            if (enume->items().isEmpty()) {
    14581701                strVal = "0";
    1459             } else {
     1702            }
     1703            else {
    14601704                QString last = enume->items().last().value();
    14611705                bool ok;
     
    14671711                        else
    14681712                            strVal = "0" + QString::number(n + 1, 8);
    1469                     } else {
     1713                    }
     1714                    else
    14701715                        strVal = QString::number(n + 1);
    1471                     }
    14721716                }
    14731717            }
     
    14751719
    14761720        enume->addItem(EnumItem(name, strVal));
    1477     } else {
     1721    }
     1722    else {
    14781723        VariableNode *var = new VariableNode(parent, name);
    14791724        var->setAccess(access);
     
    15631808        if (match(Tok_Ident)) {
    15641809            value = previousLexeme();
    1565         } else if (match(Tok_LeftParen)) {
     1810        }
     1811        else if (match(Tok_LeftParen)) {
    15661812            int depth = 1;
    15671813            while (tok != Tok_Eoi) {
     
    15821828        if (key == "READ")
    15831829            tre->addPropertyFunction(property, value, PropertyNode::Getter);
    1584         else if (key == "WRITE")
     1830        else if (key == "WRITE") {
    15851831            tre->addPropertyFunction(property, value, PropertyNode::Setter);
    1586         else if (key == "STORED")
     1832            property->setWritable(true);
     1833        } else if (key == "STORED")
    15871834            property->setStored(value.toLower() == "true");
    15881835        else if (key == "DESIGNABLE")
     
    15901837        else if (key == "RESET")
    15911838            tre->addPropertyFunction(property, value, PropertyNode::Resetter);
     1839        else if (key == "NOTIFY") {
     1840            tre->addPropertyFunction(property, value, PropertyNode::Notifier);
     1841        }
     1842
    15921843    }
    15931844    match(Tok_RightParen);
     
    17542005
    17552006            Doc::trimCStyleComment(start_loc,comment);
    1756             /*
    1757               qdoc --> doxygen
    1758               We must also remember the location of the end
    1759               of the comment, so we can construct a diff for
    1760               it.
    1761             */
    17622007            Location end_loc(location());
    17632008
     
    18222067                  There is a topic command. Process it.
    18232068                 */
     2069#ifdef QDOC_QML
     2070                if ((topic == COMMAND_QMLPROPERTY) ||
     2071                    (topic == COMMAND_QMLATTACHEDPROPERTY)) {
     2072                    Doc nodeDoc = doc;
     2073                    Node *node = processTopicCommandGroup(nodeDoc,topic,args);
     2074                    if (node != 0) {
     2075                        nodes.append(node);
     2076                        docs.append(nodeDoc);
     2077                    }
     2078                }
     2079                else {
     2080                    QStringList::ConstIterator a = args.begin();
     2081                    while (a != args.end()) {
     2082                        Doc nodeDoc = doc;
     2083                        Node *node = processTopicCommand(nodeDoc,topic,*a);
     2084                        if (node != 0) {
     2085                            nodes.append(node);
     2086                            docs.append(nodeDoc);
     2087                        }
     2088                        ++a;
     2089                    }
     2090                }
     2091#else
    18242092                QStringList::ConstIterator a = args.begin();
    18252093                while (a != args.end()) {
     
    18322100                    ++a;
    18332101                }
     2102#endif               
    18342103            }
    18352104
     
    18392108                processOtherMetaCommands(*d, *n);
    18402109                (*n)->setDoc(*d);
    1841                 if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) {
     2110                if ((*n)->isInnerNode() &&
     2111                    ((InnerNode *)*n)->includes().isEmpty()) {
    18422112                    InnerNode *m = static_cast<InnerNode *>(*n);
    18432113                    while (m->parent() != tre->root())
     
    18872157                                     QStringList *parentPathPtr,
    18882158                                     FunctionNode **funcPtr,
    1889                                      InnerNode *root)
     2159                                     InnerNode *root,
     2160                                     Node::Type type,
     2161                                     bool attached)
    18902162{
    18912163    Tokenizer *outerTokenizer = tokenizer;
     
    18992171    readToken();
    19002172
    1901     bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr);
     2173    bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr, QString(), type, attached);
    19022174    // potential memory leak with funcPtr
    19032175
    19042176    tokenizer = outerTokenizer;
    19052177    tok = outerTok;
    1906 
    19072178    return ok;
     2179}
     2180
     2181/*!
     2182  Create a new FunctionNode for a QML method or signal, as
     2183  specified by \a type, as a child of \a parent. \a sig is
     2184  the complete signature, and if \a attached is true, the
     2185  method or signal is "attached". \a qdoctag is the text of
     2186  the \a type.
     2187 */
     2188FunctionNode* CppCodeParser::makeFunctionNode(const Doc& doc,
     2189                                              const QString& sig,
     2190                                              InnerNode* parent,
     2191                                              Node::Type type,
     2192                                              bool attached,
     2193                                              QString qdoctag)
     2194{
     2195    QStringList pp;
     2196    FunctionNode* fn = 0;
     2197    if (!makeFunctionNode(sig,&pp,&fn,parent,type,attached) &&
     2198        !makeFunctionNode("void "+sig,&pp,&fn,parent,type,attached)) {
     2199        doc.location().warning(tr("Invalid syntax in '\\%1'").arg(qdoctag));
     2200    }
     2201    if (fn)
     2202        return fn;
     2203    return 0;
    19082204}
    19092205
     
    19272223        associativeIteratorDefinition = lines[2];
    19282224        mutableAssociativeIteratorDefinition = lines[3];
    1929     } else {
     2225    }
     2226    else {
    19302227        location.warning(tr("The qiterator.h hack failed"));
    19312228    }
     
    19632260                                        proFileName,
    19642261                                        userFriendlyFilePath);
     2262   
    19652263    if (fullPath.isEmpty()) {
    19662264        QString tmp = proFileName;
     
    19822280    fullPath.truncate(fullPath.lastIndexOf('/'));
    19832281
    1984     QStringList exampleFiles = Config::getFilesHere(fullPath,
    1985                                                     exampleNameFilter);
     2282    QStringList exampleFiles = Config::getFilesHere(fullPath,exampleNameFilter);
     2283    QString imagesPath = fullPath + "/images";
     2284    QStringList imageFiles = Config::getFilesHere(imagesPath,exampleImageFilter);
     2285
     2286#if 0   
     2287    qDebug() << "examplePath:" << examplePath;
     2288    qDebug() << " exampleFiles" <<  exampleFiles;
     2289    qDebug() << "imagesPath:" << imagesPath;
     2290    qDebug() << "fullPath:" << fullPath;
     2291    qDebug() << " imageFiles" <<  imageFiles;
     2292#endif   
     2293
    19862294    if (!exampleFiles.isEmpty()) {
    19872295        // move main.cpp and to the end, if it exists
     
    20092317        (void) new FakeNode(fake,
    20102318                            exampleFile.mid(sizeOfBoringPartOfName),
    2011                             FakeNode::File);
     2319                            Node::File);
     2320    foreach (const QString &imageFile, imageFiles) {
     2321        new FakeNode(fake,
     2322                     imageFile.mid(sizeOfBoringPartOfName),
     2323                     Node::Image);
     2324    }
    20122325}
    20132326
Note: See TracChangeset for help on using the changeset viewer.