qdoc: Fixed bugs causing invalid DITA XML
Fixed a bug in qdoc that caused too many end elements to be generated. Also fixed some doc errors that caused invalid DITA to be generated. Task nr: QTBUG-25302 Change-Id: Ifbbf457d28c51c2691a252888447739da7713bc9 Reviewed-by: Martin Smith <martin.smith@nokia.com> Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>bb10
parent
eb52d31ddf
commit
aabd54b8bb
|
|
@ -288,7 +288,7 @@ QT_BEGIN_NAMESPACE
|
|||
Partial matching is mainly useful in two scenarios: validating user input
|
||||
in real time and incremental/multi-segment matching.
|
||||
|
||||
\target
|
||||
\target validating user input
|
||||
\section2 Validating user input
|
||||
|
||||
Suppose that we would like the user to input a date in a specific
|
||||
|
|
|
|||
|
|
@ -249,6 +249,14 @@ QString DitaXmlGenerator::ditaTags[] =
|
|||
""
|
||||
};
|
||||
|
||||
void DitaXmlGenerator::debugPara(const QString& t)
|
||||
{
|
||||
writeStartTag(DT_p);
|
||||
xmlWriter().writeAttribute("outputclass",t);
|
||||
xmlWriter().writeCharacters(t);
|
||||
writeEndTag(); // </p>
|
||||
}
|
||||
|
||||
static bool showBrokenLinks = false;
|
||||
|
||||
/*!
|
||||
|
|
@ -693,6 +701,13 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
static bool in_para = false;
|
||||
QString guid, hc, attr;
|
||||
|
||||
#if 0
|
||||
// Leave this here for debugging.
|
||||
if (outFileName() == "modules.dita") {
|
||||
QString comment = "ATOM:" + atom->typeString();
|
||||
xmlWriter().writeComment(comment);
|
||||
}
|
||||
#endif
|
||||
switch (atom->type()) {
|
||||
case Atom::AbstractLeft:
|
||||
break;
|
||||
|
|
@ -721,6 +736,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
{
|
||||
Node::Type t = relative->type();
|
||||
if (inSection()) {
|
||||
in_para = true;
|
||||
writeStartTag(DT_p);
|
||||
xmlWriter().writeAttribute("outputclass","brief");
|
||||
}
|
||||
|
|
@ -756,6 +772,8 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
case Atom::BriefRight:
|
||||
// if (relative->type() != Node::Fake)
|
||||
writeEndTag(); // </shortdesc> or </p>
|
||||
if (in_para)
|
||||
in_para = false;
|
||||
noLinks = false;
|
||||
break;
|
||||
case Atom::C:
|
||||
|
|
@ -769,13 +787,13 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
writeEndTag(); // see writeStartElement() above
|
||||
break;
|
||||
case Atom::Code:
|
||||
{
|
||||
writeStartTag(DT_codeblock);
|
||||
xmlWriter().writeAttribute("outputclass","cpp");
|
||||
QString chars = trimmedTrailing(atom->string());
|
||||
writeText(chars, marker, relative);
|
||||
writeEndTag(); // </codeblock>
|
||||
}
|
||||
{
|
||||
writeStartTag(DT_codeblock);
|
||||
xmlWriter().writeAttribute("outputclass","cpp");
|
||||
QString chars = trimmedTrailing(atom->string());
|
||||
writeText(chars, marker, relative);
|
||||
writeEndTag(); // </codeblock>
|
||||
}
|
||||
break;
|
||||
case Atom::Qml:
|
||||
writeStartTag(DT_codeblock);
|
||||
|
|
@ -866,71 +884,71 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
case Atom::FormatIf:
|
||||
break;
|
||||
case Atom::FormattingLeft:
|
||||
{
|
||||
DitaTag t = DT_LAST;
|
||||
if (atom->string() == ATOM_FORMATTING_BOLD)
|
||||
t = DT_b;
|
||||
else if (atom->string() == ATOM_FORMATTING_PARAMETER)
|
||||
t = DT_i;
|
||||
else if (atom->string() == ATOM_FORMATTING_ITALIC)
|
||||
t = DT_i;
|
||||
else if (atom->string() == ATOM_FORMATTING_TELETYPE)
|
||||
t = DT_tt;
|
||||
else if (atom->string().startsWith("span ")) {
|
||||
t = DT_keyword;
|
||||
}
|
||||
else if (atom->string() == ATOM_FORMATTING_UICONTROL)
|
||||
t = DT_uicontrol;
|
||||
else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
|
||||
t = DT_u;
|
||||
else if (atom->string() == ATOM_FORMATTING_INDEX)
|
||||
t = DT_comment;
|
||||
else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
|
||||
t = DT_sub;
|
||||
else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
|
||||
t = DT_sup;
|
||||
else
|
||||
qDebug() << "DT_LAST";
|
||||
writeStartTag(t);
|
||||
if (atom->string() == ATOM_FORMATTING_PARAMETER) {
|
||||
if (atom->next() != 0 && atom->next()->type() == Atom::String) {
|
||||
QRegExp subscriptRegExp("([a-z]+)_([0-9n])");
|
||||
if (subscriptRegExp.exactMatch(atom->next()->string())) {
|
||||
xmlWriter().writeCharacters(subscriptRegExp.cap(1));
|
||||
writeStartTag(DT_sub);
|
||||
xmlWriter().writeCharacters(subscriptRegExp.cap(2));
|
||||
writeEndTag(); // </sub>
|
||||
skipAhead = 1;
|
||||
{
|
||||
DitaTag t = DT_LAST;
|
||||
if (atom->string() == ATOM_FORMATTING_BOLD)
|
||||
t = DT_b;
|
||||
else if (atom->string() == ATOM_FORMATTING_PARAMETER)
|
||||
t = DT_i;
|
||||
else if (atom->string() == ATOM_FORMATTING_ITALIC)
|
||||
t = DT_i;
|
||||
else if (atom->string() == ATOM_FORMATTING_TELETYPE)
|
||||
t = DT_tt;
|
||||
else if (atom->string().startsWith("span ")) {
|
||||
t = DT_keyword;
|
||||
}
|
||||
else if (atom->string() == ATOM_FORMATTING_UICONTROL)
|
||||
t = DT_uicontrol;
|
||||
else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
|
||||
t = DT_u;
|
||||
else if (atom->string() == ATOM_FORMATTING_INDEX)
|
||||
t = DT_comment;
|
||||
else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
|
||||
t = DT_sub;
|
||||
else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
|
||||
t = DT_sup;
|
||||
else
|
||||
qDebug() << "DT_LAST";
|
||||
writeStartTag(t);
|
||||
if (atom->string() == ATOM_FORMATTING_PARAMETER) {
|
||||
if (atom->next() != 0 && atom->next()->type() == Atom::String) {
|
||||
QRegExp subscriptRegExp("([a-z]+)_([0-9n])");
|
||||
if (subscriptRegExp.exactMatch(atom->next()->string())) {
|
||||
xmlWriter().writeCharacters(subscriptRegExp.cap(1));
|
||||
writeStartTag(DT_sub);
|
||||
xmlWriter().writeCharacters(subscriptRegExp.cap(2));
|
||||
writeEndTag(); // </sub>
|
||||
skipAhead = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t == DT_keyword) {
|
||||
QString attr = atom->string().mid(5);
|
||||
if (!attr.isEmpty()) {
|
||||
if (attr.contains('=')) {
|
||||
int index = 0;
|
||||
int from = 0;
|
||||
QString values;
|
||||
while (index >= 0) {
|
||||
index = attr.indexOf('"',from);
|
||||
if (index >= 0) {
|
||||
++index;
|
||||
from = index;
|
||||
else if (t == DT_keyword) {
|
||||
QString attr = atom->string().mid(5);
|
||||
if (!attr.isEmpty()) {
|
||||
if (attr.contains('=')) {
|
||||
int index = 0;
|
||||
int from = 0;
|
||||
QString values;
|
||||
while (index >= 0) {
|
||||
index = attr.indexOf('"',from);
|
||||
if (index > from) {
|
||||
if (!values.isEmpty())
|
||||
values.append(' ');
|
||||
values += attr.mid(from,index-from);
|
||||
from = index+1;
|
||||
if (index >= 0) {
|
||||
++index;
|
||||
from = index;
|
||||
index = attr.indexOf('"',from);
|
||||
if (index > from) {
|
||||
if (!values.isEmpty())
|
||||
values.append(' ');
|
||||
values += attr.mid(from,index-from);
|
||||
from = index+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
attr = values;
|
||||
}
|
||||
attr = values;
|
||||
}
|
||||
xmlWriter().writeAttribute("outputclass", attr);
|
||||
}
|
||||
xmlWriter().writeAttribute("outputclass", attr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Atom::FormattingRight:
|
||||
if (atom->string() == ATOM_FORMATTING_LINK) {
|
||||
|
|
@ -941,17 +959,17 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
}
|
||||
break;
|
||||
case Atom::AnnotatedList:
|
||||
{
|
||||
QList<Node*> values = tree_->groups().values(atom->string());
|
||||
NodeMap nodeMap;
|
||||
for (int i = 0; i < values.size(); ++i) {
|
||||
const Node* n = values.at(i);
|
||||
if ((n->status() != Node::Internal) && (n->access() != Node::Private)) {
|
||||
nodeMap.insert(n->nameForLists(),n);
|
||||
{
|
||||
QList<Node*> values = tree_->groups().values(atom->string());
|
||||
NodeMap nodeMap;
|
||||
for (int i = 0; i < values.size(); ++i) {
|
||||
const Node* n = values.at(i);
|
||||
if ((n->status() != Node::Internal) && (n->access() != Node::Private)) {
|
||||
nodeMap.insert(n->nameForLists(),n);
|
||||
}
|
||||
}
|
||||
generateAnnotatedList(relative, marker, nodeMap);
|
||||
}
|
||||
generateAnnotatedList(relative, marker, nodeMap);
|
||||
}
|
||||
break;
|
||||
case Atom::GeneratedList:
|
||||
if (atom->string() == "annotatedclasses") {
|
||||
|
|
@ -1270,34 +1288,34 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
//xmlWriter().writeEmptyElement("br");
|
||||
break;
|
||||
case Atom::Link:
|
||||
{
|
||||
const Node *node = 0;
|
||||
QString myLink = getLink(atom, relative, marker, &node);
|
||||
if (myLink.isEmpty()) {
|
||||
myLink = getCollisionLink(atom);
|
||||
{
|
||||
const Node *node = 0;
|
||||
QString myLink = getLink(atom, relative, marker, &node);
|
||||
if (myLink.isEmpty()) {
|
||||
myLink = getCollisionLink(atom);
|
||||
}
|
||||
if (myLink.isEmpty()) {
|
||||
relative->doc().location().warning(tr("Can't link to '%1'")
|
||||
.arg(atom->string()));
|
||||
}
|
||||
else if (!inSectionHeading) {
|
||||
beginLink(myLink);
|
||||
}
|
||||
skipAhead = 1;
|
||||
}
|
||||
if (myLink.isEmpty()) {
|
||||
relative->doc().location().warning(tr("Can't link to '%1'")
|
||||
.arg(atom->string()));
|
||||
}
|
||||
else if (!inSectionHeading) {
|
||||
beginLink(myLink);
|
||||
}
|
||||
skipAhead = 1;
|
||||
}
|
||||
break;
|
||||
case Atom::GuidLink:
|
||||
{
|
||||
beginLink(atom->string());
|
||||
skipAhead = 1;
|
||||
}
|
||||
{
|
||||
beginLink(atom->string());
|
||||
skipAhead = 1;
|
||||
}
|
||||
break;
|
||||
case Atom::LinkNode:
|
||||
{
|
||||
const Node* node = CodeMarker::nodeForString(atom->string());
|
||||
beginLink(linkForNode(node, relative));
|
||||
skipAhead = 1;
|
||||
}
|
||||
{
|
||||
const Node* node = CodeMarker::nodeForString(atom->string());
|
||||
beginLink(linkForNode(node, relative));
|
||||
skipAhead = 1;
|
||||
}
|
||||
break;
|
||||
case Atom::ListLeft:
|
||||
if (in_para) {
|
||||
|
|
@ -1353,8 +1371,13 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
else // (atom->string() == ATOM_LIST_NUMERIC)
|
||||
xmlWriter().writeAttribute("outputclass","numeric");
|
||||
if (atom->next() != 0 && atom->next()->string().toInt() != 1) {
|
||||
// I don't think this attribute is supported.
|
||||
xmlWriter().writeAttribute("start",atom->next()->string());
|
||||
/*
|
||||
This attribute is not supported in DITA, and at the
|
||||
moment, including it is causing a validation error
|
||||
wherever it is used. I think it is onlym used in the
|
||||
qdoc manual.
|
||||
*/
|
||||
//xmlWriter().writeAttribute("start",atom->next()->string());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1629,47 +1652,48 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
writeEndTag(); // </row>
|
||||
break;
|
||||
case Atom::TableItemLeft:
|
||||
{
|
||||
QString values;
|
||||
writeStartTag(DT_entry);
|
||||
for (int i=0; i<atom->count(); ++i) {
|
||||
attr = atom->string(i);
|
||||
if (attr.contains('=')) {
|
||||
int index = 0;
|
||||
int from = 0;
|
||||
while (index >= 0) {
|
||||
index = attr.indexOf('"',from);
|
||||
if (index >= 0) {
|
||||
++index;
|
||||
from = index;
|
||||
{
|
||||
QString values;
|
||||
writeStartTag(DT_entry);
|
||||
for (int i=0; i<atom->count(); ++i) {
|
||||
attr = atom->string(i);
|
||||
if (attr.contains('=')) {
|
||||
int index = 0;
|
||||
int from = 0;
|
||||
while (index >= 0) {
|
||||
index = attr.indexOf('"',from);
|
||||
if (index > from) {
|
||||
if (!values.isEmpty())
|
||||
values.append(' ');
|
||||
values += attr.mid(from,index-from);
|
||||
from = index+1;
|
||||
if (index >= 0) {
|
||||
++index;
|
||||
from = index;
|
||||
index = attr.indexOf('"',from);
|
||||
if (index > from) {
|
||||
if (!values.isEmpty())
|
||||
values.append(' ');
|
||||
values += attr.mid(from,index-from);
|
||||
from = index+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
QStringList spans = attr.split(QLatin1Char(','));
|
||||
if (spans.size() == 2) {
|
||||
if ((spans[0].toInt()>1) || (spans[1].toInt()>1)) {
|
||||
values += "span(" + spans[0] + QLatin1Char(',') + spans[1] + QLatin1Char(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
QStringList spans = attr.split(QLatin1Char(','));
|
||||
if (spans.size() == 2) {
|
||||
if ((spans[0].toInt()>1) || (spans[1].toInt()>1)) {
|
||||
values += "span(" + spans[0] + QLatin1Char(',') + spans[1] + QLatin1Char(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!values.isEmpty())
|
||||
xmlWriter().writeAttribute("outputclass",values);
|
||||
if (matchAhead(atom, Atom::ParaLeft))
|
||||
skipAhead = 1;
|
||||
}
|
||||
if (!values.isEmpty())
|
||||
xmlWriter().writeAttribute("outputclass",values);
|
||||
if (matchAhead(atom, Atom::ParaLeft))
|
||||
skipAhead = 1;
|
||||
}
|
||||
break;
|
||||
case Atom::TableItemRight:
|
||||
if (inTableHeader)
|
||||
if (inTableHeader) {
|
||||
writeEndTag(); // </entry>
|
||||
}
|
||||
else {
|
||||
writeEndTag(); // </entry>
|
||||
}
|
||||
|
|
@ -1677,33 +1701,33 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
|
|||
skipAhead = 1;
|
||||
break;
|
||||
case Atom::TableOfContents:
|
||||
{
|
||||
int numColumns = 1;
|
||||
const Node* node = relative;
|
||||
{
|
||||
int numColumns = 1;
|
||||
const Node* node = relative;
|
||||
|
||||
Doc::Sections sectionUnit = Doc::Section4;
|
||||
QStringList params = atom->string().split(QLatin1Char(','));
|
||||
QString columnText = params.at(0);
|
||||
QStringList pieces = columnText.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
if (pieces.size() >= 2) {
|
||||
columnText = pieces.at(0);
|
||||
pieces.pop_front();
|
||||
QString path = pieces.join(" ").trimmed();
|
||||
node = findNodeForTarget(path, relative, marker, atom);
|
||||
Doc::Sections sectionUnit = Doc::Section4;
|
||||
QStringList params = atom->string().split(QLatin1Char(','));
|
||||
QString columnText = params.at(0);
|
||||
QStringList pieces = columnText.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
if (pieces.size() >= 2) {
|
||||
columnText = pieces.at(0);
|
||||
pieces.pop_front();
|
||||
QString path = pieces.join(" ").trimmed();
|
||||
node = findNodeForTarget(path, relative, marker, atom);
|
||||
}
|
||||
|
||||
if (params.size() == 2) {
|
||||
numColumns = qMax(columnText.toInt(), numColumns);
|
||||
sectionUnit = (Doc::Sections)params.at(1).toInt();
|
||||
}
|
||||
|
||||
if (node)
|
||||
generateTableOfContents(node,
|
||||
marker,
|
||||
sectionUnit,
|
||||
numColumns,
|
||||
relative);
|
||||
}
|
||||
|
||||
if (params.size() == 2) {
|
||||
numColumns = qMax(columnText.toInt(), numColumns);
|
||||
sectionUnit = (Doc::Sections)params.at(1).toInt();
|
||||
}
|
||||
|
||||
if (node)
|
||||
generateTableOfContents(node,
|
||||
marker,
|
||||
sectionUnit,
|
||||
numColumns,
|
||||
relative);
|
||||
}
|
||||
break;
|
||||
case Atom::Target:
|
||||
if (in_para) {
|
||||
|
|
@ -2278,7 +2302,7 @@ void DitaXmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker)
|
|||
writeProlog(fake);
|
||||
|
||||
writeStartTag(DT_body);
|
||||
enterSection(QString(),QString());
|
||||
enterSection("","");
|
||||
if (fake->subType() == Node::Module) {
|
||||
generateStatus(fake, marker);
|
||||
if (moduleNamespaceMap.contains(fake->name())) {
|
||||
|
|
@ -6412,7 +6436,7 @@ void DitaXmlGenerator::generateCollisionPages()
|
|||
generateHeader(ncn, ditaTitle);
|
||||
writeProlog(ncn);
|
||||
writeStartTag(DT_body);
|
||||
enterSection(QString(),QString());
|
||||
enterSection("","");
|
||||
|
||||
NodeMap nm;
|
||||
for (int i=0; i<collisions.size(); ++i) {
|
||||
|
|
|
|||
|
|
@ -457,6 +457,7 @@ private:
|
|||
void writeDitaRefs(const DitaRefList& ditarefs);
|
||||
void writeTopicrefs(NodeMultiMap* nmm, const QString& navtitle);
|
||||
bool isDuplicate(NodeMultiMap* nmm, const QString& key, Node* node);
|
||||
void debugPara(const QString& t);
|
||||
|
||||
private:
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2973,6 +2973,13 @@
|
|||
* /
|
||||
\endcode
|
||||
|
||||
\note This doesn't work in DITA XML, so don't use it because it
|
||||
produces a DITA XML file that doesn't validate. There probably is
|
||||
a way to do this in DITA, so if we figure it out, we will put it
|
||||
in. But this capability is not used anywhere other than right
|
||||
here, so it probably isn't important. For now, if you use this
|
||||
option, qdoc will ignore it and produce a list without it.
|
||||
|
||||
QDoc renders this as:
|
||||
|
||||
\list G
|
||||
|
|
|
|||
|
|
@ -2280,7 +2280,7 @@ bool QmlPropertyNode::isWritable(Tree* tree)
|
|||
return pn->isWritable();
|
||||
}
|
||||
else {
|
||||
location().warning(tr("Can't detect if QML property %1 isread-only; writable assumed.").arg(name()));
|
||||
location().warning(tr("Can't detect if QML property %1 is read-only; writable assumed.").arg(name()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue