Changeset 561 for trunk/tools/qdoc3/generator.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/generator.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 ** … … 43 43 generator.cpp 44 44 */ 45 45 #include <QtCore> 46 46 #include <qdir.h> 47 47 #include <qdebug.h> 48 48 #include "codemarker.h" 49 49 #include "config.h" … … 66 66 QStringList Generator::imageFiles; 67 67 QStringList Generator::imageDirs; 68 QStringList Generator::exampleDirs; 69 QStringList Generator::exampleImgExts; 68 70 QString Generator::outDir; 69 71 QString Generator::project; 70 72 71 static Text stockLink(const QString &target) 72 { 73 return Text() << Atom(Atom::Link, target) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) 74 << target << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); 73 static void singularPlural(Text& text, const NodeList& nodes) 74 { 75 if (nodes.count() == 1) 76 text << " is"; 77 else 78 text << " are"; 75 79 } 76 80 77 81 Generator::Generator() 78 : amp("&"), lt("<"), gt(">"), quot("""), tag("</?@[^>]*>") 82 : amp("&"), 83 lt("<"), 84 gt(">"), 85 quot("""), 86 tag("</?@[^>]*>") 79 87 { 80 88 generators.prepend(this); … … 115 123 config.lastLocation().fatal(tr("Cannot create output directory '%1'") 116 124 .arg(outDir + "/images")); 125 if (!dirInfo.mkdir(outDir + "/images/used-in-examples")) 126 config.lastLocation().fatal(tr("Cannot create output directory '%1'") 127 .arg(outDir + "/images/used-in-examples")); 117 128 } 118 129 119 130 imageFiles = config.getStringList(CONFIG_IMAGES); 120 131 imageDirs = config.getStringList(CONFIG_IMAGEDIRS); 121 122 QString imagesDotFileExtensions = CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS; 132 exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS); 133 exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot + 134 CONFIG_IMAGEEXTENSIONS); 135 136 QString imagesDotFileExtensions = 137 CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS; 123 138 QSet<QString> formats = config.subVars(imagesDotFileExtensions); 124 139 QSet<QString>::ConstIterator f = formats.begin(); 125 140 while (f != formats.end()) { 126 imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + Config::dot + *f); 141 imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + 142 Config::dot + *f); 127 143 ++f; 128 144 } … … 132 148 if (outputFormats.contains((*g)->format())) { 133 149 (*g)->initializeGenerator(config); 134 QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES + Config::dot135 +(*g)->format());150 QStringList extraImages = 151 config.getStringList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format()); 136 152 QStringList::ConstIterator e = extraImages.begin(); 137 153 while (e != extraImages.end()) { 138 154 QString userFriendlyFilePath; 139 QString filePath = Config::findFile(config.lastLocation(), imageFiles, imageDirs, *e, 140 imgFileExts[(*g)->format()], userFriendlyFilePath); 155 QString filePath = Config::findFile(config.lastLocation(), 156 imageFiles, 157 imageDirs, 158 *e, 159 imgFileExts[(*g)->format()], 160 userFriendlyFilePath); 141 161 if (!filePath.isEmpty()) 142 Config::copyFile(config.lastLocation(), filePath, userFriendlyFilePath, 143 (*g)->outputDir() + "/images"); 162 Config::copyFile(config.lastLocation(), 163 filePath, 164 userFriendlyFilePath, 165 (*g)->outputDir() + 166 "/images"); 144 167 ++e; 145 168 } … … 157 180 QSet<QString>::ConstIterator f = formats.begin(); 158 181 while (f != formats.end()) { 159 QString def = config.getString(formattingDotName + Config::dot +160 *f);182 QString def = config.getString(formattingDotName + 183 Config::dot + *f); 161 184 if (!def.isEmpty()) { 162 185 int numParams = Config::numParams(def); … … 164 187 165 188 if (numParams != 1) { 166 config.lastLocation().warning(tr("Formatting '%1' must have exactly one" 167 " parameter (found %2)") 168 .arg(*n).arg(numParams)); 189 config.lastLocation().warning(tr("Formatting '%1' must " 190 "have exactly one " 191 "parameter (found %2)") 192 .arg(*n).arg(numParams)); 169 193 } 170 194 else if (numOccs > 1) { 171 config.lastLocation().fatal(tr("Formatting '%1' must contain exactly one" 172 " occurrence of '\\1' (found %2)") 195 config.lastLocation().fatal(tr("Formatting '%1' must " 196 "contain exactly one " 197 "occurrence of '\\1' " 198 "(found %2)") 173 199 .arg(*n).arg(numOccs)); 174 200 } … … 242 268 } 243 269 244 voidGenerator::generateText(const Text& text,270 bool Generator::generateText(const Text& text, 245 271 const Node *relative, 246 272 CodeMarker *marker) … … 255 281 numAtoms); 256 282 endText(relative, marker); 257 } 283 return true; 284 } 285 return false; 258 286 } 259 287 260 288 #ifdef QDOC_QML 261 void Generator::generateQmlText(const Text& text, 289 /*! 290 Extract sections of markup text surrounded by \e qmltext 291 and \e endqmltext and output them. 292 */ 293 bool Generator::generateQmlText(const Text& text, 262 294 const Node *relative, 263 CodeMarker *marker) 264 { 265 if (text.firstAtom() != 0) { 266 startText(relative, marker); 267 const Atom *atom = text.firstAtom(); 268 while (atom) { 269 if (atom->type() != Atom::QmlText) 270 atom = atom->next(); 271 else { 272 atom = atom->next(); 273 while (atom && (atom->type() != Atom::EndQmlText)) { 274 int n = 1 + generateAtom(atom, relative, marker); 275 while (n-- > 0) 276 atom = atom->next(); 277 } 278 } 279 } 280 endText(relative, marker); 281 } 295 CodeMarker *marker, 296 const QString& /* qmlName */ ) 297 { 298 const Atom* atom = text.firstAtom(); 299 if (atom == 0) 300 return false; 301 302 startText(relative, marker); 303 while (atom) { 304 if (atom->type() != Atom::QmlText) 305 atom = atom->next(); 306 else { 307 atom = atom->next(); 308 while (atom && (atom->type() != Atom::EndQmlText)) { 309 int n = 1 + generateAtom(atom, relative, marker); 310 while (n-- > 0) 311 atom = atom->next(); 312 } 313 } 314 } 315 endText(relative, marker); 316 return true; 282 317 } 283 318 #endif … … 296 331 else if (node->type() == Node::Fake) { 297 332 const FakeNode *fake = static_cast<const FakeNode *>(node); 298 if (fake->subType() == FakeNode::Example)333 if (fake->subType() == Node::Example) 299 334 generateExampleFiles(fake, marker); 300 else if ( fake->subType() == FakeNode::File)335 else if ((fake->subType() == Node::File) || (fake->subType() == Node::Image)) 301 336 quiet = true; 302 337 } 303 338 304 339 if (node->doc().isEmpty()) { 305 if (!quiet ) // ### might be unnecessary340 if (!quiet && !node->isReimp()) // ### might be unnecessary 306 341 node->location().warning(tr("No documentation for '%1'") 307 342 .arg(marker->plainFullName(node))); 308 343 } 309 344 else { 310 generateText(node->doc().body(), node, marker); 345 if (node->type() == Node::Function) { 346 const FunctionNode *func = static_cast<const FunctionNode *>(node); 347 if (func->reimplementedFrom() != 0) 348 generateReimplementedFrom(func, marker); 349 } 350 351 if (!generateText(node->doc().body(), node, marker)) 352 if (node->isReimp()) 353 return; 311 354 312 355 if (node->type() == Node::Enum) { … … 346 389 else if (node->type() == Node::Function) { 347 390 const FunctionNode *func = static_cast<const FunctionNode *>(node); 348 349 391 QSet<QString> definedParams; 350 392 QList<Parameter>::ConstIterator p = func->parameters().begin(); … … 383 425 func->parent()->findFunctionNode(func->name()); 384 426 if (primaryFunc) { 385 foreach (const Parameter ¶m, primaryFunc->parameters()) { 427 foreach (const Parameter ¶m, 428 primaryFunc->parameters()) { 386 429 if (param.name() == *a) { 387 430 needWarning = false; … … 391 434 } 392 435 } 393 if (needWarning )436 if (needWarning && !func->isReimp()) 394 437 node->doc().location().warning( 395 tr("Undocumented parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node))); 438 tr("Undocumented parameter '%1' in %2") 439 .arg(*a).arg(marker->plainFullName(node))); 396 440 } 397 441 ++a; … … 405 449 node->doc().location().warning(tr("Undocumented return value")); 406 450 } 407 451 #if 0 452 // Now we put this at the top, before the other text. 408 453 if (func->reimplementedFrom() != 0) 409 454 generateReimplementedFrom(func, marker); 455 #endif 410 456 } 411 457 } … … 413 459 if (node->type() == Node::Fake) { 414 460 const FakeNode *fake = static_cast<const FakeNode *>(node); 415 if (fake->subType() == FakeNode::File) {461 if (fake->subType() == Node::File) { 416 462 Text text; 417 463 Quoter quoter; … … 460 506 if ((*r).access == Node::Protected) { 461 507 text << " (protected)"; 462 } else if ((*r).access == Node::Private) { 508 } 509 else if ((*r).access == Node::Private) { 463 510 text << " (private)"; 464 511 } … … 470 517 } 471 518 } 519 520 #ifdef QDOC_QML 521 /*! 522 */ 523 void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* ) 524 { 525 // stub. 526 } 527 #endif 472 528 473 529 void Generator::generateInheritedBy(const ClassNode *classe, … … 484 540 } 485 541 542 /*! 543 This function is called when the documentation for an 544 example is being formatted. It outputs the list of source 545 files comprising the example, and the list of images used 546 by the example. The images are copied into a subtree of 547 \c{...doc/html/images/used-in-examples/...} 548 */ 549 void Generator::generateFileList(const FakeNode* fake, 550 CodeMarker* marker, 551 Node::SubType subtype, 552 const QString& tag) 553 { 554 int count = 0; 555 Text text; 556 OpenedList openedList(OpenedList::Bullet); 557 558 text << Atom::ParaLeft << tag << Atom::ParaRight 559 << Atom(Atom::ListLeft, openedList.styleString()); 560 561 foreach (const Node* child, fake->childNodes()) { 562 if (child->subType() == subtype) { 563 ++count; 564 QString file = child->name(); 565 if (subtype == Node::Image) { 566 if (!file.isEmpty()) { 567 QDir dirInfo; 568 QString userFriendlyFilePath; 569 QString srcPath = Config::findFile(fake->location(), 570 QStringList(), 571 exampleDirs, 572 file, 573 exampleImgExts, 574 userFriendlyFilePath); 575 userFriendlyFilePath.truncate(userFriendlyFilePath.lastIndexOf('/')); 576 577 QString imgOutDir = outDir + "/images/used-in-examples/" + userFriendlyFilePath; 578 if (!dirInfo.mkpath(imgOutDir)) 579 fake->location().fatal(tr("Cannot create output directory '%1'") 580 .arg(imgOutDir)); 581 582 QString imgOutName = Config::copyFile(fake->location(), 583 srcPath, 584 file, 585 imgOutDir); 586 } 587 588 } 589 590 openedList.next(); 591 text << Atom(Atom::ListItemNumber, openedList.numberString()) 592 << Atom(Atom::ListItemLeft, openedList.styleString()) 593 << Atom::ParaLeft 594 << Atom(Atom::Link, file) 595 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) 596 << file 597 << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) 598 << Atom::ParaRight 599 << Atom(Atom::ListItemRight, openedList.styleString()); 600 } 601 } 602 text << Atom(Atom::ListRight, openedList.styleString()); 603 if (count > 0) 604 generateText(text, fake, marker); 605 } 606 486 607 void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker) 487 608 { 488 609 if (fake->childNodes().isEmpty()) 489 610 return; 490 491 OpenedList openedList(OpenedList::Bullet); 492 493 Text text; 494 text << Atom::ParaLeft << "Files:" << Atom::ParaRight 495 << Atom(Atom::ListLeft, openedList.styleString()); 496 foreach (const Node *child, fake->childNodes()) { 497 QString exampleFile = child->name(); 498 openedList.next(); 499 text << Atom(Atom::ListItemNumber, openedList.numberString()) 500 << Atom(Atom::ListItemLeft, openedList.styleString()) << Atom::ParaLeft 501 << Atom(Atom::Link, exampleFile) 502 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) 503 << exampleFile 504 << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) 505 << Atom::ParaRight << Atom(Atom::ListItemRight, openedList.styleString()); 506 } 507 text << Atom(Atom::ListRight, openedList.styleString()); 508 generateText(text, fake, marker); 509 } 510 511 void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marker) 611 generateFileList(fake, marker, Node::File, QString("Files:")); 612 generateFileList(fake, marker, Node::Image, QString("Images:")); 613 } 614 615 #if 0 616 QList<Generator *>::ConstIterator g = generators.begin(); 617 while (g != generators.end()) { 618 if (outputFormats.contains((*g)->format())) { 619 (*g)->initializeGenerator(config); 620 QStringList extraImages = 621 config.getStringList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format()); 622 QStringList::ConstIterator e = extraImages.begin(); 623 while (e != extraImages.end()) { 624 QString userFriendlyFilePath; 625 QString filePath = Config::findFile(config.lastLocation(), 626 imageFiles, 627 imageDirs, 628 *e, 629 imgFileExts[(*g)->format()], 630 userFriendlyFilePath); 631 if (!filePath.isEmpty()) 632 Config::copyFile(config.lastLocation(), 633 filePath, 634 userFriendlyFilePath, 635 (*g)->outputDir() + 636 "/images"); 637 ++e; 638 } 639 } 640 ++g; 641 } 642 #endif 643 644 void Generator::generateModuleWarning(const ClassNode *classe, 645 CodeMarker *marker) 512 646 { 513 647 QString module = classe->moduleName(); 514 648 if (!module.isEmpty()) { 515 649 Text text; 516 if (Tokenizer::isTrue("defined(consoleedition)") 517 && !editionModuleMap["Console"].contains(module)) { 650 if (!editionModuleMap["DesktopLight"].contains(module)) { 518 651 text << Atom::ParaLeft 519 652 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) 520 << "This class is not part of the Qt ConsoleEdition."653 << "This class is not part of the Qt GUI Framework Edition." 521 654 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) 522 655 << Atom::ParaRight; 523 656 } 524 else if (Tokenizer::isTrue("defined(desktoplightedition)") 525 && !editionModuleMap["DesktopLight"].contains(module)) { 657 else if (module == "Qt3Support") { 526 658 text << Atom::ParaLeft 527 659 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) 528 << "This class is not part of the Qt Desktop Light Edition." 529 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) 530 << Atom::ParaRight; 531 } 532 else if (module == "Qt3Support" && Tokenizer::isTrue("defined(opensourceedition)")) { 533 text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) 534 << "Note to Qt Desktop Light Edition users:" 660 << "Note to Qt GUI Framework Edition users:" 535 661 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) 536 662 << " This class is only available in the " 537 << Atom(Atom::AutoLink, "Qt DesktopEdition")663 << Atom(Atom::AutoLink, "Qt Full Framework Edition") 538 664 << "." << Atom::ParaRight; 539 665 } … … 559 685 break; 560 686 } 561 } else { 687 } 688 else { 562 689 if (markedCode.at(i) == QLatin1Char('\n')) { 563 690 column = 0; 564 } else { 691 } 692 else { 565 693 if (column == 0) { 566 694 for (int j = 0; j < level; j++) … … 631 759 { 632 760 Location::internalError(tr("unknown atom type '%1' in %2 generator") 633 761 .arg(atom->typeString()).arg(format())); 634 762 } 635 763 … … 660 788 } 661 789 } 662 } else if (!func->name().isEmpty()) { 790 } 791 else if (!func->name().isEmpty()) { 663 792 alternateName = "set"; 664 793 alternateName += func->name()[0].toUpper(); … … 716 845 break; 717 846 case Node::Preliminary: 718 text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This " 719 << typeString(node) << " is under development and is subject to change." 720 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight; 847 text << Atom::ParaLeft 848 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) 849 << "This " 850 << typeString(node) 851 << " is under development and is subject to change." 852 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) 853 << Atom::ParaRight; 721 854 break; 722 855 case Node::Deprecated: … … 736 869 if (node->isInnerNode()) 737 870 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD); 738 text << " It is provided to keep old source code working. We strongly advise against " 871 text << " It is provided to keep old source code working. " 872 << "We strongly advise against " 739 873 << "using it in new code." << Atom::ParaRight; 740 874 break; … … 742 876 // reimplemented in HtmlGenerator subclass 743 877 if (node->isInnerNode()) { 744 text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This " 745 << typeString(node) << " is part of the Qt 3 compatibility layer." 878 text << Atom::ParaLeft 879 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) 880 << "This " 881 << typeString(node) 882 << " is part of the Qt 3 compatibility layer." 746 883 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) 747 << " It is provided to keep old source code working. We strongly advise against " 884 << " It is provided to keep old source code working. " 885 << "We strongly advise against " 748 886 << "using it in new code. See " 749 887 << Atom(Atom::AutoLink, "Porting to Qt 4") … … 763 901 Text text; 764 902 Text theStockLink; 765 Node::ThreadSafeness parent = node->parent()->inheritedThreadSafeness(); 766 767 switch (node->threadSafeness()) { 903 Node::ThreadSafeness threadSafeness = node->threadSafeness(); 904 905 Text rlink; 906 rlink << Atom(Atom::Link,"reentrant") 907 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) 908 << "reentrant" 909 << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); 910 911 Text tlink; 912 tlink << Atom(Atom::Link,"thread-safe") 913 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) 914 << "thread-safe" 915 << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); 916 917 switch (threadSafeness) { 768 918 case Node::UnspecifiedSafeness: 769 919 break; 770 920 case Node::NonReentrant: 771 text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Warning:" 772 << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This " 773 << typeString(node) << " is not " << stockLink("reentrant") << "." << Atom::ParaRight; 921 text << Atom::ParaLeft 922 << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) 923 << "Warning:" 924 << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD) 925 << " This " 926 << typeString(node) 927 << " is not " 928 << rlink 929 << "." 930 << Atom::ParaRight; 774 931 break; 775 932 case Node::Reentrant: 776 933 case Node::ThreadSafe: 777 text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); 778 if (parent == Node::ThreadSafe) { 779 text << "Warning:"; 780 } else { 781 text << "Note:"; 782 } 783 text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " "; 784 785 if (node->threadSafeness() == Node::ThreadSafe) 786 theStockLink = stockLink("thread-safe"); 787 else 788 theStockLink = stockLink("reentrant"); 934 text << Atom::ParaLeft 935 << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) 936 << "Note:" 937 << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD) 938 << " "; 789 939 790 940 if (node->isInnerNode()) { 791 const InnerNode *innerNode = static_cast<const InnerNode *>(node); 792 text << "All the functions in this " << typeString(node) << " are " 793 << theStockLink; 794 795 NodeList except; 941 const InnerNode* innerNode = static_cast<const InnerNode*>(node); 942 text << "All functions in this " 943 << typeString(node) 944 << " are "; 945 if (threadSafeness == Node::ThreadSafe) 946 text << tlink; 947 else 948 text << rlink; 949 950 bool exceptions = false; 951 NodeList reentrant; 952 NodeList threadsafe; 953 NodeList nonreentrant; 796 954 NodeList::ConstIterator c = innerNode->childNodes().begin(); 797 955 while (c != innerNode->childNodes().end()) { 798 if ((*c)->threadSafeness() != Node::UnspecifiedSafeness) 799 except.append(*c); 956 switch ((*c)->threadSafeness()) { 957 case Node::Reentrant: 958 reentrant.append(*c); 959 if (threadSafeness == Node::ThreadSafe) 960 exceptions = true; 961 break; 962 case Node::ThreadSafe: 963 threadsafe.append(*c); 964 if (threadSafeness == Node::Reentrant) 965 exceptions = true; 966 break; 967 case Node::NonReentrant: 968 nonreentrant.append(*c); 969 exceptions = true; 970 break; 971 default: 972 break; 973 } 800 974 ++c; 801 975 } 802 if ( except.isEmpty()) {976 if (!exceptions) 803 977 text << "."; 804 } 805 else { 806 text << ", except "; 807 808 NodeList::ConstIterator e = except.begin(); 809 int index = 0; 810 while (e != except.end()) { 811 appendFullName(text, *e, innerNode, marker); 812 text << separator(index++, except.count()); 813 ++e; 978 else if (threadSafeness == Node::Reentrant) { 979 if (nonreentrant.isEmpty()) { 980 if (!threadsafe.isEmpty()) { 981 text << ", but "; 982 appendFullNames(text,threadsafe,innerNode,marker); 983 singularPlural(text,threadsafe); 984 text << " also " << tlink << "."; 985 } 986 else 987 text << "."; 988 } 989 else { 990 text << ", except for "; 991 appendFullNames(text,nonreentrant,innerNode,marker); 992 text << ", which"; 993 singularPlural(text,nonreentrant); 994 text << " nonreentrant."; 995 if (!threadsafe.isEmpty()) { 996 text << " "; 997 appendFullNames(text,threadsafe,innerNode,marker); 998 singularPlural(text,threadsafe); 999 text << " " << tlink << "."; 1000 } 1001 } 1002 } 1003 else { // thread-safe 1004 if (!nonreentrant.isEmpty() || !reentrant.isEmpty()) { 1005 text << ", except for "; 1006 if (!reentrant.isEmpty()) { 1007 appendFullNames(text,reentrant,innerNode,marker); 1008 text << ", which"; 1009 singularPlural(text,reentrant); 1010 text << " only " << rlink; 1011 if (!nonreentrant.isEmpty()) 1012 text << ", and "; 1013 } 1014 if (!nonreentrant.isEmpty()) { 1015 appendFullNames(text,nonreentrant,innerNode,marker); 1016 text << ", which"; 1017 singularPlural(text,nonreentrant); 1018 text << " nonreentrant."; 1019 } 1020 text << "."; 814 1021 } 815 1022 } 816 1023 } 817 1024 else { 818 text << "This " << typeString(node) << " is " << theStockLink << "."; 1025 text << "This " << typeString(node) << " is "; 1026 if (threadSafeness == Node::ThreadSafe) 1027 text << tlink; 1028 else 1029 text << rlink; 1030 text << "."; 819 1031 } 820 1032 text << Atom::ParaRight; 821 1033 } 822 generateText(text, node,marker);1034 generateText(text,node,marker); 823 1035 } 824 1036 … … 827 1039 if (!node->since().isEmpty()) { 828 1040 Text text; 829 text << Atom::ParaLeft << "This " << typeString(node) 1041 text << Atom::ParaLeft 1042 << "This " 1043 << typeString(node) 830 1044 << " was introduced in "; 831 1045 if (project.isEmpty()) … … 857 1071 if (func->reimplementedFrom() != 0) { 858 1072 const FunctionNode *from = func->reimplementedFrom(); 859 if (from->access() != Node::Private && from->parent()->access() != Node::Private) { 1073 if (from->access() != Node::Private && 1074 from->parent()->access() != Node::Private) { 860 1075 Text text; 861 1076 text << Atom::ParaLeft << "Reimplemented from "; 862 appendFullName(text, from->parent(), func, marker, from); 1077 QString fullName = from->parent()->name() + "::" + from->name() + "()"; 1078 appendFullName(text, from->parent(), fullName, from); 863 1079 text << "." << Atom::ParaRight; 864 1080 generateText(text, func, marker); … … 898 1114 if (atom->type() == Atom::FormatEndif) { 899 1115 if (generate && numAtoms0 == numAtoms) { 900 relative->location().warning(tr("Output format %1 not handled") .901 arg(format()));1116 relative->location().warning(tr("Output format %1 not handled") 1117 .arg(format())); 902 1118 Atom unhandledFormatAtom(Atom::UnhandledFormat, format()); 903 1119 generateAtomList(&unhandledFormatAtom, … … 910 1126 } 911 1127 } 912 else if (atom->type() == Atom::FormatElse || atom->type() == Atom::FormatEndif) { 1128 else if (atom->type() == Atom::FormatElse || 1129 atom->type() == Atom::FormatEndif) { 913 1130 return atom; 914 1131 } … … 940 1157 } 941 1158 1159 void Generator::appendFullName(Text& text, 1160 const Node *apparentNode, 1161 const QString& fullName, 1162 const Node *actualNode) 1163 { 1164 if (actualNode == 0) 1165 actualNode = apparentNode; 1166 text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode)) 1167 << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) 1168 << Atom(Atom::String, fullName) 1169 << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); 1170 } 1171 1172 void Generator::appendFullNames(Text& text, 1173 const NodeList& nodes, 1174 const Node* relative, 1175 CodeMarker* marker) 1176 { 1177 NodeList::ConstIterator n = nodes.begin(); 1178 int index = 0; 1179 while (n != nodes.end()) { 1180 appendFullName(text,*n,relative,marker); 1181 text << comma(index++,nodes.count()); 1182 ++n; 1183 } 1184 } 1185 942 1186 void Generator::appendSortedNames(Text& text, 943 1187 const ClassNode *classe, … … 951 1195 r = classes.begin(); 952 1196 while (r != classes.end()) { 953 if ((*r).node->access() == Node::Public && (*r).node->status() != Node::Internal 1197 if ((*r).node->access() == Node::Public && 1198 (*r).node->status() != Node::Internal 954 1199 && !(*r).node->doc().isEmpty()) { 955 1200 Text className;
Note:
See TracChangeset
for help on using the changeset viewer.