summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc/cppcodeparser.cpp
diff options
context:
space:
mode:
authorMartin Smith <[email protected]>2012-06-11 11:29:31 +0200
committerQt by Nokia <[email protected]>2012-06-12 04:29:31 +0200
commit14b07221664f95aea7603d6b7625c4467641b57c (patch)
treec77323108d2efc9e45f57e6a39a647248b54f906 /src/tools/qdoc/cppcodeparser.cpp
parent9e1a9878aaeac75f5c9e73a0d0e1a4e489e13cbc (diff)
qdoc: Better error messages for QML command errors
Some error messages were not clear for these qdoc commands: \qmlclass, \qmlmodule, \inqmlmodule, and \qmlproperty. They have been made clearer now. Also, qdoc now parses input files in the same order all the time now. The order is alphabetic now. This might not be the optimal order. Change-Id: Id53a5ec8105009c71f4bbd41973a54aed7821099 Reviewed-by: Casper van Donderen <[email protected]>
Diffstat (limited to 'src/tools/qdoc/cppcodeparser.cpp')
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp85
1 files changed, 45 insertions, 40 deletions
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index affc985890e..87374688442 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -210,8 +210,10 @@ void CppCodeParser::parseHeaderFile(const Location& location,
Tree *tree)
{
QFile in(filePath);
+ currentFile_ = filePath;
if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Cannot open C++ header file '%1'").arg(filePath));
+ currentFile_.clear();
return;
}
createOutputSubdirectory(location, filePath);
@@ -228,6 +230,7 @@ void CppCodeParser::parseHeaderFile(const Location& location,
if (fileLocation.fileName() == "qiterator.h")
parseQiteratorDotH(location, filePath);
+ currentFile_.clear();
}
/*!
@@ -242,8 +245,10 @@ void CppCodeParser::parseSourceFile(const Location& location,
Tree *tree)
{
QFile in(filePath);
+ currentFile_ = filePath;
if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Cannot open C++ source file '%1' (%2)").arg(filePath).arg(strerror(errno)));
+ currentFile_.clear();
return;
}
createOutputSubdirectory(location, filePath);
@@ -262,6 +267,7 @@ void CppCodeParser::parseSourceFile(const Location& location,
matchDocsAndStuff();
in.close();
+ currentFile_.clear();
}
/*!
@@ -479,7 +485,7 @@ QSet<QString> CppCodeParser::topicCommands()
}
/*!
- Process the topic \a command in context \a doc with argument \a arg.
+ Process the topic \a command found in the \a doc with argument \a arg.
*/
Node* CppCodeParser::processTopicCommand(const Doc& doc,
const QString& command,
@@ -492,7 +498,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
if (!makeFunctionNode(arg.first, &parentPath, &clone) &&
!makeFunctionNode("void " + arg.first, &parentPath, &clone)) {
- arg.second.warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
+ doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
}
else {
if (!activeNamespaces_.isEmpty()) {
@@ -543,7 +549,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
if (makeFunctionNode(arg.first, &parentPath, &func, tree_->root())) {
if (!parentPath.isEmpty()) {
- arg.second.warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO));
+ doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO));
delete func;
func = 0;
}
@@ -563,7 +569,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) {
func = new FunctionNode(tree_->root(), arg.first);
func->setAccess(Node::Public);
- func->setLocation(arg.second);
+ func->setLocation(doc.startLocation());
func->setMetaness(FunctionNode::MacroWithoutParams);
}
else {
@@ -635,39 +641,39 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
else if (command == COMMAND_EXAMPLE) {
if (Config::generateExamples) {
ExampleNode* en = new ExampleNode(tree_->root(), arg.first);
- en->setLocation(arg.second);
+ en->setLocation(doc.startLocation());
createExampleFileNodes(en);
return en;
}
}
else if (command == COMMAND_EXTERNALPAGE) {
FakeNode* fn = new FakeNode(tree_->root(), arg.first, Node::ExternalPage, Node::ArticlePage);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_FILE) {
FakeNode* fn = new FakeNode(tree_->root(), arg.first, Node::File, Node::NoPageType);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_GROUP) {
FakeNode* fn = new FakeNode(tree_->root(), arg.first, Node::Group, Node::OverviewPage);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_HEADERFILE) {
FakeNode* fn = new FakeNode(tree_->root(), arg.first, Node::HeaderFile, Node::ApiPage);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_MODULE) {
FakeNode* fn = new FakeNode(tree_->root(), arg.first, Node::Module, Node::OverviewPage);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_QMLMODULE) {
FakeNode* fn = FakeNode::lookupQmlModuleNode(tree_, arg);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_PAGE) {
@@ -708,7 +714,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
fn = new DitaMapNode(tree_->root(), args[0]);
else
fn = new FakeNode(tree_->root(), args[0], Node::Page, ptype);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
if (ncn) {
ncn->addCollision(fn);
}
@@ -716,7 +722,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
else if (command == COMMAND_DITAMAP) {
FakeNode* fn = new DitaMapNode(tree_->root(), arg.first);
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
else if (command == COMMAND_QMLCLASS) {
@@ -738,14 +744,27 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
*/
NameCollisionNode* ncn = tree_->checkForCollision(names[0]);
QmlClassNode* qcn = new QmlClassNode(tree_->root(), names[0], classNode);
- qcn->setLocation(arg.second);
+ qcn->setLocation(doc.startLocation());
+ if (isParsingCpp() || isParsingQdoc()) {
+ qcn->requireCppClass();
+ if (names.size() < 2) {
+ QString msg = "C++ class name not specified for class documented as "
+ "QML type: '\\qmlclass " + arg.first + " <class name>'";
+ doc.startLocation().warning(tr(msg.toLatin1().data()));
+ }
+ else if (!classNode) {
+ QString msg = "C++ class not found in any .h file for class documented "
+ "as QML type: '\\qmlclass " + arg.first + "'";
+ doc.startLocation().warning(tr(msg.toLatin1().data()));
+ }
+ }
if (ncn)
ncn->addCollision(qcn);
return qcn;
}
else if (command == COMMAND_QMLBASICTYPE) {
QmlBasicTypeNode* n = new QmlBasicTypeNode(tree_->root(), arg.first);
- n->setLocation(arg.second);
+ n->setLocation(doc.startLocation());
return n;
}
else if ((command == COMMAND_QMLSIGNAL) ||
@@ -780,7 +799,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
attached,
command);
if (fn)
- fn->setLocation(arg.second);
+ fn->setLocation(doc.startLocation());
return fn;
}
}
@@ -891,12 +910,14 @@ bool CppCodeParser::splitQmlMethodArg(const QString& arg,
}
/*!
- Process the topic \a command group with arguments \a args.
+ Process the topic \a command group found in the \a doc with arguments \a args.
Currently, this function is called only for \e{qmlproperty}
and \e{qmlattachedproperty}.
*/
-Node *CppCodeParser::processTopicCommandGroup(const QString& command, const ArgList& args)
+Node* CppCodeParser::processTopicCommandGroup(const Doc& doc,
+ const QString& command,
+ const ArgList& args)
{
QmlPropGroupNode* qmlPropGroup = 0;
if ((command == COMMAND_QMLPROPERTY) ||
@@ -914,46 +935,30 @@ Node *CppCodeParser::processTopicCommandGroup(const QString& command, const ArgL
qmlClass = tree_->findQmlClassNode(module,element);
if (qmlClass) {
qmlPropGroup = new QmlPropGroupNode(qmlClass,property); //,attached);
- qmlPropGroup->setLocation(location());
+ qmlPropGroup->setLocation(doc.startLocation());
}
}
if (qmlPropGroup) {
- const PropertyNode *correspondingProperty = 0;
if (qmlClass->hasProperty(property)) {
- location().warning(tr("QML property documented multiple times: '%1'").arg(arg));
+ doc.startLocation().warning(tr("QML property documented multiple times: '%1'").arg(arg));
}
else {
- ClassNode *correspondingClass = static_cast<QmlClassNode*>(qmlPropGroup->parent())->classNode();
QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached);
- qmlPropNode->setLocation(location());
- qmlPropNode->setQPropertyFlag();
-
- if (correspondingClass) {
- correspondingProperty = qmlPropNode->correspondingProperty(tree_);
- }
- if (correspondingProperty) {
- bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
- qmlPropNode->setReadOnly(!(writableList || correspondingProperty->isWritable()));
- }
+ qmlPropNode->setLocation(doc.startLocation());
}
++argsIter;
while (argsIter != args.constEnd()) {
arg = argsIter->first;
if (splitQmlPropertyArg(arg,type,module,element,property)) {
if (qmlClass->hasProperty(property)) {
- location().warning(tr("QML property documented multiple times: '%1'").arg(arg));
+ doc.startLocation().warning(tr("QML property documented multiple times: '%1'").arg(arg));
}
else {
QmlPropertyNode* qmlPropNode = new QmlPropertyNode(qmlPropGroup,
property,
type,
attached);
- qmlPropNode->setLocation(location());
- qmlPropNode->setQPropertyFlag();
- if (correspondingProperty) {
- bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
- qmlPropNode->setReadOnly(!(writableList || correspondingProperty->isWritable()));
- }
+ qmlPropNode->setLocation(doc.startLocation());
}
}
++argsIter;
@@ -2256,7 +2261,7 @@ bool CppCodeParser::matchDocsAndStuff()
if ((topic == COMMAND_QMLPROPERTY) ||
(topic == COMMAND_QMLATTACHEDPROPERTY)) {
Doc nodeDoc = doc;
- Node *node = processTopicCommandGroup(topic,args);
+ Node *node = processTopicCommandGroup(nodeDoc, topic,args);
if (node != 0) {
nodes.append(node);
docs.append(nodeDoc);