qdoc: Improve resolving related non-members and their overload numbers
There were several problems related to resolving related non-member (RNM) functions for classes. This commit does the following changes: - Overload numbers for RNMs are now calculated at the time the \relates command is processed, instead of a separate step. - If a \relates refers to an entity outside the module boundary, write the argument passed to it as-is into the index file. - Delay the destruction of QDocIndexFiles singleton, to resolve the RNMs read from the index files prior to generating docs. - Remove the redundant call to normalizeOverloads() for single- exec mode as unnecessary. These changes ensure that all RNMs are listed in the documentation for the node that they belong to. A remaining issue is that if a function relates to a class outside the module boundary, that function documentation will be empty because the doc content is not stored into the index file (for obvious reasons). Single-exec mode does not have this problem. Change-Id: I33f038120728932cd9fd70da28d9090023068bd6 Task-number: QTBUG-47589 Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
This commit is contained in:
parent
53762b102b
commit
d558100aa7
@ -924,8 +924,14 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
|
||||
else if (command == COMMAND_RELATES) {
|
||||
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));
|
||||
if (!n) {
|
||||
// Store just a string to write to the index file
|
||||
if (Generator::preparing())
|
||||
node->setRelates(arg);
|
||||
else
|
||||
doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
|
||||
|
||||
}
|
||||
else
|
||||
node->setRelates(static_cast<Aggregate*>(n));
|
||||
}
|
||||
|
@ -106,7 +106,24 @@ Node::~Node()
|
||||
{
|
||||
if (parent_)
|
||||
parent_->removeChild(this);
|
||||
|
||||
if (relatesTo_)
|
||||
removeRelates();
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes this node from the aggregate's list of related
|
||||
nodes, or if this node has created a dummy "relates"
|
||||
aggregate, deletes it.
|
||||
*/
|
||||
void Node::removeRelates()
|
||||
{
|
||||
if (!relatesTo_)
|
||||
return;
|
||||
|
||||
if (relatesTo_->isDocumentNode() && !relatesTo_->parent())
|
||||
delete relatesTo_;
|
||||
else
|
||||
relatesTo_->removeRelated(this);
|
||||
}
|
||||
|
||||
@ -463,11 +480,19 @@ bool Node::fromFlagValue(FlagValue fv, bool defaultValue)
|
||||
*/
|
||||
void Node::setRelates(Aggregate *pseudoParent)
|
||||
{
|
||||
if (relatesTo_) {
|
||||
relatesTo_->removeRelated(this);
|
||||
}
|
||||
removeRelates();
|
||||
relatesTo_ = pseudoParent;
|
||||
pseudoParent->related_.append(this);
|
||||
pseudoParent->addRelated(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the (unresolved) entity \a name that this node relates to.
|
||||
*/
|
||||
void Node::setRelates(const QString& name)
|
||||
{
|
||||
removeRelates();
|
||||
// Create a dummy aggregate for writing the name into the index
|
||||
relatesTo_ = new DocumentNode(0, name, Node::NoSubtype, Node::NoPageType);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -934,8 +959,9 @@ void Aggregate::makeUndocumentedChildrenInternal()
|
||||
}
|
||||
|
||||
/*!
|
||||
This is where we should set the overload numbers, including
|
||||
the related non-members.
|
||||
This is where we set the overload numbers for function nodes.
|
||||
\note Overload numbers for related non-members are handled
|
||||
separately.
|
||||
*/
|
||||
void Aggregate::normalizeOverloads()
|
||||
{
|
||||
@ -1006,23 +1032,6 @@ void Aggregate::normalizeOverloads()
|
||||
}
|
||||
++p;
|
||||
}
|
||||
/*
|
||||
Add the related non-members here.
|
||||
*/
|
||||
if (!related_.isEmpty()) {
|
||||
foreach (Node* n, related_) {
|
||||
if (n->isFunction()) {
|
||||
FunctionNode* fn = static_cast<FunctionNode*>(n);
|
||||
QMap<QString, Node *>::Iterator p = primaryFunctionMap_.find(fn->name());
|
||||
if (p != primaryFunctionMap_.end()) {
|
||||
secondaryFunctionMap_[fn->name()].append(fn);
|
||||
fn->setOverloadNumber(secondaryFunctionMap_[fn->name()].size());
|
||||
}
|
||||
else
|
||||
fn->setOverloadNumber(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Recursive part.
|
||||
*/
|
||||
@ -1322,10 +1331,49 @@ QString Node::physicalModuleName() const
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a node from the list of nodes related to this one.
|
||||
If it is a function node, also remove from the primary/
|
||||
secondary function maps.
|
||||
*/
|
||||
void Aggregate::removeRelated(Node *pseudoChild)
|
||||
{
|
||||
related_.removeAll(pseudoChild);
|
||||
|
||||
if (pseudoChild->isFunction()) {
|
||||
QMap<QString, Node *>::Iterator p = primaryFunctionMap_.find(pseudoChild->name());
|
||||
while (p != primaryFunctionMap_.end()) {
|
||||
if (p.value() == pseudoChild) {
|
||||
primaryFunctionMap_.erase(p);
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
NodeList& overloads = secondaryFunctionMap_[pseudoChild->name()];
|
||||
overloads.removeAll(pseudoChild);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds \a pseudoChild to the list of nodes related to this one. Resolve a correct
|
||||
overload number for a related non-member function.
|
||||
*/
|
||||
void Aggregate::addRelated(Node *pseudoChild)
|
||||
{
|
||||
related_.append(pseudoChild);
|
||||
|
||||
if (pseudoChild->isFunction()) {
|
||||
FunctionNode* fn = static_cast<FunctionNode*>(pseudoChild);
|
||||
if (primaryFunctionMap_.contains(pseudoChild->name())) {
|
||||
secondaryFunctionMap_[pseudoChild->name()].append(pseudoChild);
|
||||
fn->setOverloadNumber(secondaryFunctionMap_[pseudoChild->name()].size());
|
||||
fn->setOverloadFlag(true);
|
||||
}
|
||||
else {
|
||||
primaryFunctionMap_.insert(pseudoChild->name(), pseudoChild);
|
||||
fn->setOverloadNumber(0);
|
||||
fn->setOverloadFlag(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -178,6 +178,7 @@ public:
|
||||
void setThreadSafeness(ThreadSafeness t) { safeness_ = (unsigned char) t; }
|
||||
void setSince(const QString &since);
|
||||
void setRelates(Aggregate* pseudoParent);
|
||||
void setRelates(const QString &name);
|
||||
void setPhysicalModuleName(const QString &name) { physicalModuleName_ = name; }
|
||||
void setUrl(const QString& url) { url_ = url; }
|
||||
void setTemplateStuff(const QString &t) { templateStuff_ = t; }
|
||||
@ -336,6 +337,7 @@ public:
|
||||
|
||||
protected:
|
||||
Node(NodeType type, Aggregate* parent, const QString& name);
|
||||
void removeRelates();
|
||||
|
||||
private:
|
||||
|
||||
@ -421,6 +423,7 @@ private:
|
||||
|
||||
static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2);
|
||||
void removeRelated(Node* pseudoChild);
|
||||
void addRelated(Node* pseudoChild);
|
||||
|
||||
QString outputFileName_;
|
||||
QStringList pageKeywds;
|
||||
|
@ -1295,6 +1295,10 @@ void QDocDatabase::resolveIssues() {
|
||||
resolveQmlInheritance(primaryTreeRoot());
|
||||
primaryTree()->resolveTargets(primaryTreeRoot());
|
||||
primaryTree()->resolveCppToQmlLinks();
|
||||
if (!Generator::singleExec()) {
|
||||
QDocIndexFiles::qdocIndexFiles()->resolveRelates();
|
||||
QDocIndexFiles::destroyQDocIndexFiles();
|
||||
}
|
||||
}
|
||||
|
||||
void QDocDatabase::resolveStuff()
|
||||
@ -1305,7 +1309,6 @@ void QDocDatabase::resolveStuff()
|
||||
primaryTree()->resolveCppToQmlLinks();
|
||||
primaryTree()->resolveUsingClauses();
|
||||
resolveNamespaces();
|
||||
primaryTreeRoot()->normalizeOverloads();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1495,7 +1498,6 @@ void QDocDatabase::readIndexes(const QStringList& t)
|
||||
qDebug() << "This index file is already in memory:" << f;
|
||||
}
|
||||
QDocIndexFiles::qdocIndexFiles()->readIndexes(indexFiles);
|
||||
QDocIndexFiles::destroyQDocIndexFiles();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -100,6 +100,7 @@ void QDocIndexFiles::destroyQDocIndexFiles()
|
||||
*/
|
||||
void QDocIndexFiles::readIndexes(const QStringList& indexFiles)
|
||||
{
|
||||
relatedList_.clear();
|
||||
foreach (const QString& indexFile, indexFiles) {
|
||||
QString msg = "Loading index file: " + indexFile;
|
||||
Location::logToStdErr(msg);
|
||||
@ -146,9 +147,7 @@ void QDocIndexFiles::readIndexFile(const QString& path)
|
||||
indexUrl = installDir.relativeFilePath(path).section('/', 0, -2);
|
||||
}
|
||||
project_ = attrs.value(QLatin1String("project")).toString();
|
||||
|
||||
basesList_.clear();
|
||||
relatedList_.clear();
|
||||
|
||||
NamespaceNode* root = qdb_->newIndexTree(project_);
|
||||
|
||||
@ -730,17 +729,37 @@ void QDocIndexFiles::resolveIndex()
|
||||
pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString());
|
||||
}
|
||||
}
|
||||
// No longer needed.
|
||||
basesList_.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
Goes though the list of nodes that are related to other aggregates
|
||||
that were read from all index files, and tries to find the aggregate
|
||||
nodes from the database. Calls the node's setRelates() for each
|
||||
aggregate that is found in the local module (primary tree).
|
||||
|
||||
This function is meant to be called before starting the doc generation,
|
||||
after all the index files are read.
|
||||
*/
|
||||
void QDocIndexFiles::resolveRelates()
|
||||
{
|
||||
if (relatedList_.isEmpty())
|
||||
return;
|
||||
|
||||
// Restrict searching only to the local (primary) tree
|
||||
QVector<Tree*> searchOrder = qdb_->searchOrder();
|
||||
qdb_->setLocalSearch();
|
||||
|
||||
QPair<FunctionNode*,QString> relatedPair;
|
||||
foreach (relatedPair, relatedList_) {
|
||||
QStringList path = relatedPair.second.split("::");
|
||||
Node* n = qdb_->findRelatesNode(path);
|
||||
if (n)
|
||||
relatedPair.first->setRelates(static_cast<ClassNode*>(n));
|
||||
relatedPair.first->setRelates(static_cast<Aggregate*>(n));
|
||||
}
|
||||
|
||||
// No longer needed.
|
||||
basesList_.clear();
|
||||
// Restore original search order
|
||||
qdb_->setSearchOrder(searchOrder);
|
||||
relatedList_.clear();
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ class QDocIndexFiles
|
||||
void readIndexFile(const QString& path);
|
||||
void readIndexSection(QXmlStreamReader &reader, Node* current, const QString& indexUrl);
|
||||
void resolveIndex();
|
||||
void resolveRelates();
|
||||
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
|
||||
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user