From 8c5ce68fcf09d128072c31d74878fcb0fd9b9c7a Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 6 Aug 2015 13:47:44 +0200 Subject: qdoc: Allow formal parameters in link targets This update allows qdoc to handle \l commands for linking to functions, where the formal parameters are included in the link target. For example, \l {QWidget::find(QString name)} will only match a member function of QWidget that has a single parameter of type QString. The parameter name is not used in the search. Change-Id: I8a31c9a7ed632f12a0e6d8a33cbb5cd361098317 Task-number: QTBUG-47286 Reviewed-by: Martin Smith --- src/tools/qdoc/codeparser.h | 1 - src/tools/qdoc/cppcodemarker.cpp | 8 +- src/tools/qdoc/cppcodeparser.cpp | 74 ++++++++++++------ src/tools/qdoc/cppcodeparser.h | 16 +--- src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc | 9 ++- src/tools/qdoc/generator.cpp | 18 ++--- src/tools/qdoc/node.cpp | 101 +++++++++++++++++++------ src/tools/qdoc/node.h | 26 ++++--- src/tools/qdoc/qdocdatabase.cpp | 53 +++++++++++-- src/tools/qdoc/qdocdatabase.h | 11 +-- src/tools/qdoc/qdocindexfiles.cpp | 2 +- src/tools/qdoc/qmlvisitor.cpp | 4 +- src/tools/qdoc/tokenizer.cpp | 1 + src/tools/qdoc/tree.cpp | 17 +++-- src/tools/qdoc/tree.h | 6 +- 15 files changed, 237 insertions(+), 110 deletions(-) (limited to 'src/tools') diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h index 379deb7e23..9d9e9286ec 100644 --- a/src/tools/qdoc/codeparser.h +++ b/src/tools/qdoc/codeparser.h @@ -40,7 +40,6 @@ QT_BEGIN_NAMESPACE class Config; -class Node; class QString; class QDocDatabase; diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 868b249290..774ff115b9 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -157,11 +157,11 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, synopsis += "("; if (!func->parameters().isEmpty()) { //synopsis += QLatin1Char(' '); - QList::ConstIterator p = func->parameters().constBegin(); + QVector::ConstIterator p = func->parameters().constBegin(); while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; - synopsis += typified((*p).leftType()); + synopsis += typified((*p).dataType()); if (style != Subpage && !(*p).name().isEmpty()) synopsis += "<@param>" + protect((*p).name()) + ""; @@ -328,11 +328,11 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) synopsis = name; synopsis += QLatin1Char('('); if (!func->parameters().isEmpty()) { - QList::ConstIterator p = func->parameters().constBegin(); + QVector::ConstIterator p = func->parameters().constBegin(); while (p != func->parameters().constEnd()) { if (p != func->parameters().constBegin()) synopsis += ", "; - synopsis += typified((*p).leftType()); + synopsis += typified((*p).dataType()); if (!(*p).name().isEmpty()) { if (!synopsis.endsWith(QLatin1Char('('))) synopsis += QLatin1Char(' '); diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index cab416370a..8d9596c10b 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -54,6 +54,7 @@ static bool inMacroCommand_ = false; static bool parsingHeaderFile_ = false; QStringList CppCodeParser::exampleFiles; QStringList CppCodeParser::exampleDirs; +CppCodeParser* CppCodeParser::cppParser_ = 0; /*! The constructor initializes some regular expressions @@ -63,6 +64,7 @@ CppCodeParser::CppCodeParser() : varComment("/\\*\\s*([a-zA-Z_0-9]+)\\s*\\*/"), sep("(?:<[^>]+>)?::") { reset(); + cppParser_ = this; } /*! @@ -374,12 +376,12 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, } else { func->setMetaness(FunctionNode::MacroWithParams); - QList params = func->parameters(); + QVector params = func->parameters(); for (int i = 0; i < params.size(); ++i) { Parameter ¶m = params[i]; - if (param.name().isEmpty() && !param.leftType().isEmpty() - && param.leftType() != "...") - param = Parameter("", "", param.leftType()); + if (param.name().isEmpty() && !param.dataType().isEmpty() + && param.dataType() != "...") + param = Parameter("", "", param.dataType()); } func->setParameters(params); } @@ -1308,23 +1310,23 @@ bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var) /*! Parse the next function parameter, if there is one, and - append it to parameter list \a p. Return true if a parameter - is parsed and appended to \a p. Otherwise return false. + append it to parameter vector \a pvect. Return true if + a parameter is parsed and appended to \a pvect. + Otherwise return false. */ -bool CppCodeParser::matchParameter(ParsedParameterList& pplist) +bool CppCodeParser::matchParameter(QVector& pvect, bool& isQPrivateSignal) { - ParsedParameter pp; if (match(Tok_QPrivateSignal)) { - pp.qPrivateSignal_ = true; - pplist.append(pp); + isQPrivateSignal = true; return true; } + Parameter p; CodeChunk chunk; - if (!matchDataType(&chunk, &pp.name_)) { + if (!matchDataType(&chunk, &p.name_)) { return false; } - pp.dataType_ = chunk.toString(); + p.dataType_ = chunk.toString(); chunk.clear(); match(Tok_Comment); if (match(Tok_Equal)) { @@ -1336,8 +1338,8 @@ bool CppCodeParser::matchParameter(ParsedParameterList& pplist) readToken(); } } - pp.defaultValue_ = chunk.toString(); - pplist.append(pp); + p.defaultValue_ = chunk.toString(); + pvect.append(p); return true; } @@ -1542,10 +1544,11 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent, readToken(); // A left paren was seen. Parse the parameters - ParsedParameterList pplist; + bool isQPrivateSignal = false; + QVector pvect; if (tok != Tok_RightParen) { do { - if (!matchParameter(pplist)) + if (!matchParameter(pvect, isQPrivateSignal)) return false; } while (match(Tok_Comma)); } @@ -1629,13 +1632,10 @@ bool CppCodeParser::matchFunctionDecl(Aggregate *parent, func->setStatic(matched_static); func->setConst(matchedConst); func->setVirtualness(virtuality); - if (!pplist.isEmpty()) { - foreach (const ParsedParameter& pp, pplist) { - if (pp.qPrivateSignal_) - func->setPrivateSignal(); - else - func->addParameter(Parameter(pp.dataType_, "", pp.name_, pp.defaultValue_)); - } + if (isQPrivateSignal) + func->setPrivateSignal(); + if (!pvect.isEmpty()) { + func->setParameters(pvect); } } if (parentPathPtr != 0) @@ -2416,6 +2416,34 @@ bool CppCodeParser::makeFunctionNode(const QString& signature, return ok; } +/*! + This function uses a Tokenizer to parse the \a parameters of a + function into the parameter vector \a {pvect}. + */ +bool CppCodeParser::parseParameters(const QString& parameters, + QVector& pvect, + bool& isQPrivateSignal) +{ + Tokenizer* outerTokenizer = tokenizer; + int outerTok = tok; + + QByteArray latin1 = parameters.toLatin1(); + Tokenizer stringTokenizer(Location(), latin1); + stringTokenizer.setParsingFnOrMacro(true); + tokenizer = &stringTokenizer; + readToken(); + + inMacroCommand_ = false; + do { + if (!matchParameter(pvect, isQPrivateSignal)) + return false; + } while (match(Tok_Comma)); + + tokenizer = outerTokenizer; + tok = outerTok; + return true; +} + /*! Create a new FunctionNode for a QML method or signal, as specified by \a type, as a child of \a parent. \a sig is diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h index 733418e27a..ec04482321 100644 --- a/src/tools/qdoc/cppcodeparser.h +++ b/src/tools/qdoc/cppcodeparser.h @@ -51,16 +51,6 @@ class CppCodeParser : public CodeParser { Q_DECLARE_TR_FUNCTIONS(QDoc::CppCodeParser) - struct ParsedParameter { - bool qPrivateSignal_; - QString dataType_; - QString name_; - QString defaultValue_; - ParsedParameter() : qPrivateSignal_(false) { } - }; - friend class QTypeInfo; - typedef QVector ParsedParameterList; - struct ExtraFuncData { Aggregate* root; // Used as the parent. Node::NodeType type; // The node type: Function, etc. @@ -74,6 +64,7 @@ class CppCodeParser : public CodeParser public: CppCodeParser(); ~CppCodeParser(); + static CppCodeParser* cppParser() { return cppParser_; } virtual void initializeParser(const Config& config) Q_DECL_OVERRIDE; virtual void terminateParser() Q_DECL_OVERRIDE; @@ -84,6 +75,7 @@ public: virtual void parseSourceFile(const Location& location, const QString& filePath) Q_DECL_OVERRIDE; virtual void doneParsingHeaderFiles() Q_DECL_OVERRIDE; virtual void doneParsingSourceFiles() Q_DECL_OVERRIDE; + bool parseParameters(const QString& parameters, QVector& pvect, bool& isQPrivateSignal); protected: const QSet& topicCommands(); @@ -126,7 +118,7 @@ protected: bool matchTemplateAngles(CodeChunk *type = 0); bool matchTemplateHeader(); bool matchDataType(CodeChunk *type, QString *var = 0); - bool matchParameter(ParsedParameterList& pplist); + bool matchParameter(QVector& pvect, bool& isQPrivateSignal); bool matchFunctionDecl(Aggregate *parent, QStringList *parentPathPtr, FunctionNode **funcPtr, @@ -184,10 +176,10 @@ protected: static QStringList exampleFiles; static QStringList exampleDirs; + static CppCodeParser* cppParser_; QString exampleNameFilter; QString exampleImageFilter; }; -Q_DECLARE_TYPEINFO(CppCodeParser::ParsedParameter, Q_MOVABLE_TYPE); #define COMMAND_ABSTRACT Doc::alias("abstract") #define COMMAND_CLASS Doc::alias("class") diff --git a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc index 0f9ca463bb..49cbfc0654 100644 --- a/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-markupcmds.qdoc @@ -1839,8 +1839,13 @@ \li \c {\l QWidget} - The name of a class documented with the \l {class-command} {\\class} command. - \li \c {\l QWidget::sizeHint()} - The name of a member function, - documented with or without an \l {fn-command} {\\fn} command. + \li \c {\l QWidget::sizeHint()} - The signature of a function without + parameters. If a matching function without parameters can't be found, + the link is satisfied with the first matching function found. + + \li \c {\l QWidget::removeAction(QAction* action)} - The signature + of a function with parameters. If an exact match is not found, the + link is not satisfied and qdoc reports a \e {Can't link to...} error. \li \c {\l } - The subject of a \l {headerfile-command} {\\headerfile} command. diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 5153b0de5c..7dfbbb1cb8 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -804,9 +804,9 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) else if (node->type() == Node::Function) { const FunctionNode *func = static_cast(node); QSet definedParams; - QList::ConstIterator p = func->parameters().constBegin(); + QVector::ConstIterator p = func->parameters().constBegin(); while (p != func->parameters().constEnd()) { - if ((*p).name().isEmpty() && (*p).leftType() != QLatin1String("...") + if ((*p).name().isEmpty() && (*p).dataType() != QLatin1String("...") && func->name() != QLatin1String("operator++") && func->name() != QLatin1String("operator--")) { node->doc().location().warning(tr("Missing parameter name")); @@ -836,7 +836,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) else if (!(*a).isEmpty() && !documentedParams.contains(*a)) { bool needWarning = (func->status() > Node::Obsolete); if (func->overloadNumber() > 0) { - FunctionNode *primaryFunc = func->parent()->findFunctionNode(func->name()); + FunctionNode *primaryFunc = func->parent()->findFunctionNode(func->name(), QString()); if (primaryFunc) { foreach (const Parameter ¶m, primaryFunc->parameters()) { @@ -1504,7 +1504,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker) if (i != 0) code += ", "; const Parameter &p = func->parameters().at(i); - code += p.leftType() + p.rightType(); + code += p.dataType() + p.rightType(); } code += ")"; @@ -1516,7 +1516,7 @@ void Generator::generateOverloadedSignal(const Node* node, CodeMarker* marker) if (i != 0) code += ", "; const Parameter &p = func->parameters().at(i); - code += p.leftType(); + code += p.dataType(); if (code[code.size()-1].isLetterOrNumber()) code += " "; code += p.name() + p.rightType(); @@ -2049,14 +2049,14 @@ void Generator::supplementAlsoList(const Node *node, QList &alsoList) if (func->name().startsWith("set") && func->name().size() >= 4) { alternateName = func->name()[3].toLower(); alternateName += func->name().mid(4); - alternateFunc = func->parent()->findFunctionNode(alternateName); + alternateFunc = func->parent()->findFunctionNode(alternateName, QString()); if (!alternateFunc) { alternateName = "is" + func->name().mid(3); - alternateFunc = func->parent()->findFunctionNode(alternateName); + alternateFunc = func->parent()->findFunctionNode(alternateName, QString()); if (!alternateFunc) { alternateName = "has" + func->name().mid(3); - alternateFunc = func->parent()->findFunctionNode(alternateName); + alternateFunc = func->parent()->findFunctionNode(alternateName, QString()); } } } @@ -2064,7 +2064,7 @@ void Generator::supplementAlsoList(const Node *node, QList &alsoList) alternateName = "set"; alternateName += func->name()[0].toUpper(); alternateName += func->name().mid(1); - alternateFunc = func->parent()->findFunctionNode(alternateName); + alternateFunc = func->parent()->findFunctionNode(alternateName, QString()); } if (alternateFunc && alternateFunc->access() != Node::Private) { diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 8646e699a9..1ed6820fbf 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -34,11 +34,12 @@ #include "node.h" #include "tree.h" #include "codemarker.h" -#include "codeparser.h" +#include "cppcodeparser.h" #include #include "qdocdatabase.h" #include #include "generator.h" +#include "tokenizer.h" QT_BEGIN_NAMESPACE @@ -810,9 +811,56 @@ Node* Aggregate::findChildNode(const QString& name, NodeType type) Find a function node that is a child of this nose, such that the function node has the specified \a name. */ -FunctionNode *Aggregate::findFunctionNode(const QString& name) const -{ - return static_cast(primaryFunctionMap_.value(name)); +FunctionNode *Aggregate::findFunctionNode(const QString& name, const QString& params) const +{ + FunctionNode* pfn = static_cast(primaryFunctionMap_.value(name)); + FunctionNode* fn = pfn; + if (fn) { + const QVector* funcParams = &(fn->parameters()); + if (params.isEmpty() && funcParams->isEmpty()) + return fn; + bool isQPrivateSignal = false; // Not used in the search + QVector testParams; + if (!params.isEmpty()) { + CppCodeParser* cppParser = CppCodeParser::cppParser(); + cppParser->parseParameters(params, testParams, isQPrivateSignal); + } + NodeList funcs = secondaryFunctionMap_.value(name); + int i = -1; + while (fn) { + if (testParams.size() == funcParams->size()) { + if (testParams.isEmpty()) + return fn; + bool different = false; + for (int j=0; jat(j).dataType()) { + different = true; + break; + } + } + if (!different) + return fn; + } + if (++i < funcs.size()) { + fn = static_cast(funcs.at(i)); + funcParams = &(fn->parameters()); + } + else + fn = 0; + } + if (!fn && !testParams.empty()) + return 0; + } + /* + Most \l commands that link to functions don't include + the parameter declarations in the function signature, + so if the \l is meant to go to a function that does + have parameters, the algorithm above won't find it. + Therefore we must return the pointer to the function + in the primary function map in the cases where the + parameters should have been specified in the \l command. + */ + return (fn ? fn : pfn); } /*! @@ -1090,20 +1138,20 @@ void Aggregate::setIncludes(const QStringList& includes) */ bool Aggregate::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) { - if (f1->parameters().count() != f2->parameters().count()) + if (f1->parameters().size() != f2->parameters().size()) return false; if (f1->isConst() != f2->isConst()) return false; - QList::ConstIterator p1 = f1->parameters().constBegin(); - QList::ConstIterator p2 = f2->parameters().constBegin(); + QVector::ConstIterator p1 = f1->parameters().constBegin(); + QVector::ConstIterator p2 = f2->parameters().constBegin(); while (p2 != f2->parameters().constEnd()) { if ((*p1).hasType() && (*p2).hasType()) { if ((*p1).rightType() != (*p2).rightType()) return false; - QString t1 = p1->leftType(); - QString t2 = p2->leftType(); + QString t1 = p1->dataType(); + QString t2 = p2->dataType(); if (t1.length() < t2.length()) qSwap(t1, t2); @@ -1751,33 +1799,40 @@ void TypedefNode::setAssociatedEnum(const EnumNode *enume) /*! Constructs this parameter from the left and right types - \a leftType and rightType, the parameter \a name, and the + \a dataType and rightType, the parameter \a name, and the \a defaultValue. In practice, \a rightType is not used, and I don't know what is was meant for. */ -Parameter::Parameter(const QString& leftType, +Parameter::Parameter(const QString& dataType, const QString& rightType, const QString& name, const QString& defaultValue) - : leftType_(leftType), rightType_(rightType), name_(name), defaultValue_(defaultValue) + : dataType_(dataType), + rightType_(rightType), + name_(name), + defaultValue_(defaultValue) { + // nothing. } /*! - The standard copy constructor copies the strings from \a p. + Standard copy constructor copies \p. */ Parameter::Parameter(const Parameter& p) - : leftType_(p.leftType_), rightType_(p.rightType_), name_(p.name_), defaultValue_(p.defaultValue_) + : dataType_(p.dataType_), + rightType_(p.rightType_), + name_(p.name_), + defaultValue_(p.defaultValue_) { + // nothing. } /*! - Assigning Parameter \a p to this Parameter copies the - strings across. + standard assignment operator assigns \p. */ Parameter& Parameter::operator=(const Parameter& p) { - leftType_ = p.leftType_; + dataType_ = p.dataType_; rightType_ = p.rightType_; name_ = p.name_; defaultValue_ = p.defaultValue_; @@ -1791,7 +1846,7 @@ Parameter& Parameter::operator=(const Parameter& p) */ QString Parameter::reconstruct(bool value) const { - QString p = leftType_ + rightType_; + QString p = dataType_ + rightType_; if (!p.endsWith(QChar('*')) && !p.endsWith(QChar('&')) && !p.endsWith(QChar(' '))) p += QLatin1Char(' '); p += name_; @@ -1902,8 +1957,8 @@ void FunctionNode::addParameter(const Parameter& parameter) */ void FunctionNode::borrowParameterNames(const FunctionNode *source) { - QList::Iterator t = parameters_.begin(); - QList::ConstIterator s = source->parameters_.constBegin(); + QVector::Iterator t = parameters_.begin(); + QVector::ConstIterator s = source->parameters_.constBegin(); while (s != source->parameters_.constEnd() && t != parameters_.end()) { if (!(*s).name().isEmpty()) (*t).setName((*s).name()); @@ -1958,7 +2013,7 @@ bool FunctionNode::hasActiveAssociatedProperty() const QStringList FunctionNode::parameterNames() const { QStringList names; - QList::ConstIterator p = parameters().constBegin(); + QVector::ConstIterator p = parameters().constBegin(); while (p != parameters().constEnd()) { names << (*p).name(); ++p; @@ -1975,7 +2030,7 @@ QString FunctionNode::rawParameters(bool names, bool values) const { QString raw; foreach (const Parameter ¶meter, parameters()) { - raw += parameter.leftType() + parameter.rightType(); + raw += parameter.dataType() + parameter.rightType(); if (names) raw += parameter.name(); if (values) @@ -1991,7 +2046,7 @@ QString FunctionNode::rawParameters(bool names, bool values) const QStringList FunctionNode::reconstructParameters(bool values) const { QStringList reconstructedParameters; - QList::ConstIterator p = parameters().constBegin(); + QVector::ConstIterator p = parameters().constBegin(); while (p != parameters().constEnd()) { reconstructedParameters << (*p).reconstruct(values); ++p; diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index e9816dad19..596a71b6d5 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -376,7 +376,7 @@ public: Node* findChildNode(const QString& name, Node::Genus genus) const; Node* findChildNode(const QString& name, NodeType type); virtual void findChildren(const QString& name, NodeList& nodes) const Q_DECL_OVERRIDE; - FunctionNode* findFunctionNode(const QString& name) const; + FunctionNode* findFunctionNode(const QString& name, const QString& params) const; FunctionNode* findFunctionNode(const FunctionNode* clone) const; void addInclude(const QString &include); void setIncludes(const QStringList &includes); @@ -815,12 +815,11 @@ inline void EnumNode::setFlagsType(TypedefNode* t) t->setAssociatedEnum(this); } - class Parameter { public: Parameter() {} - Parameter(const QString& leftType, + Parameter(const QString& dataType, const QString& rightType = QString(), const QString& name = QString(), const QString& defaultValue = QString()); @@ -830,21 +829,24 @@ public: void setName(const QString& name) { name_ = name; } - bool hasType() const { return leftType_.length() + rightType_.length() > 0; } - const QString& leftType() const { return leftType_; } + bool hasType() const { return dataType_.length() + rightType_.length() > 0; } + const QString& dataType() const { return dataType_; } const QString& rightType() const { return rightType_; } const QString& name() const { return name_; } const QString& defaultValue() const { return defaultValue_; } QString reconstruct(bool value = false) const; -private: - QString leftType_; - QString rightType_; + public: + QString dataType_; + QString rightType_; // mws says remove this 04/08/2015 QString name_; QString defaultValue_; }; +//friend class QTypeInfo; +//Q_DECLARE_TYPEINFO(Parameter, Q_MOVABLE_TYPE); + class FunctionNode : public LeafNode { public: @@ -874,7 +876,7 @@ public: void setOverloadNumber(unsigned char n) { overloadNumber_ = n; } void setReimplemented(bool b); void addParameter(const Parameter& parameter); - inline void setParameters(const QList& parameters); + inline void setParameters(const QVector& parameters); void borrowParameterNames(const FunctionNode* source); void setReimplementedFrom(FunctionNode* from); @@ -907,7 +909,7 @@ public: virtual bool isJsMethod() const Q_DECL_OVERRIDE { return (type() == Node::QmlMethod) && (genus() == Node::JS); } - const QList& parameters() const { return parameters_; } + const QVector& parameters() const { return parameters_; } void clearParams() { parameters_.clear(); } QStringList parameterNames() const; QString rawParameters(bool names = false, bool values = false) const; @@ -957,7 +959,7 @@ private: bool privateSignal_: 1; bool overload_ : 1; unsigned char overloadNumber_; - QList parameters_; + QVector parameters_; const FunctionNode* reimplementedFrom_; PropNodeList associatedProperties_; QList reimplementedBy_; @@ -1030,7 +1032,7 @@ private: const PropertyNode* overrides_; }; -inline void FunctionNode::setParameters(const QList &p) +inline void FunctionNode::setParameters(const QVector &p) { parameters_ = p; } diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 5f2a61bb76..7f2e64b00c 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -380,6 +380,30 @@ QString QDocForest::getLinkCounts(QStringList& strings, QVector& counts) return depends; } +/*! + */ +const Node* QDocForest::findFunctionNode(const QString& target, + const Node* relative, + Node::Genus genus) +{ + QString function, params; + int length = target.length(); + if (target.endsWith(QChar(')'))) { + int position = target.lastIndexOf(QChar('(')); + params = target.mid(position+1, length-position-2); + function = target.left(position); + } + else + function = target; + foreach (Tree* t, searchOrder()) { + const Node* n = t->findFunctionNode(function, params, relative, genus); + if (n) + return n; + relative = 0; + } + return 0; +} + /*! \class QDocDatabase This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a lot of maps and @@ -1342,8 +1366,16 @@ void QDocDatabase::resolveNamespaces() } } } - - +#if 0 +/*! + */ +const Node* QDocDatabase::findFunctionNode(const QString& target, + const Node* relative, + Node::Genus genus) +{ + return forest_.findFunctionNode(target, relative, genus); +} +#endif /*! This function is called for autolinking to a \a type, which could be a function return type or a parameter @@ -1641,6 +1673,8 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q Atom* atom = const_cast(a); QStringList targetPath = atom->string().split("#"); QString first = targetPath.first().trimmed(); + if (Generator::debugging()) + qDebug() << " first:" << first; Tree* domain = 0; Node::Genus genus = Node::DontCare; @@ -1659,8 +1693,14 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q else if (domain) { if (first.endsWith(".html")) node = domain->findNodeByNameAndType(QStringList(first), Node::Document); - else if (first.endsWith("()")) - node = domain->findFunctionNode(first, 0, genus); + else if (first.endsWith(QChar(')'))) { + QString function, params; + int length = first.length(); + int position = first.lastIndexOf(QChar('(')); + params = first.mid(position+1, length-position-2); + function = first.left(position); + node = domain->findFunctionNode(function, params, 0, genus); + } else { int flags = SearchBaseClasses | SearchEnumValues; QStringList nodePath = first.split("::"); @@ -1683,8 +1723,11 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q if (!node && first.contains("/")) return findNodeForTarget(targetPath, relative, genus, ref); } - else if (first.endsWith("()")) + else if (first.endsWith(QChar(')'))) { node = findFunctionNode(first, relative, genus); + if (Generator::debugging()) + qDebug() << " node:" << node; + } else { node = findNodeForTarget(targetPath, relative, genus, ref); return node; diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h index 5d55ea48e1..80a92af4ed 100644 --- a/src/tools/qdoc/qdocdatabase.h +++ b/src/tools/qdoc/qdocdatabase.h @@ -141,15 +141,8 @@ class QDocForest const Node* findFunctionNode(const QString& target, const Node* relative, - Node::Genus genus) { - foreach (Tree* t, searchOrder()) { - const Node* n = t->findFunctionNode(target, relative, genus); - if (n) - return n; - relative = 0; - } - return 0; - } + Node::Genus genus); + const Node* findNodeForTarget(QStringList& targetPath, const Node* relative, Node::Genus genus, diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 37194b911c..8db901bbc7 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -1238,7 +1238,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, for (int i = 0; i < functionNode->parameters().size(); ++i) { Parameter parameter = functionNode->parameters()[i]; writer.writeStartElement("parameter"); - writer.writeAttribute("left", parameter.leftType()); + writer.writeAttribute("left", parameter.dataType()); writer.writeAttribute("right", parameter.rightType()); writer.writeAttribute("name", parameter.name()); writer.writeAttribute("default", parameter.defaultValue()); diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp index 6f63624bf0..155e1de054 100644 --- a/src/tools/qdoc/qmlvisitor.cpp +++ b/src/tools/qdoc/qmlvisitor.cpp @@ -675,7 +675,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::UiPublicMember *member) QString name = member->name.toString(); FunctionNode *qmlSignal = new FunctionNode(Node::QmlSignal, current, name, false); - QList parameters; + QVector parameters; for (QQmlJS::AST::UiParameterList *it = member->parameters; it; it = it->next) { if (!it->type.isEmpty() && !it->name.isEmpty()) parameters.append(Parameter(it->type.toString(), QString(), it->name.toString())); @@ -754,7 +754,7 @@ bool QmlDocVisitor::visit(QQmlJS::AST::FunctionDeclaration* fd) } if (overloads > 1) qmlMethod->setOverloadFlag(true); - QList parameters; + QVector parameters; QQmlJS::AST::FormalParameterList* formals = fd->formals; if (formals) { QQmlJS::AST::FormalParameterList* fpl = formals; diff --git a/src/tools/qdoc/tokenizer.cpp b/src/tools/qdoc/tokenizer.cpp index a85c3b00d8..987fff548c 100644 --- a/src/tools/qdoc/tokenizer.cpp +++ b/src/tools/qdoc/tokenizer.cpp @@ -33,6 +33,7 @@ #include "config.h" #include "tokenizer.h" +#include "generator.h" #include #include diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index e0fd68d2e7..d64903e61e 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -220,6 +220,7 @@ QmlTypeNode* Tree::findQmlTypeNode(const QStringList& path) used as the starting point. */ const FunctionNode* Tree::findFunctionNode(const QStringList& path, + const QString& params, const Node* relative, int findFlags, Node::Genus genus) const @@ -234,7 +235,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path, qcn = static_cast(n); } if (qcn) - return static_cast(qcn->findFunctionNode(path[2])); + return static_cast(qcn->findFunctionNode(path[2], params)); } if (!relative) @@ -254,7 +255,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path, const Node* next; if (i == path.size() - 1) - next = ((const Aggregate*) node)->findFunctionNode(path.at(i)); + next = ((const Aggregate*) node)->findFunctionNode(path.at(i), params); else next = ((const Aggregate*) node)->findChildNode(path.at(i), genus); @@ -262,7 +263,7 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path, NodeList baseClasses = allBaseClasses(static_cast(node)); foreach (const Node* baseClass, baseClasses) { if (i == path.size() - 1) - next = static_cast(baseClass)->findFunctionNode(path.at(i)); + next = static_cast(baseClass)->findFunctionNode(path.at(i), params); else next = static_cast(baseClass)->findChildNode(path.at(i), genus); @@ -1452,13 +1453,17 @@ void Tree::insertQmlType(const QString& key, QmlTypeNode* n) Split \a target on "::" and find the function node with that path. */ -const Node* Tree::findFunctionNode(const QString& target, const Node* relative, Node::Genus genus) +const Node* Tree::findFunctionNode(const QString& target, + const QString& params, + const Node* relative, + Node::Genus genus) const { QString t = target; - if (t.endsWith("()")) + if (t.endsWith("()")) { t.chop(2); + } QStringList path = t.split("::"); - const FunctionNode* fn = findFunctionNode(path, relative, SearchBaseClasses, genus); + const FunctionNode* fn = findFunctionNode(path, params, relative, SearchBaseClasses, genus); if (fn && fn->metaness() != FunctionNode::MacroWithoutParams) return fn; return 0; diff --git a/src/tools/qdoc/tree.h b/src/tools/qdoc/tree.h index 9e195c90ae..1fef15bc6d 100644 --- a/src/tools/qdoc/tree.h +++ b/src/tools/qdoc/tree.h @@ -107,7 +107,10 @@ class Tree ClassNode* findClassNode(const QStringList& path, const Node* start = 0) const; NamespaceNode* findNamespaceNode(const QStringList& path) const; FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone); - const Node* findFunctionNode(const QString& target, const Node* relative, Node::Genus genus); + const Node* findFunctionNode(const QString& target, + const QString& params, + const Node* relative, + Node::Genus genus) const; Node* findNodeRecursive(const QStringList& path, int pathIndex, @@ -163,6 +166,7 @@ class Tree NamespaceNode *root() { return &root_; } const FunctionNode *findFunctionNode(const QStringList &path, + const QString& params, const Node *relative = 0, int findFlags = 0, Node::Genus genus = Node::DontCare) const; -- cgit v1.2.3