summaryrefslogtreecommitdiff
path: root/src/qdoc/cppcodeparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qdoc/cppcodeparser.cpp')
-rw-r--r--src/qdoc/cppcodeparser.cpp622
1 files changed, 2 insertions, 620 deletions
diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp
index 07d0f8d4a..47cb455eb 100644
--- a/src/qdoc/cppcodeparser.cpp
+++ b/src/qdoc/cppcodeparser.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
/* qmake ignore Q_OBJECT */
static bool inMacroCommand_ = false;
-static bool parsingHeaderFile_ = false;
QStringList CppCodeParser::exampleFiles;
QStringList CppCodeParser::exampleDirs;
QSet<QString> CppCodeParser::excludeDirs;
@@ -201,63 +200,6 @@ const QSet<QString>& CppCodeParser::topicCommands()
}
/*!
-
- */
-Node* CppCodeParser::processFnCommand(const ArgLocPair& arg, const Doc& doc)
-{
- ExtraFuncData extra;
- QStringList parentPath;
- FunctionNode *func = 0;
- FunctionNode *clone = 0;
-
- if (!makeFunctionNode(arg.first, &parentPath, &clone, extra) &&
- !makeFunctionNode("void " + arg.first, &parentPath, &clone, extra)) {
- doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
- }
- else {
- func = qdb_->findFunctionNode(parentPath, clone);
- if (func == 0) {
- if (parentPath.isEmpty() && !lastPath_.isEmpty())
- func = qdb_->findFunctionNode(lastPath_, clone);
- }
- /*
- If the node was not found, then search for it in the
- open C++ namespaces. We don't expect this search to
- be necessary often. Nor do we expect it to succeed
- very often.
- */
- if (func == 0)
- func = qdb_->findNodeInOpenNamespace(parentPath, clone);
- if (func) {
- lastPath_ = parentPath;
- } else if (isWorthWarningAbout(doc)) {
- if (clone && clone->isSpecialMemberFunction()) {
- ClassNode* cn = qdb_->findClassNode(parentPath);
- if (cn) {
- cn->addChild(clone);
- clone->setImplicit(true);
- return clone;
- }
- }
- doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
- .arg(clone->name() + "(...)")
- .arg(COMMAND_FN)
- .arg(arg.first),
- tr("I cannot find any function of that name with the "
- "specified signature. Make sure that the signature "
- "is identical to the declaration, including 'const' "
- "qualifiers."));
- }
- if (func) {
- func->borrowParameterNames(clone);
- func->setParentPath(clone->parentPath());
- }
- delete clone;
- }
- return func;
-}
-
-/*!
Process the topic \a command found in the \a doc with argument \a arg.
*/
Node* CppCodeParser::processTopicCommand(const Doc& doc,
@@ -266,44 +208,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
{
ExtraFuncData extra;
if (command == COMMAND_FN) {
- return processFnCommand(arg, doc);
- }
- else if (command == COMMAND_MACRO) {
- QStringList parentPath;
- FunctionNode *func = 0;
-
- extra.root = qdb_->primaryTreeRoot();
- extra.isMacro = true;
- if (makeFunctionNode(arg.first, &parentPath, &func, extra)) {
- if (!parentPath.isEmpty()) {
- doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO));
- delete func;
- func = 0;
- }
- else {
- func->setMetaness(FunctionNode::MacroWithParams);
- QVector<Parameter> params = func->parameters();
- for (int i = 0; i < params.size(); ++i) {
- Parameter &param = params[i];
- if (param.name().isEmpty() && !param.dataType().isEmpty()
- && param.dataType() != "...")
- param = Parameter("", param.dataType());
- }
- func->setParameters(params);
- }
- return func;
- }
- else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) {
- func = new FunctionNode(qdb_->primaryTreeRoot(), arg.first);
- func->setAccess(Node::Public);
- func->setLocation(doc.startLocation());
- func->setMetaness(FunctionNode::MacroWithoutParams);
- }
- else {
- doc.location().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO));
-
- }
- return func;
+ Q_UNREACHABLE();
}
else if (nodeTypeMap.contains(command)) {
/*
@@ -465,50 +370,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
(command == COMMAND_JSMETHOD) ||
(command == COMMAND_JSATTACHEDSIGNAL) ||
(command == COMMAND_JSATTACHEDMETHOD)) {
- QString module;
- QString name;
- QString type;
- if (splitQmlMethodArg(arg.first, type, module, name, doc.location())) {
- Aggregate* aggregate = qdb_->findQmlType(module, name);
- if (!aggregate)
- aggregate = qdb_->findQmlBasicType(module, name);
- if (aggregate) {
- bool attached = false;
- Node::NodeType nodeType = Node::QmlMethod;
- if ((command == COMMAND_QMLSIGNAL) ||
- (command == COMMAND_JSSIGNAL))
- nodeType = Node::QmlSignal;
- else if ((command == COMMAND_QMLATTACHEDSIGNAL) ||
- (command == COMMAND_JSATTACHEDSIGNAL)) {
- nodeType = Node::QmlSignal;
- attached = true;
- }
- else if ((command == COMMAND_QMLMETHOD) ||
- (command == COMMAND_JSMETHOD)) {
- // do nothing
- }
- else if ((command == COMMAND_QMLATTACHEDMETHOD) ||
- (command == COMMAND_JSATTACHEDMETHOD))
- attached = true;
- else
- return 0; // never get here.
- FunctionNode* fn = makeFunctionNode(doc,
- arg.first,
- aggregate,
- nodeType,
- attached,
- command);
- if (fn) {
- fn->setLocation(doc.startLocation());
- if ((command == COMMAND_JSSIGNAL) ||
- (command == COMMAND_JSMETHOD) ||
- (command == COMMAND_JSATTACHEDSIGNAL) ||
- (command == COMMAND_JSATTACHEDMETHOD))
- fn->setGenus(Node::JS);
- }
- return fn;
- }
- }
+ Q_UNREACHABLE();
}
return 0;
}
@@ -596,57 +458,6 @@ bool CppCodeParser::splitQmlPropertyArg(const QString& arg,
}
/*!
- A QML signal or method argument has the form...
-
- <type> <QML-type>::<name>(<param>, <param>, ...)
- <type> <QML-module>::<QML-type>::<name>(<param>, <param>, ...)
-
- This function splits the \a{arg}ument into one of those
- two forms, sets \a type, \a module, and \a qmlTypeName,
- and returns true. If the argument doesn't match either
- form, an error message is emitted and false is returned.
-
- \note The two QML types \e{Component} and \e{QtObject} never
- have a module qualifier.
- */
-bool CppCodeParser::splitQmlMethodArg(const QString& arg,
- QString& type,
- QString& module,
- QString& qmlTypeName,
- const Location& location)
-{
- QString name;
- int leftParen = arg.indexOf(QChar('('));
- if (leftParen > 0)
- name = arg.left(leftParen);
- else
- name = arg;
- int firstBlank = name.indexOf(QChar(' '));
- if (firstBlank > 0) {
- type = name.left(firstBlank);
- name = name.right(name.length() - firstBlank - 1);
- }
- else
- type.clear();
-
- QStringList colonSplit(name.split("::"));
- if (colonSplit.size() > 1) {
- if (colonSplit.size() > 2) {
- module = colonSplit[0];
- qmlTypeName = colonSplit[1];
- }
- else {
- module.clear();
- qmlTypeName = colonSplit[0];
- }
- return true;
- }
- QString msg = "Unrecognizable QML module/component qualifier for " + arg;
- location.warning(tr(msg.toLatin1().data()));
- return false;
-}
-
-/*!
Process the topic \a command group found in the \a doc with arguments \a args.
Currently, this function is called only for \e{qmlproperty}
@@ -1309,376 +1120,6 @@ bool CppCodeParser::matchParameter(QVector<Parameter>& pvect, bool& isQPrivateSi
}
/*!
- If the current token is any of several function modifiers,
- return that token value after reading the next token. If it
- is not one of the function modieifer tokens, return -1 but
- don\t read the next token.
- */
-int CppCodeParser::matchFunctionModifier()
-{
- switch (tok) {
- case Tok_friend:
- case Tok_inline:
- case Tok_explicit:
- case Tok_static:
- case Tok_QT_DEPRECATED:
- readToken();
- return tok;
- case Tok_QT_COMPAT:
- case Tok_QT_COMPAT_CONSTRUCTOR:
- case Tok_QT_MOC_COMPAT:
- case Tok_QT3_SUPPORT:
- case Tok_QT3_SUPPORT_CONSTRUCTOR:
- case Tok_QT3_MOC_SUPPORT:
- readToken();
- return Tok_QT_COMPAT;
- default:
- break;
- }
- return -1;
-}
-
-bool CppCodeParser::matchFunctionDecl(Aggregate *parent,
- QStringList *parentPathPtr,
- FunctionNode **funcPtr,
- const QString &templateStuff,
- ExtraFuncData& extra)
-{
- CodeChunk returnType;
- QStringList parentPath;
- QString name;
-
- bool matched_QT_DEPRECATED = false;
- bool matched_friend = false;
- bool matched_static = false;
- bool matched_inline = false;
- bool matched_explicit = false;
- bool matched_compat = false;
-
- int token = tok;
- while (token != -1) {
- switch (token) {
- case Tok_friend:
- matched_friend = true;
- break;
- case Tok_inline:
- matched_inline = true;
- break;
- case Tok_explicit:
- matched_explicit = true;
- break;
- case Tok_static:
- matched_static = true;
- break;
- case Tok_QT_DEPRECATED:
- matched_QT_DEPRECATED = true;
- Q_FALLTHROUGH(); // no break here.
- case Tok_QT_COMPAT:
- matched_compat = true;
- break;
- }
- token = matchFunctionModifier();
- }
-
- FunctionNode::Virtualness virtuality = FunctionNode::NonVirtual;
- if (match(Tok_virtual)) {
- virtuality = FunctionNode::NormalVirtual;
- if (!matched_compat)
- matched_compat = matchCompat();
- }
-
- if (!matchDataType(&returnType)) {
- if (tokenizer->parsingFnOrMacro()
- && (match(Tok_Q_DECLARE_FLAGS) ||
- match(Tok_Q_PROPERTY) ||
- match(Tok_Q_PRIVATE_PROPERTY)))
- returnType = CodeChunk(previousLexeme());
- else {
- return false;
- }
- }
-
- if (returnType.toString() == "QBool")
- returnType = CodeChunk("bool");
-
- if (!matched_compat)
- matched_compat = matchCompat();
-
- if (tok == Tok_operator &&
- (returnType.toString().isEmpty() ||
- returnType.toString().endsWith("::"))) {
- // 'QString::operator const char *()'
- parentPath = returnType.toString().split(sep);
- parentPath.removeAll(QString());
- returnType = CodeChunk();
- readToken();
-
- CodeChunk restOfName;
- if (tok != Tok_Tilde && matchDataType(&restOfName)) {
- name = "operator " + restOfName.toString();
- }
- else {
- name = previousLexeme() + lexeme();
- readToken();
- while (tok != Tok_LeftParen && tok != Tok_Eoi) {
- name += lexeme();
- readToken();
- }
- }
- if (tok != Tok_LeftParen) {
- return false;
- }
- }
- else if (tok == Tok_LeftParen) {
- // constructor or destructor
- parentPath = returnType.toString().split(sep);
- if (!parentPath.isEmpty()) {
- name = parentPath.last();
- parentPath.erase(parentPath.end() - 1);
- }
- returnType = CodeChunk();
- }
- else {
- while (match(Tok_Ident)) {
- name = previousLexeme();
- /*
- This is a hack to let QML module identifiers through.
- */
- matchModuleQualifier(name);
- matchTemplateAngles();
-
- if (match(Tok_Gulbrandsen))
- parentPath.append(name);
- else
- break;
- }
-
- if (tok == Tok_operator) {
- name = lexeme();
- readToken();
- while (tok != Tok_Eoi) {
- name += lexeme();
- readToken();
- if (tok == Tok_LeftParen)
- break;
- }
- }
- if (parent && (tok == Tok_Semicolon ||
- tok == Tok_LeftBracket ||
- tok == Tok_Colon || tok == Tok_Equal)
- && access != Node::Private) {
- if (tok == Tok_LeftBracket) {
- returnType.appendHotspot();
-
- int bracketDepth0 = tokenizer->bracketDepth();
- while ((tokenizer->bracketDepth() >= bracketDepth0 &&
- tok != Tok_Eoi) ||
- tok == Tok_RightBracket) {
- returnType.append(lexeme());
- readToken();
- }
- if (tok != Tok_Semicolon) {
- return false;
- }
- }
- else if (tok == Tok_Colon || tok == Tok_Equal) {
- returnType.appendHotspot();
-
- while (tok != Tok_Semicolon && tok != Tok_Eoi) {
- returnType.append(lexeme());
- readToken();
- }
- if (tok != Tok_Semicolon) {
- return false;
- }
- }
-
- VariableNode *var = new VariableNode(parent, name);
- var->setAccess(access);
- if (parsingHeaderFile_)
- var->setLocation(declLoc());
- else
- var->setLocation(location());
- var->setLeftType(returnType.left());
- var->setRightType(returnType.right());
- if (matched_compat)
- var->setStatus(Node::Compat);
- var->setStatic(matched_static);
- return false;
- }
- if (tok != Tok_LeftParen)
- return false;
- }
- readToken();
-
- // A left paren was seen. Parse the parameters
- bool isQPrivateSignal = false;
- QVector<Parameter> pvect;
- if (tok != Tok_RightParen) {
- do {
- if (!matchParameter(pvect, isQPrivateSignal))
- return false;
- } while (match(Tok_Comma));
- }
- // The parameters must end with a right paren
- if (!match(Tok_RightParen))
- return false;
-
- // look for const
- bool matchedConst = match(Tok_const);
- bool matchedRef = match(Tok_Ampersand);
- bool matchedRefRef = false;
- if (match(Tok_Ampersand)) {
- matchedRef = false;
- matchedRefRef = true;
- }
- bool matchFinal = match(Tok_final);
- bool matchOverride = match(Tok_override);
-
- bool isDeleted = false;
- bool isDefaulted = false;
- if (match(Tok_Equal)) {
- if (match(Tok_Number)) // look for 0 indicating pure virtual
- virtuality = FunctionNode::PureVirtual;
- else if (match(Tok_delete))
- isDeleted = true;
- else if (match(Tok_default))
- isDefaulted = true;
- }
- // look for colon indicating ctors which must be skipped
- if (match(Tok_Colon)) {
- while (tok != Tok_LeftBrace && tok != Tok_Eoi)
- readToken();
- }
-
- // If no ';' expect a body, which must be skipped.
- bool body_expected = false;
- bool body_present = false;
- if (!match(Tok_Semicolon) && tok != Tok_Eoi) {
- body_expected = true;
- int nesting = tokenizer->braceDepth();
- if (!match(Tok_LeftBrace))
- return false;
- // skip the body
- while (tokenizer->braceDepth() >= nesting && tok != Tok_Eoi)
- readToken();
- body_present = true;
- match(Tok_RightBrace);
- }
-
- FunctionNode *func = 0;
- bool createFunctionNode = false;
- if (parsingHeaderFile_) {
- if (matched_friend) {
- if (matched_inline) {
- // nothing yet
- }
- if (body_present) {
- if (body_expected) {
- // nothing yet
- }
- createFunctionNode = true;
- if (parent && parent->parent())
- parent = parent->parent();
- else
- return false;
- }
- }
- else
- createFunctionNode = true;
- }
- else
- createFunctionNode = true;
-
- if (createFunctionNode) {
- func = new FunctionNode(extra.type, parent, name, extra.isAttached);
- if (matched_friend)
- access = Node::Public;
- func->setAccess(access);
- if (parsingHeaderFile_)
- func->setLocation(declLoc());
- else
- func->setLocation(location());
- func->setReturnType(returnType.toString());
- func->setParentPath(parentPath);
- func->setTemplateStuff(templateStuff);
- if (matched_compat)
- func->setStatus(Node::Compat);
- if (matched_QT_DEPRECATED)
- func->setStatus(Node::Deprecated);
- if (matched_explicit) { /* What can be done? */ }
- if (!pvect.isEmpty()) {
- func->setParameters(pvect);
- }
- func->setMetaness(metaness_);
- if ((parent && (name == parent->name())) ||
- (!parentPath.isEmpty() && name == parentPath.at(parentPath.size()-1))) {
- FunctionNode::Metaness m = FunctionNode::Ctor;
- if (!pvect.isEmpty()) {
- for (int i=0; i<pvect.size(); i++) {
- const Parameter& p = pvect.at(i);
- if (p.dataType().contains(name)) {
- if (p.dataType().endsWith(QLatin1String("&&"))) {
- m = FunctionNode::MCtor;
- break;
- }
- if (p.dataType().endsWith(QLatin1String("&"))) {
- m = FunctionNode::CCtor;
- break;
- }
- }
- }
- }
- func->setMetaness(m);
- }
- else if (name.startsWith(QLatin1Char('~')))
- func->setMetaness(FunctionNode::Dtor);
- else if (name == QLatin1String("operator=")) {
- FunctionNode::Metaness m = FunctionNode::Plain;
- if (pvect.size() == 1) {
- if (parent) {
- if (pvect.at(0).dataType().contains(parent->name())) {
- if (pvect.at(0).dataType().endsWith(QLatin1String("&&"))) {
- m = FunctionNode::MAssign;
- }
- else if (pvect.at(0).dataType().endsWith(QLatin1String("&"))) {
- m = FunctionNode::CAssign;
- }
- }
- }
- else if (!parentPath.isEmpty()) {
- if (pvect.at(0).dataType().contains(parentPath.at(parentPath.size()-1))) {
- if (pvect.at(0).dataType().endsWith(QLatin1String("&&"))) {
- m = FunctionNode::MAssign;
- }
- else if (pvect.at(0).dataType().endsWith(QLatin1String("&"))) {
- m = FunctionNode::CAssign;
- }
- }
- }
- }
- func->setMetaness(m);
- }
- func->setStatic(matched_static);
- func->setConst(matchedConst);
- func->setVirtualness(virtuality);
- func->setIsDeleted(isDeleted);
- func->setIsDefaulted(isDefaulted);
- func->setFinal(matchFinal);
- func->setOverride(matchOverride);
- if (isQPrivateSignal)
- func->setPrivateSignal();
- func->setRef(matchedRef);
- func->setRefRef(matchedRefRef);
- }
- if (parentPathPtr != 0)
- *parentPathPtr = parentPath;
- if (funcPtr != 0)
- *funcPtr = func;
- return true;
-}
-
-/*!
Match a C++ \c using clause. Return \c true if the match
is successful. Otherwise false.
@@ -1752,37 +1193,6 @@ bool CppCodeParser::matchUsingDecl(Aggregate* parent)
}
/*!
- This function uses a Tokenizer to parse the function \a signature
- in an attempt to match it to the signature of a child node of \a root.
- If a match is found, \a funcPtr is set to point to the matching node
- and true is returned.
- */
-bool CppCodeParser::makeFunctionNode(const QString& signature,
- QStringList* parentPathPtr,
- FunctionNode** funcPtr,
- ExtraFuncData& extra)
-{
- Tokenizer* outerTokenizer = tokenizer;
- int outerTok = tok;
-
- QByteArray latin1 = signature.toLatin1();
- Location tmpLoc(signature); // FIXME give a proper location with a filename.
- Tokenizer stringTokenizer(tokenizer ? location() : tmpLoc, latin1);
- stringTokenizer.setParsingFnOrMacro(true);
- tokenizer = &stringTokenizer;
- readToken();
-
- inMacroCommand_ = extra.isMacro;
- bool ok = matchFunctionDecl(extra.root, parentPathPtr, funcPtr, QString(), extra);
- inMacroCommand_ = false;
- // potential memory leak with funcPtr
-
- tokenizer = outerTokenizer;
- tok = outerTok;
- return ok;
-}
-
-/*!
This function uses a Tokenizer to parse the \a parameters of a
function into the parameter vector \a {pvect}.
*/
@@ -1810,34 +1220,6 @@ bool CppCodeParser::parseParameters(const QString& parameters,
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
- the complete signature, and if \a attached is true, the
- method or signal is "attached". \a qdoctag is the text of
- the \a type.
-
- \a parent is the QML class node. The QML module and QML
- type names have already been consumed to find \a parent.
- What remains in \a sig is the method signature. The method
- must be a child of \a parent.
- */
-FunctionNode* CppCodeParser::makeFunctionNode(const Doc& doc,
- const QString& sig,
- Aggregate* parent,
- Node::NodeType type,
- bool attached,
- QString qdoctag)
-{
- QStringList pp;
- FunctionNode* fn = 0;
- ExtraFuncData extra(parent, type, attached);
- if (!makeFunctionNode(sig, &pp, &fn, extra) && !makeFunctionNode("void " + sig, &pp, &fn, extra)) {
- doc.location().warning(tr("Invalid syntax in '\\%1'").arg(qdoctag));
- }
- return fn;
-}
-
void CppCodeParser::createExampleFileNodes(DocumentNode *dn)
{
QString examplePath = dn->name();