qdoc: Generate the links-to-broken-links page

The cross-module link report now contains an entry
for the links to broken links subpage. It is the
last entry in the links-to-links table on the QA
page.

Change-Id: I9e0b3ba5f2efe76055902467348db878dbed9991
Task-number: QTBUG-41850
Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
bb10
Martin Smith 2014-11-05 12:51:12 +01:00
parent 623891acd6
commit 98e77dab75
5 changed files with 87 additions and 23 deletions

View File

@ -340,14 +340,26 @@ void HtmlGenerator::generateQAPage()
out() << "<table class=\"valuelist\"><tr valign=\"top\" "
<< "class=\"even\"><th class=\"tblConst\">Destination Module</th>"
<< "<th class=\"tblval\">Link Count</th></tr>\n";
QString fileName;
for (int i = 0; i< strings.size(); ++i) {
QString fileName = generateLinksToLinksPage(strings.at(i), marker);
fileName = generateLinksToLinksPage(strings.at(i), marker);
out() << "<tr><td class=\"topAlign\"><tt>"
<< "<a href=\"" << fileName << "\">"
<< strings.at(i) << "</a>"
<< "</tt></td><td class=\"topAlign\"><tt>" << counts.at(i)
<< "</tt></td></tr>\n";
}
int count = 0;
fileName = generateLinksToBrokenLinksPage(marker, count);
if (count != 0) {
out() << "<tr><td class=\"topAlign\"><tt>"
<< "<a href=\"" << fileName << "\">"
<< "Broken Links" << "</a>"
<< "</tt></td><td class=\"topAlign\"><tt>" << count
<< "</tt></td></tr>\n";
}
out() << "</table>\n";
t = "The Optimal \"depends\" Variable";
out() << "<h2>" << protectEnc(t) << "</h2>\n";
@ -361,6 +373,10 @@ void HtmlGenerator::generateQAPage()
}
/*!
This function writes an html file containing a list of
links to links that originate in the current module and
go to targets in the specified \a module. The \a marker
is used for the same thing the marker is always used for.
*/
QString HtmlGenerator::generateLinksToLinksPage(const QString& module, CodeMarker* marker)
{
@ -391,6 +407,44 @@ QString HtmlGenerator::generateLinksToLinksPage(const QString& module, CodeMarke
return fileName;
}
/*!
This function writes an html file containing a list of
links to broken links that originate in the current
module and go nowwhere. It returns the name of the file
it generates, and it sets \a count to the number of
broken links that were found. The \a marker is used for
the same thing the marker is always used for.
*/
QString HtmlGenerator::generateLinksToBrokenLinksPage(CodeMarker* marker, int& count)
{
QString fileName;
NamespaceNode* node = qdb_->primaryTreeRoot();
TargetList* tlist = qdb_->getTargetList("broken");
if (tlist && !tlist->isEmpty()) {
count = tlist->size();
fileName = "aaa-links-to-broken-links.html";
beginSubPage(node, fileName);
QString title = "Links from " + defaultModuleName() + " that go nowhere";
generateHeader(title, node, marker);
generateTitle(title, Text(), SmallSubTitle, node, marker);
out() << "<p>This is the complete list of broken links in " << defaultModuleName() << ". ";
out() << "Click on a link to go directly to the actual link in the docs. ";
out() << "The target for the link could not be found.</p>\n";
out() << "<table class=\"alignedsummary\">\n";
foreach (TargetLoc* t, *tlist) {
// e.g.: <a name="link-8421"></a><a href="layout.html">Layout Management</a>
out() << "<tr><td class=\"memItemLeft leftAlign topAlign\">";
out() << "<a href=\"" << t->fileName_ << "#" << t->target_ << "\">";
out() << t->text_ << "</a>";
out() << "</td></tr>\n";
}
out() << "</table>\n";
generateFooter();
endSubPage();
}
return fileName;
}
/*!
Generate html from an instance of Atom.
*/
@ -421,8 +475,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
if ((relative->parent() != node) && !relative->isObsolete())
link.clear();
}
if (link.isEmpty())
if (link.isEmpty()) {
out() << protectEnc(atom->string());
}
else {
if (Generator::writeQaPages() && node && (atom->type() != Atom::NavAutoLink)) {
QString text = atom->string();
@ -918,6 +973,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
QString link = getLink(atom, relative, &node);
if (link.isEmpty() && (node != relative) && !noLinkErrors()) {
relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string()));
if (Generator::writeQaPages() && (atom->type() != Atom::NavAutoLink)) {
QString text = atom->next()->next()->string();
QString target = qdb_->getNewLinkTarget(node, outFileName(), text, true);
out() << "<a id=\"" << Doc::canonicalTitle(target) << "\" class=\"qa-mark\"></a>";
}
}
else {
if (Generator::writeQaPages() && node && (atom->type() != Atom::NavLink)) {

View File

@ -91,6 +91,7 @@ public:
protected:
virtual void generateQAPage();
QString generateLinksToLinksPage(const QString& module, CodeMarker* marker);
QString generateLinksToBrokenLinksPage(CodeMarker* marker, int& count);
virtual int generateAtom(const Atom *atom,
const Node *relative,
CodeMarker *marker);

View File

@ -392,8 +392,8 @@ class QDocDatabase
QString getLinkCounts(QStringList& strings, QVector<int>& counts) {
return forest_.getLinkCounts(strings, counts);
}
QString getNewLinkTarget(const Node* t, const QString& fileName, QString& text) {
return primaryTree()->getNewLinkTarget(t, fileName, text);
QString getNewLinkTarget(const Node* t, const QString& fileName, QString& text, bool broken = false) {
return primaryTree()->getNewLinkTarget(t, fileName, text, broken);
}
TargetList* getTargetList(const QString& t) { return primaryTree()->getTargetList(t); }
QStringList getTargetListKeys() { return primaryTree()->getTargetListKeys(); }

View File

@ -1423,27 +1423,29 @@ const Node* Tree::checkForCollision(const QString& name)
The node \a t
*/
QString Tree::getNewLinkTarget(const Node* t, const QString& fileName, QString& text)
QString Tree::getNewLinkTarget(const Node* t, const QString& fileName, QString& text, bool broken)
{
QString target;
if (t) {
QString moduleName;
if (t && !broken) {
Tree* tree = t->tree();
incrementLinkCount();
if (tree != this)
tree->incrementLinkCount();
target = QString("qa-target-%1").arg(-(linkCount()));
QString moduleName = tree->moduleName();
TargetLoc* tloc = new TargetLoc(target, fileName, text);
TargetList* tList = 0;
TargetListMap::iterator i = targetListMap_->find(moduleName);
if (i == targetListMap_->end()) {
tList = new TargetList;
i = targetListMap_->insert(moduleName, tList);
}
else
tList = i.value();
tList->append(tloc);
moduleName = tree->moduleName();
}
else
moduleName = "broken";
incrementLinkCount();
QString target = QString("qa-target-%1").arg(-(linkCount()));
TargetLoc* tloc = new TargetLoc(target, fileName, text, broken);
TargetList* tList = 0;
TargetListMap::iterator i = targetListMap_->find(moduleName);
if (i == targetListMap_->end()) {
tList = new TargetList;
i = targetListMap_->insert(moduleName, tList);
}
else
tList = i.value();
tList->append(tloc);
return target;
}

View File

@ -70,11 +70,12 @@ struct TargetRec
struct TargetLoc
{
public:
TargetLoc(const QString& t, const QString& fileName, const QString& text)
: target_(t), fileName_(fileName), text_(text) { }
TargetLoc(const QString& t, const QString& fileName, const QString& text, bool broken = false)
: target_(t), fileName_(fileName), text_(text), broken_(broken) { }
QString target_;
QString fileName_;
QString text_;
bool broken_;
};
typedef QMultiMap<QString, TargetRec*> TargetMap;
@ -205,7 +206,7 @@ class Tree
bool docsHaveBeenGenerated() const { return docsHaveBeenGenerated_; }
void setTreeHasBeenAnalyzed() { treeHasBeenAnalyzed_ = true; }
void setdocsHaveBeenGenerated() { docsHaveBeenGenerated_ = true; }
QString getNewLinkTarget(const Node* t, const QString& fileName, QString& text);
QString getNewLinkTarget(const Node* t, const QString& fileName, QString& text, bool broken);
TargetList* getTargetList(const QString& module);
QStringList getTargetListKeys() { return targetListMap_->keys(); }