Changeset 561 for trunk/tools/qdoc3/cppcodeparser.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/tools/qdoc3/cppcodeparser.cpp
r2 r561 2 2 ** 3 3 ** 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) 5 6 ** 6 7 ** This file is part of the tools applications of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 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. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** 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. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 48 48 49 49 #include <stdio.h> 50 #include <errno.h> 50 51 51 52 #include "codechunk.h" … … 88 89 #define COMMAND_QMLCLASS Doc::alias("qmlclass") 89 90 #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") 90 98 #endif 91 99 … … 110 118 *link = arg.left(spaceAt).trimmed(); 111 119 *desc = arg.mid(spaceAt).trimmed(); 112 } else { 120 } 121 else { 113 122 *link = arg; 114 123 *desc = arg; … … 189 198 CppCodeParser::~CppCodeParser() 190 199 { 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 */ 193 208 void CppCodeParser::initializeParser(const Config &config) 194 209 { … … 203 218 nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable); 204 219 205 #ifdef QDOC_QML206 // nodeTypeMap.insert(COMMAND_QMLCLASS, Node::Class);207 nodeTypeMap.insert(COMMAND_QMLPROPERTY, Node::Property);208 #endif209 210 220 exampleFiles = config.getStringList(CONFIG_EXAMPLES); 211 221 exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS); … … 217 227 else 218 228 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 */ 221 243 void CppCodeParser::terminateParser() 222 244 { … … 225 247 } 226 248 249 /*! 250 Returns "Cpp". 251 */ 227 252 QString CppCodeParser::language() 228 253 { … … 230 255 } 231 256 257 /*! 258 Returns a list of extensions for header files. 259 */ 232 260 QString CppCodeParser::headerFileNameFilter() 233 261 { … … 235 263 } 236 264 265 /*! 266 Returns a list of extensions for source files, i.e. not 267 header files. 268 */ 237 269 QString CppCodeParser::sourceFileNameFilter() 238 270 { … … 282 314 FILE *in = fopen(QFile::encodeName(filePath), "r"); 283 315 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))); 285 317 return; 286 318 } … … 296 328 } 297 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 */ 298 336 void CppCodeParser::doneParsingHeaderFiles(Tree *tree) 299 337 { … … 342 380 } 343 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 */ 344 388 void CppCodeParser::doneParsingSourceFiles(Tree *tree) 345 389 { … … 350 394 } 351 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 */ 352 403 const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis, 353 404 Tree *tree, … … 478 529 << COMMAND_SERVICE 479 530 << COMMAND_TYPEDEF 480 #ifdef QDOC_QML 531 #ifdef QDOC_QML 481 532 << COMMAND_VARIABLE 482 533 << 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 485 541 << COMMAND_VARIABLE; 486 #endif 542 #endif 487 543 } 488 544 … … 539 595 lastPath = parentPath; 540 596 } 541 542 if (func) 597 if (func) { 543 598 func->borrowParameterNames(clone); 599 func->setParentPath(clone->parentPath()); 600 } 544 601 delete clone; 545 602 } … … 588 645 */ 589 646 // ### split(" ") hack is there to support header file syntax 590 QStringList paths = arg.split(" "); 647 QStringList paths = arg.split(" "); 591 648 QStringList path = paths[0].split("::"); 592 593 #if QDOC2DOX594 // 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 // zzz604 }605 }606 #endif607 608 649 Node *node = 0; 609 650 if (!usedNamespaces.isEmpty()) { … … 644 685 } 645 686 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 } 646 695 return node; 647 696 } 648 697 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); 650 699 createExampleFileNodes(fake); 651 700 return fake; 652 701 } 653 702 else if (command == COMMAND_EXTERNALPAGE) { 654 return new FakeNode(tre->root(), arg, FakeNode::ExternalPage);703 return new FakeNode(tre->root(), arg, Node::ExternalPage); 655 704 } 656 705 else if (command == COMMAND_FILE) { 657 return new FakeNode(tre->root(), arg, FakeNode::File);706 return new FakeNode(tre->root(), arg, Node::File); 658 707 } 659 708 else if (command == COMMAND_GROUP) { 660 return new FakeNode(tre->root(), arg, FakeNode::Group);709 return new FakeNode(tre->root(), arg, Node::Group); 661 710 } 662 711 else if (command == COMMAND_HEADERFILE) { 663 return new FakeNode(tre->root(), arg, FakeNode::HeaderFile);712 return new FakeNode(tre->root(), arg, Node::HeaderFile); 664 713 } 665 714 else if (command == COMMAND_MODULE) { 666 return new FakeNode(tre->root(), arg, FakeNode::Module);715 return new FakeNode(tre->root(), arg, Node::Module); 667 716 } 668 717 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 672 721 else if (command == COMMAND_QMLCLASS) { 673 722 const ClassNode* classNode = 0; 674 QStringList names = arg.split(" "); 675 //qDebug() << "QMLCLASS" << names; 723 QStringList names = arg.split(" "); 676 724 if (names.size() > 1) { 677 725 Node* n = tre->findNode(names[1].split("::"),Node::Class); 678 if (n) {726 if (n) 679 727 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 686 756 return 0; 687 757 } 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 */ 771 bool 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 */ 804 bool 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 */ 833 Node *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 688 884 689 885 /*! … … 701 897 << COMMAND_PREVIOUSPAGE 702 898 << COMMAND_INDEXPAGE 899 #ifdef QDOC_QML 900 << COMMAND_STARTPAGE 901 << COMMAND_QMLINHERITS 902 << COMMAND_QMLDEFAULT; 903 #else 703 904 << COMMAND_STARTPAGE; 905 #endif 704 906 } 705 907 … … 743 945 "with the same signature or it exists but isn't virtual.")); 744 946 } 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 */ 748 953 else if (from->access() == Node::Private 749 954 || 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") 752 956 .arg(COMMAND_REIMP).arg(node->name())); 753 957 } 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 */ 758 966 func->setAccess(Node::Private); 759 967 func->setStatus(Node::Internal); 968 #endif 969 func->setReimp(true); 760 970 } 761 971 else { … … 768 978 InnerNode *pseudoParent; 769 979 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)); 771 983 } 772 984 else { 773 985 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)); 775 989 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)); 778 993 } 779 994 if (!pseudoParent) { … … 800 1015 setLink(node, Node::StartLink, arg); 801 1016 } 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 802 1026 else { 803 1027 processCommonMetaCommand(doc.location(),command,arg,node,tre); … … 879 1103 return true; 880 1104 } 881 else {1105 else 882 1106 return false; 883 }884 1107 } 885 1108 … … 916 1139 if (tok == Tok_LeftAngle) { 917 1140 leftAngleDepth++; 918 } else if (tok == Tok_RightAngle) { 1141 } 1142 else if (tok == Tok_RightAngle) { 919 1143 leftAngleDepth--; 920 } else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) { 1144 } 1145 else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) { 921 1146 ++parenAndBraceDepth; 922 } else if (tok == Tok_RightParen || tok == Tok_RightBrace) { 1147 } 1148 else if (tok == Tok_RightParen || tok == Tok_RightBrace) { 923 1149 if (--parenAndBraceDepth < 0) 924 1150 return false; … … 983 1209 else 984 1210 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)) { 986 1213 dataType->append(previousLexeme()); 987 1214 } … … 1083 1310 } 1084 1311 } 1085 func->addParameter(Parameter(dataType.toString(), "", name, 1086 defaultValue.toString())); // ### 1312 func->addParameter(Parameter(dataType.toString(), 1313 "", 1314 name, 1315 defaultValue.toString())); // ### 1087 1316 return true; 1088 1317 } … … 1091 1320 QStringList *parentPathPtr, 1092 1321 FunctionNode **funcPtr, 1093 const QString &templateStuff) 1322 const QString &templateStuff, 1323 Node::Type type, 1324 bool attached) 1094 1325 { 1095 1326 CodeChunk returnType; … … 1121 1352 && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY))) 1122 1353 returnType = CodeChunk(previousLexeme()); 1123 else 1354 else { 1124 1355 return false; 1356 } 1125 1357 } 1126 1358 … … 1132 1364 1133 1365 if (tok == Tok_operator && 1134 (returnType.toString().isEmpty() || returnType.toString().endsWith("::"))) { 1366 (returnType.toString().isEmpty() || 1367 returnType.toString().endsWith("::"))) { 1135 1368 // 'QString::operator const char *()' 1136 1369 parentPath = returnType.toString().split(sep); … … 1151 1384 } 1152 1385 } 1153 if (tok != Tok_LeftParen) 1386 if (tok != Tok_LeftParen) { 1154 1387 return false; 1388 } 1155 1389 } 1156 1390 else if (tok == Tok_LeftParen) { … … 1168 1402 matchTemplateAngles(); 1169 1403 1170 if (match(Tok_Gulbrandsen)) {1404 if (match(Tok_Gulbrandsen)) 1171 1405 parentPath.append(name); 1172 } else {1406 else 1173 1407 break; 1174 }1175 1408 } 1176 1409 … … 1185 1418 } 1186 1419 } 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) 1188 1423 && access != Node::Private) { 1189 1424 if (tok == Tok_LeftBracket) { … … 1197 1432 readToken(); 1198 1433 } 1199 if (tok != Tok_Semicolon) 1434 if (tok != Tok_Semicolon) { 1200 1435 return false; 1201 } else if (tok == Tok_Colon) { 1436 } 1437 } 1438 else if (tok == Tok_Colon) { 1202 1439 returnType.appendHotspot(); 1203 1440 … … 1206 1443 readToken(); 1207 1444 } 1208 if (tok != Tok_Semicolon) 1445 if (tok != Tok_Semicolon) { 1209 1446 return false; 1447 } 1210 1448 } 1211 1449 … … 1220 1458 return false; 1221 1459 } 1222 if (tok != Tok_LeftParen) 1460 if (tok != Tok_LeftParen) { 1223 1461 return false; 1462 } 1224 1463 } 1225 1464 readToken(); 1226 1465 1227 FunctionNode *func = new FunctionNode( parent, name);1466 FunctionNode *func = new FunctionNode(type, parent, name, attached); 1228 1467 func->setAccess(access); 1229 1468 func->setLocation(location()); 1230 1469 func->setReturnType(returnType.toString()); 1470 func->setParentPath(parentPath); 1231 1471 func->setTemplateStuff(templateStuff); 1232 1472 if (compat) … … 1245 1485 if (tok != Tok_RightParen) { 1246 1486 do { 1247 if (!matchParameter(func)) 1487 if (!matchParameter(func)) { 1248 1488 return false; 1489 } 1249 1490 } while (match(Tok_Comma)); 1250 1491 } 1251 if (!match(Tok_RightParen)) 1492 if (!match(Tok_RightParen)) { 1252 1493 return false; 1494 } 1253 1495 1254 1496 func->setConst(match(Tok_const)); … … 1266 1508 int braceDepth0 = tokenizer->braceDepth(); 1267 1509 1268 if (!match(Tok_LeftBrace)) 1510 if (!match(Tok_LeftBrace)) { 1269 1511 return false; 1512 } 1270 1513 while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi) 1271 1514 readToken(); … … 1391 1634 NamespaceNode *namespasse = 0; 1392 1635 if (parent) 1393 namespasse = static_cast<NamespaceNode 1636 namespasse = static_cast<NamespaceNode*>(parent->findNode(namespaceName, Node::Namespace)); 1394 1637 if (!namespasse) { 1395 1638 namespasse = new NamespaceNode(parent, namespaceName); … … 1457 1700 if (enume->items().isEmpty()) { 1458 1701 strVal = "0"; 1459 } else { 1702 } 1703 else { 1460 1704 QString last = enume->items().last().value(); 1461 1705 bool ok; … … 1467 1711 else 1468 1712 strVal = "0" + QString::number(n + 1, 8); 1469 } else { 1713 } 1714 else 1470 1715 strVal = QString::number(n + 1); 1471 }1472 1716 } 1473 1717 } … … 1475 1719 1476 1720 enume->addItem(EnumItem(name, strVal)); 1477 } else { 1721 } 1722 else { 1478 1723 VariableNode *var = new VariableNode(parent, name); 1479 1724 var->setAccess(access); … … 1563 1808 if (match(Tok_Ident)) { 1564 1809 value = previousLexeme(); 1565 } else if (match(Tok_LeftParen)) { 1810 } 1811 else if (match(Tok_LeftParen)) { 1566 1812 int depth = 1; 1567 1813 while (tok != Tok_Eoi) { … … 1582 1828 if (key == "READ") 1583 1829 tre->addPropertyFunction(property, value, PropertyNode::Getter); 1584 else if (key == "WRITE") 1830 else if (key == "WRITE") { 1585 1831 tre->addPropertyFunction(property, value, PropertyNode::Setter); 1586 else if (key == "STORED") 1832 property->setWritable(true); 1833 } else if (key == "STORED") 1587 1834 property->setStored(value.toLower() == "true"); 1588 1835 else if (key == "DESIGNABLE") … … 1590 1837 else if (key == "RESET") 1591 1838 tre->addPropertyFunction(property, value, PropertyNode::Resetter); 1839 else if (key == "NOTIFY") { 1840 tre->addPropertyFunction(property, value, PropertyNode::Notifier); 1841 } 1842 1592 1843 } 1593 1844 match(Tok_RightParen); … … 1754 2005 1755 2006 Doc::trimCStyleComment(start_loc,comment); 1756 /*1757 qdoc --> doxygen1758 We must also remember the location of the end1759 of the comment, so we can construct a diff for1760 it.1761 */1762 2007 Location end_loc(location()); 1763 2008 … … 1822 2067 There is a topic command. Process it. 1823 2068 */ 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 1824 2092 QStringList::ConstIterator a = args.begin(); 1825 2093 while (a != args.end()) { … … 1832 2100 ++a; 1833 2101 } 2102 #endif 1834 2103 } 1835 2104 … … 1839 2108 processOtherMetaCommands(*d, *n); 1840 2109 (*n)->setDoc(*d); 1841 if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { 2110 if ((*n)->isInnerNode() && 2111 ((InnerNode *)*n)->includes().isEmpty()) { 1842 2112 InnerNode *m = static_cast<InnerNode *>(*n); 1843 2113 while (m->parent() != tre->root()) … … 1887 2157 QStringList *parentPathPtr, 1888 2158 FunctionNode **funcPtr, 1889 InnerNode *root) 2159 InnerNode *root, 2160 Node::Type type, 2161 bool attached) 1890 2162 { 1891 2163 Tokenizer *outerTokenizer = tokenizer; … … 1899 2171 readToken(); 1900 2172 1901 bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr );2173 bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr, QString(), type, attached); 1902 2174 // potential memory leak with funcPtr 1903 2175 1904 2176 tokenizer = outerTokenizer; 1905 2177 tok = outerTok; 1906 1907 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; 1908 2204 } 1909 2205 … … 1927 2223 associativeIteratorDefinition = lines[2]; 1928 2224 mutableAssociativeIteratorDefinition = lines[3]; 1929 } else { 2225 } 2226 else { 1930 2227 location.warning(tr("The qiterator.h hack failed")); 1931 2228 } … … 1963 2260 proFileName, 1964 2261 userFriendlyFilePath); 2262 1965 2263 if (fullPath.isEmpty()) { 1966 2264 QString tmp = proFileName; … … 1982 2280 fullPath.truncate(fullPath.lastIndexOf('/')); 1983 2281 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 1986 2294 if (!exampleFiles.isEmpty()) { 1987 2295 // move main.cpp and to the end, if it exists … … 2009 2317 (void) new FakeNode(fake, 2010 2318 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 } 2012 2325 } 2013 2326
Note:
See TracChangeset
for help on using the changeset viewer.