tools/qdoc3/cppcodeparser.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    89 #define COMMAND_QMLCLASS                Doc::alias("qmlclass")
    89 #define COMMAND_QMLCLASS                Doc::alias("qmlclass")
    90 #define COMMAND_QMLPROPERTY             Doc::alias("qmlproperty")
    90 #define COMMAND_QMLPROPERTY             Doc::alias("qmlproperty")
    91 #define COMMAND_QMLATTACHEDPROPERTY     Doc::alias("qmlattachedproperty")
    91 #define COMMAND_QMLATTACHEDPROPERTY     Doc::alias("qmlattachedproperty")
    92 #define COMMAND_QMLINHERITS             Doc::alias("inherits")
    92 #define COMMAND_QMLINHERITS             Doc::alias("inherits")
    93 #define COMMAND_QMLSIGNAL               Doc::alias("qmlsignal")
    93 #define COMMAND_QMLSIGNAL               Doc::alias("qmlsignal")
       
    94 #define COMMAND_QMLATTACHEDSIGNAL       Doc::alias("qmlattachedsignal")
    94 #define COMMAND_QMLMETHOD               Doc::alias("qmlmethod")
    95 #define COMMAND_QMLMETHOD               Doc::alias("qmlmethod")
       
    96 #define COMMAND_QMLATTACHEDMETHOD       Doc::alias("qmlattachedmethod")
    95 #define COMMAND_QMLDEFAULT              Doc::alias("default")
    97 #define COMMAND_QMLDEFAULT              Doc::alias("default")
    96 #endif
    98 #endif
    97 
    99 
    98 QStringList CppCodeParser::exampleFiles;
   100 QStringList CppCodeParser::exampleFiles;
    99 QStringList CppCodeParser::exampleDirs;
   101 QStringList CppCodeParser::exampleDirs;
   193 /*!
   195 /*!
   194   The destructor is trivial.
   196   The destructor is trivial.
   195  */
   197  */
   196 CppCodeParser::~CppCodeParser()
   198 CppCodeParser::~CppCodeParser()
   197 {
   199 {
   198 }
   200     // nothing.
   199 
   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  */
   200 void CppCodeParser::initializeParser(const Config &config)
   208 void CppCodeParser::initializeParser(const Config &config)
   201 {
   209 {
   202     CodeParser::initializeParser(config);
   210     CodeParser::initializeParser(config);
   203 
   211 
   204     nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace);
   212     nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace);
   216 
   224 
   217     if (!exampleFilePatterns.isEmpty())
   225     if (!exampleFilePatterns.isEmpty())
   218         exampleNameFilter = exampleFilePatterns.join(" ");
   226         exampleNameFilter = exampleFilePatterns.join(" ");
   219     else
   227     else
   220         exampleNameFilter = "*.cpp *.h *.js *.xq *.svg *.xml *.ui";
   228         exampleNameFilter = "*.cpp *.h *.js *.xq *.svg *.xml *.ui";
   221 }
   229 
   222 
   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  */
   223 void CppCodeParser::terminateParser()
   243 void CppCodeParser::terminateParser()
   224 {
   244 {
   225     nodeTypeMap.clear();
   245     nodeTypeMap.clear();
   226     CodeParser::terminateParser();
   246     CodeParser::terminateParser();
   227 }
   247 }
   228 
   248 
       
   249 /*!
       
   250   Returns "Cpp".
       
   251  */
   229 QString CppCodeParser::language()
   252 QString CppCodeParser::language()
   230 {
   253 {
   231     return "Cpp";
   254     return "Cpp";
   232 }
   255 }
   233 
   256 
       
   257 /*!
       
   258   Returns a list of extensions for header files.
       
   259  */
   234 QString CppCodeParser::headerFileNameFilter()
   260 QString CppCodeParser::headerFileNameFilter()
   235 {
   261 {
   236     return "*.ch *.h *.h++ *.hh *.hpp *.hxx";
   262     return "*.ch *.h *.h++ *.hh *.hpp *.hxx";
   237 }
   263 }
   238 
   264 
       
   265 /*!
       
   266   Returns a list of extensions for source files, i.e. not
       
   267   header files.
       
   268  */
   239 QString CppCodeParser::sourceFileNameFilter()
   269 QString CppCodeParser::sourceFileNameFilter()
   240 {
   270 {
   241     return "*.c++ *.cc *.cpp *.cxx";
   271     return "*.c++ *.cc *.cpp *.cxx";
   242 }
   272 }
   243 
   273 
   295     usedNamespaces.clear();
   325     usedNamespaces.clear();
   296     matchDocsAndStuff();
   326     matchDocsAndStuff();
   297     fclose(in);
   327     fclose(in);
   298 }
   328 }
   299 
   329 
       
   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  */
   300 void CppCodeParser::doneParsingHeaderFiles(Tree *tree)
   336 void CppCodeParser::doneParsingHeaderFiles(Tree *tree)
   301 {
   337 {
   302     tree->resolveInheritance();
   338     tree->resolveInheritance();
   303 
   339 
   304     QMapIterator<QString, QString> i(sequentialIteratorClasses);
   340     QMapIterator<QString, QString> i(sequentialIteratorClasses);
   341     mutableSequentialIteratorClasses.clear();
   377     mutableSequentialIteratorClasses.clear();
   342     associativeIteratorClasses.clear();
   378     associativeIteratorClasses.clear();
   343     mutableAssociativeIteratorClasses.clear();
   379     mutableAssociativeIteratorClasses.clear();
   344 }
   380 }
   345 
   381 
       
   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  */
   346 void CppCodeParser::doneParsingSourceFiles(Tree *tree)
   388 void CppCodeParser::doneParsingSourceFiles(Tree *tree)
   347 {
   389 {
   348     tree->root()->makeUndocumentedChildrenInternal();
   390     tree->root()->makeUndocumentedChildrenInternal();
   349     tree->root()->normalizeOverloads();
   391     tree->root()->normalizeOverloads();
   350     tree->fixInheritance();
   392     tree->fixInheritance();
   351     tree->resolveProperties();
   393     tree->resolveProperties();
   352 }
   394 }
   353 
   395 
       
   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  */
   354 const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis,
   403 const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis,
   355                                                     Tree *tree,
   404                                                     Tree *tree,
   356                                                     Node *relative,
   405                                                     Node *relative,
   357                                                     bool fuzzy)
   406                                                     bool fuzzy)
   358 {
   407 {
   483                            << COMMAND_VARIABLE
   532                            << COMMAND_VARIABLE
   484                            << COMMAND_QMLCLASS
   533                            << COMMAND_QMLCLASS
   485                            << COMMAND_QMLPROPERTY
   534                            << COMMAND_QMLPROPERTY
   486                            << COMMAND_QMLATTACHEDPROPERTY
   535                            << COMMAND_QMLATTACHEDPROPERTY
   487                            << COMMAND_QMLSIGNAL
   536                            << COMMAND_QMLSIGNAL
   488                            << COMMAND_QMLMETHOD;
   537                            << COMMAND_QMLATTACHEDSIGNAL
       
   538                            << COMMAND_QMLMETHOD
       
   539                            << COMMAND_QMLATTACHEDMETHOD;
   489 #else
   540 #else
   490                            << COMMAND_VARIABLE;
   541                            << COMMAND_VARIABLE;
   491 #endif
   542 #endif
   492 }
   543 }
   493 
   544 
   676                 classNode = static_cast<const ClassNode*>(n);
   727                 classNode = static_cast<const ClassNode*>(n);
   677         }
   728         }
   678         return new QmlClassNode(tre->root(), names[0], classNode);
   729         return new QmlClassNode(tre->root(), names[0], classNode);
   679     }
   730     }
   680     else if ((command == COMMAND_QMLSIGNAL) ||
   731     else if ((command == COMMAND_QMLSIGNAL) ||
   681              (command == COMMAND_QMLMETHOD)) {
   732              (command == COMMAND_QMLMETHOD) ||
       
   733              (command == COMMAND_QMLATTACHEDSIGNAL) ||
       
   734              (command == COMMAND_QMLATTACHEDMETHOD)) {
   682         QString element;
   735         QString element;
   683         QString name;
   736         QString type;
   684         QmlClassNode* qmlClass = 0;
   737         QmlClassNode* qmlClass = 0;
   685         if (splitQmlArg(doc,arg,element,name)) {
   738         if (splitQmlMethodArg(doc,arg,type,element)) {
   686             Node* n = tre->findNode(QStringList(element),Node::Fake);
   739             Node* n = tre->findNode(QStringList(element),Node::Fake);
   687             if (n && n->subType() == Node::QmlClass) {
   740             if (n && n->subType() == Node::QmlClass) {
   688                 qmlClass = static_cast<QmlClassNode*>(n);
   741                 qmlClass = static_cast<QmlClassNode*>(n);
   689                 if (command == COMMAND_QMLSIGNAL)
   742                 if (command == COMMAND_QMLSIGNAL)
   690                     return new QmlSignalNode(qmlClass,name);
   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);
   691                 else
   750                 else
   692                     return new QmlMethodNode(qmlClass,name);
   751                     return 0; // never get here.
   693             }
   752             }
   694         }
   753         }
   695     }
   754     }
   696 #endif
   755 #endif
   697     return 0;
   756     return 0;
   703   A QML property argument has the form...
   762   A QML property argument has the form...
   704 
   763 
   705   <type> <element>::<name>
   764   <type> <element>::<name>
   706 
   765 
   707   This function splits the argument into those three
   766   This function splits the argument into those three
   708   parts, sets \a type, \a element, and \a property,
   767   parts, sets \a type, \a element, and \a name,
   709   and returns true. If any of the parts isn't found,
   768   and returns true. If any of the parts isn't found,
   710   a debug message is output and false is returned.
   769   a qdoc warning is output and false is returned.
   711  */
   770  */
   712 bool CppCodeParser::splitQmlPropertyArg(const Doc& doc,
   771 bool CppCodeParser::splitQmlPropertyArg(const Doc& doc,
   713                                         const QString& arg,
   772                                         const QString& arg,
   714                                         QString& type,
   773                                         QString& type,
   715                                         QString& element,
   774                                         QString& element,
   716                                         QString& property)
   775                                         QString& name)
   717 {
   776 {
   718     QStringList blankSplit = arg.split(" ");
   777     QStringList blankSplit = arg.split(" ");
   719     if (blankSplit.size() > 1) {
   778     if (blankSplit.size() > 1) {
   720         type = blankSplit[0];
   779         type = blankSplit[0];
   721         QStringList colonSplit(blankSplit[1].split("::"));
   780         QStringList colonSplit(blankSplit[1].split("::"));
   722         if (colonSplit.size() > 1) {
   781         if (colonSplit.size() > 1) {
   723             element = colonSplit[0];
   782             element = colonSplit[0];
   724             property = colonSplit[1];
   783             name = colonSplit[1];
   725             return true;
   784             return true;
   726         }
   785         }
   727         else
   786         else
   728             doc.location().warning(tr("Missing QML element name or property name"));
   787             doc.location().warning(tr("Missing parent QML element name"));
   729     }
   788     }
   730     else
   789     else
   731         doc.location().warning(tr("Missing QML property type or property path"));
   790         doc.location().warning(tr("Missing property type"));
   732     return false;
   791     return false;
   733 }
   792 }
   734 
   793 
   735 /*!
   794 /*!
   736   A QML signal or method argument has the form...
   795   A QML signal or method argument has the form...
   737 
   796 
   738   <element>::<name>
   797   <type> <element>::<name>(<param>, <param>, ...)
   739 
   798 
   740   This function splits the argument into those two
   799   This function splits the argument into those two
   741   parts, sets \a element, and \a name, and returns
   800   parts, sets \a element, and \a name, and returns
   742   true. If either of the parts isn't found, a debug
   801   true. If either of the parts isn't found, a debug
   743   message is output and false is returned.
   802   message is output and false is returned.
   744  */
   803  */
   745 bool CppCodeParser::splitQmlArg(const Doc& doc,
   804 bool CppCodeParser::splitQmlMethodArg(const Doc& doc,
   746                                 const QString& arg,
   805                                       const QString& arg,
   747                                 QString& element,
   806                                       QString& type,
   748                                 QString& name)
   807                                       QString& element)
   749 {
   808 {
   750     QStringList colonSplit(arg.split("::"));
   809     QStringList colonSplit(arg.split("::"));
   751     if (colonSplit.size() > 1) {
   810     if (colonSplit.size() > 1) {
   752         element = colonSplit[0];
   811         QStringList blankSplit = colonSplit[0].split(" ");
   753         name = colonSplit[1];
   812         if (blankSplit.size() > 1) {
       
   813             type = blankSplit[0];
       
   814             element = blankSplit[1];
       
   815         }
       
   816         else {
       
   817             type = QString("");
       
   818             element = colonSplit[0];
       
   819         }
   754         return true;
   820         return true;
   755     }
   821     }
   756     else
   822     else
   757         doc.location().warning(tr("Missing QML element name or signal/method name"));
   823         doc.location().warning(tr("Missing parent QML element or method signature"));
   758     return false;
   824     return false;
   759 }
   825 }
   760 
   826 
   761 /*!
   827 /*!
   762   Process the topic \a command group with arguments \a args.
   828   Process the topic \a command group with arguments \a args.
   785                                                         property,
   851                                                         property,
   786                                                         attached);
   852                                                         attached);
   787             }
   853             }
   788         }
   854         }
   789         if (qmlPropGroup) {
   855         if (qmlPropGroup) {
   790             new QmlPropertyNode(qmlPropGroup,property,type,attached);
   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             }
   791             ++arg;
   865             ++arg;
   792             while (arg != args.end()) {
   866             while (arg != args.end()) {
   793                 if (splitQmlPropertyArg(doc,(*arg),type,element,property)) {
   867                 if (splitQmlPropertyArg(doc,(*arg),type,element,property)) {
   794                     new QmlPropertyNode(qmlPropGroup,
   868                     QmlPropertyNode* qmlPropNode = new QmlPropertyNode(qmlPropGroup,
   795                                         property,
   869                                                                        property,
   796                                         type,
   870                                                                        type,
   797                                         attached);
   871                                                                        attached);
       
   872                     if (correspondingProperty) {
       
   873                         bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
       
   874                         qmlPropNode->setWritable(writableList || correspondingProperty->isWritable());
       
   875                     }
   798                 }
   876                 }
   799                 ++arg;
   877                 ++arg;
   800             }
   878             }
   801         }
   879         }
   802     }
   880     }
  1239 }
  1317 }
  1240 
  1318 
  1241 bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
  1319 bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
  1242                                       QStringList *parentPathPtr,
  1320                                       QStringList *parentPathPtr,
  1243                                       FunctionNode **funcPtr,
  1321                                       FunctionNode **funcPtr,
  1244                                       const QString &templateStuff)
  1322                                       const QString &templateStuff,
       
  1323                                       Node::Type type,
       
  1324                                       bool attached)
  1245 {
  1325 {
  1246     CodeChunk returnType;
  1326     CodeChunk returnType;
  1247     QStringList parentPath;
  1327     QStringList parentPath;
  1248     QString name;
  1328     QString name;
  1249 
  1329 
  1269 
  1349 
  1270     if (!matchDataType(&returnType)) {
  1350     if (!matchDataType(&returnType)) {
  1271         if (tokenizer->parsingFnOrMacro()
  1351         if (tokenizer->parsingFnOrMacro()
  1272                 && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY)))
  1352                 && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY)))
  1273             returnType = CodeChunk(previousLexeme());
  1353             returnType = CodeChunk(previousLexeme());
  1274         else
  1354         else {
  1275             return false;
  1355             return false;
       
  1356         }
  1276     }
  1357     }
  1277 
  1358 
  1278     if (returnType.toString() == "QBool")
  1359     if (returnType.toString() == "QBool")
  1279         returnType = CodeChunk("bool");
  1360         returnType = CodeChunk("bool");
  1280 
  1361 
  1300             while (tok != Tok_LeftParen && tok != Tok_Eoi) {
  1381             while (tok != Tok_LeftParen && tok != Tok_Eoi) {
  1301                 name += lexeme();
  1382                 name += lexeme();
  1302                 readToken();
  1383                 readToken();
  1303             }
  1384             }
  1304         }
  1385         }
  1305         if (tok != Tok_LeftParen)
  1386         if (tok != Tok_LeftParen) {
  1306             return false;
  1387             return false;
       
  1388         }
  1307     }
  1389     }
  1308     else if (tok == Tok_LeftParen) {
  1390     else if (tok == Tok_LeftParen) {
  1309         // constructor or destructor
  1391         // constructor or destructor
  1310         parentPath = returnType.toString().split(sep);
  1392         parentPath = returnType.toString().split(sep);
  1311         if (!parentPath.isEmpty()) {
  1393         if (!parentPath.isEmpty()) {
  1347                          tok != Tok_Eoi) ||
  1429                          tok != Tok_Eoi) ||
  1348                         tok == Tok_RightBracket) {
  1430                         tok == Tok_RightBracket) {
  1349                     returnType.append(lexeme());
  1431                     returnType.append(lexeme());
  1350                     readToken();
  1432                     readToken();
  1351                 }
  1433                 }
  1352                 if (tok != Tok_Semicolon)
  1434                 if (tok != Tok_Semicolon) {
  1353                     return false;
  1435                     return false;
       
  1436                 }
  1354             }
  1437             }
  1355             else if (tok == Tok_Colon) {
  1438             else if (tok == Tok_Colon) {
  1356                 returnType.appendHotspot();
  1439                 returnType.appendHotspot();
  1357 
  1440 
  1358                 while (tok != Tok_Semicolon && tok != Tok_Eoi) {
  1441                 while (tok != Tok_Semicolon && tok != Tok_Eoi) {
  1359                     returnType.append(lexeme());
  1442                     returnType.append(lexeme());
  1360                     readToken();
  1443                     readToken();
  1361                 }
  1444                 }
  1362                 if (tok != Tok_Semicolon)
  1445                 if (tok != Tok_Semicolon) {
  1363                     return false;
  1446                     return false;
       
  1447                 }
  1364             }
  1448             }
  1365 
  1449 
  1366             VariableNode *var = new VariableNode(parent, name);
  1450             VariableNode *var = new VariableNode(parent, name);
  1367             var->setAccess(access);
  1451             var->setAccess(access);
  1368             var->setLocation(location());
  1452             var->setLocation(location());
  1371             if (compat)
  1455             if (compat)
  1372                 var->setStatus(Node::Compat);
  1456                 var->setStatus(Node::Compat);
  1373             var->setStatic(sta);
  1457             var->setStatic(sta);
  1374             return false;
  1458             return false;
  1375         }
  1459         }
  1376         if (tok != Tok_LeftParen)
  1460         if (tok != Tok_LeftParen) {
  1377             return false;
  1461             return false;
       
  1462         }
  1378     }
  1463     }
  1379     readToken();
  1464     readToken();
  1380 
  1465 
  1381     FunctionNode *func = new FunctionNode(parent, name);
  1466     FunctionNode *func = new FunctionNode(type, parent, name, attached);
  1382     func->setAccess(access);
  1467     func->setAccess(access);
  1383     func->setLocation(location());
  1468     func->setLocation(location());
  1384     func->setReturnType(returnType.toString());
  1469     func->setReturnType(returnType.toString());
  1385     func->setParentPath(parentPath);
  1470     func->setParentPath(parentPath);
  1386     func->setTemplateStuff(templateStuff);
  1471     func->setTemplateStuff(templateStuff);
  1397     }
  1482     }
  1398     func->setStatic(sta);
  1483     func->setStatic(sta);
  1399 
  1484 
  1400     if (tok != Tok_RightParen) {
  1485     if (tok != Tok_RightParen) {
  1401         do {
  1486         do {
  1402             if (!matchParameter(func))
  1487             if (!matchParameter(func)) {
  1403                 return false;
  1488                 return false;
       
  1489             }
  1404         } while (match(Tok_Comma));
  1490         } while (match(Tok_Comma));
  1405     }
  1491     }
  1406     if (!match(Tok_RightParen))
  1492     if (!match(Tok_RightParen)) {
  1407         return false;
  1493         return false;
       
  1494     }
  1408 
  1495 
  1409     func->setConst(match(Tok_const));
  1496     func->setConst(match(Tok_const));
  1410 
  1497 
  1411     if (match(Tok_Equal) && match(Tok_Number))
  1498     if (match(Tok_Equal) && match(Tok_Number))
  1412         vir = FunctionNode::PureVirtual;
  1499         vir = FunctionNode::PureVirtual;
  1418     }
  1505     }
  1419 
  1506 
  1420     if (!match(Tok_Semicolon) && tok != Tok_Eoi) {
  1507     if (!match(Tok_Semicolon) && tok != Tok_Eoi) {
  1421         int braceDepth0 = tokenizer->braceDepth();
  1508         int braceDepth0 = tokenizer->braceDepth();
  1422 
  1509 
  1423         if (!match(Tok_LeftBrace))
  1510         if (!match(Tok_LeftBrace)) {
  1424             return false;
  1511             return false;
       
  1512         }
  1425         while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi)
  1513         while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi)
  1426             readToken();
  1514             readToken();
  1427         match(Tok_RightBrace);
  1515         match(Tok_RightBrace);
  1428     }
  1516     }
  1429     if (parentPathPtr != 0)
  1517     if (parentPathPtr != 0)
  1737             value = "?";
  1825             value = "?";
  1738         }
  1826         }
  1739 
  1827 
  1740         if (key == "READ")
  1828         if (key == "READ")
  1741             tre->addPropertyFunction(property, value, PropertyNode::Getter);
  1829             tre->addPropertyFunction(property, value, PropertyNode::Getter);
  1742         else if (key == "WRITE")
  1830         else if (key == "WRITE") {
  1743             tre->addPropertyFunction(property, value, PropertyNode::Setter);
  1831             tre->addPropertyFunction(property, value, PropertyNode::Setter);
  1744         else if (key == "STORED")
  1832             property->setWritable(true);
       
  1833         } else if (key == "STORED")
  1745             property->setStored(value.toLower() == "true");
  1834             property->setStored(value.toLower() == "true");
  1746         else if (key == "DESIGNABLE")
  1835         else if (key == "DESIGNABLE")
  1747             property->setDesignable(value.toLower() == "true");
  1836             property->setDesignable(value.toLower() == "true");
  1748         else if (key == "RESET")
  1837         else if (key == "RESET")
  1749             tre->addPropertyFunction(property, value, PropertyNode::Resetter);
  1838             tre->addPropertyFunction(property, value, PropertyNode::Resetter);
  1750 
       
  1751         else if (key == "NOTIFY") {
  1839         else if (key == "NOTIFY") {
  1752             tre->addPropertyFunction(property, value, PropertyNode::Notifier);
  1840             tre->addPropertyFunction(property, value, PropertyNode::Notifier);
  1753         }
  1841         }
  1754 
  1842 
  1755     }
  1843     }
  2066 }
  2154 }
  2067 
  2155 
  2068 bool CppCodeParser::makeFunctionNode(const QString& synopsis,
  2156 bool CppCodeParser::makeFunctionNode(const QString& synopsis,
  2069                                      QStringList *parentPathPtr,
  2157                                      QStringList *parentPathPtr,
  2070                                      FunctionNode **funcPtr,
  2158                                      FunctionNode **funcPtr,
  2071                                      InnerNode *root)
  2159                                      InnerNode *root,
       
  2160                                      Node::Type type,
       
  2161                                      bool attached)
  2072 {
  2162 {
  2073     Tokenizer *outerTokenizer = tokenizer;
  2163     Tokenizer *outerTokenizer = tokenizer;
  2074     int outerTok = tok;
  2164     int outerTok = tok;
  2075 
  2165 
  2076     Location loc;
  2166     Location loc;
  2078     Tokenizer stringTokenizer(loc, latin1);
  2168     Tokenizer stringTokenizer(loc, latin1);
  2079     stringTokenizer.setParsingFnOrMacro(true);
  2169     stringTokenizer.setParsingFnOrMacro(true);
  2080     tokenizer = &stringTokenizer;
  2170     tokenizer = &stringTokenizer;
  2081     readToken();
  2171     readToken();
  2082 
  2172 
  2083     bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr);
  2173     bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr, QString(), type, attached);
  2084     // potential memory leak with funcPtr
  2174     // potential memory leak with funcPtr
  2085 
  2175 
  2086     tokenizer = outerTokenizer;
  2176     tokenizer = outerTokenizer;
  2087     tok = outerTok;
  2177     tok = outerTok;
  2088 
       
  2089     return ok;
  2178     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  */
       
  2188 FunctionNode* 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;
  2090 }
  2204 }
  2091 
  2205 
  2092 void CppCodeParser::parseQiteratorDotH(const Location &location,
  2206 void CppCodeParser::parseQiteratorDotH(const Location &location,
  2093                                        const QString &filePath)
  2207                                        const QString &filePath)
  2094 {
  2208 {
  2143     QString fullPath = Config::findFile(fake->doc().location(),
  2257     QString fullPath = Config::findFile(fake->doc().location(),
  2144                                         exampleFiles,
  2258                                         exampleFiles,
  2145                                         exampleDirs,
  2259                                         exampleDirs,
  2146                                         proFileName,
  2260                                         proFileName,
  2147                                         userFriendlyFilePath);
  2261                                         userFriendlyFilePath);
       
  2262     
  2148     if (fullPath.isEmpty()) {
  2263     if (fullPath.isEmpty()) {
  2149         QString tmp = proFileName;
  2264         QString tmp = proFileName;
  2150         proFileName = examplePath + "/" + "qbuild.pro";
  2265         proFileName = examplePath + "/" + "qbuild.pro";
  2151         userFriendlyFilePath.clear();
  2266         userFriendlyFilePath.clear();
  2152         fullPath = Config::findFile(fake->doc().location(),
  2267         fullPath = Config::findFile(fake->doc().location(),
  2162     }
  2277     }
  2163 
  2278 
  2164     int sizeOfBoringPartOfName = fullPath.size() - proFileName.size();
  2279     int sizeOfBoringPartOfName = fullPath.size() - proFileName.size();
  2165     fullPath.truncate(fullPath.lastIndexOf('/'));
  2280     fullPath.truncate(fullPath.lastIndexOf('/'));
  2166 
  2281 
  2167     QStringList exampleFiles = Config::getFilesHere(fullPath,
  2282     QStringList exampleFiles = Config::getFilesHere(fullPath,exampleNameFilter);
  2168                                                     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 
  2169     if (!exampleFiles.isEmpty()) {
  2294     if (!exampleFiles.isEmpty()) {
  2170         // move main.cpp and to the end, if it exists
  2295         // move main.cpp and to the end, if it exists
  2171         QString mainCpp;
  2296         QString mainCpp;
  2172         QMutableStringListIterator i(exampleFiles);
  2297         QMutableStringListIterator i(exampleFiles);
  2173         i.toBack();
  2298         i.toBack();
  2190 
  2315 
  2191     foreach (const QString &exampleFile, exampleFiles)
  2316     foreach (const QString &exampleFile, exampleFiles)
  2192         (void) new FakeNode(fake,
  2317         (void) new FakeNode(fake,
  2193                             exampleFile.mid(sizeOfBoringPartOfName),
  2318                             exampleFile.mid(sizeOfBoringPartOfName),
  2194                             Node::File);
  2319                             Node::File);
       
  2320     foreach (const QString &imageFile, imageFiles) {
       
  2321         new FakeNode(fake,
       
  2322                      imageFile.mid(sizeOfBoringPartOfName),
       
  2323                      Node::Image);
       
  2324     }
  2195 }
  2325 }
  2196 
  2326 
  2197 QT_END_NAMESPACE
  2327 QT_END_NAMESPACE