qdoc: Remove all collision node stuff from qdoc

Now that the qdoc link command has ability to tell qdoc which module
contains a link target or whether to link to a QML or CPP entity,
collision pages should no longer be necessary. In fact, qdoc hasn't
been generating any collisions for some time. This task removes all
the collision node code from qdoc.

Task-number: QTBUG-40506
Change-Id: I34d1980ca1c0fe4bb5ad27dd4b00e61fa7e6e335
Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
This commit is contained in:
Martin Smith 2014-07-30 13:44:15 +02:00
parent 701b72c261
commit a5570bbf9a
16 changed files with 72 additions and 711 deletions

View File

@ -410,8 +410,7 @@ QString CppCodeMarker::markedUpEnumValue(const QString &enumValue, const Node *r
QString fullName;
while (node->parent()) {
fullName.prepend(markedUpName(node));
if (node->parent() == relative || node->parent()->name().isEmpty() ||
node->parent()->isCollisionNode())
if (node->parent() == relative || node->parent()->name().isEmpty())
break;
fullName.prepend("<@op>::</@op>");
node = node->parent();

View File

@ -497,27 +497,12 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
ptype = Node::DitaMapPage;
}
/*
Search for a node with the same name. If there is one,
then there is a collision, so create a collision node
and make the existing node a child of the collision
node, and then create the new Page node and make
it a child of the collision node as well. Return the
collision node.
If there is no collision, just create a new Page
node and return that one.
*/
NameCollisionNode* ncn = qdb_->checkForCollision(args[0]);
DocNode* dn = 0;
if (ptype == Node::DitaMapPage)
dn = new DitaMapNode(qdb_->primaryTreeRoot(), args[0]);
else
dn = new DocNode(qdb_->primaryTreeRoot(), args[0], Node::Page, ptype);
dn->setLocation(doc.startLocation());
if (ncn) {
ncn->addCollision(dn);
}
return dn;
}
else if (command == COMMAND_DITAMAP) {
@ -549,40 +534,9 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
classNode = qdb_->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
and make the existing node a child of the collision
node, and then create the new QML class node and make
it a child of the collision node as well. Return the
collision node.
If there is no collision, just create a new QML class
node and return that one.
*/
NameCollisionNode* ncn = qdb_->checkForCollision(names[0]);
QmlClassNode* qcn = new QmlClassNode(qdb_->primaryTreeRoot(), names[0]);
qcn->setClassNode(classNode);
qcn->setLocation(doc.startLocation());
#if 0
// to be removed if \qmltype and \instantiates work ok
if (isParsingCpp() || isParsingQdoc()) {
qcn->requireCppClass();
if (names.size() < 2) {
QString msg = "C++ class name not specified for class documented as "
"QML type: '\\qmlclass " + arg.first + " <class name>'";
doc.startLocation().warning(tr(msg.toLatin1().data()));
}
else if (!classNode) {
QString msg = "C++ class not found in any .h file for class documented "
"as QML type: '\\qmlclass " + arg.first + "'";
doc.startLocation().warning(tr(msg.toLatin1().data()));
}
}
#endif
if (ncn) {
ncn->addCollision(qcn);
}
return qcn;
}
else if (command == COMMAND_QMLBASICTYPE) {

View File

@ -671,10 +671,8 @@ GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName)
*/
void DitaXmlGenerator::generateDocs()
{
if (!runPrepareOnly()) {
if (!runPrepareOnly())
Generator::generateDocs();
generateCollisionPages();
}
if (!runGenerateOnly()) {
QString fileBase = project.toLower().simplified().replace(QLatin1Char(' '), QLatin1Char('-'));
@ -2275,10 +2273,6 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
QList<Section>::const_iterator s;
QString fullTitle = dn->fullTitle();
if (dn->subType() == Node::Collision) {
fullTitle = "Name Collision: " + fullTitle;
}
generateHeader(dn, fullTitle);
generateBrief(dn, marker); // <shortdesc>
writeProlog(dn);
@ -2553,9 +2547,6 @@ void DitaXmlGenerator::generateHeader(const Node* node, const QString& name)
case Node::ExternalPage: // not used
outputclass = "externalpage";
break;
case Node::Collision:
outputclass = "collision";
break;
default:
outputclass = "page";
}
@ -5277,27 +5268,16 @@ DitaXmlGenerator::generateInnerNode(InnerNode* node)
*/
CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
if (node->parent() != 0) {
/*
Skip name collision nodes here and process them
later in generateCollisionPages(). Each one is
appended to a list for later.
*/
if (node->isCollisionNode()) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
}
else {
if (!node->name().endsWith(".ditamap"))
beginSubPage(node, fileName(node));
if (node->isNamespace() || node->isClass() || node->isQmlType() || node->isHeaderFile())
generateClassLikeNode(node, marker);
else if (node->isDocNode())
generateDocNode(static_cast<DocNode*>(node), marker);
else if (node->isQmlBasicType())
generateQmlBasicTypePage(static_cast<QmlBasicTypeNode*>(node), marker);
if (!node->name().endsWith(".ditamap"))
endSubPage();
}
if (!node->name().endsWith(".ditamap"))
beginSubPage(node, fileName(node));
if (node->isNamespace() || node->isClass() || node->isQmlType() || node->isHeaderFile())
generateClassLikeNode(node, marker);
else if (node->isDocNode())
generateDocNode(static_cast<DocNode*>(node), marker);
else if (node->isQmlBasicType())
generateQmlBasicTypePage(static_cast<QmlBasicTypeNode*>(node), marker);
if (!node->name().endsWith(".ditamap"))
endSubPage();
}
NodeList::ConstIterator c = node->childNodes().constBegin();
@ -5363,13 +5343,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
QString message;
for (int i=0; i<children.size(); ++i) {
Node* child = children[i];
if (child->isCollisionNode()) {
const DocNode* fake = static_cast<const DocNode*>(child);
Node* n = collectNodesByTypeAndSubtype(fake);
if (n)
rootPageNode = n;
continue;
}
if (!child || child->isInternal() || child->doc().isEmpty() || child->isIndexNode())
continue;
@ -5428,10 +5401,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeSubtypeMaps[Node::ExternalPage],child->title(),child))
nodeSubtypeMaps[Node::ExternalPage]->insert(child->title(),child);
break;
case Node::Collision:
if (!isDuplicate(nodeSubtypeMaps[Node::Collision],child->title(),child))
nodeSubtypeMaps[Node::Collision]->insert(child->title(),child);
break;
default:
break;
}
@ -6029,122 +5998,4 @@ 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; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i);
if (!ncn)
continue;
NodeList collisions;
const NodeList& nl = ncn->childNodes();
if (!nl.isEmpty()) {
NodeList::ConstIterator it = nl.constBegin();
while (it != nl.constEnd()) {
if (!(*it)->isInternal())
collisions.append(*it);
++it;
}
}
if (collisions.size() <= 1)
continue;
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; i<collisions.size(); ++i) {
Node* n = collisions.at(i);
QString t;
if (!n->qmlModuleName().isEmpty())
t = n->qmlModuleName() + QLatin1Char(' ');
t += protectEnc(fullTitle);
nm.insertMulti(t,n);
}
generateAnnotatedList(ncn, marker, nm);
QList<QString> targets;
if (!ncn->linkTargets().isEmpty()) {
QMap<QString,QString>::ConstIterator t = ncn->linkTargets().constBegin();
while (t != ncn->linkTargets().constEnd()) {
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
if (n->findChildNode(t.key(), Node::DontCare)) {
++count;
if (count > 1) {
targets.append(t.key());
break;
}
}
}
++t;
}
}
if (!targets.isEmpty()) {
QList<QString>::ConstIterator t = targets.constBegin();
while (t != targets.constEnd()) {
writeStartTag(DT_p);
writeGuidAttribute(Doc::canonicalTitle(*t));
xmlWriter().writeAttribute("outputclass","h2");
writeCharacters(protectEnc(*t));
writeEndTag(); // </p>
writeStartTag(DT_ul);
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
Node* p = n->findChildNode(*t, Node::DontCare);
if (p) {
QString link = linkForNode(p,0);
QString label;
if (!n->qmlModuleName().isEmpty())
label = n->qmlModuleName() + "::";
label += n->name() + "::" + p->name();
writeStartTag(DT_li);
writeStartTag(DT_xref);
xmlWriter().writeAttribute("href", link);
writeCharacters(protectEnc(label));
writeEndTag(); // </xref>
writeEndTag(); // </li>
}
}
writeEndTag(); // </ul>
++t;
}
}
leaveSection(); // </section>
writeEndTag(); // </body>
endSubPage();
}
}
QT_END_NAMESPACE

View File

@ -303,7 +303,6 @@ public:
virtual QString format();
virtual bool canHandleFormat(const QString& format);
virtual void generateDocs();
void generateCollisionPages();
QString protectEnc(const QString& string);
static QString protect(const QString& string, const QString& encoding = "ISO-8859-1");

View File

@ -319,9 +319,6 @@ QString Generator::fileBase(const Node *node) const
QString base;
if (node->isDocNode()) {
base = node->name();
if (node->subType() == Node::Collision)
base.prepend("collision-");
//Was QDOC2_COMPAT, required for index.html
if (base.endsWith(".html"))
base.truncate(base.length() - 5);
@ -976,10 +973,6 @@ void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
\note DitaXmlGenerator overrides this function, but
HtmlGenerator does not.
\note NameCollisionNodes are skipped here and processed
later. See HtmlGenerator::generateCollisionPages() for
more on this.
*/
void Generator::generateInnerNode(InnerNode* node)
{
@ -1010,65 +1003,54 @@ void Generator::generateInnerNode(InnerNode* node)
CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
if (node->parent() != 0) {
/*
Skip name collision nodes here and process them
later in generateCollisionPages(). Each one is
appended to a list for later.
*/
if (node->isCollisionNode()) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
if (node->isNamespace() || node->isClass()) {
beginSubPage(node, fileName(node));
generateClassLikeNode(node, marker);
endSubPage();
}
else {
if (node->isNamespace() || node->isClass()) {
beginSubPage(node, fileName(node));
generateClassLikeNode(node, marker);
endSubPage();
}
if (node->isQmlType()) {
beginSubPage(node, fileName(node));
QmlClassNode* qcn = static_cast<QmlClassNode*>(node);
generateQmlTypePage(qcn, marker);
endSubPage();
}
else if (node->isDocNode()) {
beginSubPage(node, fileName(node));
generateDocNode(static_cast<DocNode*>(node), marker);
endSubPage();
}
else if (node->isQmlBasicType()) {
beginSubPage(node, fileName(node));
QmlBasicTypeNode* qbtn = static_cast<QmlBasicTypeNode*>(node);
generateQmlBasicTypePage(qbtn, marker);
endSubPage();
}
else if (node->isCollectionNode()) {
CollectionNode* cn = static_cast<CollectionNode*>(node);
/*
A collection node is one of: group, module,
or QML module.
if (node->isQmlType()) {
beginSubPage(node, fileName(node));
QmlClassNode* qcn = static_cast<QmlClassNode*>(node);
generateQmlTypePage(qcn, marker);
endSubPage();
}
else if (node->isDocNode()) {
beginSubPage(node, fileName(node));
generateDocNode(static_cast<DocNode*>(node), marker);
endSubPage();
}
else if (node->isQmlBasicType()) {
beginSubPage(node, fileName(node));
QmlBasicTypeNode* qbtn = static_cast<QmlBasicTypeNode*>(node);
generateQmlBasicTypePage(qbtn, marker);
endSubPage();
}
else if (node->isCollectionNode()) {
CollectionNode* cn = static_cast<CollectionNode*>(node);
/*
A collection node is one of: group, module,
or QML module.
Don't output an HTML page for the collection
node unless the \group, \module, or \qmlmodule
command was actually seen by qdoc in the qdoc
comment for the node.
Don't output an HTML page for the collection
node unless the \group, \module, or \qmlmodule
command was actually seen by qdoc in the qdoc
comment for the node.
A key prerequisite in this case is the call to
mergeCollections(cn). We don't know if this
collection (group, module, or QML module) has
members in other modules. We know at this point
that cn's members list contains only members in
the current module. Therefore, before outputting
the page for cn, we must search for members of
cn in the other modules and add them to the
members list.
*/
if (cn->wasSeen()) {
qdb_->mergeCollections(cn);
beginSubPage(node, fileName(node));
generateCollectionNode(cn, marker);
endSubPage();
}
A key prerequisite in this case is the call to
mergeCollections(cn). We don't know if this
collection (group, module, or QML module) has
members in other modules. We know at this point
that cn's members list contains only members in
the current module. Therefore, before outputting
the page for cn, we must search for members of
cn in the other modules and add them to the
members list.
*/
if (cn->wasSeen()) {
qdb_->mergeCollections(cn);
beginSubPage(node, fileName(node));
generateCollectionNode(cn, marker);
endSubPage();
}
}
}
@ -1446,47 +1428,6 @@ Generator *Generator::generatorForFormat(const QString& format)
return 0;
}
#if 0
/*!
This function might be useless now with the addition of
multiple node trees. It is called a few hundred times,
but it never finds a collision node. The single call has
been commented out by mws (19/05/2014). If it is no
longer needed, it will be removed.
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 <element> :: <name>, where <element> is a QML
element or component without a module qualifier. If so, it
constructs a link to the <name> clause on the disambiguation
page for <element> and returns that link string. It also
adds the <name> as a target in the NameCollisionNode for
<element>. 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 = qdb_->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;
}
#endif
/*!
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,

View File

@ -157,7 +157,6 @@ 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);
@ -175,7 +174,6 @@ protected:
void unknownAtom(const Atom *atom);
void appendSortedQmlNames(Text& text, const Node* base, const NodeList& subs);
QList<NameCollisionNode*> collisionNodes;
QMap<QString, QStringList> editionGroupMap;
QMap<QString, QStringList> editionModuleMap;
QString naturalLanguage;

View File

@ -716,8 +716,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (node == 0)
node = qdb_->findNodeByNameAndType(QStringList("index.html"), Node::Document);
QString indexPath;
// Never use a collision node as a landing page
if (node && !node->isCollisionNode())
if (node)
indexPath = gen_->fullDocumentLocation(node,Generator::useOutputSubdirs());
else
indexPath = "index.html";

View File

@ -274,10 +274,8 @@ void HtmlGenerator::generateDocs()
Node* qflags = qdb_->findClassNode(QStringList("QFlags"));
if (qflags)
qflagsHref_ = linkForNode(qflags,0);
if (!runPrepareOnly()) {
if (!runPrepareOnly())
Generator::generateDocs();
generateCollisionPages();
}
if (!runGenerateOnly()) {
QString fileBase = project.toLower().simplified().replace(QLatin1Char(' '), QLatin1Char('-'));
@ -1431,117 +1429,6 @@ void HtmlGenerator::generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker*
generateFooter(qbtn);
}
/*!
We delayed generation of the disambiguation 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
component page, but the link doesn't specify the module identifer
for the component, and the component 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 disambiguation page for
each collision is generated. The disambiguation page will not only
disambiguate links to the component pages, but it will also disambiguate
links to properties, section headers, etc.
*/
void HtmlGenerator::generateCollisionPages()
{
if (collisionNodes.isEmpty())
return;
for (int i=0; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i);
if (!ncn)
continue;
NodeList collisions;
const NodeList& nl = ncn->childNodes();
if (!nl.isEmpty()) {
NodeList::ConstIterator it = nl.constBegin();
while (it != nl.constEnd()) {
if (!(*it)->isInternal())
collisions.append(*it);
++it;
}
}
if (collisions.size() <= 1)
continue;
beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = ncn->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(fullTitle, ncn, marker);
if (!fullTitle.isEmpty())
out() << "<h1 class=\"title\">" << protectEnc(fullTitle) << "</h1>\n";
NodeMap nm;
for (int i=0; i<collisions.size(); ++i) {
Node* n = collisions.at(i);
QString t;
if (!n->qmlModuleName().isEmpty())
t = n->qmlModuleName() + "::";
t += protectEnc(fullTitle);
nm.insertMulti(t,n);
}
generateAnnotatedList(ncn, marker, nm);
QList<QString> targets;
if (!ncn->linkTargets().isEmpty()) {
QMap<QString,QString>::ConstIterator t = ncn->linkTargets().constBegin();
while (t != ncn->linkTargets().constEnd()) {
int count = 0;
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
if (n->findChildNode(t.key(), Node::DontCare)) {
++count;
if (count > 1) {
targets.append(t.key());
break;
}
}
}
++t;
}
}
if (!targets.isEmpty()) {
QList<QString>::ConstIterator t = targets.constBegin();
while (t != targets.constEnd()) {
out() << "<a name=\"" << Doc::canonicalTitle(*t) << "\"></a>";
out() << "<h2 class=\"title\">" << protectEnc(*t) << "</h2>\n";
out() << "<ul>\n";
for (int i=0; i<collisions.size(); ++i) {
InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
Node* p = n->findChildNode(*t, Node::DontCare);
if (p) {
QString link = linkForNode(p,0);
QString label;
if (!n->qmlModuleName().isEmpty())
label = n->qmlModuleName() + "::";
label += n->name() + "::" + p->name();
out() << "<li>";
out() << "<a href=\"" << link << "\">";
out() << protectEnc(label) << "</a>";
out() << "</li>\n";
}
}
out() << "</ul>\n";
++t;
}
}
generateFooter(ncn);
endSubPage();
}
}
/*!
Generate the HTML page for an entity that doesn't map
to any underlying parsable C++ class or QML component.
@ -1569,8 +1456,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
Generate the TOC for the new doc format.
Don't generate a TOC for the home page.
*/
if ((dn->subType() != Node::Collision) &&
(dn->name() != QString("index.html")) &&
if ((dn->name() != QString("index.html")) &&
(dn->name() != QString("qtexamplesandtutorials.html")))
generateTableOfContents(dn,marker,0);
@ -4700,8 +4586,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break;
case Node::ExternalPage:
break;
case Node::Collision:
break;
default:
break;
}

View File

@ -89,7 +89,6 @@ public:
virtual void terminateGenerator();
virtual QString format();
virtual void generateDocs();
void generateCollisionPages();
void generateManifestFiles();
QString protectEnc(const QString &string);

View File

@ -144,8 +144,7 @@ QString Node::plainFullName(const Node* relative) const
const Node* node = this;
while (node) {
fullName.prepend(node->plainName());
if (node->parent() == relative || node->parent()->subType() == Node::Collision ||
node->parent()->name().isEmpty())
if (node->parent() == relative || node->parent()->name().isEmpty())
break;
fullName.prepend(QLatin1String("::"));
node = node->parent();
@ -154,18 +153,12 @@ QString Node::plainFullName(const Node* relative) const
}
/*!
Constructs and returns this node's full name. The \a relative
node is either null or is a collision node.
Constructs and returns this node's full name.
*/
QString Node::fullName(const Node* relative) const
{
if (isDocNode() || isCollectionNode()) {
const DocNode* dn = static_cast<const DocNode*>(this);
// Only print modulename::type on collision pages.
if (!dn->qmlModuleName().isEmpty() && relative != 0 && relative->isCollisionNode())
return dn->qmlModuleName() + "::" + dn->title();
return dn->title();
}
if (isDocNode())
return title();
else if (isClass()) {
const ClassNode* cn = static_cast<const ClassNode*>(this);
if (!cn->serviceName().isEmpty())
@ -415,8 +408,6 @@ QString Node::nodeSubtypeString(unsigned t)
return "external page";
case DitaMap:
return "ditamap";
case Collision:
return "collision";
case NoSubType:
default:
break;
@ -832,12 +823,6 @@ Node* InnerNode::findChildNode(const QString& name, bool qml) const
This function is like findChildNode(), 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::findChildNode(const QString& name, Type type)
{
@ -1007,18 +992,13 @@ void InnerNode::setOverload(const FunctionNode *func, bool overlode)
Mark all child nodes that have no documentation as having
private access and internal status. qdoc will then ignore
them for documentation purposes.
\note Exception: Name collision nodes are not marked
private/internal.
*/
void InnerNode::makeUndocumentedChildrenInternal()
{
foreach (Node *child, childNodes()) {
if (child->doc().isEmpty()) {
if (child->subType() != Node::Collision) {
child->setAccess(Node::Private);
child->setStatus(Node::Internal);
}
child->setAccess(Node::Private);
child->setStatus(Node::Internal);
}
}
}
@ -1689,9 +1669,6 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
case Example:
setPageType(ExamplePage);
break;
case Collision:
setPageType(ptype);
break;
default:
break;
}
@ -1735,9 +1712,6 @@ QString DocNode::fullTitle() const
else
return name() + " - " + title();
}
else if (nodeSubtype_ == Collision) {
return title();
}
else {
return title();
}
@ -2465,137 +2439,6 @@ QString QmlPropertyNode::element() const
return parent()->name();
}
/*! \class NameCollisionNode
An instance of this node is inserted in the tree
whenever qdoc discovers that two nodes have the
same name.
*/
/*!
Constructs a name collision node containing \a child
as its first child. The parent of \a child becomes
this node's parent.
*/
NameCollisionNode::NameCollisionNode(InnerNode* child)
: DocNode(child->parent(), child->name(), Collision, Node::NoPageType)
{
setTitle("Name Collision: " + child->name());
addCollision(child);
}
/*!
Add a collision to this collision node. \a child has
the same name as the other children in this collision
node. \a child becomes the current child.
*/
void NameCollisionNode::addCollision(InnerNode* child)
{
if (child) {
if (child->parent())
child->parent()->removeChild(child);
child->setParent((InnerNode*)this);
children_.append(child);
}
}
/*!
The destructor does nothing.
*/
NameCollisionNode::~NameCollisionNode()
{
// nothing.
}
/*!
Returns \c true if this collision node's current node is a QML node.
*/
bool NameCollisionNode::isQmlNode() const
{
return false;
}
/*!
Find any of this collision node's children that has type \a t
and subtype \a st and return a pointer to it.
*/
InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st)
{
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
if ((*i)->type() == t && (*i)->subType() == st)
return static_cast<InnerNode*>(*i);
++i;
}
return 0;
}
/*!
This node is a name collision node. Find a child of this node
such that the child's QML module name matches origin's QML module
Name. Return the matching node, or return this node if there is
no matching node.
*/
const Node* NameCollisionNode::applyModuleName(const Node* origin) const
{
if (origin && !origin->qmlModuleName().isEmpty()) {
const NodeList& cn = childNodes();
NodeList::ConstIterator i = cn.constBegin();
while (i != cn.constEnd()) {
if ((*i)->isQmlType()) {
if (origin->qmlModuleName() == (*i)->qmlModuleName())
return (*i);
}
++i;
}
}
return this;
}
/*!
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.
*/
@ -2849,10 +2692,6 @@ QString Node::idForNode() const
str = name();
str.replace(QLatin1Char('/'), QLatin1Char('-'));
break;
case Node::Collision:
str = title();
str.replace(": ","-");
break;
default:
qDebug() << "ERROR: A case was not handled in Node::idForNode():"
<< "subType():" << subType() << "type():" << type();

View File

@ -66,7 +66,6 @@ class PropertyNode;
class QmlModuleNode;
class CollectionNode;
class QmlPropertyNode;
class NameCollisionNode;
typedef QList<Node*> NodeList;
typedef QMap<QString, Node*> NodeMap;
@ -113,7 +112,6 @@ public:
Page,
ExternalPage,
DitaMap,
Collision,
LastSubtype
};
@ -223,7 +221,6 @@ public:
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 bool isAttached() const { return false; }
virtual bool isAlias() const { return false; }
virtual bool isWrapper() const;
@ -410,7 +407,6 @@ protected:
private:
friend class Node;
friend class NameCollisionNode;
static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2);
void addChild(Node* child);
@ -555,24 +551,6 @@ protected:
QString subtitle_;
};
class NameCollisionNode : public DocNode
{
public:
NameCollisionNode(InnerNode* child);
~NameCollisionNode();
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; }
void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); }
private:
QMap<QString,QString> targets;
};
class ExampleNode : public DocNode
{
public:

View File

@ -785,15 +785,8 @@ QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name
QStringList path(name);
Node* n = forest_.findNodeByNameAndType(path, Node::QmlType);
if (n) {
if (n->isQmlType())
return static_cast<QmlClassNode*>(n);
else if (n->isCollisionNode()) {
NameCollisionNode* ncn;
ncn = static_cast<NameCollisionNode*>(n);
return static_cast<QmlClassNode*>(ncn->findAny(Node::QmlType, Node::NoSubType));
}
}
if (n && n->isQmlType())
return static_cast<QmlClassNode*>(n);
return 0;
}
@ -1365,9 +1358,8 @@ const Node* QDocDatabase::findNodeForTarget(const QString& target, const Node* r
const Node* node = 0;
if (target.isEmpty())
node = relative;
else if (target.endsWith(".html")) {
else if (target.endsWith(".html"))
node = findNodeByNameAndType(QStringList(target), Node::Document);
}
else {
QStringList path = target.split("::");
int flags = SearchBaseClasses | SearchEnumValues; // | NonFunction;

View File

@ -304,12 +304,6 @@ class QDocDatabase
}
FunctionNode* findNodeInOpenNamespace(const QStringList& parentPath, const FunctionNode* clone);
Node* findNodeInOpenNamespace(QStringList& path, Node::Type type);
NameCollisionNode* findCollisionNode(const QString& name) {
return primaryTree()->findCollisionNode(name);
}
NameCollisionNode* checkForCollision(const QString& name) {
return primaryTree()->checkForCollision(name);
}
/*******************************************************************/
/*******************************************************************

View File

@ -1337,20 +1337,7 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
std::sort(cnodes.begin(), cnodes.end(), compareNodes);
foreach (Node* child, cnodes) {
/*
Don't generate anything for a collision node. We want
children of collision nodes in the index, but leaving
out the parent collision page will make searching for
nodes easier.
*/
if (child->subType() == Node::Collision) {
const InnerNode* pgn = static_cast<const InnerNode*>(child);
foreach (Node* c, pgn->childNodes()) {
generateIndexSections(writer, c, generateInternalNodes);
}
}
else
generateIndexSections(writer, child, generateInternalNodes);
generateIndexSections(writer, child, generateInternalNodes);
}
}

View File

@ -193,47 +193,6 @@ QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, root(), Node::QmlType));
}
/*!
First, search for a node with the specified \a name. If a matching
node is found, if it is a collision node, another collision with
this name has been found, so return the collision node. If the
matching node is not a collision node, the first collision for this
name has been found, so create a NameCollisionNode with the matching
node as its first child, and return a pointer to the new
NameCollisionNode. Otherwise return 0.
*/
NameCollisionNode* Tree::checkForCollision(const QString& name)
{
Node* n = const_cast<Node*>(findNode(QStringList(name), 0, 0, Node::DontCare));
if (n) {
if (n->subType() == Node::Collision) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(n);
return ncn;
}
if (n->isInnerNode())
return new NameCollisionNode(static_cast<InnerNode*>(n));
}
return 0;
}
/*!
This function is like checkForCollision() in that it searches
for a collision node with the specified \a name. But it doesn't
create anything. If it finds a match, it returns the pointer.
Otherwise it returns 0.
*/
NameCollisionNode* Tree::findCollisionNode(const QString& name) const
{
Node* n = const_cast<Node*>(findNode(QStringList(name), 0, 0, Node::DontCare));
if (n) {
if (n->subType() == Node::Collision) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(n);
return ncn;
}
}
return 0;
}
/*!
This function begins searching the tree at \a relative for
the \l {FunctionNode} {function node} identified by \a path.
@ -252,15 +211,8 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
if (!qcn) {
QStringList p(path[1]);
Node* n = findNodeByNameAndType(p, Node::QmlType);
if (n) {
if (n->isQmlType())
qcn = static_cast<QmlClassNode*>(n);
else if (n->subType() == Node::Collision) {
NameCollisionNode* ncn;
ncn = static_cast<NameCollisionNode*>(n);
qcn = static_cast<QmlClassNode*>(ncn->findAny(Node::QmlType, Node::NoSubType));
}
}
if (n && n->isQmlType())
qcn = static_cast<QmlClassNode*>(n);
}
if (qcn)
return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
@ -1018,9 +970,6 @@ void Tree::resolveTargets(InnerNode* root)
if (!alreadyThere)
docNodesByTitle_.insert(key, node);
}
if (node->subType() == Node::Collision) {
resolveTargets(node);
}
}
if (child->doc().hasTableOfContents()) {

View File

@ -130,8 +130,6 @@ class Tree
Node* findNodeByNameAndType(const QStringList& path, Node::Type type) const;
InnerNode* findRelatesNode(const QStringList& path);
NameCollisionNode* checkForCollision(const QString& name);
NameCollisionNode* findCollisionNode(const QString& name) const;
QString getRef(const QString& target, const Node* node) const;
void insertTarget(const QString& name,
const QString& title,