diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp index 9f22a287d20..fe0b366350a 100644 --- a/src/tools/qdoc/codemarker.cpp +++ b/src/tools/qdoc/codemarker.cpp @@ -649,7 +649,6 @@ QStringList CodeMarker::macRefsForNode(Node *node) } case Node::Namespace: case Node::Fake: - case Node::Target: default: return QStringList(); } diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 3e7d190fe43..aea8ed2119d 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -826,61 +826,38 @@ QList
CppCodeMarker::sections(const InnerNode *inner, return sections; } +/*! + Search the \a tree for a node named \a target + */ const Node *CppCodeMarker::resolveTarget(const QString& target, const Tree* tree, const Node* relative, const Node* self) { + const Node* node = 0; if (target.endsWith("()")) { - const FunctionNode *func; QString funcName = target; funcName.chop(2); - QStringList path = funcName.split("::"); - if ((func = tree->findFunctionNode(path, - relative, - Tree::SearchBaseClasses)) - && func->metaness() != FunctionNode::MacroWithoutParams) - return func; + const FunctionNode* fn = tree->findFunctionNode(path, relative, Tree::SearchBaseClasses); + if (fn) { + /* + Why is this case not accepted? + */ + if (fn->metaness() != FunctionNode::MacroWithoutParams) + node = fn; + } } else if (target.contains(QLatin1Char('#'))) { - // ### this doesn't belong here; get rid of TargetNode hack - int hashAt = target.indexOf(QLatin1Char('#')); - QString link = target.left(hashAt); - QString ref = target.mid(hashAt + 1); - const Node *node; - if (link.isEmpty()) { - node = relative; - } - else { - QStringList path(link); - node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses); - } - if (node && node->isInnerNode()) { - const Atom *atom = node->doc().body().firstAtom(); - while (atom) { - if (atom->type() == Atom::Target && atom->string() == ref) { - Node *parentNode = const_cast(node); - return new TargetNode(static_cast(parentNode), - ref); - } - atom = atom->next(); - } - } + // This error message is never printed; I think we can remove the case. + qDebug() << "qdoc: target case not handled:" << target; } else { QStringList path = target.split("::"); - const Node *node; - int flags = Tree::SearchBaseClasses | - Tree::SearchEnumValues | - Tree::NonFunction; - if ((node = tree->findNode(path, - relative, - flags, - self))) - return node; + int flags = Tree::SearchBaseClasses | Tree::SearchEnumValues | Tree::NonFunction; + node = tree->findNode(path, relative, flags, self); } - return 0; + return node; } static const char * const typeTable[] = { diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index a308da1f987..7dfb32bde04 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -79,7 +79,6 @@ QT_BEGIN_NAMESPACE #define COMMAND_PROPERTY Doc::alias("property") #define COMMAND_REIMP Doc::alias("reimp") #define COMMAND_RELATES Doc::alias("relates") -#define COMMAND_SERVICE Doc::alias("service") #define COMMAND_STARTPAGE Doc::alias("startpage") #define COMMAND_TYPEDEF Doc::alias("typedef") #define COMMAND_VARIABLE Doc::alias("variable") @@ -119,7 +118,7 @@ QStringList CppCodeParser::exampleDirs; This is used for fuzzy matching only, which in turn is only used for Qt Jambi. */ -static QString cleanType(const QString &type, const Tree *tree) +static QString cleanType(const QString &type, Tree* tree) { QString result = type; result.replace("qlonglong", "long long"); @@ -145,14 +144,13 @@ static QString cleanType(const QString &type, const Tree *tree) while ((pos = result.indexOf(regExp, pos)) != -1) { // we assume that the path for the associated enum // is the same as for the flag typedef - QStringList path = regExp.cap(2).split("::", - QString::SkipEmptyParts); - const EnumNode *enume = static_cast( - tree->findNode(QStringList(path) << regExp.cap(3), - Node::Enum)); - if (enume && enume->flagsType()) - result.replace(pos, regExp.matchedLength(), - (QStringList(path) << enume->flagsType()->name()).join("::")); + QStringList path = regExp.cap(2).split("::", QString::SkipEmptyParts); + QStringList tmpPath = QStringList(path) << regExp.cap(3); + EnumNode* en = tree->findEnumNode(tmpPath); + if (en && en->flagsType()) { + tmpPath = QStringList(path) << en->flagsType()->name(); + result.replace(pos, regExp.matchedLength(), tmpPath.join("::")); + } ++pos; } } @@ -191,9 +189,12 @@ void CppCodeParser::initializeParser(const Config &config) { CodeParser::initializeParser(config); + /* + All these can appear in a C++ namespace. Don't add + anything that can't be in a C++ namespace. + */ nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace); nodeTypeMap.insert(COMMAND_CLASS, Node::Class); - nodeTypeMap.insert(COMMAND_SERVICE, Node::Class); nodeTypeMap.insert(COMMAND_ENUM, Node::Enum); nodeTypeMap.insert(COMMAND_TYPEDEF, Node::Typedef); nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property); @@ -306,7 +307,13 @@ void CppCodeParser::parseSourceFile(const Location& location, Tokenizer fileTokenizer(fileLocation, in); tokenizer = &fileTokenizer; readToken(); - usedNamespaces.clear(); + + /* + The set of active namespaces is cleared before parsing + each source file. The word "source" here means cpp file. + */ + activeNamespaces_.clear(); + matchDocsAndStuff(); in.close(); } @@ -403,14 +410,14 @@ const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis, This is necessary because Roberto's parser resolves typedefs. */ if (!func && fuzzy) { - func = tre->findFunctionNode(parentPath + + func = tree_->findFunctionNode(parentPath + QStringList(clone->name()), relative, flags); if (!func && clone->name().contains('_')) { QStringList path = parentPath; path << clone->name().split('_'); - func = tre->findFunctionNode(path, relative, flags); + func = tree_->findFunctionNode(path, relative, flags); } if (func) { @@ -512,7 +519,6 @@ QSet CppCodeParser::topicCommands() << COMMAND_NAMESPACE << COMMAND_PAGE << COMMAND_PROPERTY - << COMMAND_SERVICE << COMMAND_TYPEDEF << COMMAND_VARIABLE << COMMAND_QMLCLASS @@ -543,21 +549,21 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, doc.location().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN)); } else { - if (!usedNamespaces.isEmpty()) { - foreach (const QString &usedNamespace, usedNamespaces) { - QStringList newPath = usedNamespace.split("::") + parentPath; - func = tre->findFunctionNode(newPath, clone); + if (!activeNamespaces_.isEmpty()) { + foreach (const QString& usedNamespace_, activeNamespaces_) { + QStringList newPath = usedNamespace_.split("::") + parentPath; + func = tree_->findFunctionNode(newPath, clone); if (func) break; } } // Search the root namespace if no match was found. if (func == 0) - func = tre->findFunctionNode(parentPath, clone); + func = tree_->findFunctionNode(parentPath, clone); if (func == 0) { if (parentPath.isEmpty() && !lastPath.isEmpty()) - func = tre->findFunctionNode(lastPath, clone); + func = tree_->findFunctionNode(lastPath, clone); if (func == 0) { doc.location().warning(tr("Cannot find '%1' in '\\%2'") .arg(clone->name() + "(...)") @@ -589,7 +595,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, QStringList parentPath; FunctionNode *func = 0; - if (makeFunctionNode(arg, &parentPath, &func, tre->root())) { + if (makeFunctionNode(arg, &parentPath, &func, tree_->root())) { if (!parentPath.isEmpty()) { doc.location().warning(tr("Invalid syntax in '\\%1'") .arg(COMMAND_MACRO)); @@ -610,7 +616,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, return func; } else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg)) { - func = new FunctionNode(tre->root(), arg); + func = new FunctionNode(tree_->root(), arg); func->setAccess(Node::Public); func->setLocation(doc.location()); func->setMetaness(FunctionNode::MacroWithoutParams); @@ -624,25 +630,45 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, } else if (nodeTypeMap.contains(command)) { /* - The command was neither "fn" nor "macro" . + We should only get in here if the command refers to + something that can appear in a C++ namespace, + i.e. a class, another namespace, an enum, a typedef, + a property or a variable. I think these are handled + this way to allow the writer to refer to the entity + without including the namespace qualifier. */ - // ### split(QLatin1Char(' ')) hack is there to support header file syntax + Node::Type type = nodeTypeMap[command]; + Node::SubType subtype = Node::NoSubType; + if (type == Node::Fake) + subtype = Node::QmlClass; + QStringList paths = arg.split(QLatin1Char(' ')); QStringList path = paths[0].split("::"); Node *node = 0; - if (!usedNamespaces.isEmpty()) { - foreach (const QString &usedNamespace, usedNamespaces) { - QStringList newPath = usedNamespace.split("::") + path; - node = tre->findNode(newPath, nodeTypeMap[command]); + + /* + If the command refers to something that can be in a + C++ namespace, search for it first in all the known + C++ namespaces. + */ + if (!activeNamespaces_.isEmpty()) { + foreach (const QString& usedNamespace_, activeNamespaces_) { + QStringList newPath = usedNamespace_.split("::") + path; + node = tree_->findNodeByNameAndType(newPath, type, subtype, 0); if (node) { path = newPath; break; } } } - // Search the root namespace if no match was found. - if (node == 0) - node = tre->findNode(path, nodeTypeMap[command]); + + /* + If the node was not found in a C++ namespace, search + for it in the root namespace. + */ + if (node == 0) { + node = tree_->findNodeByNameAndType(path, type, subtype, 0); + } if (node == 0) { doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file") @@ -650,63 +676,40 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, lastPath = path; } - else if (command == COMMAND_SERVICE) { - // If the command is "\service", then we need to tag the - // class with the actual service name. - QStringList args = arg.split(QLatin1Char(' ')); - if (args.size() > 1) { - ClassNode *cnode = static_cast(node); - cnode->setServiceName(args[1]); - cnode->setHideFromMainList(true); - } - } else if (node->isInnerNode()) { + /* + This treets a class as a namespace. + */ if (path.size() > 1) { path.pop_back(); - usedNamespaces.insert(path.join("::")); + QString ns = path.join("::"); + activeNamespaces_.insert(ns); } } -#if 0 - /* - This code apparently does nothing. After further - investigation to verify it is useless, it will - be removed. - */ - if (command == COMMAND_CLASS) { - if (paths.size() > 1) { - if (!paths[1].endsWith(".h")) { - ClassNode* cnode = static_cast(node); - cnode->setQmlElement(paths[1]); - } - } - } -#endif return node; } else if (command == COMMAND_EXAMPLE) { - if (Config::generateExamples) { - ExampleNode* en = new ExampleNode(tre->root(), arg); - createExampleFileNodes(en); - return en; - } + ExampleNode* en = new ExampleNode(tree_->root(), arg); + createExampleFileNodes(en); + return en; } else if (command == COMMAND_EXTERNALPAGE) { - return new FakeNode(tre->root(), arg, Node::ExternalPage, Node::ArticlePage); + return new FakeNode(tree_->root(), arg, Node::ExternalPage, Node::ArticlePage); } else if (command == COMMAND_FILE) { - return new FakeNode(tre->root(), arg, Node::File, Node::NoPageType); + return new FakeNode(tree_->root(), arg, Node::File, Node::NoPageType); } else if (command == COMMAND_GROUP) { - return new FakeNode(tre->root(), arg, Node::Group, Node::OverviewPage); + return new FakeNode(tree_->root(), arg, Node::Group, Node::OverviewPage); } else if (command == COMMAND_HEADERFILE) { - return new FakeNode(tre->root(), arg, Node::HeaderFile, Node::ApiPage); + return new FakeNode(tree_->root(), arg, Node::HeaderFile, Node::ApiPage); } else if (command == COMMAND_MODULE) { - return new FakeNode(tre->root(), arg, Node::Module, Node::OverviewPage); + return new FakeNode(tree_->root(), arg, Node::Module, Node::OverviewPage); } else if (command == COMMAND_QMLMODULE) { - return new FakeNode(tre->root(), arg, Node::QmlModule, Node::OverviewPage); + return new FakeNode(tree_->root(), arg, Node::QmlModule, Node::OverviewPage); } else if (command == COMMAND_PAGE) { Node::PageType ptype = Node::ArticlePage; @@ -740,30 +743,27 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, If there is no collision, just create a new Page node and return that one. */ - NameCollisionNode* ncn = tre->checkForCollision(args[0]); + NameCollisionNode* ncn = tree_->checkForCollision(args[0]); FakeNode* fn = 0; if (ptype == Node::DitaMapPage) - fn = new DitaMapNode(tre->root(), args[0]); + fn = new DitaMapNode(tree_->root(), args[0]); else - fn = new FakeNode(tre->root(), args[0], Node::Page, ptype); + fn = new FakeNode(tree_->root(), args[0], Node::Page, ptype); if (ncn) { ncn->addCollision(fn); } return fn; } else if (command == COMMAND_DITAMAP) { - FakeNode* fn = new DitaMapNode(tre->root(), arg); + FakeNode* fn = new DitaMapNode(tree_->root(), arg); return fn; } else if (command == COMMAND_QMLCLASS) { - const ClassNode* classNode = 0; + ClassNode* classNode = 0; QStringList names = arg.split(QLatin1Char(' ')); - if (names.size() > 1) { - Node* n = tre->findNode(names[1].split("::"),Node::Class); - if (n) { - classNode = static_cast(n); - } - } + if (names.size() > 1) + classNode = tree_->findClassNode(names[1].split("::")); + /* Search for a node with the same name. If there is one, then there is a collision, so create a collision node @@ -775,15 +775,14 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, If there is no collision, just create a new QML class node and return that one. */ - NameCollisionNode* ncn = tre->checkForCollision(names[0]); - QmlClassNode* qcn = new QmlClassNode(tre->root(), names[0], classNode); - if (ncn) { + NameCollisionNode* ncn = tree_->checkForCollision(names[0]); + QmlClassNode* qcn = new QmlClassNode(tree_->root(), names[0], classNode); + if (ncn) ncn->addCollision(qcn); - } return qcn; } else if (command == COMMAND_QMLBASICTYPE) { - return new QmlBasicTypeNode(tre->root(), arg); + return new QmlBasicTypeNode(tree_->root(), arg); } else if ((command == COMMAND_QMLSIGNAL) || (command == COMMAND_QMLMETHOD) || @@ -793,7 +792,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, QString element; QString type; if (splitQmlMethodArg(doc,arg,type,module,element)) { - QmlClassNode* qmlClass = tre->findQmlClassNode(module,element); + QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element); if (qmlClass) { if (command == COMMAND_QMLSIGNAL) return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,false,COMMAND_QMLSIGNAL); @@ -936,18 +935,18 @@ Node *CppCodeParser::processTopicCommandGroup(const Doc& doc, bool attached = (command == COMMAND_QMLATTACHEDPROPERTY); QStringList::ConstIterator arg = args.begin(); if (splitQmlPropertyArg(doc,(*arg),type,module,element,property)) { - QmlClassNode* qmlClass = tre->findQmlClassNode(module,element); + QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element); if (qmlClass) { qmlPropGroup = new QmlPropGroupNode(qmlClass,property,attached); } } if (qmlPropGroup) { - const ClassNode *correspondingClass = static_cast(qmlPropGroup->parent())->classNode(); + ClassNode *correspondingClass = static_cast(qmlPropGroup->parent())->classNode(); QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached); const PropertyNode *correspondingProperty = 0; if (correspondingClass) { - correspondingProperty = qmlPropNode->correspondingProperty(tre); + correspondingProperty = qmlPropNode->correspondingProperty(tree_); } if (correspondingProperty) { bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*'); @@ -1053,28 +1052,37 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } } else if (command == COMMAND_RELATES) { - InnerNode *pseudoParent; + /* + Find the node that this node relates to. + */ + Node* n = 0; if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) { - pseudoParent = - static_cast(tre->findNode(QStringList(arg), - Node::Fake)); + /* + It should be a header file, I think. + */ + n = tree_->findNodeByNameAndType(QStringList(arg), Node::Fake, Node::NoSubType, 0); } else { + /* + If it wasn't a file, it should be either a class or a namespace. + */ QStringList newPath = arg.split("::"); - pseudoParent = - static_cast(tre->findNode(QStringList(newPath), - Node::Class)); - if (!pseudoParent) - pseudoParent = - static_cast(tre->findNode(QStringList(newPath), - Node::Namespace)); + n = tree_->findClassNode(QStringList(newPath)); + if (!n) + n = tree_->findNamespaceNode(QStringList(newPath)); } - if (!pseudoParent) { - doc.location().warning(tr("Cannot find '%1' in '\\%2'") - .arg(arg).arg(COMMAND_RELATES)); + + if (!n) { + /* + Didn't ind it. Error... + */ + doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES)); } else { - node->setRelates(pseudoParent); + /* + Found it. This node relates to it. + */ + node->setRelates(static_cast(n)); } } else if (command == COMMAND_CONTENTSPAGE) { @@ -1136,7 +1144,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, } } else { - processCommonMetaCommand(doc.location(),command,arg,node,tre); + processCommonMetaCommand(doc.location(),command,arg,node,tree_); } } @@ -1165,7 +1173,7 @@ void CppCodeParser::processOtherMetaCommands(const Doc& doc, Node *node) */ void CppCodeParser::reset(Tree *tree) { - tre = tree; + tree_ = tree; tokenizer = 0; tok = 0; access = Node::Public; @@ -1691,7 +1699,7 @@ bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass) if (!matchDataType(&baseClass)) return false; - tre->addBaseClass(classe, + tree_->addBaseClass(classe, access, baseClass.toPath(), baseClass.toString(), @@ -1773,18 +1781,18 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent) So far, so good. We have 'namespace Foo {'. */ QString namespaceName = previousLexeme(); - NamespaceNode *namespasse = 0; + NamespaceNode* ns = 0; if (parent) { - namespasse = static_cast(parent->findNode(namespaceName, Node::Namespace)); + ns = static_cast(parent->findChildNodeByNameAndType(namespaceName, Node::Namespace)); } - if (!namespasse) { - namespasse = new NamespaceNode(parent, namespaceName); - namespasse->setAccess(access); - namespasse->setLocation(location()); + if (!ns) { + ns = new NamespaceNode(parent, namespaceName); + ns->setAccess(access); + ns->setLocation(location()); } readToken(); // skip '{' - bool matched = matchDeclList(namespasse); + bool matched = matchDeclList(ns); return matched && match(Tok_RightBrace); } @@ -1817,7 +1825,7 @@ bool CppCodeParser::matchUsingDecl() /* So far, so good. We have 'using namespace Foo;'. */ - usedNamespaces.insert(name); + activeNamespaces_.insert(name); return true; } @@ -1915,10 +1923,10 @@ bool CppCodeParser::matchTypedefDecl(InnerNode *parent) if (!match(Tok_Semicolon)) return false; - if (parent && !parent->findNode(name, Node::Typedef)) { - TypedefNode *typedeffe = new TypedefNode(parent, name); - typedeffe->setAccess(access); - typedeffe->setLocation(location()); + if (parent && !parent->findChildNodeByNameAndType(name, Node::Typedef)) { + TypedefNode* td = new TypedefNode(parent, name); + td->setAccess(access); + td->setLocation(location()); } return true; } @@ -1977,9 +1985,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent) } if (key == "READ") - tre->addPropertyFunction(property, value, PropertyNode::Getter); + tree_->addPropertyFunction(property, value, PropertyNode::Getter); else if (key == "WRITE") { - tre->addPropertyFunction(property, value, PropertyNode::Setter); + tree_->addPropertyFunction(property, value, PropertyNode::Setter); property->setWritable(true); } else if (key == "STORED") @@ -1996,9 +2004,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent) } } else if (key == "RESET") - tre->addPropertyFunction(property, value, PropertyNode::Resetter); + tree_->addPropertyFunction(property, value, PropertyNode::Resetter); else if (key == "NOTIFY") { - tre->addPropertyFunction(property, value, PropertyNode::Notifier); + tree_->addPropertyFunction(property, value, PropertyNode::Notifier); } else if (key == "REVISION") { int revision; bool ok; @@ -2130,15 +2138,13 @@ bool CppCodeParser::matchDeclList(InnerNode *parent) if (match(Tok_LeftParen) && match(Tok_Ident)) { QString flagsType = previousLexeme(); if (match(Tok_Comma) && match(Tok_Ident)) { - QString enumType = previousLexeme(); + QString name = previousLexeme(); TypedefNode *flagsNode = new TypedefNode(parent, flagsType); flagsNode->setAccess(access); flagsNode->setLocation(location()); - EnumNode *enumNode = - static_cast(parent->findNode(enumType, - Node::Enum)); - if (enumNode) - enumNode->setFlagsType(flagsNode); + EnumNode* en = static_cast(parent->findChildNodeByNameAndType(name, Node::Enum)); + if (en) + en->setFlagsType(flagsNode); } } match(Tok_RightParen); @@ -2219,14 +2225,14 @@ bool CppCodeParser::matchDocsAndStuff() FunctionNode *func = 0; if (matchFunctionDecl(0, &parentPath, &clone)) { - foreach (const QString &usedNamespace, usedNamespaces) { - QStringList newPath = usedNamespace.split("::") + parentPath; - func = tre->findFunctionNode(newPath, clone); + foreach (const QString& usedNamespace_, activeNamespaces_) { + QStringList newPath = usedNamespace_.split("::") + parentPath; + func = tree_->findFunctionNode(newPath, clone); if (func) break; } if (func == 0) - func = tre->findFunctionNode(parentPath, clone); + func = tree_->findFunctionNode(parentPath, clone); if (func) { func->borrowParameterNames(clone); @@ -2280,7 +2286,7 @@ bool CppCodeParser::matchDocsAndStuff() if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { InnerNode *m = static_cast(*n); - while (m->parent() != tre->root()) + while (m->parent() != tree_->root()) m = m->parent(); if (m == *n) ((InnerNode *)*n)->addInclude((*n)->name()); @@ -2309,7 +2315,7 @@ bool CppCodeParser::matchDocsAndStuff() Signals are implemented in uninteresting files generated by moc. */ - node = tre->findFunctionNode(parentPath, clone); + node = tree_->findFunctionNode(parentPath, clone); if (node != 0 && node->metaness() != FunctionNode::Signal) node->setLocation(clone->location()); delete clone; @@ -2421,7 +2427,7 @@ void CppCodeParser::instantiateIteratorMacro(const QString &container, Tokenizer stringTokenizer(loc, latin1); tokenizer = &stringTokenizer; readToken(); - matchDeclList(tre->root()); + matchDeclList(tree_->root()); } void CppCodeParser::createExampleFileNodes(FakeNode *fake) diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h index f33ff6430d9..74abb994d9a 100644 --- a/src/tools/qdoc/cppcodeparser.h +++ b/src/tools/qdoc/cppcodeparser.h @@ -165,7 +165,7 @@ private: void createExampleFileNodes(FakeNode *fake); QMap nodeTypeMap; - Tree *tre; + Tree* tree_; Tokenizer *tokenizer; int tok; Node::Access access; @@ -179,7 +179,7 @@ private: QString mutableSequentialIteratorDefinition; QString associativeIteratorDefinition; QString mutableAssociativeIteratorDefinition; - QSet usedNamespaces; + QSet activeNamespaces_; QMap sequentialIteratorClasses; QMap mutableSequentialIteratorClasses; QMap associativeIteratorClasses; diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp index 8fa7f938d1a..1458b640d18 100644 --- a/src/tools/qdoc/ditaxmlgenerator.cpp +++ b/src/tools/qdoc/ditaxmlgenerator.cpp @@ -418,7 +418,6 @@ DitaXmlGenerator::DitaXmlGenerator() sectionNestingLevel(0), tableColumnCount(0), funcLeftParen("\\S(\\()"), - tree_(0), nodeTypeMaps(Node::LastType,0), nodeSubtypeMaps(Node::LastSubtype,0), pageTypeMaps(Node::OnBeyondZebra,0) @@ -618,7 +617,7 @@ GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName) This is where the DITA XML files are written. \note The file is created in PageGenerator::generateTree(). */ -void DitaXmlGenerator::generateTree(const Tree *tree) +void DitaXmlGenerator::generateTree(Tree *tree) { tree_ = tree; nonCompatClasses.clear(); @@ -638,6 +637,7 @@ void DitaXmlGenerator::generateTree(const Tree *tree) findAllSince(tree->root()); Generator::generateTree(tree); + generateCollisionPages(); writeDitaMap(tree); } @@ -1269,19 +1269,15 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, const Node *node = 0; QString myLink = getLink(atom, relative, marker, &node); if (myLink.isEmpty()) { - relative->doc().location().warning(tr("Can't link to '%1' in %2") - .arg(atom->string()) - .arg(marker->plainFullName(relative))); + myLink = getCollisionLink(atom); + } + if (myLink.isEmpty()) { + relative->doc().location().warning(tr("Can't link to '%1'") + .arg(atom->string())); } else if (!inSectionHeading) { beginLink(myLink); } -#if 0 - else { - //xmlWriter().writeCharacters(atom->string()); - //qDebug() << "MYLINK:" << myLink << outFileName() << atom->string(); - } -#endif skipAhead = 1; } break; @@ -1744,7 +1740,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom, for marking up the code. I don't know what that means exactly. */ void -DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* marker) +DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) { QList
::ConstIterator s; @@ -2143,8 +2139,8 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark writeEndTag(); // } else if ((inner->type() == Node::Fake) && (inner->subType() == Node::QmlClass)) { - const QmlClassNode* qcn = const_cast(static_cast(inner)); - const ClassNode* cn = qcn->classNode(); + QmlClassNode* qcn = const_cast(static_cast(inner)); + ClassNode* cn = qcn->classNode(); rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); title = rawTitle + " Element"; @@ -2248,7 +2244,7 @@ void DitaXmlGenerator::writeXrefListItem(const QString& link, const QString& tex Generate the DITA page for a qdoc file that doesn't map to an underlying c++ file. */ -void DitaXmlGenerator::generateFakeNode(const FakeNode* fake, CodeMarker* marker) +void DitaXmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker) { /* If the fake node is a page node, and if the page type @@ -2499,6 +2495,9 @@ void DitaXmlGenerator::generateHeader(const Node* node, case Node::ExternalPage: // not used outputclass = "externalpage"; break; + case Node::Collision: + outputclass = "collision"; + break; default: outputclass = "page"; } @@ -3302,16 +3301,11 @@ void DitaXmlGenerator::generateOverviewList(const Node* relative, CodeMarker* /* else if (!isGroupPage) { // If we encounter a page that belongs to a group then // we add that page to the list for that group. - const FakeNode* groupNode = - static_cast(tree_->root()->findNode(group, Node::Fake)); - if (groupNode) - fakeNodeMap[groupNode].insert(sortKey, fakeNode); - //else - // uncategorizedNodeMap.insert(sortKey, fakeNode); - }// else - // uncategorizedNodeMap.insert(sortKey, fakeNode); - }// else - // uncategorizedNodeMap.insert(sortKey, fakeNode); + const FakeNode* gn = tree_->findGroupNode(QStringList(group)); + if (gn) + fakeNodeMap[gn].insert(sortKey, fakeNode); + } + } } } @@ -3877,8 +3871,6 @@ QString DitaXmlGenerator::guidForNode(const Node* node) return node->guid(); case Node::Variable: return node->guid(); - case Node::Target: - return node->guid(); } return QString(); } @@ -4143,7 +4135,7 @@ const Node* DitaXmlGenerator::findNodeForTarget(const QString& target, node = relative; } else if (target.endsWith(".html")) { - node = tree_->root()->findNode(target, Node::Fake); + node = tree_->root()->findChildNodeByNameAndType(target, Node::Fake); } else if (marker) { node = marker->resolveTarget(target, tree_, relative); @@ -4204,7 +4196,7 @@ QString DitaXmlGenerator::getLink(const Atom* atom, *node = relative; } else if (first.endsWith(".html")) { - *node = tree_->root()->findNode(first, Node::Fake); + *node = tree_->root()->findChildNodeByNameAndType(first, Node::Fake); } else { *node = marker->resolveTarget(first, tree_, relative); @@ -4292,17 +4284,6 @@ QString DitaXmlGenerator::getLink(const Atom* atom, return link; } -/*! - This function can be called if getLink() returns an empty - string. - */ -QString DitaXmlGenerator::getDisambiguationLink(const Atom *, CodeMarker *) -{ - qDebug() << "Unimplemented function called: " - << "QString DitaXmlGenerator::getDisambiguationLink()"; - return QString(); -} - void DitaXmlGenerator::generateIndex(const QString& fileBase, const QString& url, const QString& title) @@ -4419,19 +4400,19 @@ void DitaXmlGenerator::generateQmlSummary(const Section& section, Outputs the DITA detailed documentation for a section on a QML element reference page. */ -void DitaXmlGenerator::generateDetailedQmlMember(const Node* node, +void DitaXmlGenerator::generateDetailedQmlMember(Node* node, const InnerNode* relative, CodeMarker* marker) { QString marked; - const QmlPropertyNode* qpn = 0; + QmlPropertyNode* qpn = 0; if (node->subType() == Node::QmlPropertyGroup) { const QmlPropGroupNode* qpgn = static_cast(node); NodeList::ConstIterator p = qpgn->childNodes().begin(); writeStartTag(DT_ul); while (p != qpgn->childNodes().end()) { if ((*p)->type() == Node::QmlProperty) { - qpn = static_cast(*p); + qpn = static_cast(*p); writeStartTag(DT_li); writeGuidAttribute((Node*)qpn); QString attr; @@ -4457,7 +4438,7 @@ void DitaXmlGenerator::generateDetailedQmlMember(const Node* node, writeEndTag(); // } else if (node->type() == Node::QmlProperty) { - qpn = static_cast(node); + qpn = static_cast(node); /* If the QML property node has a single subproperty, override, replace qpn with that override node and @@ -4466,7 +4447,7 @@ void DitaXmlGenerator::generateDetailedQmlMember(const Node* node, if (qpn->qmlPropNodes().size() == 1) { Node* n = qpn->qmlPropNodes().at(0); if (n->type() == Node::QmlProperty) - qpn = static_cast(n); + qpn = static_cast(n); } /* Now qpn either has no overrides, or it has more @@ -4600,10 +4581,9 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* If there is no class node, or if the class node status is set to Node::Internal, do nothing. */ -void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, - CodeMarker* marker) +void DitaXmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker) { - const ClassNode* cn = qcn->classNode(); + ClassNode* cn = qcn->classNode(); if (cn && (cn->status() != Node::Internal)) { writeStartTag(DT_p); xmlWriter().writeAttribute("outputclass","instantiates"); @@ -4631,8 +4611,7 @@ void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, If there is no QML element, or if the class node status is set to Node::Internal, do nothing. */ -void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn, - CodeMarker* marker) +void DitaXmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker) { if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) { const QmlClassNode* qcn = cn->qmlElement(); @@ -5628,13 +5607,13 @@ void DitaXmlGenerator::writeNestedClasses(const Section& s, Recursive writing of DITA XML files from the root \a node. */ void -DitaXmlGenerator::generateInnerNode(const InnerNode* node) +DitaXmlGenerator::generateInnerNode(InnerNode* node) { if (!node->url().isNull()) return; if (node->type() == Node::Fake) { - const FakeNode *fakeNode = static_cast(node); + FakeNode* fakeNode = static_cast(node); if (fakeNode->subType() == Node::ExternalPage) return; if (fakeNode->subType() == Node::Image) @@ -5653,27 +5632,38 @@ DitaXmlGenerator::generateInnerNode(const InnerNode* node) CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath()); if (node->parent() != 0) { - if (!node->name().endsWith(".ditamap")) - beginSubPage(node, fileName(node)); - if (node->type() == Node::Namespace || node->type() == Node::Class) { - generateClassLikeNode(node, marker); + /* + Skip name collision nodes here and process them + later in generateCollisionPages(). Each one is + appended to a list for later. + */ + if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) { + NameCollisionNode* ncn = static_cast(node); + collisionNodes.append(const_cast(ncn)); } - else if (node->type() == Node::Fake) { - if (node->subType() == Node::HeaderFile) + else { + if (!node->name().endsWith(".ditamap")) + beginSubPage(node, fileName(node)); + if (node->type() == Node::Namespace || node->type() == Node::Class) { generateClassLikeNode(node, marker); - else if (node->subType() == Node::QmlClass) - generateClassLikeNode(node, marker); - else - generateFakeNode(static_cast(node), marker); + } + else if (node->type() == Node::Fake) { + if (node->subType() == Node::HeaderFile) + generateClassLikeNode(node, marker); + else if (node->subType() == Node::QmlClass) + generateClassLikeNode(node, marker); + else + generateFakeNode(static_cast(node), marker); + } + if (!node->name().endsWith(".ditamap")) + endSubPage(); } - if (!node->name().endsWith(".ditamap")) - endSubPage(); } NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->isInnerNode() && (*c)->access() != Node::Private) - generateInnerNode((const InnerNode*) *c); + generateInnerNode((InnerNode*)*c); ++c; } } @@ -5819,8 +5809,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent) break; case Node::Variable: break; - case Node::Target: - break; case Node::QmlProperty: break; case Node::QmlSignal: @@ -5840,7 +5828,7 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent) Creates the DITA map for the qdoc run. The map is written to the file \e{qt.ditamap" in the DITA XML output directory. */ -void DitaXmlGenerator::writeDitaMap(const Tree *tree) +void DitaXmlGenerator::writeDitaMap(Tree *tree) { QString doctype; @@ -6374,5 +6362,125 @@ QString DitaXmlGenerator::stripMarkup(const QString& src) const return text; } +/*! + We delayed generation of the collision pages until now, after + all the other pages have been generated. We do this because we might + encounter a link command that tries to link to a target on a QML + type page, but the link doesn't specify the module identifer + for the QML type, and the QML type name without a module + identifier is ambiguous. When such a link is found, qdoc can't find + the target, so it appends the target to the NameCollisionNode. After + the tree has been traversed and all these ambiguous links have been + added to the name collision nodes, this function is called. The list + of collision nodes is traversed here, and the collision page for + each collision is generated. The collision page will not only + disambiguate links to the QML type pages, but it will also disambiguate + links to properties, section headers, etc. + */ +void DitaXmlGenerator::generateCollisionPages() +{ + if (collisionNodes.isEmpty()) + return; + + for (int i=0; ichildNodes(); + if (!nl.isEmpty()) { + NodeList::ConstIterator it = nl.begin(); + while (it != nl.end()) { + if (!(*it)->isInternal()) + collisions.append(*it); + ++it; + } + } + if (collisions.size() <= 1) + continue; + + ncn->clearCurrentChild(); + beginSubPage(ncn, Generator::fileName(ncn)); + QString fullTitle = ncn->fullTitle(); + QString ditaTitle = fullTitle; + CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath()); + if (ncn->isQmlNode()) { + // Replace the marker with a QML code marker. + if (ncn->isQmlNode()) + marker = CodeMarker::markerForLanguage(QLatin1String("QML")); + } + + generateHeader(ncn, ditaTitle); + writeProlog(ncn); + writeStartTag(DT_body); + enterSection(QString(),QString()); + + NodeMap nm; + for (int i=0; iqmlModuleIdentifier().isEmpty()) + t = n->qmlModuleIdentifier() + " "; + t += protectEnc(fullTitle); + nm.insertMulti(t,n); + } + generateAnnotatedList(ncn, marker, nm); + + QList targets; + if (!ncn->linkTargets().isEmpty()) { + QMap::ConstIterator t = ncn->linkTargets().begin(); + while (t != ncn->linkTargets().end()) { + int count = 0; + for (int i=0; i(collisions.at(i)); + if (n->findChildNodeByName(t.key())) { + ++count; + if (count > 1) { + targets.append(t.key()); + break; + } + } + } + ++t; + } + } + if (!targets.isEmpty()) { + QList::ConstIterator t = targets.begin(); + while (t != targets.end()) { + writeStartTag(DT_p); + writeGuidAttribute(Doc::canonicalTitle(*t)); + xmlWriter().writeAttribute("outputclass","h2"); + writeCharacters(protectEnc(*t)); + writeEndTag(); //

+ writeStartTag(DT_ul); + for (int i=0; i(collisions.at(i)); + Node* p = n->findChildNodeByName(*t); + if (p) { + QString link = linkForNode(p,0); + QString label; + if (!n->qmlModuleIdentifier().isEmpty()) + label = n->qmlModuleIdentifier() + "::"; + label += n->name() + "::" + p->name(); + writeStartTag(DT_li); + writeStartTag(DT_xref); + xmlWriter().writeAttribute("href", link); + writeCharacters(protectEnc(label)); + writeEndTag(); // + writeEndTag(); // + } + } + writeEndTag(); // + ++t; + } + } + leaveSection(); //
+ writeEndTag(); // + endSubPage(); + } +} + + QT_END_NAMESPACE diff --git a/src/tools/qdoc/ditaxmlgenerator.h b/src/tools/qdoc/ditaxmlgenerator.h index 07cd08043a3..6eea6dc0634 100644 --- a/src/tools/qdoc/ditaxmlgenerator.h +++ b/src/tools/qdoc/ditaxmlgenerator.h @@ -266,8 +266,8 @@ public: virtual void terminateGenerator(); virtual QString format(); virtual bool canHandleFormat(const QString& format); - virtual void generateTree(const Tree *tree); - virtual void generateDisambiguationPages() { } + virtual void generateTree(Tree *tree); + void generateCollisionPages(); QString protectEnc(const QString& string); static QString protect(const QString& string, const QString& encoding = "ISO-8859-1"); @@ -279,8 +279,8 @@ protected: virtual int generateAtom(const Atom* atom, const Node* relative, CodeMarker* marker); - virtual void generateClassLikeNode(const InnerNode* inner, CodeMarker* marker); - virtual void generateFakeNode(const FakeNode* fake, CodeMarker* marker); + virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); + virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker); virtual QString fileExtension(const Node* node) const; virtual QString guidForNode(const Node* node); virtual QString linkForNode(const Node* node, const Node* relative); @@ -377,12 +377,12 @@ private: const Node* relative, CodeMarker* marker, bool summary); - void generateDetailedQmlMember(const Node* node, + void generateDetailedQmlMember(Node* node, const InnerNode* relative, CodeMarker* marker); void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); - void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); - void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); + void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker); + void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker); void generateSection(const NodeList& nl, const Node* relative, @@ -421,7 +421,6 @@ private: const Node *relative, CodeMarker *marker, const Node **node); - QString getDisambiguationLink(const Atom* atom, CodeMarker* marker); virtual void generateIndex(const QString& fileBase, const QString& url, const QString& title); @@ -437,11 +436,11 @@ private: GuidMap* lookupGuidMap(const QString& fileName); virtual void beginSubPage(const InnerNode* node, const QString& fileName); virtual void endSubPage(); - virtual void generateInnerNode(const InnerNode* node); + virtual void generateInnerNode(InnerNode* node); QXmlStreamWriter& xmlWriter(); void writeApiDesc(const Node* node, CodeMarker* marker, const QString& title); void addLink(const QString& href, const QStringRef& text, DitaTag t = DT_xref); - void writeDitaMap(const Tree* tree); + void writeDitaMap(Tree* tree); void writeDitaMap(const DitaMapNode* node); void writeStartTag(DitaTag t); bool writeEndTag(DitaTag t=DT_NONE); @@ -501,7 +500,6 @@ private: QStringList vrm; QStringList stylesheets; QStringList customHeadElements; - const Tree* tree_; QMap refMap; QMap name2guidMap; GuidMaps guidMaps; diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index a2d5277c889..8cda8b7667d 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -102,7 +102,8 @@ Generator::Generator() gt(">"), lt("<"), quot("""), - tag("]*>") + tag("]*>"), + tree_(0) { generators.prepend(this); } @@ -452,11 +453,12 @@ QString Generator::fullName(const Node *node, { if (node->type() == Node::Fake) { const FakeNode* fn = static_cast(node); -#if 0 + // Removed for QTBUG-22870 + // Unremoved by mws 30/03/12 if (!fn->qmlModuleIdentifier().isEmpty()) - return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title(); -#endif + return fn->qmlModuleIdentifier() + "::" + fn->title(); + return fn->title(); } else if (node->type() == Node::Class && @@ -700,8 +702,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) } } -void Generator::generateClassLikeNode(const InnerNode * /* classe */, - CodeMarker * /* marker */) +void Generator::generateClassLikeNode(InnerNode* /* classe */, CodeMarker* /* marker */) { } @@ -713,8 +714,7 @@ void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker) generateFileList(fake, marker, Node::Image, QString("Images:")); } -void Generator::generateFakeNode(const FakeNode * /* fake */, - CodeMarker * /* marker */) +void Generator::generateFakeNode(FakeNode* /* fake */, CodeMarker* /* marker */) { } @@ -837,16 +837,16 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker) Recursive writing of HTML files from the root \a node. \note NameCollisionNodes are skipped here and processed - later. See HtmlGenerator::generateDisambiguationPages() - for more on this. + later. See HtmlGenerator::generateCollisionPages() for + more on this. */ -void Generator::generateInnerNode(const InnerNode* node) +void Generator::generateInnerNode(InnerNode* node) { if (!node->url().isNull()) return; if (node->type() == Node::Fake) { - const FakeNode *fakeNode = static_cast(node); + FakeNode* fakeNode = static_cast(node); if (fakeNode->subType() == Node::ExternalPage) return; if (fakeNode->subType() == Node::Image) @@ -867,11 +867,11 @@ void Generator::generateInnerNode(const InnerNode* node) if (node->parent() != 0) { /* Skip name collision nodes here and process them - later in generateDisambiguationPages(). Each one - is appended to a list for later. + later in generateCollisionPages(). Each one is + appended to a list for later. */ if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) { - const NameCollisionNode* ncn = static_cast(node); + NameCollisionNode* ncn = static_cast(node); collisionNodes.append(const_cast(ncn)); } else { @@ -880,7 +880,7 @@ void Generator::generateInnerNode(const InnerNode* node) generateClassLikeNode(node, marker); } else if (node->type() == Node::Fake) { - generateFakeNode(static_cast(node), marker); + generateFakeNode(static_cast(node), marker); } endSubPage(); } @@ -889,7 +889,7 @@ void Generator::generateInnerNode(const InnerNode* node) NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->isInnerNode() && (*c)->access() != Node::Private) { - generateInnerNode((const InnerNode *) *c); + generateInnerNode((InnerNode*)*c); } ++c; } @@ -1249,8 +1249,9 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker) /*! This function is recursive. */ -void Generator::generateTree(const Tree *tree) +void Generator::generateTree(Tree *tree) { + tree_ = tree; generateInnerNode(tree->root()); } @@ -1265,6 +1266,40 @@ Generator *Generator::generatorForFormat(const QString& format) return 0; } +/*! + This function can be called if getLink() returns an empty + string. It tests the \a atom string to see if it is a link + of the form :: , where is a QML + element or component without a module qualifier. If so, it + constructs a link to the clause on the disambiguation + page for and returns that link string. It also + adds the as a target in the NameCollisionNode for + . These clauses are then constructed when the + disambiguation page is actually generated. + */ +QString Generator::getCollisionLink(const Atom* atom) +{ + QString link; + if (!atom->string().contains("::")) + return link; + QStringList path = atom->string().split("::"); + NameCollisionNode* ncn = tree_->findCollisionNode(path[0]); + if (ncn) { + QString label; + if (atom->next() && atom->next()->next()) { + if (atom->next()->type() == Atom::FormattingLeft && + atom->next()->next()->type() == Atom::String) + label = atom->next()->next()->string(); + } + ncn->addLinkTarget(path[1],label); + link = fileName(ncn); + link += QLatin1Char('#'); + link += Doc::canonicalTitle(path[1]); + } + return link; +} + + /*! Looks up the tag \a t in the map of metadata values for the current topic in \a inner. If a value for the tag is found, diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h index 5676dd23a2d..c97e59602dd 100644 --- a/src/tools/qdoc/generator.h +++ b/src/tools/qdoc/generator.h @@ -85,7 +85,7 @@ public: virtual bool canHandleFormat(const QString &format) { return format == this->format(); } virtual QString format() = 0; - virtual void generateTree(const Tree *tree); + virtual void generateTree(Tree *tree); virtual void initializeGenerator(const Config &config); virtual void terminateGenerator(); @@ -109,13 +109,13 @@ protected: const Node *relative, CodeMarker *marker); virtual void generateBody(const Node *node, CodeMarker *marker); - virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); - virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); + virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); + virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker); virtual void generateInheritedBy(const ClassNode *classe, CodeMarker *marker); virtual void generateInherits(const ClassNode *classe, CodeMarker *marker); - virtual void generateInnerNode(const InnerNode *node); + virtual void generateInnerNode(InnerNode* node); virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker); virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker); virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); @@ -155,6 +155,7 @@ protected: void generateSince(const Node *node, CodeMarker *marker); void generateStatus(const Node *node, CodeMarker *marker); void generateThreadSafeness(const Node *node, CodeMarker *marker); + QString getCollisionLink(const Atom* atom); QString getMetadataElement(const InnerNode* inner, const QString& t); QStringList getMetadataElements(const InnerNode* inner, const QString& t); QString indent(int level, const QString& markedCode); @@ -230,6 +231,9 @@ private: QString lt; QString quot; QRegExp tag; + + protected: + Tree* tree_; }; QT_END_NAMESPACE diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp index 5efd6ef928f..da2a43d7e81 100644 --- a/src/tools/qdoc/helpprojectwriter.cpp +++ b/src/tools/qdoc/helpprojectwriter.cpp @@ -117,13 +117,10 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList typeHash["function"] = Node::Function; typeHash["property"] = Node::Property; typeHash["variable"] = Node::Variable; - typeHash["target"] = Node::Target; -#ifdef QDOC_QML typeHash["qmlproperty"] = Node::QmlProperty; typeHash["qmlsignal"] = Node::QmlSignal; typeHash["qmlsignalhandler"] = Node::QmlSignalHandler; typeHash["qmlmethod"] = Node::QmlMethod; -#endif QHash subTypeHash; subTypeHash["example"] = Node::Example; @@ -133,11 +130,9 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList subTypeHash["module"] = Node::Module; subTypeHash["page"] = Node::Page; subTypeHash["externalpage"] = Node::ExternalPage; -#ifdef QDOC_QML subTypeHash["qmlclass"] = Node::QmlClass; subTypeHash["qmlpropertygroup"] = Node::QmlPropertyGroup; subTypeHash["qmlbasictype"] = Node::QmlBasicType; -#endif QSet allSubTypes = QSet::fromList(subTypeHash.values()); diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index e61f0f66e7c..7203bdbdb8c 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -100,7 +100,6 @@ HtmlGenerator::HtmlGenerator() numTableRows(0), threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"), - myTree(0), obsoleteLinks(false) { } @@ -255,9 +254,9 @@ QString HtmlGenerator::format() \note The HTML file generation is done in the base class, PageGenerator::generateTree(). */ -void HtmlGenerator::generateTree(const Tree *tree) +void HtmlGenerator::generateTree(Tree *tree) { - myTree = tree; + tree_ = tree; nonCompatClasses.clear(); mainClasses.clear(); compatClasses.clear(); @@ -268,6 +267,7 @@ void HtmlGenerator::generateTree(const Tree *tree) legaleseTexts.clear(); serviceClasses.clear(); qmlClasses.clear(); + findAllClasses(tree->root()); findAllFunctions(tree->root()); findAllLegaleseTexts(tree->root()); @@ -275,13 +275,13 @@ void HtmlGenerator::generateTree(const Tree *tree) findAllSince(tree->root()); Generator::generateTree(tree); - reportOrphans(tree->root()); - generateDisambiguationPages(); + //reportOrphans(tree->root()); + generateCollisionPages(); QString fileBase = project.toLower().simplified().replace(" ", "-"); generateIndex(fileBase, projectUrl, projectDescription); - helpProjectWriter->generate(myTree); + helpProjectWriter->generate(tree_); generateManifestFiles(); } @@ -492,7 +492,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, break; case Atom::AnnotatedList: { - QList values = myTree->groups().values(atom->string()); + QList values = tree_->groups().values(atom->string()); NodeMap nodeMap; for (int i = 0; i < values.size(); ++i) { const Node* n = values.at(i); @@ -538,7 +538,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, // Add additional groups and remove groups of classes that // should be excluded from the edition. - QMultiMap groups = myTree->groups(); + QMultiMap groups = tree_->groups(); foreach (const QString &groupName, editionGroupMap[editionName]) { QList groupClasses; if (groupName.startsWith(QLatin1Char('-'))) { @@ -833,7 +833,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *node = 0; QString myLink = getLink(atom, relative, marker, &node); if (myLink.isEmpty()) { - myLink = getDisambiguationLink(atom, marker); + myLink = getCollisionLink(atom); if (myLink.isEmpty()) { relative->doc().location().warning(tr("Can't create link to '%1'") .arg(atom->string())); @@ -1160,13 +1160,12 @@ int HtmlGenerator::generateAtom(const Atom *atom, /*! Generate a reference page for a C++ class. */ -void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, - CodeMarker *marker) +void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) { QList
sections; QList
::ConstIterator s; - const ClassNode *classe = 0; + ClassNode* classe = 0; QString title; QString rawTitle; @@ -1177,7 +1176,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, title = rawTitle + " Namespace"; } else if (inner->type() == Node::Class) { - classe = static_cast(inner); + classe = static_cast(inner); rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); title = rawTitle + " Class"; @@ -1370,15 +1369,32 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, disambiguate links to the component pages, but it will also disambiguate links to properties, section headers, etc. */ -void HtmlGenerator::generateDisambiguationPages() +void HtmlGenerator::generateCollisionPages() { if (collisionNodes.isEmpty()) return; + for (int i=0; ichildNodes(); + if (!nl.isEmpty()) { + NodeList::ConstIterator it = nl.begin(); + while (it != nl.end()) { + if (!(*it)->isInternal()) + collisions.append(*it); + ++it; + } + } + if (collisions.size() <= 1) + continue; + ncn->clearCurrentChild(); beginSubPage(ncn, Generator::fileName(ncn)); - QString fullTitle = "Name Collision: " + ncn->fullTitle(); + QString fullTitle = ncn->fullTitle(); QString htmlTitle = fullTitle; CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath()); if (ncn->isQmlNode()) { @@ -1390,36 +1406,56 @@ void HtmlGenerator::generateDisambiguationPages() generateHeader(htmlTitle, ncn, marker); if (!fullTitle.isEmpty()) out() << "

" << protectEnc(fullTitle) << "

\n"; - const NodeList& nl = ncn->childNodes(); + NodeMap nm; - NodeList::ConstIterator it = nl.begin(); - while (it != nl.end()) { - QString t = (*it)->qmlModuleIdentifier() + " " + protectEnc(fullTitle); - nm.insertMulti(t,(*it)); - ++it; + for (int i=0; iqmlModuleIdentifier().isEmpty()) + t = n->qmlModuleIdentifier() + "::"; + t += protectEnc(fullTitle); + nm.insertMulti(t,n); } generateAnnotatedList(ncn, marker, nm, true); - const QMap& targets = ncn->linkTargets(); + QList targets; + if (!ncn->linkTargets().isEmpty()) { + QMap::ConstIterator t = ncn->linkTargets().begin(); + while (t != ncn->linkTargets().end()) { + int count = 0; + for (int i=0; i(collisions.at(i)); + if (n->findChildNodeByName(t.key())) { + ++count; + if (count > 1) { + targets.append(t.key()); + break; + } + } + } + ++t; + } + } if (!targets.isEmpty()) { - QMap::ConstIterator t = targets.begin(); + QList::ConstIterator t = targets.begin(); while (t != targets.end()) { - out() << ""; - out() << "

" << protectEnc(t.key()) << "

\n"; + out() << ""; + out() << "

" << protectEnc(*t) << "

\n"; out() << "
    \n"; - it = nl.begin(); - while (it != nl.end()) { - InnerNode* n = static_cast(*it); - Node* p = n->findNode(t.key()); + for (int i=0; i(collisions.at(i)); + Node* p = n->findChildNodeByName(*t); if (p) { QString link = linkForNode(p,0); - QString label = n->qmlModuleIdentifier() + "::" + n->name() + "::" + p->name(); + QString label; + if (!n->qmlModuleIdentifier().isEmpty()) + label = n->qmlModuleIdentifier() + "::"; + label += n->name() + "::" + p->name(); out() << "
  • "; out() << ""; out() << protectEnc(label) << ""; out() << "
  • \n"; } - ++it; } out() << "
\n"; ++t; @@ -1435,7 +1471,7 @@ void HtmlGenerator::generateDisambiguationPages() Generate the HTML page for an entity that doesn't map to any underlying parsable C++ class or QML component. */ -void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) +void HtmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker) { /* If the fake node is a page node, and if the page type @@ -1471,9 +1507,9 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) Generate the TOC for the new doc format. Don't generate a TOC for the home page. */ - const QmlClassNode* qml_cn = 0; + QmlClassNode* qml_cn = 0; if (fake->subType() == Node::QmlClass) { - qml_cn = static_cast(fake); + qml_cn = static_cast(fake); sections = marker->qmlSections(qml_cn,CodeMarker::Summary); generateTableOfContents(fake,marker,§ions); @@ -1537,7 +1573,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) } else if (fake->subType() == Node::QmlClass) { const_cast(fake)->setCurrentChild(); - const ClassNode* cn = qml_cn->classNode(); + ClassNode* cn = qml_cn->classNode(); generateBrief(qml_cn, marker); generateQmlInherits(qml_cn, marker); generateQmlInheritedBy(qml_cn, marker); @@ -1793,7 +1829,7 @@ void HtmlGenerator::generateHeader(const QString& title, if (node && !node->doc().location().isEmpty()) out() << "\n"; - QString shortVersion = myTree->version(); + QString shortVersion = tree_->version(); if (shortVersion.count(QChar('.')) == 2) shortVersion.truncate(shortVersion.lastIndexOf(QChar('.'))); if (!project.isEmpty()) @@ -1814,9 +1850,9 @@ void HtmlGenerator::generateHeader(const QString& title, generateMacRef(node, marker); #endif - out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); + out() << QString(postHeader).replace("\\" + COMMAND_VERSION, tree_->version()); generateBreadCrumbs(title,node,marker); - out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); + out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, tree_->version()); navigationLinks.clear(); @@ -1901,8 +1937,8 @@ void HtmlGenerator::generateFooter(const Node *node) if (node && !node->links().empty()) out() << "

\n" << navigationLinks << "

\n"; - out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version()) - << QString(address).replace("\\" + COMMAND_VERSION, myTree->version()); + out() << QString(footer).replace("\\" + COMMAND_VERSION, tree_->version()) + << QString(address).replace("\\" + COMMAND_VERSION, tree_->version()); out() << "\n"; out() << "\n"; @@ -2633,7 +2669,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m QMap uncategorizedNodeMap; QRegExp singleDigit("\\b([0-9])\\b"); - const NodeList children = myTree->root()->childNodes(); + const NodeList children = tree_->root()->childNodes(); foreach (Node *child, children) { if (child->type() == Node::Fake && child != relative) { FakeNode *fakeNode = static_cast(child); @@ -2685,15 +2721,11 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m else if (!isGroupPage) { // If we encounter a page that belongs to a group then // we add that page to the list for that group. - const FakeNode *groupNode = static_cast(myTree->root()->findNode(group, Node::Fake)); - if (groupNode) - fakeNodeMap[groupNode].insert(sortKey, fakeNode); - //else - // uncategorizedNodeMap.insert(sortKey, fakeNode); - }// else - // uncategorizedNodeMap.insert(sortKey, fakeNode); - }// else - // uncategorizedNodeMap.insert(sortKey, fakeNode); + const FakeNode* gn = tree_->findGroupNode(QStringList(group)); + if (gn) + fakeNodeMap[gn].insert(sortKey, fakeNode); + } + } } } @@ -2994,7 +3026,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { const Node* n = marker->resolveTarget(par1.toString(), - myTree, + tree_, relative); QString link = linkForNode(n, relative); addLink(link, arg, &html); @@ -3020,7 +3052,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, bool handled = false; if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { par1 = QStringRef(); - const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self); + const Node* n = marker->resolveTarget(arg.toString(), tree_, relative, self); html += QLatin1String(""); if (n && n->subType() == Node::QmlBasicType) { if (relative && relative->subType() == Node::QmlClass) @@ -3035,13 +3067,13 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, } else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { par1 = QStringRef(); - const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + const Node* n = marker->resolveTarget(arg.toString(), tree_, relative); addLink(linkForNode(n,relative), arg, &html); handled = true; } else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { par1 = QStringRef(); - const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + const Node* n = marker->resolveTarget(arg.toString(), tree_, relative); addLink(linkForNode(n,relative), arg, &html); handled = true; } @@ -3352,8 +3384,6 @@ QString HtmlGenerator::refForNode(const Node *node) case Node::Variable: ref = node->name() + "-var"; break; - case Node::Target: - return protectEnc(node->name()); } return registerRef(ref); } @@ -3699,15 +3729,15 @@ const Node *HtmlGenerator::findNodeForTarget(const QString &target, node = relative; } else if (target.endsWith(".html")) { - node = myTree->root()->findNode(target, Node::Fake); + node = tree_->root()->findChildNodeByNameAndType(target, Node::Fake); } else if (marker) { - node = marker->resolveTarget(target, myTree, relative); + node = marker->resolveTarget(target, tree_, relative); if (!node) { - node = myTree->findFakeNodeByTitle(target, relative); + node = tree_->findFakeNodeByTitle(target, relative); } if (!node && atom) { - node = myTree->findUnambiguousTarget(target, *const_cast(&atom), relative); + node = tree_->findUnambiguousTarget(target, *const_cast(&atom), relative); } } @@ -3762,15 +3792,21 @@ QString HtmlGenerator::getLink(const Atom *atom, *node = relative; } else if (first.endsWith(".html")) { - *node = myTree->root()->findNode(first, Node::Fake); + /* + This is not a recursive search. That's ok in + this case, because we are searching for a page + node, which must be a direct child of the tree + root. + */ + *node = tree_->root()->findChildNodeByNameAndType(first, Node::Fake); } else { - *node = marker->resolveTarget(first, myTree, relative); + *node = marker->resolveTarget(first, tree_, relative); if (!*node) { - *node = myTree->findFakeNodeByTitle(first, relative); + *node = tree_->findFakeNodeByTitle(first, relative); } if (!*node) { - *node = myTree->findUnambiguousTarget(first, targetAtom, relative); + *node = tree_->findUnambiguousTarget(first, targetAtom, relative); } } if (*node) { @@ -3824,7 +3860,7 @@ QString HtmlGenerator::getLink(const Atom *atom, target. */ while (!path.isEmpty()) { - targetAtom = myTree->findTarget(path.first(), *node); + targetAtom = tree_->findTarget(path.first(), *node); if (targetAtom == 0) break; path.removeFirst(); @@ -3861,44 +3897,11 @@ QString HtmlGenerator::getLink(const Atom *atom, return link; } -/*! - This function can be called if getLink() returns an empty - string. It tests the \a atom string to see if it is a link - of the form :: , where is a QML - element or component without a module qualifier. If so, it - constructs a link to the clause on the disambiguation - page for and returns that link string. It also - adds the as a target in the NameCollisionNode for - . These clauses are then constructed when the - disambiguation page is actually generated. - */ -QString HtmlGenerator::getDisambiguationLink(const Atom *atom, CodeMarker *) -{ - QString link; - if (!atom->string().contains("::")) - return link; - QStringList path = atom->string().split("::"); - NameCollisionNode* ncn = myTree->findCollisionNode(path[0]); - if (ncn) { - QString label; - if (atom->next() && atom->next()->next()) { - if (atom->next()->type() == Atom::FormattingLeft && - atom->next()->next()->type() == Atom::String) - label = atom->next()->next()->string(); - } - ncn->addLinkTarget(path[1],label); - link = fileName(ncn); - link += QLatin1Char('#'); - link += Doc::canonicalTitle(path[1]); - } - return link; -} - void HtmlGenerator::generateIndex(const QString &fileBase, const QString &url, const QString &title) { - myTree->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index", url, title); + tree_->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index", url, title); } void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) @@ -3922,12 +3925,12 @@ void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) << "We strongly advise against " << "using it in new code. See "; - const FakeNode *fakeNode = myTree->findFakeNodeByTitle("Porting To Qt 4"); + const FakeNode *fakeNode = tree_->findFakeNodeByTitle("Porting To Qt 4"); Atom *targetAtom = 0; if (fakeNode && node->type() == Node::Class) { QString oldName(node->name()); oldName.remove(QLatin1Char('3')); - targetAtom = myTree->findTarget(oldName, + targetAtom = tree_->findTarget(oldName, fakeNode); } @@ -4044,11 +4047,11 @@ void HtmlGenerator::generateQmlSummary(const Section& section, Outputs the html detailed documentation for a section on a QML element reference page. */ -void HtmlGenerator::generateDetailedQmlMember(const Node *node, +void HtmlGenerator::generateDetailedQmlMember(Node *node, const InnerNode *relative, CodeMarker *marker) { - const QmlPropertyNode* qpn = 0; + QmlPropertyNode* qpn = 0; #ifdef GENERATE_MAC_REFS generateMacRef(node, marker); #endif @@ -4061,14 +4064,14 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, out() << ""; while (p != qpgn->childNodes().end()) { if ((*p)->type() == Node::QmlProperty) { - qpn = static_cast(*p); + qpn = static_cast(*p); out() << ""; out() << "

"; out() << ""; int ro = qpn->getReadOnly(); if (ro < 0) { - if (!qpn->isWritable(myTree)) { + if (!qpn->isWritable(tree_)) { out() << "read-only"; } } @@ -4086,7 +4089,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, out() << ""; } else if (node->type() == Node::QmlProperty) { - qpn = static_cast(node); + qpn = static_cast(node); /* If the QML property node has a single subproperty, override, replace qpn with that override node and @@ -4095,7 +4098,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, if (qpn->qmlPropNodes().size() == 1) { Node* n = qpn->qmlPropNodes().at(0); if (n->type() == Node::QmlProperty) - qpn = static_cast(n); + qpn = static_cast(n); } /* Now qpn either has no overrides, or it has more @@ -4110,7 +4113,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, int ro = qpn->getReadOnly(); if (ro < 0) { const ClassNode* cn = qpn->declarativeCppNode(); - if (cn && !qpn->isWritable(myTree)) { + if (cn && !qpn->isWritable(tree_)) { out() << "read-only"; } } @@ -4142,7 +4145,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, int ro = qpn->getReadOnly(); if (ro < 0) { - if (!qpn->isWritable(myTree)) { + if (!qpn->isWritable(tree_)) { out() << "read-only"; } } @@ -4235,9 +4238,9 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* mar If there is no class node, or if the class node status is set to Node::Internal, do nothing. */ -void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker) +void HtmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker) { - const ClassNode* cn = qcn->classNode(); + ClassNode* cn = qcn->classNode(); if (cn && (cn->status() != Node::Internal)) { Text text; text << Atom::ParaLeft; @@ -4269,7 +4272,7 @@ void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* If there is no QML element, or if the class node status is set to Node::Internal, do nothing. */ -void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker) +void HtmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker) { if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) { const QmlClassNode* qcn = cn->qmlElement(); @@ -4460,9 +4463,6 @@ QString HtmlGenerator::fullDocumentLocation(const Node *node, bool subdir) case Node::Variable: anchorRef = QLatin1Char('#') + node->name() + "-var"; break; - case Node::Target: - anchorRef = QLatin1Char('#') + Doc::canonicalTitle(node->name()); - break; case Node::Fake: { /* @@ -4753,8 +4753,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent) if (!related) child->location().warning(tr("Global variable, %1, %2").arg(child->name()).arg(message)); break; - case Node::Target: - break; case Node::QmlProperty: if (!related) child->location().warning(tr("Global QML property, %1, %2").arg(child->name()).arg(message)); @@ -4863,7 +4861,7 @@ void HtmlGenerator::writeDitaRefs(const DitaRefList& ditarefs) xmlWriter().writeStartElement("topicref"); xmlWriter().writeAttribute("navtitle",t->navtitle()); if (t->href().isEmpty()) { - const FakeNode* fn = myTree->findFakeNodeByTitle(t->navtitle()); + const FakeNode* fn = tree_->findFakeNodeByTitle(t->navtitle()); if (fn) xmlWriter().writeAttribute("href",fileName(fn)); } diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h index 1ba88f83df7..403c1f0899f 100644 --- a/src/tools/qdoc/htmlgenerator.h +++ b/src/tools/qdoc/htmlgenerator.h @@ -86,8 +86,8 @@ public: virtual void initializeGenerator(const Config& config); virtual void terminateGenerator(); virtual QString format(); - virtual void generateTree(const Tree *tree); - virtual void generateDisambiguationPages(); + virtual void generateTree(Tree *tree); + void generateCollisionPages(); void generateManifestFiles(); QString protectEnc(const QString &string); @@ -101,8 +101,8 @@ protected: virtual int generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker); - virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); - virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); + virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); + virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker); virtual QString fileExtension(const Node *node) const; virtual QString refForNode(const Node *node); virtual QString linkForNode(const Node *node, const Node *relative); @@ -176,12 +176,12 @@ private: const Node *relative, CodeMarker *marker, bool summary); - void generateDetailedQmlMember(const Node *node, + void generateDetailedQmlMember(Node *node, const InnerNode *relative, CodeMarker *marker); void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); - void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker); - void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker); + void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker); + void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker); void generateSection(const NodeList& nl, const Node *relative, @@ -227,7 +227,6 @@ private: const Node *relative, CodeMarker *marker, const Node** node); - QString getDisambiguationLink(const Atom* atom, CodeMarker* marker); virtual void generateIndex(const QString &fileBase, const QString &url, const QString &title); @@ -278,7 +277,6 @@ private: QString manifestDir; QStringList stylesheets; QStringList customHeadElements; - const Tree *myTree; bool obsoleteLinks; QMap moduleClassMap; QMap moduleNamespaceMap; diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index fb4a3fe271e..703c0735549 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -237,8 +237,6 @@ QString Node::nodeTypeString(unsigned t) return "property"; case Variable: return "variable"; - case Target: - return "target"; case QmlProperty: return "QML property"; case QmlSignal: @@ -524,14 +522,14 @@ QString Node::ditaXmlHref() If it is a child of a QML class node, return a pointer to the QML class node. Otherwise, return 0; */ -const QmlClassNode* Node::qmlClassNode() const +QmlClassNode* Node::qmlClassNode() { if (isQmlNode()) { - const Node* n = this; + Node* n = this; while (n && n->subType() != Node::QmlClass) n = n->parent(); if (n && n->subType() == Node::QmlClass) - return static_cast(n); + return static_cast(n); } return 0; } @@ -543,14 +541,29 @@ const QmlClassNode* Node::qmlClassNode() const class node is a component. It will be non-null if the QML class node is a QML element. */ -const ClassNode* Node::declarativeCppNode() const +ClassNode* Node::declarativeCppNode() { - const QmlClassNode* qcn = qmlClassNode(); + QmlClassNode* qcn = qmlClassNode(); if (qcn) return qcn->classNode(); return 0; } +/*! + Returns true if the node's status is Internal, or if its + parent is a class with internal status. + */ +bool Node::isInternal() const +{ + if (status() == Internal) + return true; + if (parent() && parent()->status() == Internal) + return true; + if (relates() && relates()->status() == Internal) + return true; + return false; +} + /*! \class InnerNode */ @@ -571,7 +584,7 @@ InnerNode::~InnerNode() sure to also look in the children of its property group nodes. Return the matching node or 0. */ -Node *InnerNode::findNode(const QString& name) +Node *InnerNode::findChildNodeByName(const QString& name) { Node *node = childMap.value(name); if (node && node->subType() != QmlPropertyGroup) @@ -580,7 +593,7 @@ Node *InnerNode::findNode(const QString& name) for (int i=0; isubType() == QmlPropertyGroup) { - node = static_cast(n)->findNode(name); + node = static_cast(n)->findChildNodeByName(name); if (node) return node; } @@ -604,7 +617,7 @@ void InnerNode::findNodes(const QString& name, QList& n) for (int i=0; isubType() == QmlPropertyGroup) { - node = static_cast(node)->findNode(name); + node = static_cast(node)->findChildNodeByName(name); if (node) { n.append(node); return; @@ -628,7 +641,7 @@ void InnerNode::findNodes(const QString& name, QList& n) if (node->subType() != QmlPropertyGroup) n.append(node); else { - node = static_cast(node)->findNode(name); + node = static_cast(node)->findChildNodeByName(name); if (node) n.append(node); } @@ -644,13 +657,14 @@ void InnerNode::findNodes(const QString& name, QList& n) /*! Find the node in this node's children that has the given \a name. If this node is a QML class node, be sure to also look in the children - of its property group nodes. Return the matching node or 0. + of its property group nodes. Return the matching node or 0. This is + not a recearsive search. If \a qml is true, only match a node for which node->isQmlNode() returns true. If \a qml is false, only match a node for which node->isQmlNode() returns false. */ -Node* InnerNode::findNode(const QString& name, bool qml) +Node* InnerNode::findChildNodeByName(const QString& name, bool qml) { QList nodes = childMap.values(name); if (!nodes.isEmpty()) { @@ -668,7 +682,7 @@ Node* InnerNode::findNode(const QString& name, bool qml) for (int i=0; isubType() == QmlPropertyGroup) { - node = static_cast(node)->findNode(name); + node = static_cast(node)->findChildNodeByName(name); if (node) return node; } @@ -678,28 +692,31 @@ Node* InnerNode::findNode(const QString& name, bool qml) } /*! - Same as the other findNode(), but if the node with the - specified \a name is not of the specified \a type, return - 0. + This function is like findChildNodeByName(), but if a node + with the specified \a name is found but it is not of the + specified \a type, 0 is returned. + + This function is not recursive and therefore can't handle + collisions. If it finds a collision node named \a name, it + will return that node. But it might not find the collision + node because it looks up \a name in the child map, not the + list. */ -Node *InnerNode::findNode(const QString& name, Type type) +Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) { - if (type == Function) { + if (type == Function) return primaryFunctionMap.value(name); - } else { Node *node = childMap.value(name); - if (node && node->type() == type) { + if (node && node->type() == type) return node; - } - else { - return 0; - } } + return 0; } /*! - Find the function node in this node for the function named \a name. + Find a function node that is a child of this nose, such + that the function node has the specified \a name. */ FunctionNode *InnerNode::findFunctionNode(const QString& name) { @@ -707,12 +724,13 @@ FunctionNode *InnerNode::findFunctionNode(const QString& name) } /*! - Find the function node in this node that has the same name as \a clone. + Find the function node that is a child of this node, such + that the function has the same name and signature as the + \a clone node. */ FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) { - QMap::ConstIterator c = - primaryFunctionMap.find(clone->name()); + QMap::ConstIterator c = primaryFunctionMap.find(clone->name()); if (c != primaryFunctionMap.end()) { if (isSameSignature(clone, (FunctionNode *) *c)) { return (FunctionNode *) *c; @@ -907,10 +925,10 @@ void InnerNode::deleteChildren() /*! */ -const Node *InnerNode::findNode(const QString& name) const +const Node *InnerNode::findChildNodeByName(const QString& name) const { InnerNode *that = (InnerNode *) this; - return that->findNode(name); + return that->findChildNodeByName(name); } /*! @@ -918,22 +936,26 @@ const Node *InnerNode::findNode(const QString& name) const returns true. If \a qml is false, only match a node for which node->isQmlNode() returns false. */ -const Node* InnerNode::findNode(const QString& name, bool qml) const +const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const { InnerNode*that = (InnerNode*) this; - return that->findNode(name, qml); + return that->findChildNodeByName(name, qml); } /*! + Searches this node's children for a child named \a name + with the specified node \a type. */ -const Node *InnerNode::findNode(const QString& name, Type type) const +const Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) const { InnerNode *that = (InnerNode *) this; - return that->findNode(name, type); + return that->findChildNodeByNameAndType(name, type); } /*! - Find the function node in this node that has the given \a name. + Find a function node that is a child of this nose, such + that the function node has the specified \a name. This + function calls the non-const version of itself. */ const FunctionNode *InnerNode::findFunctionNode(const QString& name) const { @@ -942,7 +964,9 @@ const FunctionNode *InnerNode::findFunctionNode(const QString& name) const } /*! - Find the function node in this node that has the same name as \a clone. + Find the function node that is a child of this node, such + that the function has the same name and signature as the + \a clone node. This function calls the non-const version. */ const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const { @@ -1196,13 +1220,9 @@ void InnerNode::removeRelated(Node *pseudoChild) \class LeafNode */ -/*! +/*! \fn bool LeafNode::isInnerNode() const Returns false because this is a LeafNode. */ -bool LeafNode::isInnerNode() const -{ - return false; -} /*! Constructs a leaf node named \a name of the specified @@ -1339,19 +1359,19 @@ void ClassNode::fixBaseClasses() Search the child list to find the property node with the specified \a name. */ -const PropertyNode *ClassNode::findPropertyNode(const QString &name) const +PropertyNode* ClassNode::findPropertyNode(const QString& name) { - const Node *n = findNode(name, Node::Property); + Node* n = findChildNodeByNameAndType(name, Node::Property); if (n) - return static_cast(n); + return static_cast(n); - const PropertyNode *pn = 0; + PropertyNode* pn = 0; const QList &bases = baseClasses(); if (!bases.isEmpty()) { for (int i = 0; i < bases.size(); ++i) { - const ClassNode *cn = bases[i].node; + ClassNode* cn = bases[i].node; pn = cn->findPropertyNode(name); if (pn) break; @@ -1360,7 +1380,7 @@ const PropertyNode *ClassNode::findPropertyNode(const QString &name) const const QList& ignoredBases = ignoredBaseClasses(); if (!ignoredBases.isEmpty()) { for (int i = 0; i < ignoredBases.size(); ++i) { - const ClassNode *cn = ignoredBases[i].node; + ClassNode* cn = ignoredBases[i].node; pn = cn->findPropertyNode(name); if (pn) break; @@ -1376,20 +1396,20 @@ const PropertyNode *ClassNode::findPropertyNode(const QString &name) const finds one, it returns the pointer to that QML element. If it doesn't find one, it returns null. */ -const QmlClassNode* ClassNode::findQmlBaseNode() const +QmlClassNode* ClassNode::findQmlBaseNode() { - const QmlClassNode* result = 0; + QmlClassNode* result = 0; const QList& bases = baseClasses(); if (!bases.isEmpty()) { for (int i = 0; i < bases.size(); ++i) { - const ClassNode* cn = bases[i].node; + ClassNode* cn = bases[i].node; if (cn && cn->qmlElement()) { return cn->qmlElement(); } } for (int i = 0; i < bases.size(); ++i) { - const ClassNode* cn = bases[i].node; + ClassNode* cn = bases[i].node; if (cn) { result = cn->findQmlBaseNode(); if (result != 0) { @@ -1467,12 +1487,15 @@ QString FakeNode::fullTitle() const else return title(); } - else if ((nodeSubtype_ == HeaderFile) || (nodeSubtype_ == Collision)) { + else if (nodeSubtype_ == HeaderFile) { if (title().isEmpty()) return name(); else return name() + " - " + title(); } + else if (nodeSubtype_ == Collision) { + return title(); + } else { return title(); } @@ -1832,21 +1855,6 @@ QString FunctionNode::signature(bool values) const return s; } -/*! - Returns true if the node's status is Internal, or if its - parent is a class with internal status. - */ -bool FunctionNode::isInternal() const -{ - if (status() == Internal) - return true; - if (parent() && parent()->status() == Internal) - return true; - if (relates() && relates()->status() == Internal) - return true; - return false; -} - /*! Print some debugging stuff. */ @@ -1964,25 +1972,6 @@ bool PropertyNode::fromTrool(Trool troolean, bool defaultValue) } } -/*! - \class TargetNode - */ - -/*! - */ -TargetNode::TargetNode(InnerNode *parent, const QString& name) - : LeafNode(Target, parent, name) -{ -} - -/*! - Returns false because this is a TargetNode. - */ -bool TargetNode::isInnerNode() const -{ - return false; -} - bool QmlClassNode::qmlOnly = false; QMultiMap QmlClassNode::inheritedBy; QMap QmlClassNode::moduleMap; @@ -1996,7 +1985,7 @@ QMap QmlClassNode::moduleMap; */ QmlClassNode::QmlClassNode(InnerNode *parent, const QString& name, - const ClassNode* cn) + ClassNode* cn) : FakeNode(parent, name, QmlClass, Node::ApiPage), abstract(false), cnode_(cn), @@ -2132,15 +2121,15 @@ void QmlClassNode::clearCurrentChild() to output the line in the documentation that specifies the QML element that a QML element inherits. */ -void QmlClassNode::resolveInheritance(const Tree* tree) +void QmlClassNode::resolveInheritance(Tree* tree) { if (!links().empty() && links().contains(Node::InheritsLink)) { QPair linkPair; linkPair = links()[Node::InheritsLink]; QStringList strList = linkPair.first.split("::"); - const Node* n = tree->findNode(strList,Node::Fake); - if (n && (n->subType() == Node::QmlClass || n->subType() == Node::Collision)) { - base_ = static_cast(n); + Node* n = tree->findQmlClassNode(strList); + if (n) { + base_ = static_cast(n); if (base_ && base_->subType() == Node::QmlClass) { return; } @@ -2152,7 +2141,7 @@ void QmlClassNode::resolveInheritance(const Tree* tree) QString qmid = importList_.at(i).first + importList_.at(i).second; for (int j=0; jqmlModuleIdentifier()) { - base_ = static_cast(children.at(j)); + base_ = static_cast(children.at(j)); return; } } @@ -2160,7 +2149,7 @@ void QmlClassNode::resolveInheritance(const Tree* tree) QString qmid = qmlModuleIdentifier(); for (int k=0; kqmlModuleIdentifier()) { - base_ = static_cast(children.at(k)); + base_ = static_cast(children.at(k)); return; } } @@ -2169,7 +2158,7 @@ void QmlClassNode::resolveInheritance(const Tree* tree) return; } if (cnode_) { - const QmlClassNode* qcn = cnode_->findQmlBaseNode(); + QmlClassNode* qcn = cnode_->findQmlBaseNode(); if (qcn != 0) base_ = qcn; } @@ -2302,12 +2291,12 @@ bool QmlPropertyNode::fromTrool(Trool troolean, bool defaultValue) doesn't work for qmlproperty bool PropertyChanges::explicit, because the tokenizer gets confused on "explicit". */ -bool QmlPropertyNode::isWritable(const Tree* tree) const +bool QmlPropertyNode::isWritable(Tree* tree) { if (wri != Trool_Default) return fromTrool(wri, false); - const PropertyNode *pn = correspondingProperty(tree); + PropertyNode* pn = correspondingProperty(tree); if (pn) return pn->isWritable(); else { @@ -2316,16 +2305,16 @@ bool QmlPropertyNode::isWritable(const Tree* tree) const } } -const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) const +PropertyNode* QmlPropertyNode::correspondingProperty(Tree *tree) { - const PropertyNode *pn; + PropertyNode* pn; Node* n = parent(); while (n && n->subType() != Node::QmlClass) n = n->parent(); if (n) { - const QmlClassNode* qcn = static_cast(n); - const ClassNode* cn = qcn->classNode(); + QmlClassNode* qcn = static_cast(n); + ClassNode* cn = qcn->classNode(); if (cn) { QStringList dotSplit = name().split(QChar('.')); pn = cn->findPropertyNode(dotSplit[0]); @@ -2335,10 +2324,10 @@ const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) con // the property group, .. QStringList path(extractClassName(pn->qualifiedDataType())); - const Node* nn = tree->findNode(path,Class); + Node* nn = tree->findClassNode(path); if (nn) { - const ClassNode* cn = static_cast(nn); - const PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]); + ClassNode* cn = static_cast(nn); + PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]); if (pn2) return pn2; // Return the property for the QML property. else @@ -2374,7 +2363,7 @@ const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) con NameCollisionNode::NameCollisionNode(InnerNode* child) : FakeNode(child->parent(), child->name(), Collision, Node::NoPageType) { - setTitle("Name Collisions For: " + child->name()); + setTitle("Name Collision: " + child->name()); addCollision(child); current = 0; } @@ -2431,7 +2420,7 @@ bool NameCollisionNode::isQmlNode() const Find any of this collision node's children that has type \a t and subtype \a st and return a pointer to it. */ -const InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st) const +InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st) { if (current) { if (current->type() == t && current->subType() == st) @@ -2441,7 +2430,7 @@ const InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st) cons NodeList::ConstIterator i = cn.begin(); while (i != cn.end()) { if ((*i)->type() == t && (*i)->subType() == st) - return static_cast(*i); + return static_cast(*i); ++i; } return 0; @@ -2756,9 +2745,6 @@ QString Node::idForNode() const case Node::Variable: str = "var-" + name(); break; - case Node::Target: - str = name(); - break; default: qDebug() << "ERROR: A case was not handled in Node::idForNode():" << "type():" << type() << "subType():" << subType(); diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 5b1eb211134..cfd446dd895 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -83,7 +83,6 @@ public: Function, Property, Variable, - Target, QmlProperty, QmlSignal, QmlSignalHandler, @@ -177,14 +176,17 @@ public: virtual void setOutputFileName(const QString& ) { } virtual bool isInnerNode() const = 0; + virtual bool isLeaf() const { return false; } virtual bool isReimp() const { return false; } virtual bool isFunction() const { return false; } virtual bool isQmlNode() const { return false; } - virtual bool isInternal() const { return false; } virtual bool isQtQuickNode() const { return false; } virtual bool isAbstract() const { return false; } + virtual bool isQmlPropertyGroup() const { return false; } + virtual bool isCollisionNode() const { return false; } virtual void setAbstract(bool ) { } virtual QString title() const { return QString(); } + bool isInternal() const; bool isIndexNode() const { return indexNodeFlag_; } Type type() const { return nodeType_; } virtual SubType subType() const { return NoSubType; } @@ -196,6 +198,8 @@ public: QString url() const; virtual QString nameForLists() const { return name_; } virtual QString outputFileName() const { return QString(); } + virtual void addGroupMember(Node* ) { } + virtual void addQmlModuleMember(Node* ) { } Access access() const { return access_; } QString accessString() const; @@ -223,13 +227,13 @@ public: virtual QString qmlModuleVersion() const { return qmlModuleVersion_; } virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersion_; } virtual void setQmlModuleName(const QString& ); - virtual const ClassNode* classNode() const { return 0; } + virtual ClassNode* classNode() { return 0; } virtual void clearCurrentChild() { } virtual const ImportList* importList() const { return 0; } virtual void setImportList(const ImportList& ) { } virtual const Node* applyModuleIdentifier(const Node* ) const { return 0; } - const QmlClassNode* qmlClassNode() const; - const ClassNode* declarativeCppNode() const; + QmlClassNode* qmlClassNode(); + ClassNode* declarativeCppNode(); const QString& outputSubdirectory() const { return outSubDir_; } QString fullDocumentName() const; static QString cleanId(QString str); @@ -290,9 +294,9 @@ class InnerNode : public Node public: virtual ~InnerNode(); - Node* findNode(const QString& name); - Node* findNode(const QString& name, bool qml); - Node* findNode(const QString& name, Type type); + Node* findChildNodeByName(const QString& name); + Node* findChildNodeByName(const QString& name, bool qml); + Node* findChildNodeByNameAndType(const QString& name, Type type); void findNodes(const QString& name, QList& n); FunctionNode* findFunctionNode(const QString& name); FunctionNode* findFunctionNode(const FunctionNode* clone); @@ -306,9 +310,10 @@ public: void removeFromRelated(); virtual bool isInnerNode() const { return true; } - const Node* findNode(const QString& name) const; - const Node* findNode(const QString& name, bool qml) const; - const Node* findNode(const QString& name, Type type) const; + virtual bool isLeaf() const { return false; } + const Node* findChildNodeByName(const QString& name) const; + const Node* findChildNodeByName(const QString& name, bool qml) const; + const Node* findChildNodeByNameAndType(const QString& name, Type type) const; const FunctionNode* findFunctionNode(const QString& name) const; const FunctionNode* findFunctionNode(const FunctionNode* clone) const; const EnumNode* findEnumNodeForValue(const QString &enumValue) const; @@ -358,7 +363,8 @@ public: LeafNode(); virtual ~LeafNode() { } - virtual bool isInnerNode() const; + virtual bool isInnerNode() const { return false; } + virtual bool isLeaf() const { return true; } protected: LeafNode(Type type, InnerNode* parent, const QString& name); @@ -412,12 +418,12 @@ public: QString serviceName() const { return sname; } void setServiceName(const QString& value) { sname = value; } - const QmlClassNode* qmlElement() const { return qmlelement; } + QmlClassNode* qmlElement() { return qmlelement; } void setQmlElement(QmlClassNode* qcn) { qmlelement = qcn; } virtual bool isAbstract() const { return abstract; } virtual void setAbstract(bool b) { abstract = b; } - const PropertyNode* findPropertyNode(const QString& name) const; - const QmlClassNode* findQmlBaseNode() const; + PropertyNode* findPropertyNode(const QString& name); + QmlClassNode* findQmlBaseNode(); private: QList bases; @@ -441,8 +447,8 @@ public: void setTitle(const QString &title) { title_ = title; } void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; } - void addGroupMember(Node* node) { nodeList.append(node); } - void addQmlModuleMember(Node* node) { nodeList.append(node); } + virtual void addGroupMember(Node* node) { nodeList.append(node); } + virtual void addQmlModuleMember(Node* node) { nodeList.append(node); } SubType subType() const { return nodeSubtype_; } virtual QString title() const; @@ -453,6 +459,7 @@ public: const NodeList& qmlModuleMembers() const { return nodeList; } virtual QString nameForLists() const { return title(); } virtual void setImageFileName(const QString& ) { } + virtual bool isQmlPropertyGroup() const { return (nodeSubtype_ == QmlPropertyGroup); } protected: SubType nodeSubtype_; @@ -470,8 +477,9 @@ public: virtual void setCurrentChild(InnerNode* child) { current = child; } virtual void clearCurrentChild() { current = 0; } virtual bool isQmlNode() const; + virtual bool isCollisionNode() const { return true; } virtual const Node* applyModuleIdentifier(const Node* origin) const; - const InnerNode* findAny(Node::Type t, Node::SubType st) const; + InnerNode* findAny(Node::Type t, Node::SubType st); void addCollision(InnerNode* child); const QMap& linkTargets() const { return targets; } void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); } @@ -503,11 +511,11 @@ class QmlClassNode : public FakeNode public: QmlClassNode(InnerNode* parent, const QString& name, - const ClassNode* cn); + ClassNode* cn); virtual ~QmlClassNode(); virtual bool isQmlNode() const { return true; } virtual bool isQtQuickNode() const { return (qmlModuleName() == QLatin1String("QtQuick")); } - virtual const ClassNode* classNode() const { return cnode_; } + virtual ClassNode* classNode() { return cnode_; } virtual QString fileBase() const; virtual void setCurrentChild(); virtual void clearCurrentChild(); @@ -516,7 +524,7 @@ public: virtual bool isAbstract() const { return abstract; } virtual void setAbstract(bool b) { abstract = b; } const FakeNode* qmlBase() const { return base_; } - void resolveInheritance(const Tree* tree); + void resolveInheritance(Tree* tree); static void addInheritedBy(const QString& base, Node* sub); static void subclasses(const QString& base, NodeList& subs); static void terminate(); @@ -528,8 +536,8 @@ public: private: bool abstract; - const ClassNode* cnode_; - const FakeNode* base_; + ClassNode* cnode_; + FakeNode* base_; ImportList importList_; }; @@ -601,7 +609,7 @@ public: bool isDefault() const { return isdefault_; } bool isStored() const { return fromTrool(sto,true); } bool isDesignable() const { return fromTrool(des,false); } - bool isWritable(const Tree* tree) const; + bool isWritable(Tree* tree); bool isAttached() const { return attached_; } bool isReadOnly() const { return (readOnly_ > 0); } virtual bool isQmlNode() const { return true; } @@ -610,7 +618,7 @@ public: virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); } virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); } - const PropertyNode *correspondingProperty(const Tree *tree) const; + PropertyNode* correspondingProperty(Tree* tree); const QString& element() const { return static_cast(parent())->element(); } void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); } @@ -784,7 +792,6 @@ public: QString signature(bool values = false) const; const QString& element() const { return parent()->name(); } bool isAttached() const { return attached_; } - virtual bool isInternal() const; virtual bool isQmlNode() const { return ((type() == QmlSignal) || (type() == QmlMethod) || @@ -945,15 +952,6 @@ inline VariableNode::VariableNode(InnerNode* parent, const QString &name) // nothing. } -class TargetNode : public LeafNode -{ -public: - TargetNode(InnerNode* parent, const QString& name); - virtual ~TargetNode() { } - - virtual bool isInnerNode() const; -}; - class DitaMapNode : public FakeNode { public: diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index 450f2d777cc..a735f02d262 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -124,18 +124,7 @@ Tree::~Tree() delete priv; } -/*! - This function simply calls the const version of itself and - returns the result. - */ -Node* Tree::findNode(const QStringList& path, Node* relative, int findFlags, const Node* self) -{ - return const_cast(const_cast(this)->findNode(path, - relative, - findFlags, - self)); -} - +// 1 calls 2 /*! Searches the tree for a node that matches the \a path. The search begins at \a start but can move up the parent chain @@ -162,16 +151,16 @@ const Node* Tree::findNode(const QStringList& path, return n; } +// 2 is private; it is only called by 1. /*! - This code in this function was extracted from the other - version of findNode() that has the same signature without - the last bool parameter \a qml. This function is called - only by that other findNode(). It can be called a second - time if the first call returns null. If \a qml is false, - the search will only match a node that is not a QML node. - If \a qml is true, the search will only match a node that - is a QML node. - */ + This overload function was extracted from the one above that has the + same signature without the last bool parameter, \a qml. This version + is called only by that other one. It is therefore private. It can + be called a second time by that other version, if the first call + returns null. If \a qml is false, the search will only match a node + that is not a QML node. If \a qml is true, the search will only + match a node that is a QML node. +*/ const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags, @@ -204,7 +193,7 @@ const Node* Tree::findNode(const QStringList& path, if (node == 0 || !node->isInnerNode()) break; - const Node* next = static_cast(node)->findNode(path.at(i), qml); + const Node* next = static_cast(node)->findChildNodeByName(path.at(i), qml); if (!next && (findFlags & SearchEnumValues) && i == path.size()-1) next = static_cast(node)->findEnumNodeForValue(path.at(i)); @@ -212,10 +201,9 @@ const Node* Tree::findNode(const QStringList& path, if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) { NodeList baseClasses = allBaseClasses(static_cast(node)); foreach (const Node* baseClass, baseClasses) { - next = static_cast(baseClass)->findNode(path.at(i)); + next = static_cast(baseClass)->findChildNodeByName(path.at(i)); if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1) - next = static_cast(baseClass) - ->findEnumNodeForValue(path.at(i)); + next = static_cast(baseClass)->findEnumNodeForValue(path.at(i)); if (next) break; } @@ -238,45 +226,6 @@ const Node* Tree::findNode(const QStringList& path, return 0; } -/*! - Find the node with the specified \a path name of the - specified \a type. - */ -Node* Tree::findNode(const QStringList& path, - Node::Type type, - Node* relative, - int findFlags) -{ - return const_cast(const_cast(this)->findNode(path, - type, - relative, - findFlags)); -} - -/*! - This function just calls the const version of itself and returns - a pointer to the QML class node, or null. - */ -QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& element) -{ - return const_cast(const_cast(this)->findQmlClassNode(module, element)); -} - -/*! - Find the node with the specified \a path name of the - specified \a type. - */ -const Node* Tree::findNode(const QStringList& path, - Node::Type type, - const Node* relative, - int findFlags) const -{ - const Node* node = findNode(path, relative, findFlags); - if (node != 0 && node->type() == type) - return node; - return 0; -} - /*! Find the QML class node for the specified \a module and \a name identifiers. The \a module identifier may be empty. If the module @@ -286,17 +235,17 @@ const Node* Tree::findNode(const QStringList& path, child is a QML class. If the collision node does not have a child that is a QML class node, return 0. */ -const QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name) const +QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name) { if (module.isEmpty()) { - const Node* n = findNode(QStringList(name), Node::Fake); + Node* n = findQmlClassNode(QStringList(name)); if (n) { if (n->subType() == Node::QmlClass) - return static_cast(n); + return static_cast(n); else if (n->subType() == Node::Collision) { - const NameCollisionNode* ncn; - ncn = static_cast(n); - return static_cast(ncn->findAny(Node::Fake,Node::QmlClass)); + NameCollisionNode* ncn; + ncn = static_cast(n); + return static_cast(ncn->findAny(Node::Fake,Node::QmlClass)); } } return 0; @@ -397,16 +346,15 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path, if (i == path.size() - 1) next = ((InnerNode*) node)->findFunctionNode(path.at(i)); else - next = ((InnerNode*) node)->findNode(path.at(i)); + next = ((InnerNode*) node)->findChildNodeByName(path.at(i)); - if (!next && node->type() == Node::Class && - (findFlags & SearchBaseClasses)) { + if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) { NodeList baseClasses = allBaseClasses(static_cast(node)); foreach (const Node* baseClass, baseClasses) { if (i == path.size() - 1) next = static_cast(baseClass)->findFunctionNode(path.at(i)); else - next = static_cast(baseClass)->findNode(path.at(i)); + next = static_cast(baseClass)->findChildNodeByName(path.at(i)); if (next) break; @@ -474,6 +422,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, return ((InnerNode*)parent)->findFunctionNode(clone); } } +//findNode(parameter.leftType().split("::"), 0, SearchBaseClasses|NonFunction); static const int NumSuffixes = 3; static const char* const suffixes[NumSuffixes] = { "", "s", "es" }; @@ -768,17 +717,12 @@ void Tree::resolveInheritance(int pass, ClassNode* classe) QList bounds = priv->unresolvedInheritanceMap[classe]; QList::ConstIterator b = bounds.begin(); while (b != bounds.end()) { - ClassNode* baseClass = (ClassNode*)findNode((*b).basePath, - Node::Class); - if (!baseClass && (*b).parent) { - baseClass = (ClassNode*)findNode((*b).basePath, - Node::Class, - (*b).parent); + Node* n = findClassNode((*b).basePath); + if (!n && (*b).parent) { + n = findClassNode((*b).basePath, (*b).parent); } - if (baseClass) { - classe->addBaseClass((*b).access, - baseClass, - (*b).dataTypeWithTemplateArgs); + if (n) { + classe->addBaseClass((*b).access, static_cast(n), (*b).dataTypeWithTemplateArgs); } ++b; } @@ -814,11 +758,9 @@ void Tree::resolveGroups() if (i.value()->access() == Node::Private) continue; - FakeNode* fake = - static_cast(findNode(QStringList(i.key()),Node::Fake)); - if (fake && fake->subType() == Node::Group) { - fake->addGroupMember(i.value()); - } + Node* n = findGroupNode(QStringList(i.key())); + if (n) + n->addGroupMember(i.value()); } } @@ -830,11 +772,9 @@ void Tree::resolveQmlModules() { NodeMultiMap::const_iterator i; for (i = priv->qmlModuleMap.constBegin(); i != priv->qmlModuleMap.constEnd(); ++i) { - FakeNode* fake = - static_cast(findNode(QStringList(i.key()),Node::Fake)); - if (fake && fake->subType() == Node::QmlModule) { - fake->addQmlModuleMember(i.value()); - } + Node* n = findQmlModuleNode(QStringList(i.key())); + if (n) + n->addQmlModuleMember(i.value()); } } @@ -978,15 +918,13 @@ FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classe, /*! */ -void Tree::fixPropertyUsingBaseClasses(ClassNode* classe, - PropertyNode* property) +void Tree::fixPropertyUsingBaseClasses(ClassNode* classe, PropertyNode* property) { QList::const_iterator r = classe->baseClasses().begin(); while (r != classe->baseClasses().end()) { - PropertyNode* baseProperty = - static_cast(r->node->findNode(property->name(), - Node::Property)); - if (baseProperty) { + Node* n = r->node->findChildNodeByNameAndType(property->name(), Node::Property); + if (n) { + PropertyNode* baseProperty = static_cast(n); fixPropertyUsingBaseClasses(r->node, baseProperty); property->setOverriddenFrom(baseProperty); } @@ -1414,10 +1352,9 @@ void Tree::resolveIndex() foreach (pair, priv->basesList) { foreach (const QString& base, pair.second.split(QLatin1Char(','))) { - Node* baseClass = root()->findNode(base, Node::Class); - if (baseClass) { - pair.first->addBaseClass(Node::Public, - static_cast(baseClass)); + Node* n = root()->findChildNodeByNameAndType(base, Node::Class); + if (n) { + pair.first->addBaseClass(Node::Public, static_cast(n)); } } } @@ -1425,9 +1362,9 @@ void Tree::resolveIndex() QPair relatedPair; foreach (relatedPair, priv->relatedList) { - Node* classNode = root()->findNode(relatedPair.second, Node::Class); - if (classNode) - relatedPair.first->setRelates(static_cast(classNode)); + Node* n = root()->findChildNodeByNameAndType(relatedPair.second, Node::Class); + if (n) + relatedPair.first->setRelates(static_cast(n)); } } @@ -1437,8 +1374,8 @@ void Tree::resolveIndex() false. */ bool Tree::generateIndexSection(QXmlStreamWriter& writer, - const Node* node, - bool generateInternalNodes) const + Node* node, + bool generateInternalNodes) { if (!node->url().isEmpty()) return false; @@ -1473,9 +1410,6 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer, case Node::Variable: nodeName = "variable"; break; - case Node::Target: - nodeName = "target"; - break; case Node::QmlProperty: nodeName = "qmlproperty"; break; @@ -1716,7 +1650,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer, case Node::QmlProperty: { - const QmlPropertyNode* qpn = static_cast(node); + QmlPropertyNode* qpn = static_cast(node); writer.writeAttribute("type", qpn->dataType()); writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false"); writer.writeAttribute("writable", qpn->isWritable(this) ? "true" : "false"); @@ -1840,22 +1774,18 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer, foreach (const Parameter& parameter, functionNode->parameters()) { QString leftType = parameter.leftType(); - const Node* leftNode = - const_cast(this)->findNode(parameter.leftType().split("::"), - Node::Typedef, 0, SearchBaseClasses|NonFunction); - if (!leftNode) { - leftNode = const_cast(this)->findNode( - parameter.leftType().split("::"), Node::Typedef, + const Node* leftNode = const_cast(this)->findNode(parameter.leftType().split("::"), + 0, SearchBaseClasses|NonFunction); + if (!leftNode || leftNode->type() != Node::Typedef) { + leftNode = const_cast(this)->findNode(parameter.leftType().split("::"), node->parent(), SearchBaseClasses|NonFunction); } - if (leftNode) { + if (leftNode && leftNode->type() == Node::Typedef) { if (leftNode->type() == Node::Typedef) { const TypedefNode* typedefNode = static_cast(leftNode); if (typedefNode->associatedEnum()) { - leftType = "QFlags<" + - typedefNode->associatedEnum()->fullDocumentName() + - QLatin1Char('>'); + leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() + QLatin1Char('>'); } } else @@ -1973,8 +1903,8 @@ bool compareNodes(const Node* n1, const Node* n2) they will be omitted. */ void Tree::generateIndexSections(QXmlStreamWriter& writer, - const Node* node, - bool generateInternalNodes) const + Node* node, + bool generateInternalNodes) { if (generateIndexSection(writer, node, generateInternalNodes)) { @@ -1984,7 +1914,7 @@ void Tree::generateIndexSections(QXmlStreamWriter& writer, NodeList cnodes = inner->childNodes(); qSort(cnodes.begin(), cnodes.end(), compareNodes); - foreach (const Node* child, cnodes) { + foreach (Node* child, cnodes) { /* Don't generate anything for a QML property group node. It is just a place holder for a collection of QML property @@ -1993,7 +1923,7 @@ void Tree::generateIndexSections(QXmlStreamWriter& writer, */ if (child->subType() == Node::QmlPropertyGroup) { const InnerNode* pgn = static_cast(child); - foreach (const Node* c, pgn->childNodes()) { + foreach (Node* c, pgn->childNodes()) { generateIndexSections(writer, c, generateInternalNodes); } } @@ -2018,7 +1948,7 @@ void Tree::generateIndexSections(QXmlStreamWriter& writer, void Tree::generateIndex(const QString& fileName, const QString& url, const QString& title, - bool generateInternalNodes) const + bool generateInternalNodes) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) @@ -2047,8 +1977,7 @@ void Tree::generateIndex(const QString& fileName, specified, returning true if an element was written; otherwise returns false. */ -void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, - const InnerNode* inner) const +void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, const InnerNode* inner) { foreach (const Node* node, inner->childNodes()) { @@ -2068,7 +1997,6 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, case Node::Property: case Node::Function: case Node::Variable: - case Node::Target: default: continue; } @@ -2130,8 +2058,7 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, /*! */ -void Tree::generateTagFileMembers(QXmlStreamWriter& writer, - const InnerNode* inner) const +void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inner) { foreach (const Node* node, inner->childNodes()) { @@ -2164,7 +2091,6 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, nodeName = "class"; break; case Node::Variable: - case Node::Target: default: continue; } @@ -2247,18 +2173,15 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, foreach (const Parameter& parameter, functionNode->parameters()) { QString leftType = parameter.leftType(); const Node* leftNode = const_cast(this)->findNode(parameter.leftType().split("::"), - Node::Typedef, 0, SearchBaseClasses|NonFunction); - if (!leftNode) { - leftNode = const_cast(this)->findNode( - parameter.leftType().split("::"), Node::Typedef, - node->parent(), SearchBaseClasses|NonFunction); + 0, SearchBaseClasses|NonFunction); + if (!leftNode || leftNode->type() != Node::Typedef) { + leftNode = const_cast(this)->findNode(parameter.leftType().split("::"), + node->parent(), SearchBaseClasses|NonFunction); } - if (leftNode) { + if (leftNode && leftNode->type() == Node::Typedef) { const TypedefNode* typedefNode = static_cast(leftNode); if (typedefNode->associatedEnum()) { - leftType = "QFlags<" + - typedefNode->associatedEnum()->fullDocumentName() + - QLatin1Char('>'); + leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() + QLatin1Char('>'); } } signatureList.append(leftType + QLatin1Char(' ') + parameter.name()); @@ -2324,7 +2247,6 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, break; case Node::Variable: - case Node::Target: default: break; } @@ -2332,8 +2254,9 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, } /*! + Writes a tag file named \a fileName. */ -void Tree::generateTagFile(const QString& fileName) const +void Tree::generateTagFile(const QString& fileName) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) @@ -2366,4 +2289,239 @@ void Tree::addExternalLink(const QString& url, const Node* relative) fakeNode->setDoc(doc); } +/*! + Find the node with the specified \a path name that is of + the specified \a type and \a subtype. Begin the search at + the \a start node. If the \a start node is 0, begin the + search at the tree root. \a subtype is not used unless + \a type is \c{Fake}. + */ +Node* Tree::findNodeByNameAndType(const QStringList& path, + Node::Type type, + Node::SubType subtype, + Node* start, + bool acceptCollision) +{ + if (!start) + start = const_cast(root()); + Node* result = findNodeRecursive(path, 0, start, type, subtype, acceptCollision); + return result; +} + +#if 0 + if (result) + qDebug() << "FOUND:" << path << Node::nodeTypeString(type) + << Node::nodeSubtypeString(subtype); + else + qDebug() << "NOT FOUND:" << path << Node::nodeTypeString(type) + << Node::nodeSubtypeString(subtype); +#endif + +/*! + Recursive search for a node identified by \a path. Each + path element is a name. \a pathIndex specifies the index + of the name in \a path to try to match. \a start is the + node whose children shoulod be searched for one that has + that name. Each time a match is found, increment the + \a pathIndex and call this function recursively. + + If the end of the path is reached (i.e. if a matching + node is found for each name in the \a path), the \a type + must match the type of the last matching node, and if the + type is \e{Fake}, the \a subtype must match as well. + + If the algorithm is successful, the pointer to the final + node is returned. Otherwise 0 is returned. + */ +Node* Tree::findNodeRecursive(const QStringList& path, + int pathIndex, + Node* start, + Node::Type type, + Node::SubType subtype, + bool acceptCollision) +{ + if (!start || path.isEmpty()) + return 0; // no place to start, or nothing to search for. + if (start->isLeaf()) { + if (pathIndex >= path.size()) + return start; // found a match. + return 0; // premature leaf + } + if (pathIndex >= path.size()) + return 0; // end of search path. + + InnerNode* current = static_cast(start); + const NodeList& children = current->childNodes(); + const QString& name = path.at(pathIndex); + for (int i=0; iisQmlPropertyGroup()) { + if (type == Node::QmlProperty) { + n = findNodeRecursive(path, pathIndex, n, type, subtype); + if (n) + return n; + } + } + else if (n->name() == name) { + if (pathIndex+1 >= path.size()) { + if (n->type() == type) { + if (type == Node::Fake) { + if (n->subType() == subtype) + return n; + else if (n->subType() == Node::Collision && acceptCollision) + return n; + else if (subtype == Node::NoSubType) + return n; // don't care what subtype is. + return 0; + } + else + return n; + } + else if (n->isCollisionNode()) { + if (acceptCollision) + return n; + return n = findNodeRecursive(path, pathIndex, n, type, subtype); + if (n) + return n; + } + else + return 0; + } + else { // Not at the end of the path. + n = findNodeRecursive(path, pathIndex+1, n, type, subtype); + if (n) + return n; + } + } + } + return 0; +} + +/*! + Find the Enum type node named \a path. Begin the search at the + \a start node. If the \a start node is 0, begin the search + at the root of the tree. Only an Enum type node named \a path is + acceptible. If one is not found, 0 is returned. + */ +EnumNode* Tree::findEnumNode(const QStringList& path, Node* start) +{ + return static_cast(findNodeRecursive(path, 0, start, Node::Enum, Node::NoSubType)); +} + +/*! + Find the C++ class node named \a path. Begin the search at the + \a start node. If the \a start node is 0, begin the search + at the root of the tree. Only a C++ class node named \a path is + acceptible. If one is not found, 0 is returned. + */ +ClassNode* Tree::findClassNode(const QStringList& path, Node* start) +{ + return static_cast(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType)); +} + +/*! + Find the Qml class node named \a path. Begin the search at the + \a start node. If the \a start node is 0, begin the search + at the root of the tree. Only a Qml class node named \a path is + acceptible. If one is not found, 0 is returned. + */ +QmlClassNode* Tree::findQmlClassNode(const QStringList& path, Node* start) +{ + /* + If the path contains one or two double colons ("::"), + check first to see if the first two path strings refer + to a QML element. If yes, that reference identifies a + QML class node. + */ + if (path.size() >= 2) { + QmlClassNode* qcn = QmlClassNode::moduleMap.value(path[0]+ "::" +path[1]); + if (qcn) + return qcn; + } + + return static_cast(findNodeRecursive(path, 0, start, Node::Fake, Node::QmlClass)); +} + +/*! + Find the Namespace node named \a path. Begin the search at the + \a start node. If the \a start node is 0, begin the search + at the root of the tree. Only a Namespace node named \a path is + acceptible. If one is not found, 0 is returned. + */ +NamespaceNode* Tree::findNamespaceNode(const QStringList& path, Node* start) +{ + return static_cast(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType)); +} + +/*! + Find the Group node named \a path. Begin the search at the + \a start node. If the \a start node is 0, begin the search + at the root of the tree. Only a Group node named \a path is + acceptible. If one is not found, 0 is returned. + */ +FakeNode* Tree::findGroupNode(const QStringList& path, Node* start) +{ + return static_cast(findNodeRecursive(path, 0, start, Node::Fake, Node::Group)); +} + +/*! + Find the Qml module node named \a path. Begin the search at the + \a start node. If the \a start node is 0, begin the search + at the root of the tree. Only a Qml module node named \a path is + acceptible. If one is not found, 0 is returned. + */ +FakeNode* Tree::findQmlModuleNode(const QStringList& path, Node* start) +{ + return static_cast(findNodeRecursive(path, 0, start, Node::Fake, Node::QmlModule)); +} + QT_END_NAMESPACE + +#if 0 +const Node* Tree::findNodeXXX(const QStringList& path, bool qml) const +{ + const Node* current = root(); + do { + const Node* node = current; + int i; + int start_idx = 0; + + /* + If the path contains one or two double colons ("::"), + check first to see if the first two path strings refer + to a QML element. If yes, that reference identifies a + QML class node. + */ + if (qml && path.size() >= 2) { + QmlClassNode* qcn = QmlClassNode::moduleMap.value(path[0]+ "::" +path[1]); + if (qcn) { + node = qcn; + if (path.size() == 2) + return node; + start_idx = 2; + } + } + + for (i = start_idx; i < path.size(); ++i) { + if (node == 0 || !node->isInnerNode()) + break; + + const Node* next = static_cast(node)->findChildNodeByName(path.at(i), qml); + node = next; + } + if (node && i == path.size()) { + if (node->subType() != Node::QmlPropertyGroup) { + if (node->subType() == Node::Collision) { + node = node->applyModuleIdentifier(start); + } + return node; + } + } + current = current->parent(); + } while (current); + + return 0; +} +#endif diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h index d39babfab0f..62f599598ea 100644 --- a/src/tools/qdoc/tree.h +++ b/src/tools/qdoc/tree.h @@ -65,19 +65,39 @@ public: Tree(); ~Tree(); - Node* findNode(const QStringList &path, - Node* relative=0, - int findFlags=0, - const Node* self=0); - Node* findNode(const QStringList &path, - Node::Type type, - Node* relative = 0, - int findFlags = 0); + EnumNode* findEnumNode(const QStringList& path, Node* start = 0); + ClassNode* findClassNode(const QStringList& path, Node* start = 0); + QmlClassNode* findQmlClassNode(const QStringList& path, Node* start = 0); + NamespaceNode* findNamespaceNode(const QStringList& path, Node* start = 0); + FakeNode* findGroupNode(const QStringList& path, Node* start = 0); + FakeNode* findQmlModuleNode(const QStringList& path, Node* start = 0); + + Node* findNodeByNameAndType(const QStringList& path, + Node::Type type, + Node::SubType subtype, + Node* start, + bool acceptCollision = false); + + Node* findNodeRecursive(const QStringList& path, + int pathIndex, + Node* start, + Node::Type type, + Node::SubType subtype, + bool acceptCollision = false); + + const Node* findNode(const QStringList &path, + const Node* relative = 0, + int findFlags = 0, + const Node* self=0) const; + + private: const Node* findNode(const QStringList& path, const Node* start, int findFlags, const Node* self, bool qml) const; + + public: QmlClassNode* findQmlClassNode(const QString& module, const QString& name); NameCollisionNode* checkForCollision(const QString& name) const; NameCollisionNode* findCollisionNode(const QString& name) const; @@ -111,17 +131,8 @@ public: void fixInheritance(NamespaceNode *rootNode = 0); void setVersion(const QString &version) { vers = version; } NamespaceNode *root() { return &roo; } - QString version() const { return vers; } - const Node* findNode(const QStringList &path, - const Node* relative = 0, - int findFlags = 0, - const Node* self=0) const; - const Node* findNode(const QStringList &path, - Node::Type type, const - Node* relative = 0, - int findFlags = 0) const; - const QmlClassNode* findQmlClassNode(const QString& module, const QString& element) const; + const FunctionNode *findFunctionNode(const QStringList &path, const Node *relative = 0, int findFlags = 0) const; @@ -134,19 +145,17 @@ public: Atom *findTarget(const QString &target, const Node *node) const; const NamespaceNode *root() const { return &roo; } void readIndexes(const QStringList &indexFiles); - bool generateIndexSection(QXmlStreamWriter &writer, const Node *node, - bool generateInternalNodes = false) const; - void generateIndexSections(QXmlStreamWriter &writer, const Node *node, - bool generateInternalNodes = false) const; + bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); + void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); void generateIndex(const QString &fileName, const QString &url, const QString &title, - bool generateInternalNodes = false) const; + bool generateInternalNodes = false); void generateTagFileCompounds(QXmlStreamWriter &writer, - const InnerNode *inner) const; + const InnerNode *inner); void generateTagFileMembers(QXmlStreamWriter &writer, - const InnerNode *inner) const; - void generateTagFile(const QString &fileName) const; + const InnerNode *inner); + void generateTagFile(const QString &fileName); void addExternalLink(const QString &url, const Node *relative); QString fullDocumentLocation(const Node *node) const; void resolveQmlInheritance();