qdoc3: qdoc now handles overloaded methods for QML

When a C++ class is documented as a QML type, it can
have overloaded QML methods. These are now handled
correctly by qdoc. The method list for QML types is
now output with the full method signature. For signals
and handlers too.

Task-number:  QTBUG-24670
Change-Id: If529d4136f5b480373b6ac25d2dceef15e6ea3db
Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
bb10
Martin Smith 2012-03-13 14:46:28 +01:00 committed by Qt by Nokia
parent 8ac05adca7
commit 0d43b8c617
8 changed files with 81 additions and 15 deletions

View File

@ -288,12 +288,17 @@ QString CodeMarker::taggedNode(const Node* node)
}
tag = QLatin1String("@property");
break;
case Node::QmlMethod:
case Node::QmlSignal:
case Node::QmlSignalHandler:
tag = QLatin1String("@function");
break;
default:
tag = QLatin1String("@unknown");
break;
}
return QLatin1Char('<') + tag + QLatin1Char('>') + protect(name)
+ QLatin1String("</") + tag + QLatin1Char('>');
return (QLatin1Char('<') + tag + QLatin1Char('>') + protect(name)
+ QLatin1String("</") + tag + QLatin1Char('>'));
}
QString CodeMarker::taggedQmlNode(const Node* node)
@ -373,6 +378,13 @@ QString CodeMarker::sortName(const Node *node, const QString* name)
if (node->type() == Node::Property || node->type() == Node::Variable)
return QLatin1Char('E') + nodeName;
if ((node->type() == Node::QmlMethod) ||
(node->type() == Node::QmlSignal) ||
(node->type() == Node::QmlSignalHandler)) {
const FunctionNode* func = static_cast<const FunctionNode *>(node);
return QLatin1String("E") + func->signature();
}
return QLatin1Char('B') + nodeName;
}

View File

@ -342,19 +342,47 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node,
QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary)
{
QString name = taggedQmlNode(node);
if (summary) {
if (summary)
name = linkTag(node,name);
} else if (node->type() == Node::QmlProperty) {
else if (node->type() == Node::QmlProperty) {
const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node);
if (pn->isAttached())
name.prepend(pn->element() + QLatin1Char('.'));
}
name = "<@name>" + name + "</@name>";
QString synopsis = name;
QString synopsis;
if (node->type() == Node::QmlProperty) {
const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node);
synopsis += " : " + typified(pn->dataType());
synopsis = name + " : " + typified(pn->dataType());
}
else if ((node->type() == Node::QmlMethod) ||
(node->type() == Node::QmlSignal) ||
(node->type() == Node::QmlSignalHandler)) {
const FunctionNode* func = static_cast<const FunctionNode*>(node);
if (!func->returnType().isEmpty())
synopsis = typified(func->returnType()) + QLatin1Char(' ') + name;
else
synopsis = name;
synopsis += "(";
if (!func->parameters().isEmpty()) {
QList<Parameter>::ConstIterator p = func->parameters().begin();
while (p != func->parameters().end()) {
if (p != func->parameters().begin())
synopsis += ", ";
synopsis += typified((*p).leftType());
if (!(*p).name().isEmpty()) {
if (!synopsis.endsWith("("))
synopsis += " ";
synopsis += "<@param>" + protect((*p).name()) + "</@param>";
}
synopsis += protect((*p).rightType());
++p;
}
}
synopsis += QLatin1Char(')');
}
else
synopsis = name;
QString extra;
if (summary) {

View File

@ -797,8 +797,9 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,false,COMMAND_QMLSIGNAL);
else if (command == COMMAND_QMLATTACHEDSIGNAL)
return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,true,COMMAND_QMLATTACHEDSIGNAL);
else if (command == COMMAND_QMLMETHOD)
else if (command == COMMAND_QMLMETHOD) {
return makeFunctionNode(doc,arg,qmlClass,Node::QmlMethod,false,COMMAND_QMLMETHOD);
}
else if (command == COMMAND_QMLATTACHEDMETHOD)
return makeFunctionNode(doc,arg,qmlClass,Node::QmlMethod,true,COMMAND_QMLATTACHEDMETHOD);
else

View File

@ -297,14 +297,23 @@ void DitaXmlGenerator::writeStartTag(DitaTag t)
/*!
Pop the current DITA tag off the stack, and write the
appropriate end tag to the DITA XML file.
appropriate end tag to the DITA XML file. If \a t is
not \e DT_NONE (default), then \a t contains the enum
value of the tag that should be on top of the stack.
If the stack is empty, no end tag is written and false
is returned. Otherwise, an end tag is written and true
is returned.
*/
void DitaXmlGenerator::writeEndTag(DitaTag t)
bool DitaXmlGenerator::writeEndTag(DitaTag t)
{
if (tagStack.isEmpty())
return false;
DitaTag top = tagStack.pop();
if (t > DT_NONE && top != t)
qDebug() << "Expected:" << t << "ACTUAL:" << top;
xmlWriter().writeEndElement();
return true;
}
/*!
@ -2316,7 +2325,10 @@ void DitaXmlGenerator::generateFakeNode(const FakeNode* fake, CodeMarker* marker
}
}
leaveSection(); // </section>
writeEndTag(); // </body>
if (!writeEndTag()) { // </body>
fake->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(fake->name()));
return;
}
writeRelatedLinks(fake, marker);
writeEndTag(); // </topic>
}
@ -3215,16 +3227,19 @@ void DitaXmlGenerator::generateQmlItem(const Node* node,
}
marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
"<i>\\1<sub>\\2</sub></i>");
#if 0
marked.replace("<@param>", "<i>");
marked.replace("</@param>", "</i>");
marked.replace("<@extra>", "<tt>");
marked.replace("</@extra>", "</tt>");
#endif
if (summary) {
marked.remove("<@type>");
marked.remove("</@type>");
}
if (marked.contains("setAudioAlertEnabled"))
qDebug() << "MARKED:" << marked;
writeText(marked, marker, relative);
}
@ -3572,7 +3587,8 @@ void DitaXmlGenerator::writeText(const QString& markedCode,
html.clear();
}
writeStartTag(DT_i);
writeCharacters(" " + arg.toString());
//writeCharacters(" " + arg.toString());
writeCharacters(arg.toString());
writeEndTag(); // </i>
}
else if (k == 5) { // <@extra>

View File

@ -445,7 +445,7 @@ private:
void writeDitaMap(const Tree* tree);
void writeDitaMap(const DitaMapNode* node);
void writeStartTag(DitaTag t);
void writeEndTag(DitaTag t=DT_NONE);
bool writeEndTag(DitaTag t=DT_NONE);
DitaTag currentTag();
void clearSectionNesting() { sectionNestingLevel = 0; }
int enterApiDesc(const QString& outputclass, const QString& title);

View File

@ -98,6 +98,7 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
safeness_(UnspecifiedSafeness),
pageType_(NoPageType),
status_(Commendable),
indexNodeFlag_(false),
parent_(parent),
relatesTo_(0),
name_(name)

View File

@ -173,6 +173,7 @@ public:
void setPageType(PageType t) { pageType_ = t; }
void setPageType(const QString& t);
void setParent(InnerNode* n) { parent_ = n; }
void setIndexNodeFlag() { indexNodeFlag_ = true; }
virtual bool isInnerNode() const = 0;
virtual bool isReimp() const { return false; }
@ -183,6 +184,7 @@ public:
virtual bool isAbstract() const { return false; }
virtual void setAbstract(bool ) { }
virtual QString title() const { return QString(); }
bool isIndexNode() const { return indexNodeFlag_; }
Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; }
InnerNode* parent() const { return parent_; }
@ -240,13 +242,16 @@ protected:
private:
#ifdef Q_WS_WIN
Type nodeType_;
Access access_;
ThreadSafeness safeness_;
PageType pageType_;
Status status_;
#else
bool indexNodeFlag_;
#if 0
//ifdef Q_WS_WIN
//else
Type nodeType_ : 4;
Access access_ : 2;
ThreadSafeness safeness_ : 2;

View File

@ -1050,6 +1050,8 @@ void Tree::readIndexFile(const QString& path)
}
/*!
Read a <section> element from the index file and create the
appropriate node(s).
*/
void Tree::readIndexSection(const QDomElement& element,
InnerNode* parent,
@ -1364,6 +1366,7 @@ void Tree::readIndexSection(const QDomElement& element,
Doc doc(location, location, " ", emptySet); // placeholder
section->setDoc(doc);
section->setIndexNodeFlag();
if (section->isInnerNode()) {
InnerNode* inner = static_cast<InnerNode*>(section);