summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc
diff options
context:
space:
mode:
authorMartin Smith <martin.smith@digia.com>2014-01-06 12:57:17 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-31 21:04:43 +0200
commite9954e31624c77d986077ec5431c7ec4a9b058e0 (patch)
treece07acd32f8a03c07fa0f16cfc9ab186459c13fa /src/tools/qdoc
parent4f50be8d1885e685ec8df3796e4156eb015affa7 (diff)
qdoc: Teach qdoc to use multiple trees
qdoc now builds a separate Node Tree for each index file it parsed. The main Node Tree now contains only the Nodes of things being documented in the current module. This should make qdoc run a little faster. qdoc now uses these separate trees to make intra-module and inter-module linking more robust by searching the trees in an order that depends on the type of link it is searching for. The tree for the current module is always searched first. Then qdoc searches the trees for either the C++ modules or the QML modules, depending on whether it is looking for a C++ link or a QML link. In preparation for this update, qdoc was also simplified a lot. Many functions became obsolete and were removed. Others were combined. Task-number: QTBUG-35377 Change-Id: Iea4e49869ff6a6ff0f4d53090728770d40d892f3 Reviewed-by: Topi Reiniƶ <topi.reinio@digia.com>
Diffstat (limited to 'src/tools/qdoc')
-rw-r--r--src/tools/qdoc/cppcodemarker.cpp6
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp45
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp38
-rw-r--r--src/tools/qdoc/generator.cpp39
-rw-r--r--src/tools/qdoc/helpprojectwriter.cpp2
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp37
-rw-r--r--src/tools/qdoc/htmlgenerator.h3
-rw-r--r--src/tools/qdoc/main.cpp4
-rw-r--r--src/tools/qdoc/node.cpp296
-rw-r--r--src/tools/qdoc/node.h63
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp11
-rw-r--r--src/tools/qdoc/qdocdatabase.h53
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp113
-rw-r--r--src/tools/qdoc/qdoctagfiles.cpp32
-rw-r--r--src/tools/qdoc/tree.cpp566
-rw-r--r--src/tools/qdoc/tree.h73
16 files changed, 704 insertions, 677 deletions
diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp
index 64b11109f7..58fbd45453 100644
--- a/src/tools/qdoc/cppcodemarker.cpp
+++ b/src/tools/qdoc/cppcodemarker.cpp
@@ -629,7 +629,8 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
QList<RelatedClass>::ConstIterator r =
ancestorClass->baseClasses().constBegin();
while (r != ancestorClass->baseClasses().constEnd()) {
- stack.prepend((*r).node);
+ if ((*r).node_)
+ stack.prepend((*r).node_);
++r;
}
}
@@ -724,7 +725,8 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
QList<RelatedClass>::ConstIterator r =
ancestorClass->baseClasses().constBegin();
while (r != ancestorClass->baseClasses().constEnd()) {
- stack.prepend((*r).node);
+ if ((*r).node_)
+ stack.prepend((*r).node_);
++r;
}
}
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index bb403bd4d9..c22a5227a6 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -225,8 +225,6 @@ void CppCodeParser::parseSourceFile(const Location& location, const QString& fil
*/
void CppCodeParser::doneParsingHeaderFiles()
{
- qdb_->resolveInheritance();
-
QMapIterator<QString, QString> i(sequentialIteratorClasses);
while (i.hasNext()) {
i.next();
@@ -959,38 +957,12 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
}
else if (command == COMMAND_RELATES) {
- /*
- Find the node that this node relates to.
- */
- Node* n = 0;
- if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) {
- /*
- It should be a header file, I think.
- */
- n = qdb_->findNodeByNameAndType(QStringList(arg), Node::Document, Node::NoSubType);
- }
- else {
- /*
- If it wasn't a file, it should be either a class or a namespace.
- */
- QStringList newPath = arg.split("::");
- n = qdb_->findClassNode(newPath);
- if (!n)
- n = qdb_->findNamespaceNode(newPath);
- }
-
- if (!n) {
- /*
- Didn't ind it. Error...
- */
+ QStringList path = arg.split("::");
+ Node* n = qdb_->findRelatesNode(path);
+ if (!n)
doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
- }
- else {
- /*
- Found it. This node relates to it.
- */
+ else
node->setRelates(static_cast<InnerNode*>(n));
- }
}
else if (command == COMMAND_CONTENTSPAGE) {
setLink(node, Node::ContentsLink, arg);
@@ -1636,11 +1608,7 @@ bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass)
if (!matchDataType(&baseClass))
return false;
- qdb_->addBaseClass(classe,
- access,
- baseClass.toPath(),
- baseClass.toString(),
- classe->parent());
+ classe->addUnresolvedBaseClass(access, baseClass.toPath(), baseClass.toString());
return true;
}
@@ -1735,9 +1703,8 @@ bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
*/
QString namespaceName = previousLexeme();
NamespaceNode* ns = 0;
- if (parent) {
+ if (parent)
ns = static_cast<NamespaceNode*>(parent->findChildNodeByNameAndType(namespaceName, Node::Namespace));
- }
if (!ns) {
ns = new NamespaceNode(parent, namespaceName);
ns->setAccess(access);
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index e3b9bdd264..c4f08e45df 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -2696,8 +2696,8 @@ void DitaXmlGenerator::generateClassHierarchy(const Node* relative, NodeMap& cla
NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.access != Node::Private && !d.node->doc().isEmpty())
- newTop.insert(d.node->name(), d.node);
+ if (d.node_ && d.access_ != Node::Private && !d.node_->doc().isEmpty())
+ newTop.insert(d.node_->name(), d.node_);
}
if (!newTop.isEmpty()) {
stack.push(newTop);
@@ -3858,7 +3858,7 @@ QString DitaXmlGenerator::getLink(const Atom* atom, const Node* relative, const
*node = relative;
}
else if (first.endsWith(".html")) {
- *node = qdb_->treeRoot()->findChildNodeByNameAndType(first, Node::Document);
+ *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document, Node::NoSubType);
}
else {
*node = qdb_->resolveTarget(first, relative);
@@ -4365,25 +4365,27 @@ void DitaXmlGenerator::writeDerivations(const ClassNode* cn)
writeStartTag(DT_cxxClassDerivations);
r = cn->baseClasses().constBegin();
while (r != cn->baseClasses().constEnd()) {
- writeStartTag(DT_cxxClassDerivation);
- writeStartTag(DT_cxxClassDerivationAccessSpecifier);
- xmlWriter().writeAttribute("value",(*r).accessString());
- writeEndTag(); // </cxxClassDerivationAccessSpecifier>
+ ClassNode* bcn = (*r).node_;
+ if (bcn) {
+ writeStartTag(DT_cxxClassDerivation);
+ writeStartTag(DT_cxxClassDerivationAccessSpecifier);
+ xmlWriter().writeAttribute("value",(*r).accessString());
+ writeEndTag(); // </cxxClassDerivationAccessSpecifier>
- // not included: <cxxClassDerivationVirtual>
+ // not included: <cxxClassDerivationVirtual>
- writeStartTag(DT_cxxClassBaseClass);
- QString attr = fileName((*r).node) + QLatin1Char('#') + (*r).node->guid();
- xmlWriter().writeAttribute("href",attr);
- writeCharacters((*r).node->plainFullName());
- writeEndTag(); // </cxxClassBaseClass>
+ writeStartTag(DT_cxxClassBaseClass);
+ QString attr = fileName(bcn) + QLatin1Char('#') + bcn->guid();
+ xmlWriter().writeAttribute("href",attr);
+ writeCharacters(bcn->plainFullName());
+ writeEndTag(); // </cxxClassBaseClass>
- // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
+ // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
- writeEndTag(); // </cxxClassDerivation>
-
- // not included: <cxxStructDerivation>
+ writeEndTag(); // </cxxClassDerivation>
+ // not included: <cxxStructDerivation>
+ }
++r;
}
writeEndTag(); // </cxxClassDerivations>
@@ -4623,7 +4625,7 @@ void DitaXmlGenerator::replaceTypesWithLinks(const Node* n, const InnerNode* par
}
i += 2;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
- const Node* tn = qdb_->resolveTarget(arg.toString(), parent, n);
+ const Node* tn = qdb_->resolveTarget(arg.toString(), parent);
if (tn) {
//Do not generate a link from a C++ function to a QML Basic Type (such as int)
if (n->type() == Node::Function && tn->subType() == Node::QmlBasicType)
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 9b82e80927..d563546192 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -189,19 +189,20 @@ void Generator::appendFullNames(Text& text, const NodeList& nodes, const Node* r
}
}
-void Generator::appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes)
+void Generator::appendSortedNames(Text& text, const ClassNode* cn, const QList<RelatedClass>& rc)
{
QList<RelatedClass>::ConstIterator r;
QMap<QString,Text> classMap;
int index = 0;
- r = classes.constBegin();
- while (r != classes.constEnd()) {
- if ((*r).node->access() == Node::Public &&
- (*r).node->status() != Node::Internal
- && !(*r).node->doc().isEmpty()) {
+ r = rc.constBegin();
+ while (r != rc.constEnd()) {
+ ClassNode* rcn = (*r).node_;
+ if (rcn && rcn->access() == Node::Public &&
+ rcn->status() != Node::Internal &&
+ !rcn->doc().isEmpty()) {
Text className;
- appendFullName(className, (*r).node, classe);
+ appendFullName(className, rcn, cn);
classMap[className.toString().toLower()] = className;
}
++r;
@@ -936,18 +937,20 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
r = classe->baseClasses().constBegin();
index = 0;
while (r != classe->baseClasses().constEnd()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
+ if ((*r).node_) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node_))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).signature_)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access_ == Node::Protected) {
+ text << " (protected)";
+ }
+ else if ((*r).access_ == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
}
- text << separator(index++, classe->baseClasses().count());
++r;
}
text << Atom::ParaRight;
diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp
index d46f887518..2057bcd3bc 100644
--- a/src/tools/qdoc/helpprojectwriter.cpp
+++ b/src/tools/qdoc/helpprojectwriter.cpp
@@ -655,7 +655,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
writer.writeStartElement("section");
const Node* node = qdb_->findDocNodeByTitle(project.indexTitle);
if (node == 0)
- node = qdb_->findNode(QStringList("index.html"));
+ node = qdb_->findNodeByNameAndType(QStringList("index.html"), Node::Document, Node::Page);
QString indexPath;
// Never use a collision node as a landing page
if (node && !node->isCollisionNode())
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 641e59f018..ca52d98596 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -1923,18 +1923,20 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker)
r = classe->baseClasses().constBegin();
index = 0;
while (r != classe->baseClasses().constEnd()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
+ if ((*r).node_) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node_))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).signature_)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access_ == Node::Protected) {
+ text << " (protected)";
+ }
+ else if ((*r).access_ == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
}
- text << separator(index++, classe->baseClasses().count());
++r;
}
text << Atom::ParaRight;
@@ -2448,8 +2450,8 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap& classM
NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.access != Node::Private && !d.node->doc().isEmpty())
- newTop.insert(d.node->name(), d.node);
+ if (d.node_ && (d.access_ != Node::Private && !d.node_->doc().isEmpty()))
+ newTop.insert(d.node_->name(), d.node_);
}
if (!newTop.isEmpty()) {
stack.push(newTop);
@@ -2786,7 +2788,7 @@ void HtmlGenerator::generateQmlItem(const Node *node,
marked.remove("<@type>");
marked.remove("</@type>");
}
- out() << highlightedCode(marked, relative, false, node);
+ out() << highlightedCode(marked, relative, false);
}
void HtmlGenerator::generateOverviewList(const Node *relative)
@@ -3099,8 +3101,7 @@ void HtmlGenerator::generateSynopsis(const Node *node,
QString HtmlGenerator::highlightedCode(const QString& markedCode,
const Node* relative,
- bool alignNames,
- const Node* self)
+ bool alignNames)
{
QString src = markedCode;
QString html;
@@ -3174,7 +3175,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
bool handled = false;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = qdb_->resolveTarget(arg.toString(), relative, self);
+ const Node* n = qdb_->resolveTarget(arg.toString(), relative);
html += QLatin1String("<span class=\"type\">");
if (n && n->subType() == Node::QmlBasicType) {
if (relative && relative->subType() == Node::QmlClass)
@@ -3751,7 +3752,7 @@ QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, const Nod
node, which must be a direct child of the tree
root.
*/
- *node = qdb_->treeRoot()->findChildNodeByNameAndType(first, Node::Document);
+ *node = qdb_->findNodeByNameAndType(QStringList(first), Node::Document, Node::NoSubType);
}
else {
*node = qdb_->resolveTarget(first, relative);
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index ae16f3c54f..476bd58452 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -200,8 +200,7 @@ private:
void generateSectionInheritedList(const Section& section, const Node *relative);
QString highlightedCode(const QString& markedCode,
const Node* relative,
- bool alignNames = false,
- const Node* self = 0);
+ bool alignNames = false);
void generateFullName(const Node *apparentNode, const Node *relative, const Node *actualNode = 0);
void generateDetailedMember(const Node *node,
diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp
index 398d188464..a5da6b3edd 100644
--- a/src/tools/qdoc/main.cpp
+++ b/src/tools/qdoc/main.cpp
@@ -296,7 +296,7 @@ static void processQdocconfFile(const QString &fileName)
currentDir = QFileInfo(fileName).path();
Location::initialize(config);
config.load(fileName);
-
+ //qDebug() << "\nSTART PROJECT:" << config.getString(CONFIG_PROJECT).toLower();
/*
Add the defines to the configuration variables.
*/
@@ -472,6 +472,8 @@ static void processQdocconfFile(const QString &fileName)
codeParser->doneParsingHeaderFiles();
usedParsers.clear();
+ qdb->resolveInheritance();
+
/*
Parse each source text file in the set using the appropriate parser and
add it to the big tree.
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index c88ebfc760..6399616725 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -143,6 +143,31 @@ QString Node::fullName(const Node* relative) const
}
/*!
+ Try to match this node's type and subtype with one of the
+ pairs in \a types. If a match is found, return true. If no
+ match is found, return false.
+
+ \a types is a list of type/subtype pairs, where the first
+ value in the pair is a Node::Type, and the second value is
+ a Node::SubType. The second value is used in the match if
+ this node's type is Node::Document.
+ */
+bool Node::match(const NodeTypeList& types) const
+{
+ for (int i=0; i<types.size(); ++i) {
+ if (type() == types.at(i).first) {
+ if (type() == Node::Document) {
+ if (subType() == types.at(i).second)
+ return true;
+ }
+ else
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
Sets this Node's Doc to \a doc. If \a replace is false and
this Node already has a Doc, a warning is reported that the
Doc is being overridden, and it reports where the previous
@@ -515,7 +540,7 @@ QString Node::extractClassName(const QString &string) const
*/
QString RelatedClass::accessString() const
{
- switch (access) {
+ switch (access_) {
case Node::Protected:
return "protected";
case Node::Private:
@@ -739,15 +764,15 @@ void InnerNode::getMemberClasses(NodeMap& out)
sure to also look in the children of its property
group nodes. Return the matching node or 0.
*/
-Node *InnerNode::findChildNodeByName(const QString& name)
+Node *InnerNode::findChildNodeByName(const QString& name) const
{
Node *node = childMap.value(name);
- if (node && node->type() != QmlPropertyGroup)
+ if (node && !node->isQmlPropertyGroup())
return node;
- if ((type() == Document) && (subType() == QmlClass)) {
+ if (isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
Node* n = children_.at(i);
- if (n->type() == QmlPropertyGroup) {
+ if (n->isQmlPropertyGroup()) {
node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
if (node)
return node;
@@ -756,6 +781,9 @@ Node *InnerNode::findChildNodeByName(const QString& name)
}
return primaryFunctionMap.value(name);
}
+
+/*!
+ */
void InnerNode::findNodes(const QString& name, QList<Node*>& n)
{
n.clear();
@@ -763,15 +791,15 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
QList<Node*> nodes = childMap.values(name);
/*
<sigh> If this node's child map contains no nodes named
- name, then if this node is a QML class, seach each of its
+ name, then if this node is a QML class, search each of its
property group nodes for a node named name. If a match is
found, append it to the output list and return immediately.
*/
if (nodes.isEmpty()) {
- if ((type() == Document) && (subType() == QmlClass)) {
+ if (isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
+ if (node->isQmlPropertyGroup()) {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) {
n.append(node);
@@ -793,7 +821,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
*/
for (int i=0; i<nodes.size(); ++i) {
node = nodes.at(i);
- if (node->type() != QmlPropertyGroup)
+ if (!node->isQmlPropertyGroup())
n.append(node);
else {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
@@ -819,7 +847,7 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
returns \c true. If \a qml is false, only match a node for which
node->isQmlNode() returns \c false.
*/
-Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
+Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
{
QList<Node*> nodes = childMap.values(name);
if (!nodes.isEmpty()) {
@@ -829,14 +857,14 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
if (!node->isQmlNode())
return node;
}
- else if (node->isQmlNode() && (node->type() != QmlPropertyGroup))
+ else if (node->isQmlNode() && !node->isQmlPropertyGroup())
return node;
}
}
- if (qml && (type() == Document) && (subType() == QmlClass)) {
+ if (qml && isQmlType()) {
for (int i=0; i<children_.size(); ++i) {
Node* node = children_.at(i);
- if (node->type() == QmlPropertyGroup) {
+ if (node->isQmlPropertyGroup()) {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node)
return node;
@@ -876,7 +904,7 @@ Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
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)
+FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{
return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
}
@@ -1092,64 +1120,17 @@ bool Node::isWrapper() const
}
/*!
- */
-const Node *InnerNode::findChildNodeByName(const QString& name) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByName(name);
-}
-
-/*!
- If \a qml is true, only match a node for which node->isQmlNode()
- returns \c true. If \a qml is false, only match a node for which
- node->isQmlNode() returns \c false.
- */
-const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
-{
- InnerNode*that = (InnerNode*) this;
- 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::findChildNodeByNameAndType(const QString& name, Type type) const
-{
- InnerNode *that = (InnerNode *) this;
- return that->findChildNodeByNameAndType(name, type);
-}
-
-/*!
- 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
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(name);
-}
-
-/*!
- 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
-{
- InnerNode *that = (InnerNode *) this;
- return that->findFunctionNode(clone);
-}
-
-/*!
+ Finds the enum type node that has \a enumValue as one of
+ its enum values and returns a pointer to it. Returns 0 if
+ no enum type node is found that has \a enumValue as one
+ of its values.
*/
const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
{
foreach (const Node *node, enumChildren_) {
- const EnumNode *enume = static_cast<const EnumNode *>(node);
- if (enume->hasItem(enumValue))
- return enume;
+ const EnumNode *en = static_cast<const EnumNode *>(node);
+ if (en->hasItem(enumValue))
+ return en;
}
return 0;
}
@@ -1381,7 +1362,7 @@ QmlPropertyNode* InnerNode::hasQmlProperty(const QString& n) const
if (child->name() == n)
return static_cast<QmlPropertyNode*>(child);
}
- else if (child->type() == Node::QmlPropertyGroup) {
+ else if (child->isQmlPropertyGroup()) {
QmlPropertyNode* t = child->hasQmlProperty(n);
if (t)
return t;
@@ -1480,13 +1461,27 @@ ClassNode::ClassNode(InnerNode *parent, const QString& name)
}
/*!
+ Adds the base class \a node to this class's list of base
+ classes. The base class has the specified \a access. This
+ is a resolved base class.
*/
-void ClassNode::addBaseClass(Access access,
- ClassNode *node,
- const QString &dataTypeWithTemplateArgs)
+void ClassNode::addResolvedBaseClass(Access access, ClassNode* node)
{
- bases.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
- node->derived.append(RelatedClass(access, this));
+ bases_.append(RelatedClass(access, node));
+ node->derived_.append(RelatedClass(access, this));
+}
+
+/*!
+ Add an unresolved base class to this class node's list of
+ base classes. The unresolved base class will be resolved
+ before the generate phase of qdoc. In an unresolved base
+ class, the pointer to the base class node is 0.
+ */
+void ClassNode::addUnresolvedBaseClass(Access access,
+ const QStringList& path,
+ const QString& signature)
+{
+ bases_.append(RelatedClass(access, path, signature));
}
/*!
@@ -1498,15 +1493,15 @@ void ClassNode::fixBaseClasses()
QSet<ClassNode *> found;
// Remove private and duplicate base classes.
- while (i < bases.size()) {
- ClassNode* bc = bases.at(i).node;
- if (bc->access() == Node::Private || found.contains(bc)) {
- RelatedClass rc = bases.at(i);
- bases.removeAt(i);
- ignoredBases.append(rc);
+ while (i < bases_.size()) {
+ ClassNode* bc = bases_.at(i).node_;
+ if (bc && (bc->access() == Node::Private || found.contains(bc))) {
+ RelatedClass rc = bases_.at(i);
+ bases_.removeAt(i);
+ ignoredBases_.append(rc);
const QList<RelatedClass> &bb = bc->baseClasses();
for (int j = bb.size() - 1; j >= 0; --j)
- bases.insert(i, bb.at(j));
+ bases_.insert(i, bb.at(j));
}
else {
++i;
@@ -1515,13 +1510,13 @@ void ClassNode::fixBaseClasses()
}
i = 0;
- while (i < derived.size()) {
- ClassNode* dc = derived.at(i).node;
- if (dc->access() == Node::Private) {
- derived.removeAt(i);
+ while (i < derived_.size()) {
+ ClassNode* dc = derived_.at(i).node_;
+ if (dc && dc->access() == Node::Private) {
+ derived_.removeAt(i);
const QList<RelatedClass> &dd = dc->derivedClasses();
for (int j = dd.size() - 1; j >= 0; --j)
- derived.insert(i, dd.at(j));
+ derived_.insert(i, dd.at(j));
}
else {
++i;
@@ -1530,6 +1525,28 @@ void ClassNode::fixBaseClasses()
}
/*!
+ Not sure why this is needed.
+ */
+void ClassNode::fixPropertyUsingBaseClasses(PropertyNode* pn)
+{
+ QList<RelatedClass>::const_iterator bc = baseClasses().constBegin();
+ while (bc != baseClasses().constEnd()) {
+ ClassNode* cn = bc->node_;
+ if (cn) {
+ Node* n = cn->findChildNodeByNameAndType(pn->name(), Node::Property);
+ if (n) {
+ PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
+ cn->fixPropertyUsingBaseClasses(baseProperty);
+ pn->setOverriddenFrom(baseProperty);
+ }
+ else
+ cn->fixPropertyUsingBaseClasses(pn);
+ }
+ ++bc;
+ }
+}
+
+/*!
Search the child list to find the property node with the
specified \a name.
*/
@@ -1545,19 +1562,23 @@ PropertyNode* ClassNode::findPropertyNode(const QString& name)
const QList<RelatedClass> &bases = baseClasses();
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- ClassNode* cn = bases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = bases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
if (!ignoredBases.isEmpty()) {
for (int i = 0; i < ignoredBases.size(); ++i) {
- ClassNode* cn = ignoredBases[i].node;
- pn = cn->findPropertyNode(name);
- if (pn)
- break;
+ ClassNode* cn = ignoredBases[i].node_;
+ if (cn) {
+ pn = cn->findPropertyNode(name);
+ if (pn)
+ break;
+ }
}
}
@@ -1577,13 +1598,13 @@ QmlClassNode* ClassNode::findQmlBaseNode()
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- 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) {
- ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node_;
if (cn) {
result = cn->findQmlBaseNode();
if (result != 0) {
@@ -2354,7 +2375,7 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
if (qcn) {
if (qcn->cppClassRequired()) {
if (qcn->classNode()) {
- PropertyNode* pn = correspondingProperty(qdb);
+ PropertyNode* pn = findCorrespondingCppProperty(qdb);
if (pn)
return pn->isWritable();
else
@@ -2377,10 +2398,9 @@ bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
Returns a pointer this QML property's corresponding C++
property, if it has one.
*/
-PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
+PropertyNode* QmlPropertyNode::findCorrespondingCppProperty(QDocDatabase* qdb)
{
PropertyNode* pn;
-
Node* n = parent();
while (n && n->subType() != Node::QmlClass)
n = n->parent();
@@ -2388,35 +2408,40 @@ PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
QmlClassNode* qcn = static_cast<QmlClassNode*>(n);
ClassNode* cn = qcn->classNode();
if (cn) {
+ /*
+ If there is a dot in the property name, first
+ find the C++ property corresponding to the QML
+ property group.
+ */
QStringList dotSplit = name().split(QChar('.'));
pn = cn->findPropertyNode(dotSplit[0]);
if (pn) {
+ /*
+ Now find the C++ property corresponding to
+ the QML property in the QML property group,
+ <group>.<property>.
+ */
if (dotSplit.size() > 1) {
- // Find the C++ property corresponding to the QML property in
- // the property group, <group>.<property>.
-
QStringList path(extractClassName(pn->qualifiedDataType()));
Node* nn = qdb->findClassNode(path);
if (nn) {
ClassNode* cn = static_cast<ClassNode*>(nn);
PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
- if (pn2)
- return pn2; // Return the property for the QML property.
- else
- return pn; // Return the property for the QML group.
+ /*
+ If found, return the C++ property
+ corresponding to the QML property.
+ Otherwise, return the C++ property
+ corresponding to the QML property
+ group.
+ */
+ return (pn2 ? pn2 : pn);
}
}
else
return pn;
}
- else {
- pn = cn->findPropertyNode(dotSplit[0]);
- if (pn)
- return pn;
- }
}
}
-
return 0;
}
@@ -2520,7 +2545,7 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
- if ((*i)->type() == Node::Document && (*i)->subType() == Node::QmlClass) {
+ if ((*i)->isQmlType()) {
if (origin->qmlModuleName() == (*i)->qmlModuleName())
return (*i);
}
@@ -2531,6 +2556,49 @@ const Node* NameCollisionNode::applyModuleName(const Node* origin) const
}
/*!
+ First, find all the colliding nodes that have the correct
+ type \a t and subtype \a st. If there is only one node
+ having the correct type and subtype, return that one.
+ If there is more than one node having the correct type
+ and subtype, then, in that subset, if there is only one
+ non-index node, return that one. If there are multiple
+ non-index nodes, return this collision node because we
+ can't disambiguate. Otherwise, if there are multiple
+ nodes having the correct type and subtype, return this
+ collision node because, again, we can't disambiguate.
+ But if there are no nodes at all that have the correct
+ type and subtype, return 0.
+ */
+Node* NameCollisionNode::disambiguate(Type t, SubType st)
+{
+ NodeList nl;
+ const NodeList& cn = childNodes();
+ NodeList::ConstIterator i = cn.constBegin();
+ while (i != cn.constEnd()) {
+ if ((*i)->type() == t) {
+ if ((st == NoSubType) || ((*i)->subType() == st))
+ nl.append((*i));
+ }
+ ++i;
+ }
+ Node* n = 0;
+ if (!nl.isEmpty()) {
+ i = nl.constBegin();
+ if (nl.size() == 1)
+ return (*i);
+ while (i != nl.constEnd()) {
+ if (!(*i)->isIndexNode()) {
+ if (n)
+ return this;
+ n = (*i);
+ }
+ ++i;
+ }
+ }
+ return n;
+}
+
+/*!
Construct the full document name for this node and return it.
*/
QString Node::fullDocumentName() const
@@ -2539,7 +2607,7 @@ QString Node::fullDocumentName() const
const Node* n = this;
do {
- if (!n->name().isEmpty() && n->type() != Node::QmlPropertyGroup)
+ if (!n->name().isEmpty() && !n->isQmlPropertyGroup())
pieces.insert(0, n->name());
if (n->type() == Node::Document) {
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 236b495bd0..ea21e9dcd9 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -68,6 +68,9 @@ typedef QMap<QString, Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
+typedef QPair<int, int> NodeTypePair;
+typedef QList<NodeTypePair> NodeTypeList;
+
class Node
{
Q_DECLARE_TR_FUNCTIONS(QDoc::Node)
@@ -228,10 +231,12 @@ public:
virtual bool isInternal() const;
virtual void setDataType(const QString& ) { }
virtual void setReadOnly(bool ) { }
+ virtual Node* disambiguate(Type , SubType ) { return this; }
bool isIndexNode() const { return indexNodeFlag_; }
bool wasSeen() const { return seen_; }
Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; }
+ bool match(const NodeTypeList& types) const;
InnerNode* parent() const { return parent_; }
InnerNode* relates() const { return relatesTo_; }
const QString& name() const { return name_; }
@@ -334,11 +339,11 @@ class InnerNode : public Node
public:
virtual ~InnerNode();
- Node* findChildNodeByName(const QString& name);
- Node* findChildNodeByName(const QString& name, bool qml);
+ Node* findChildNodeByName(const QString& name) const;
+ Node* findChildNodeByName(const QString& name, bool qml) const;
Node* findChildNodeByNameAndType(const QString& name, Type type);
void findNodes(const QString& name, QList<Node*>& n);
- FunctionNode* findFunctionNode(const QString& name);
+ FunctionNode* findFunctionNode(const QString& name) const;
FunctionNode* findFunctionNode(const FunctionNode* clone);
void addInclude(const QString &include);
void setIncludes(const QStringList &includes);
@@ -351,11 +356,6 @@ public:
virtual bool isInnerNode() const { return true; }
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;
const NodeList & childNodes() const { return children_; }
const NodeList & relatedNodes() const { return related_; }
@@ -437,17 +437,18 @@ class ClassNode;
struct RelatedClass
{
RelatedClass() { }
- RelatedClass(Node::Access access0,
- ClassNode* node0,
- const QString& dataTypeWithTemplateArgs0 = QString())
- : access(access0),
- node(node0),
- dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0) { }
+ // constructor for resolved base class
+ RelatedClass(Node::Access access, ClassNode* node)
+ : access_(access), node_(node) { }
+ // constructor for unresolved base class
+ RelatedClass(Node::Access access, const QStringList& path, const QString& signature)
+ : access_(access), node_(0), path_(path), signature_(signature) { }
QString accessString() const;
- Node::Access access;
- ClassNode* node;
- QString dataTypeWithTemplateArgs;
+ Node::Access access_;
+ ClassNode* node_;
+ QStringList path_;
+ QString signature_;
};
class PropertyNode;
@@ -463,14 +464,18 @@ public:
virtual void setObsoleteLink(const QString& t) { obsoleteLink_ = t; }
virtual void setWrapper() { wrapper_ = true; }
- void addBaseClass(Access access,
- ClassNode* node,
- const QString &dataTypeWithTemplateArgs = QString());
+ void addResolvedBaseClass(Access access, ClassNode* node);
+ void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature);
void fixBaseClasses();
+ void fixPropertyUsingBaseClasses(PropertyNode* pn);
+
+ QList<RelatedClass>& baseClasses() { return bases_; }
+ QList<RelatedClass>& derivedClasses() { return derived_; }
+ QList<RelatedClass>& ignoredBaseClasses() { return ignoredBases_; }
- const QList<RelatedClass> &baseClasses() const { return bases; }
- const QList<RelatedClass> &derivedClasses() const { return derived; }
- const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases; }
+ const QList<RelatedClass> &baseClasses() const { return bases_; }
+ const QList<RelatedClass> &derivedClasses() const { return derived_; }
+ const QList<RelatedClass> &ignoredBaseClasses() const { return ignoredBases_; }
QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; }
@@ -482,9 +487,9 @@ public:
QmlClassNode* findQmlBaseNode();
private:
- QList<RelatedClass> bases;
- QList<RelatedClass> derived;
- QList<RelatedClass> ignoredBases;
+ QList<RelatedClass> bases_;
+ QList<RelatedClass> derived_;
+ QList<RelatedClass> ignoredBases_;
bool abstract_;
bool wrapper_;
QString sname;
@@ -558,6 +563,7 @@ public:
virtual bool isQmlNode() const;
virtual bool isCollisionNode() const { return true; }
virtual const Node* applyModuleName(const Node* origin) const;
+ virtual Node* disambiguate(Type t, SubType st);
InnerNode* findAny(Node::Type t, Node::SubType st);
void addCollision(InnerNode* child);
const QMap<QString,QString>& linkTargets() const { return targets; }
@@ -723,10 +729,11 @@ public:
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
- PropertyNode* correspondingProperty(QDocDatabase* qdb);
-
const QString& element() const { return static_cast<QmlPropertyGroupNode*>(parent())->element(); }
+ private:
+ PropertyNode* findCorrespondingCppProperty(QDocDatabase* qdb);
+
private:
QString type_;
FlagValue stored_;
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index 1011a3ac97..bbcb92c30d 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -751,9 +751,7 @@ void QDocDatabase::resolveIssues() {
Searches the \a database for a node named \a target and returns
a pointer to it if found.
*/
-const Node* QDocDatabase::resolveTarget(const QString& target,
- const Node* relative,
- const Node* self)
+const Node* QDocDatabase::resolveTarget(const QString& target, const Node* relative)
{
const Node* node = 0;
if (target.endsWith("()")) {
@@ -776,7 +774,7 @@ const Node* QDocDatabase::resolveTarget(const QString& target,
else {
QStringList path = target.split("::");
int flags = SearchBaseClasses | SearchEnumValues | NonFunction;
- node = tree_->findNode(path, relative, flags, self);
+ node = tree_->findNode(path, relative, flags);
}
return node;
}
@@ -790,8 +788,9 @@ const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* r
const Node* node = 0;
if (target.isEmpty())
node = relative;
- else if (target.endsWith(".html"))
- node = tree_->root()->findChildNodeByNameAndType(target, Node::Document);
+ else if (target.endsWith(".html")) {
+ node = findNodeByNameAndType(QStringList(target), Node::Document, Node::NoSubType);
+ }
else {
node = resolveTarget(target, relative);
if (!node)
diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h
index 4decba5f79..4e50396817 100644
--- a/src/tools/qdoc/qdocdatabase.h
+++ b/src/tools/qdoc/qdocdatabase.h
@@ -134,10 +134,6 @@ class QDocDatabase
const NodeMap& getQmlTypeMap(const QString& key) const;
const NodeMultiMap& getSinceMap(const QString& key) const;
- const Node* resolveTarget(const QString& target, const Node* relative, const Node* self=0);
- const Node* findNodeForTarget(const QString& target, const Node* relative);
- void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
-
/* convenience functions
Many of these will be either eliminated or replaced.
*/
@@ -150,35 +146,44 @@ class QDocDatabase
void fixInheritance() { tree_->fixInheritance(); }
void resolveProperties() { tree_->resolveProperties(); }
- const Node* findNode(const QStringList& path) { return tree_->findNode(path); }
- ClassNode* findClassNode(const QStringList& path) { return tree_->findClassNode(path); }
- NamespaceNode* findNamespaceNode(const QStringList& path) { return tree_->findNamespaceNode(path); }
-
- NameCollisionNode* findCollisionNode(const QString& name) const {
- return tree_->findCollisionNode(name);
- }
-
- const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) const;
- const Node *findUnambiguousTarget(const QString &target, QString& ref, const Node* relative);
+ /*******************************************************************
+ The functions declared below don't search in the tree(s).
+ ********************************************************************/
QString findTarget(const QString &target, const Node *node) const;
void resolveTargets(InnerNode* root);
+ void insertTarget(const QString& name, TargetRec::Type type, Node* node, int priority);
+ /*******************************************************************/
+ /*******************************************************************
+ The functions declared below are called for the current tree only.
+ ********************************************************************/
FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone) {
return tree_->findFunctionNode(parentPath, clone);
}
+ FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
+ Node* findNodeInOpenNamespace(QStringList& path, Node::Type type, Node::SubType subtype);
+ NameCollisionNode* findCollisionNode(const QString& name) const {
+ return tree_->findCollisionNode(name);
+ }
+ /*******************************************************************/
+
+ /*******************************************************************
+ The functions declared below are called for all trees.
+ ********************************************************************/
+ ClassNode* findClassNode(const QStringList& path) { return tree_->findClassNode(path); }
+ InnerNode* findRelatesNode(const QStringList& path) { return tree_->findRelatesNode(path); }
+ const Node* resolveTarget(const QString& target, const Node* relative);
+ const Node* findNodeForTarget(const QString& target, const Node* relative);
+ const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) const;
+ const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative);
Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype){
return tree_->findNodeByNameAndType(path, type, subtype, 0);
}
NameCollisionNode* checkForCollision(const QString& name) const {
return tree_->checkForCollision(name);
}
- void addBaseClass(ClassNode* subclass,
- Node::Access access,
- const QStringList& basePath,
- const QString& dataTypeWithTemplateArgs,
- InnerNode* parent) {
- tree_->addBaseClass(subclass, access, basePath, dataTypeWithTemplateArgs, parent);
- }
+ /*******************************************************************/
+
void addPropertyFunction(PropertyNode* property,
const QString& funcName,
PropertyNode::FunctionRole funcRole) {
@@ -198,8 +203,6 @@ class QDocDatabase
void clearOpenNamespaces() { openNamespaces_.clear(); }
void insertOpenNamespace(const QString& path) { openNamespaces_.insert(path); }
- FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
- Node* findNodeInOpenNamespace(QStringList& path, Node::Type type, Node::SubType subtype);
void setShowInternal(bool value) { showInternal_ = value; }
/* debugging functions */
@@ -210,10 +213,6 @@ class QDocDatabase
friend class QDocIndexFiles;
friend class QDocTagFiles;
- const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
- return tree_->findNode(path, relative, findFlags);
- }
-
private:
QDocDatabase();
QDocDatabase(QDocDatabase const& ) { }; // copy constructor is private
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 47e302dad6..55e580427f 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -109,8 +109,10 @@ void QDocIndexFiles::readIndexes(const QStringList& indexFiles)
foreach (const QString& indexFile, indexFiles) {
QString msg = "Loading index file: " + indexFile;
Location::logToStdErr(msg);
+ //qDebug() << "READING INDEX:" << indexFile;
readIndexFile(indexFile);
}
+ //qDebug() << "DONE READING INDEX FILES";
}
/*!
@@ -189,9 +191,11 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
else if (element.nodeName() == "class") {
node = new ClassNode(parent, name);
- basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node),
- element.attribute("bases")));
-
+ if (element.hasAttribute("bases")) {
+ QString bases = element.attribute("bases");
+ if (!bases.isEmpty())
+ basesList_.append(QPair<ClassNode*,QString>(static_cast<ClassNode*>(node), bases));
+ }
if (!indexUrl.isEmpty())
location = Location(indexUrl + QLatin1Char('/') + name.toLower() + ".html");
else if (!indexUrl.isNull())
@@ -383,31 +387,33 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
else if (element.nodeName() == "function") {
FunctionNode::Virtualness virt;
- if (element.attribute("virtual") == "non")
+ QString t = element.attribute("virtual");
+ if (t == "non")
virt = FunctionNode::NonVirtual;
- else if (element.attribute("virtual") == "impure")
+ else if (t == "impure")
virt = FunctionNode::ImpureVirtual;
- else if (element.attribute("virtual") == "pure")
+ else if (t == "pure")
virt = FunctionNode::PureVirtual;
else
return;
+ t = element.attribute("meta");
FunctionNode::Metaness meta;
- if (element.attribute("meta") == "plain")
+ if (t == "plain")
meta = FunctionNode::Plain;
- else if (element.attribute("meta") == "signal")
+ else if (t == "signal")
meta = FunctionNode::Signal;
- else if (element.attribute("meta") == "slot")
+ else if (t == "slot")
meta = FunctionNode::Slot;
- else if (element.attribute("meta") == "constructor")
+ else if (t == "constructor")
meta = FunctionNode::Ctor;
- else if (element.attribute("meta") == "destructor")
+ else if (t == "destructor")
meta = FunctionNode::Dtor;
- else if (element.attribute("meta") == "macro")
+ else if (t == "macro")
meta = FunctionNode::MacroWithParams;
- else if (element.attribute("meta") == "macrowithparams")
+ else if (t == "macrowithparams")
meta = FunctionNode::MacroWithParams;
- else if (element.attribute("meta") == "macrowithoutparams")
+ else if (t == "macrowithoutparams")
meta = FunctionNode::MacroWithoutParams;
else
return;
@@ -426,6 +432,10 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QPair<FunctionNode*,QString>(functionNode,
element.attribute("relates")));
}
+ /*
+ Note: The "signature" attribute was written to the
+ index file, but it is not read back in. Is that ok?
+ */
QDomElement child = element.firstChildElement("parameter");
while (!child.isNull()) {
@@ -534,10 +544,12 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
if (dn) {
dn->addMember(node);
}
+#if 0
else {
qDebug() << "NODE:" << node->name() << "GROUPS:" << groupNames;
qDebug() << "DID NOT FIND GROUP:" << dn->name() << "for:" << node->name();
}
+#endif
}
}
@@ -584,22 +596,37 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
}
/*!
+ This function tries to resolve class inheritance immediately
+ after the index file is read. It is not always possible to
+ resolve a class inheritance at this point, because the base
+ class might be in an index file that hasn't been read yet, or
+ it might be in one of the header files that will be read for
+ the current module. These cases will be resolved after all
+ the index files and header and source files have been read,
+ just prior to beginning the generate phase for the current
+ module.
+
+ I don't think this is completely correct because it always
+ sets the access to public.
*/
void QDocIndexFiles::resolveIndex()
{
QPair<ClassNode*,QString> pair;
foreach (pair, basesList_) {
foreach (const QString& base, pair.second.split(QLatin1Char(','))) {
- Node* n = qdb_->treeRoot()->findChildNodeByNameAndType(base, Node::Class);
- if (n) {
- pair.first->addBaseClass(Node::Public, static_cast<ClassNode*>(n));
- }
+ QStringList basePath = base.split(QString("::"));
+ Node* n = qdb_->findNodeByNameAndType(basePath, Node::Class, Node::NoSubType);
+ if (n)
+ pair.first->addResolvedBaseClass(Node::Public, static_cast<ClassNode*>(n));
+ else
+ pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString());
}
}
QPair<FunctionNode*,QString> relatedPair;
foreach (relatedPair, relatedList_) {
- Node* n = qdb_->treeRoot()->findChildNodeByNameAndType(relatedPair.second, Node::Class);
+ QStringList path = relatedPair.second.split("::");
+ Node* n = qdb_->findRelatesNode(path);
if (n)
relatedPair.first->setRelates(static_cast<ClassNode*>(n));
}
@@ -856,10 +883,12 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QList<RelatedClass> bases = classNode->baseClasses();
QSet<QString> baseStrings;
foreach (const RelatedClass& related, bases) {
- ClassNode* baseClassNode = related.node;
- baseStrings.insert(baseClassNode->name());
+ ClassNode* n = related.node_;
+ if (n)
+ baseStrings.insert(n->fullName());
}
- writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
+ if (!baseStrings.isEmpty())
+ writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
if (!node->moduleName().isEmpty())
writer.writeAttribute("module", node->moduleName());
writeMembersAttribute(writer, classNode, Node::Document, Node::Group, "groups");
@@ -995,8 +1024,9 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("overload", functionNode->isOverload()?"true":"false");
if (functionNode->isOverload())
writer.writeAttribute("overload-number", QString::number(functionNode->overloadNumber()));
- if (functionNode->relates())
+ if (functionNode->relates()) {
writer.writeAttribute("relates", functionNode->relates()->name());
+ }
const PropertyNode* propertyNode = functionNode->associatedProperty();
if (propertyNode)
writer.writeAttribute("associated-property", propertyNode->name());
@@ -1127,36 +1157,11 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
}
else if (node->type() == Node::Function) {
const FunctionNode* functionNode = static_cast<const FunctionNode*>(node);
- // Write a signature attribute for convenience.
- QStringList signatureList;
- QStringList resolvedParameters;
- foreach (const Parameter& parameter, functionNode->parameters()) {
- QString leftType = parameter.leftType();
- const Node* leftNode = qdb_->findNode(parameter.leftType().split("::"),
- 0,
- SearchBaseClasses|NonFunction);
- if (!leftNode || leftNode->type() != Node::Typedef) {
- leftNode = qdb_->findNode(parameter.leftType().split("::"),
- node->parent(),
- SearchBaseClasses|NonFunction);
- }
- if (leftNode && leftNode->type() == Node::Typedef) {
- if (leftNode->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
- if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
- }
- }
- else
- leftType = leftNode->fullDocumentName();
- }
- resolvedParameters.append(leftType);
- signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
- }
-
- QString signature = functionNode->name() + QLatin1Char('(') + signatureList.join(", ") +
- QLatin1Char(')');
+ /*
+ Note: The "signature" attribute is written to the
+ index file, but it is not read back in. Is that ok?
+ */
+ QString signature = functionNode->signature();
if (functionNode->isConst())
signature += " const";
writer.writeAttribute("signature", signature);
@@ -1164,7 +1169,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
for (int i = 0; i < functionNode->parameters().size(); ++i) {
Parameter parameter = functionNode->parameters()[i];
writer.writeStartElement("parameter");
- writer.writeAttribute("left", resolvedParameters[i]);
+ writer.writeAttribute("left", parameter.leftType());
writer.writeAttribute("right", parameter.rightType());
writer.writeAttribute("name", parameter.name());
writer.writeAttribute("default", parameter.defaultValue());
diff --git a/src/tools/qdoc/qdoctagfiles.cpp b/src/tools/qdoc/qdoctagfiles.cpp
index a0054ea229..23c10c01b5 100644
--- a/src/tools/qdoc/qdoctagfiles.cpp
+++ b/src/tools/qdoc/qdoctagfiles.cpp
@@ -162,8 +162,9 @@ void QDocTagFiles::generateTagFileCompounds(QXmlStreamWriter& writer, const Inne
const ClassNode* classNode = static_cast<const ClassNode*>(node);
QList<RelatedClass> bases = classNode->baseClasses();
foreach (const RelatedClass& related, bases) {
- ClassNode* baseClassNode = related.node;
- writer.writeTextElement("base", baseClassNode->name());
+ ClassNode* n = related.node_;
+ if (n)
+ writer.writeTextElement("base", n->name());
}
// Recurse to write all members.
@@ -294,31 +295,8 @@ void QDocTagFiles::generateTagFileMembers(QXmlStreamWriter& writer, const InnerN
QStringList pieces = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()).split(QLatin1Char('#'));
writer.writeTextElement("anchorfile", pieces[0]);
writer.writeTextElement("anchor", pieces[1]);
-
- // Write a signature attribute for convenience.
- QStringList signatureList;
-
- foreach (const Parameter& parameter, functionNode->parameters()) {
- QString leftType = parameter.leftType();
- const Node* leftNode = qdb_->findNode(parameter.leftType().split("::"),
- 0,
- SearchBaseClasses|NonFunction);
- if (!leftNode || leftNode->type() != Node::Typedef) {
- leftNode = qdb_->findNode(parameter.leftType().split("::"),
- node->parent(),
- SearchBaseClasses|NonFunction);
- }
- if (leftNode && leftNode->type() == Node::Typedef) {
- const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
- if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
- }
- }
- signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
- }
-
- QString signature = QLatin1Char('(')+signatureList.join(", ")+QLatin1Char(')');
+ QString signature = functionNode->signature();
+ signature = signature.mid(signature.indexOf(QChar('('))).trimmed();
if (functionNode->isConst())
signature += " const";
if (functionNode->virtualness() == FunctionNode::PureVirtual)
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index 113220059c..98ac64246e 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -49,6 +49,8 @@
#include <limits.h>
#include <qdebug.h>
+bool Tree::debug_ = false;
+
QT_BEGIN_NAMESPACE
/*!
@@ -79,113 +81,59 @@ Tree::~Tree()
{
}
-// 1 calls 2
+/* API members */
+
/*!
- Searches the tree for a node that matches the \a path. The
- search begins at \a start but can move up the parent chain
- recursively if no match is found.
+ 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.
*/
-const Node* Tree::findNode(const QStringList& path,
- const Node* start,
- int findFlags,
- const Node* self) const
+ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
{
- const Node* current = start;
- if (!current)
- current = root();
-
- /*
- First, search for a node assuming we don't want a QML node.
- If that search fails, search again assuming we do want a
- QML node.
- */
- const Node* n = findNode(path,current,findFlags,self,false);
- if (!n) {
- n = findNode(path,current,findFlags,self,true);
- }
- return n;
+ if (!start)
+ start = const_cast<NamespaceNode*>(root());
+ return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
}
-// 2 is private; it is only called by 1.
/*!
- 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,
- const Node* self,
- bool qml) const
+ Find the Namespace node named \a path. 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) const
{
- const Node* current = start;
- 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 they do, path[0] will be the QML
- module identifier, and path[1] will be the QML type.
- If the anser is yes, the reference identifies a QML
- class node.
- */
- if (qml && path.size() >= 2 && !path[0].isEmpty()) {
- QmlClassNode* qcn = qdb_->findQmlType(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<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
- if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
- next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+ Node* start = const_cast<NamespaceNode*>(root());
+ return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
+}
- if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
- NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
- foreach (const Node* baseClass, baseClasses) {
- next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
- if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
- next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
- if (next)
- break;
- }
- }
- node = next;
- }
- if (node && i == path.size()
- && (!(findFlags & NonFunction) || node->type() != Node::Function
- || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
- if ((node != self) && (node->type() != Node::QmlPropertyGroup)) {
- if (node->subType() == Node::Collision) {
- node = node->applyModuleName(start);
- }
- return node;
- }
- }
- current = current->parent();
- } while (current);
+/*!
+ This function first ignores the \a clone node and searches
+ for the parent node with \a parentPath. If that search is
+ successful, it searches for a child node of the parent that
+ matches the \a clone node. If it finds a node that is just
+ like the \a clone, it returns a pointer to the found node.
- return 0;
+ There should be a way to avoid creating the clone in the
+ first place. Investigate when time allows.
+ */
+FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const FunctionNode* clone)
+{
+ const Node* parent = findNamespaceNode(parentPath);
+ if (parent == 0)
+ parent = findClassNode(parentPath, 0);
+ if (parent == 0)
+ parent = findNode(parentPath);
+ if (parent == 0 || !parent->isInnerNode())
+ return 0;
+ return ((InnerNode*)parent)->findFunctionNode(clone);
}
+
/*!
Find the Qml 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 a Qml type node named \a path is
+ at the root of the tree. Only a Qml type node named <\a path is
acceptible. If one is not found, 0 is returned.
*/
QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
@@ -248,18 +196,6 @@ NameCollisionNode* Tree::findCollisionNode(const QString& name) const
}
/*!
- This function just calls the const version of the same function
- and returns the function node.
- */
-FunctionNode* Tree::findFunctionNode(const QStringList& path,
- Node* relative,
- int findFlags)
-{
- return const_cast<FunctionNode*>
- (const_cast<const Tree*>(this)->findFunctionNode(path,relative,findFlags));
-}
-
-/*!
This function begins searching the tree at \a relative for
the \l {FunctionNode} {function node} identified by \a path.
The \a findFlags are used to restrict the search. If a node
@@ -339,57 +275,34 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
return 0;
}
-/*!
- This function just calls the const version of itself and
- returns the result.
- */
-FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
- const FunctionNode* clone,
- Node* relative,
- int findFlags)
+static NodeTypeList t;
+static const NodeTypeList& relatesTypes()
{
- return const_cast<FunctionNode*>(
- const_cast<const Tree*>(this)->findFunctionNode(parentPath,
- clone,
- relative,
- findFlags));
+ if (t.isEmpty()) {
+ t.reserve(3);
+ t.append(NodeTypePair(Node::Class, Node::NoSubType));
+ t.append(NodeTypePair(Node::Namespace, Node::NoSubType));
+ t.append(NodeTypePair(Node::Document, Node::HeaderFile));
+ }
+ return t;
}
/*!
- This function first ignores the \a clone node and searches
- for the node having the \a parentPath by calling the main
- findFunction(\a {parentPath}, \a {relative}, \a {findFlags}).
- If that search is successful, then it searches for the \a clone
- in the found parent node.
- */
-const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
- const FunctionNode* clone,
- const Node* relative,
- int findFlags) const
-{
- const Node* parent = findNamespaceNode(parentPath);
- if (parent == 0)
- parent = findClassNode(parentPath, 0);
- if (parent == 0)
- parent = findNode(parentPath, relative, findFlags);
- if (parent == 0 || !parent->isInnerNode())
- return 0;
- return ((InnerNode*)parent)->findFunctionNode(clone);
-}
+ This function searches for the node specified by \a path.
+ The matching node can be one of several different types
+ including a C++ class, a C++ namespace, or a C++ header
+ file.
-/*!
+ I'm not sure if it can be a QML type, but if that is a
+ possibility, the code can easily accommodate it.
+
+ If a matching node is found, a pointer to it is returned.
+ Otherwise 0 is returned.
*/
-void Tree::addBaseClass(ClassNode* subclass, Node::Access access,
- const QStringList& basePath,
- const QString& dataTypeWithTemplateArgs,
- InnerNode* parent)
+InnerNode* Tree::findRelatesNode(const QStringList& path)
{
- unresolvedInheritanceMap[subclass].append(
- InheritanceBound(access,
- basePath,
- dataTypeWithTemplateArgs,
- parent)
- );
+ Node* n = findNodeRecursive(path, 0, root(), relatesTypes());
+ return ((n && n->isInnerNode()) ? static_cast<InnerNode*>(n) : 0);
}
/*!
@@ -402,24 +315,25 @@ void Tree::addPropertyFunction(PropertyNode* property,
}
/*!
- This function resolves inheritance and reimplementation settings
- for each C++ class node found in the namspace beginning at \a rootNode.
- If it finds another namespace node in the child list of \a rootNode,
- it calls itself recursively. For each child of \a rootNode that is a
- class node, it calls the other resolveInheritance() function.
+ This function resolves C++ inheritance and reimplementation
+ settings for each C++ class node found in the tree beginning
+ at \a n. It also calls itself recursively for each C++ class
+ node or namespace node it encounters. For each child of \a n
+ that is a class node, it calls resolveInheritanceHelper().
This function does not resolve QML inheritance.
*/
-void Tree::resolveInheritance(NamespaceNode* rootNode)
+void Tree::resolveInheritance(InnerNode* n)
{
- if (!rootNode)
- rootNode = root();
+ if (!n)
+ n = root();
for (int pass = 0; pass < 2; pass++) {
- NodeList::ConstIterator c = rootNode->childNodes().constBegin();
- while (c != rootNode->childNodes().constEnd()) {
+ NodeList::ConstIterator c = n->childNodes().constBegin();
+ while (c != n->childNodes().constEnd()) {
if ((*c)->type() == Node::Class) {
- resolveInheritance(pass, (ClassNode*)* c);
+ resolveInheritanceHelper(pass, (ClassNode*)*c);
+ resolveInheritance((ClassNode*)*c);
}
else if ((*c)->type() == Node::Namespace) {
NamespaceNode* ns = static_cast<NamespaceNode*>(*c);
@@ -427,8 +341,67 @@ void Tree::resolveInheritance(NamespaceNode* rootNode)
}
++c;
}
- if (rootNode == root())
- unresolvedInheritanceMap.clear();
+ }
+}
+
+/*!
+ This function is run twice for eachclass node \a cn in the
+ tree. First it is run with \a pass set to 0 for each
+ class node \a cn. Then it is run with \a pass set to 1 for
+ eachclass node \a cn.
+
+ In \a pass 0, all the base classes ofclass node \a cn are
+ found and added to the base class list forclass node \a cn.
+
+ In \a pass 1, each child ofclass node \a cn that is a function
+ that is reimplemented from one of the base classes is marked
+ as being reimplemented from that class.
+
+ Some property node fixing up is also done in \a pass 1.
+ */
+void Tree::resolveInheritanceHelper(int pass, ClassNode* cn)
+{
+ if (pass == 0) {
+ QList<RelatedClass>& bases = cn->baseClasses();
+ QList<RelatedClass>::iterator b = bases.begin();
+ while (b != bases.end()) {
+ if (!(*b).node_) {
+ InnerNode* parent = cn->parent();
+ Node* n = findClassNode((*b).path_);
+ /*
+ If the node for the base class was not found,
+ the reason might be that the subclass is in a
+ namespace and the base class is in the same
+ namespace, but the base class name was not
+ qualified with the namespace name. That is the
+ case most of the time. Then restart the search
+ at the parent of the subclass node (the namespace
+ node) using the unqualified base class name.
+ */
+ if (!n)
+ n = findClassNode((*b).path_, parent);
+ if (n)
+ (*b).node_ = static_cast<ClassNode*>(n);
+ }
+ ++b;
+ }
+ }
+ else {
+ NodeList::ConstIterator c = cn->childNodes().constBegin();
+ while (c != cn->childNodes().constEnd()) {
+ if ((*c)->type() == Node::Function) {
+ FunctionNode* func = (FunctionNode*)* c;
+ FunctionNode* from = findVirtualFunctionInBaseClasses(cn, func);
+ if (from != 0) {
+ if (func->virtualness() == FunctionNode::NonVirtual)
+ func->setVirtualness(FunctionNode::ImpureVirtual);
+ func->setReimplementedFrom(from);
+ }
+ }
+ else if ((*c)->type() == Node::Property)
+ cn->fixPropertyUsingBaseClasses(static_cast<PropertyNode*>(*c));
+ ++c;
+ }
}
}
@@ -486,57 +459,6 @@ void Tree::resolveProperties()
}
/*!
- This function is run twice for each \a classNode in the
- tree. First it is run with \a pass set to 0 for each
- \a classNode. Then it is run with \a pass set to 1 for
- each \a classNode.
-
- In \a pass 0, all the base classes of \a classNode are
- found and added to the base class list for \a classNode.
-
- In \a pass 1, each child of \a classNode that is a function
- that is reimplemented from one of the base classes is marked
- as being reimplemented from that class.
-
- Some property node fixing up is also done in \a pass 1.
- */
-void Tree::resolveInheritance(int pass, ClassNode* classNode)
-{
- if (pass == 0) {
- QList<InheritanceBound> bounds = unresolvedInheritanceMap[classNode];
- QList<InheritanceBound>::ConstIterator b = bounds.constBegin();
- while (b != bounds.constEnd()) {
- Node* n = findClassNode((*b).basePath);
- if (!n && (*b).parent) {
- n = findClassNode((*b).basePath, (*b).parent);
- }
- if (n) {
- classNode->addBaseClass((*b).access, static_cast<ClassNode*>(n), (*b).dataTypeWithTemplateArgs);
- }
- ++b;
- }
- }
- else {
- NodeList::ConstIterator c = classNode->childNodes().constBegin();
- while (c != classNode->childNodes().constEnd()) {
- if ((*c)->type() == Node::Function) {
- FunctionNode* func = (FunctionNode*)* c;
- FunctionNode* from = findVirtualFunctionInBaseClasses(classNode, func);
- if (from != 0) {
- if (func->virtualness() == FunctionNode::NonVirtual)
- func->setVirtualness(FunctionNode::ImpureVirtual);
- func->setReimplementedFrom(from);
- }
- }
- else if ((*c)->type() == Node::Property) {
- fixPropertyUsingBaseClasses(classNode, static_cast<PropertyNode*>(*c));
- }
- ++c;
- }
- }
-}
-
-/*!
For each QML class node that points to a C++ class node,
follow its C++ class node pointer and set the C++ class
node's QML class node pointer back to the QML class node.
@@ -575,16 +497,18 @@ void Tree::fixInheritance(NamespaceNode* rootNode)
/*!
*/
-FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classNode,
- FunctionNode* clone)
+FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* cn, FunctionNode* clone)
{
- QList<RelatedClass>::ConstIterator r = classNode->baseClasses().constBegin();
- while (r != classNode->baseClasses().constEnd()) {
+ const QList<RelatedClass>& rc = cn->baseClasses();
+ QList<RelatedClass>::ConstIterator r = rc.constBegin();
+ while (r != rc.constEnd()) {
FunctionNode* func;
- if (((func = findVirtualFunctionInBaseClasses((*r).node, clone)) != 0 ||
- (func = (*r).node->findFunctionNode(clone)) != 0)) {
- if (func->virtualness() != FunctionNode::NonVirtual)
- return func;
+ if ((*r).node_) {
+ if (((func = findVirtualFunctionInBaseClasses((*r).node_, clone)) != 0 ||
+ (func = (*r).node_->findFunctionNode(clone)) != 0)) {
+ if (func->virtualness() != FunctionNode::NonVirtual)
+ return func;
+ }
}
++r;
}
@@ -593,31 +517,14 @@ FunctionNode* Tree::findVirtualFunctionInBaseClasses(ClassNode* classNode,
/*!
*/
-void Tree::fixPropertyUsingBaseClasses(ClassNode* classNode, PropertyNode* property)
-{
- QList<RelatedClass>::const_iterator r = classNode->baseClasses().constBegin();
- while (r != classNode->baseClasses().constEnd()) {
- Node* n = r->node->findChildNodeByNameAndType(property->name(), Node::Property);
- if (n) {
- PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
- fixPropertyUsingBaseClasses(r->node, baseProperty);
- property->setOverriddenFrom(baseProperty);
- }
- else {
- fixPropertyUsingBaseClasses(r->node, property);
- }
- ++r;
- }
-}
-
-/*!
- */
NodeList Tree::allBaseClasses(const ClassNode* classNode) const
{
NodeList result;
foreach (const RelatedClass& r, classNode->baseClasses()) {
- result += r.node;
- result += allBaseClasses(r.node);
+ if (r.node_) {
+ result += r.node_;
+ result += allBaseClasses(r.node_);
+ }
}
return result;
}
@@ -641,6 +548,8 @@ Node* Tree::findNodeByNameAndType(const QStringList& path,
return result;
}
+/* internal members */
+
/*!
Recursive search for a node identified by \a path. Each
path element is a name. \a pathIndex specifies the index
@@ -694,24 +603,27 @@ Node* Tree::findNodeRecursive(const QStringList& path,
if (type == Node::Document) {
if (n->subType() == subtype)
return n;
- else if (n->subType() == Node::Collision && acceptCollision)
- return n;
+ else if (n->subType() == Node::Collision) {
+ if (acceptCollision)
+ return n;
+ return n->disambiguate(type, subtype);
+ }
else if (subtype == Node::NoSubType)
- return n; // don't care what subtype is.
- return 0;
+ return n;
+ continue;
}
- else
- return n;
+ return n;
}
else if (n->isCollisionNode()) {
if (acceptCollision)
return n;
return findNodeRecursive(path, pathIndex, n, type, subtype);
}
- else
- return 0;
+ else {
+ continue;
+ }
}
- else { // Not at the end of the path.
+ else { // Search the children of n for the next name in the path.
n = findNodeRecursive(path, pathIndex+1, n, type, subtype);
if (n)
return n;
@@ -722,40 +634,146 @@ Node* Tree::findNodeRecursive(const QStringList& path,
}
/*!
- 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.
+ 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 name 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), test the
+ matching node's type and subtype values against the ones
+ listed in \a types. If a match is found there, return the
+ pointer to the final node. Otherwise return 0.
*/
-EnumNode* Tree::findEnumNode(const QStringList& path, Node* start)
+Node* Tree::findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ const NodeTypeList& types) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- return static_cast<EnumNode*>(findNodeRecursive(path, 0, start, Node::Enum, Node::NoSubType));
+ /*
+ Safety checks
+ */
+ if (!start || path.isEmpty())
+ return 0;
+ if (start->isLeaf())
+ return ((pathIndex >= path.size()) ? start : 0);
+ if (pathIndex >= path.size())
+ return 0;
+
+ InnerNode* current = static_cast<InnerNode*>(start);
+ const NodeList& children = current->childNodes();
+ for (int i=0; i<children.size(); ++i) {
+ Node* n = children.at(i);
+ if (n && n->name() == path.at(pathIndex)) {
+ if (pathIndex+1 >= path.size()) {
+ if (n->match(types))
+ return n;
+ }
+ else if (!n->isLeaf()) {
+ n = findNodeRecursive(path, pathIndex+1, n, types);
+ if (n)
+ return n;
+ }
+ }
+ }
+ return 0;
}
/*!
- 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.
+ Searches the tree for a node that matches the \a path. The
+ search begins at \a start but can move up the parent chain
+ recursively if no match is found.
+
+ This findNode() callse the other findNode(), which is not
+ called anywhere else.
*/
-ClassNode* Tree::findClassNode(const QStringList& path, Node* start) const
+const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags) const
{
- if (!start)
- start = const_cast<NamespaceNode*>(root());
- return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
+ const Node* current = start;
+ if (!current)
+ current = root();
+
+ /*
+ First, search for a node assuming we don't want a QML node.
+ If that search fails, search again assuming we do want a
+ QML node.
+ */
+ const Node* n = findNode(path, current, findFlags, false);
+ return (n ? n : findNode(path, current, findFlags, true));
}
/*!
- Find the Namespace node named \a path. 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) const
+ 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.
+
+ This findNode() is only called by the other findNode().
+*/
+const Node* Tree::findNode(const QStringList& path, const Node* start, int findFlags, bool qml) const
{
- Node* start = const_cast<NamespaceNode*>(root());
- return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
+ const Node* current = start;
+ 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 they do, path[0] will be the QML
+ module identifier, and path[1] will be the QML type.
+ If the anser is yes, the reference identifies a QML
+ class node.
+ */
+ if (qml && path.size() >= 2 && !path[0].isEmpty()) {
+ QmlClassNode* qcn = qdb_->findQmlType(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<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
+ if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
+ next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+
+ if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
+ foreach (const Node* baseClass, baseClasses) {
+ next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
+ if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
+ next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
+ if (next)
+ break;
+ }
+ }
+ node = next;
+ }
+ if (node && i == path.size()
+ && (!(findFlags & NonFunction) || node->type() != Node::Function
+ || ((FunctionNode*)node)->metaness() == FunctionNode::MacroWithoutParams)) {
+ if (!node->isQmlPropertyGroup()) {
+ if (node->isCollisionNode())
+ node = node->applyModuleName(start);
+ return node;
+ }
+ }
+ current = current->parent();
+ } while (current);
+
+ return 0;
}
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h
index 26dd982abd..e1a08dd471 100644
--- a/src/tools/qdoc/tree.h
+++ b/src/tools/qdoc/tree.h
@@ -61,73 +61,54 @@ class Tree
typedef QMap<PropertyNode::FunctionRole, QString> RoleMap;
typedef QMap<PropertyNode*, RoleMap> PropertyMap;
- struct InheritanceBound
- {
- Node::Access access;
- QStringList basePath;
- QString dataTypeWithTemplateArgs;
- InnerNode* parent;
-
- InheritanceBound() : access(Node::Public) { }
- InheritanceBound(Node::Access access0,
- const QStringList& basePath0,
- const QString& dataTypeWithTemplateArgs0,
- InnerNode* parent)
- : access(access0), basePath(basePath0),
- dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0),
- parent(parent) { }
- };
-
Tree(QDocDatabase* qdb);
~Tree();
- EnumNode* findEnumNode(const QStringList& path, Node* start = 0);
+ /* API members */
ClassNode* findClassNode(const QStringList& path, Node* start = 0) const;
- QmlClassNode* findQmlTypeNode(const QStringList& path);
NamespaceNode* findNamespaceNode(const QStringList& path) const;
+ FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone);
- Node* findNodeByNameAndType(const QStringList& path,
- Node::Type type,
- Node::SubType subtype,
- Node* start,
- bool acceptCollision = false);
-
+ /* internal members */
Node* findNodeRecursive(const QStringList& path,
int pathIndex,
Node* start,
Node::Type type,
Node::SubType subtype,
bool acceptCollision = false) const;
+ Node* findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ const NodeTypeList& types) const;
const Node* findNode(const QStringList &path,
const Node* relative = 0,
- int findFlags = 0,
- const Node* self=0) const;
+ int findFlags = 0) const;
const Node* findNode(const QStringList& path,
const Node* start,
int findFlags,
- const Node* self,
bool qml) const;
+// ---------------------------------------------------------------------
+ QmlClassNode* findQmlTypeNode(const QStringList& path);
+
+ Node* findNodeByNameAndType(const QStringList& path,
+ Node::Type type,
+ Node::SubType subtype,
+ Node* start,
+ bool acceptCollision = false);
+
+
+ InnerNode* findRelatesNode(const QStringList& path);
NameCollisionNode* checkForCollision(const QString& name) const;
NameCollisionNode* findCollisionNode(const QString& name) const;
- FunctionNode *findFunctionNode(const QStringList &path,
- Node *relative = 0,
- int findFlags = 0);
- FunctionNode *findFunctionNode(const QStringList &parentPath,
- const FunctionNode *clone,
- Node *relative = 0,
- int findFlags = 0);
- void addBaseClass(ClassNode *subclass,
- Node::Access access,
- const QStringList &basePath,
- const QString &dataTypeWithTemplateArgs,
- InnerNode *parent);
+
void addPropertyFunction(PropertyNode *property,
const QString &funcName,
PropertyNode::FunctionRole funcRole);
- void resolveInheritance(NamespaceNode *rootNode = 0);
+ void resolveInheritance(InnerNode* n = 0);
+ void resolveInheritanceHelper(int pass, ClassNode* cn);
void resolveProperties();
void resolveCppToQmlLinks();
void fixInheritance(NamespaceNode *rootNode = 0);
@@ -136,22 +117,18 @@ class Tree
const FunctionNode *findFunctionNode(const QStringList &path,
const Node *relative = 0,
int findFlags = 0) const;
- const FunctionNode *findFunctionNode(const QStringList &parentPath,
- const FunctionNode *clone,
- const Node *relative = 0,
- int findFlags = 0) const;
const NamespaceNode *root() const { return &root_; }
- void resolveInheritance(int pass, ClassNode *classe);
FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe,
FunctionNode *clone);
- void fixPropertyUsingBaseClasses(ClassNode *classe, PropertyNode *property);
NodeList allBaseClasses(const ClassNode *classe) const;
+ public:
+ static bool debug_;
+
private:
QDocDatabase* qdb_;
NamespaceNode root_;
- QMap<ClassNode* , QList<InheritanceBound> > unresolvedInheritanceMap;
PropertyMap unresolvedPropertyMap;
};