summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tools/qdoc/codeparser.cpp24
-rw-r--r--src/tools/qdoc/codeparser.h6
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp85
-rw-r--r--src/tools/qdoc/cppcodeparser.h6
-rw-r--r--src/tools/qdoc/doc.cpp20
-rw-r--r--src/tools/qdoc/doc.h2
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp4
-rw-r--r--src/tools/qdoc/main.cpp50
-rw-r--r--src/tools/qdoc/node.cpp66
-rw-r--r--src/tools/qdoc/node.h17
-rw-r--r--src/tools/qdoc/puredocparser.cpp5
-rw-r--r--src/tools/qdoc/qmlcodeparser.cpp3
12 files changed, 205 insertions, 83 deletions
diff --git a/src/tools/qdoc/codeparser.cpp b/src/tools/qdoc/codeparser.cpp
index bfa0064631..1f82171d82 100644
--- a/src/tools/qdoc/codeparser.cpp
+++ b/src/tools/qdoc/codeparser.cpp
@@ -418,4 +418,28 @@ void CodeParser::createOutputSubdirectory(const Location& location,
}
}
+/*!
+ Returns true if the file being parsed is a .h file.
+ */
+bool CodeParser::isParsingH() const
+{
+ return currentFile_.endsWith(".h");
+}
+
+/*!
+ Returns true if the file being parsed is a .cpp file.
+ */
+bool CodeParser::isParsingCpp() const
+{
+ return currentFile_.endsWith(".cpp");
+}
+
+/*!
+ Returns true if the file being parsed is a .qdoc file.
+ */
+bool CodeParser::isParsingQdoc() const
+{
+ return currentFile_.endsWith(".qdoc");
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/codeparser.h b/src/tools/qdoc/codeparser.h
index c4429ff79a..94529338ad 100644
--- a/src/tools/qdoc/codeparser.h
+++ b/src/tools/qdoc/codeparser.h
@@ -75,6 +75,11 @@ public:
virtual void doneParsingHeaderFiles(Tree *tree);
virtual void doneParsingSourceFiles(Tree *tree) = 0;
+ bool isParsingH() const;
+ bool isParsingCpp() const;
+ bool isParsingQdoc() const;
+ const QString& currentFile() const { return currentFile_; }
+
void createOutputSubdirectory(const Location& location, const QString& filePath);
static void initialize(const Config& config);
@@ -95,6 +100,7 @@ protected:
static void extractPageLinkAndDesc(const QString& arg,
QString* link,
QString* desc);
+ QString currentFile_;
private:
static QString currentSubDir_;
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index affc985890..8737468844 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);
diff --git a/src/tools/qdoc/cppcodeparser.h b/src/tools/qdoc/cppcodeparser.h
index 45a6c466ec..68ed041481 100644
--- a/src/tools/qdoc/cppcodeparser.h
+++ b/src/tools/qdoc/cppcodeparser.h
@@ -86,10 +86,12 @@ public:
protected:
virtual QSet<QString> topicCommands();
- virtual Node *processTopicCommand(const Doc& doc,
+ virtual Node* processTopicCommand(const Doc& doc,
const QString& command,
const ArgLocPair& arg);
- virtual Node *processTopicCommandGroup(const QString& command, const ArgList& args);
+ virtual Node *processTopicCommandGroup(const Doc& doc,
+ const QString& command,
+ const ArgList& args);
bool splitQmlPropertyArg(const QString& arg,
QString& type,
QString& module,
diff --git a/src/tools/qdoc/doc.cpp b/src/tools/qdoc/doc.cpp
index 15d194e0af..268c20d690 100644
--- a/src/tools/qdoc/doc.cpp
+++ b/src/tools/qdoc/doc.cpp
@@ -1626,6 +1626,9 @@ void DocParser::parse(const QString& source,
priv->text.stripFirstAtom();
}
+/*!
+ Returns the current location.
+ */
Location &DocParser::location()
{
while (!openedInputs.isEmpty() && openedInputs.top() <= pos) {
@@ -2868,6 +2871,23 @@ const Location &Doc::location() const
return priv == 0 ? dummy : priv->start_loc;
}
+/*!
+ Returns the starting location of a qdoc comment.
+ */
+const Location& Doc::startLocation() const
+{
+ return location();
+}
+
+/*!
+ Returns the ending location of a qdoc comment.
+ */
+const Location& Doc::endLocation() const
+{
+ static const Location dummy;
+ return priv == 0 ? dummy : priv->end_loc;
+}
+
const QString &Doc::source() const
{
static QString null;
diff --git a/src/tools/qdoc/doc.h b/src/tools/qdoc/doc.h
index 1f83f95362..9d65eadbf1 100644
--- a/src/tools/qdoc/doc.h
+++ b/src/tools/qdoc/doc.h
@@ -156,6 +156,8 @@ public:
const DitaRefList& ditamap() const;
const Location &location() const;
+ const Location& startLocation() const;
+ const Location& endLocation() const;
bool isEmpty() const;
const QString& source() const;
const Text& body() const;
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index b5fec5d36d..991aae0306 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -4070,9 +4070,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node,
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
- if (!qpn->isReadOnlySet())
- qpn->setReadOnly(!qpn->isWritable(tree_));
- if (qpn->isReadOnly())
+ if (!qpn->isWritable(tree_))
out() << "<span class=\"qmlreadonly\">read-only</span>";
if (qpn->isDefault())
out() << "<span class=\"qmldefault\">default</span>";
diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp
index 9e1e3cddd0..41d2f44a68 100644
--- a/src/tools/qdoc/main.cpp
+++ b/src/tools/qdoc/main.cpp
@@ -319,8 +319,6 @@ static void processQdocconfFile(const QString &fileName)
QSet<QString> excludedDirs;
QSet<QString> excludedFiles;
- QSet<QString> headers;
- QSet<QString> sources;
QStringList headerList;
QStringList sourceList;
QStringList excludedDirsList;
@@ -339,23 +337,48 @@ static void processQdocconfFile(const QString &fileName)
}
headerList = config.getAllFiles(CONFIG_HEADERS,CONFIG_HEADERDIRS,excludedDirs,excludedFiles);
- headers = QSet<QString>::fromList(headerList);
+ QMap<QString,QString> headers;
+ for (int i=0; i<headerList.size(); ++i)
+ headers.insert(headerList[i],headerList[i]);
sourceList = config.getAllFiles(CONFIG_SOURCES,CONFIG_SOURCEDIRS,excludedDirs,excludedFiles);
- sources = QSet<QString>::fromList(sourceList);
-
+ QMap<QString,QString> sources;
+ for (int i=0; i<sourceList.size(); ++i)
+ sources.insert(sourceList[i],sourceList[i]);
+ QFile* files = new QFile("/Users/msmith/depot/qt5/qtdoc/files.out");
+ files->open(QFile::WriteOnly);
+ QTextStream* filesout = new QTextStream(files);
+#if 0
+ {
+ QSet<QString>::ConstIterator i = headers.begin();
+ while (i != headers.end()) {
+ //(*filesout) << (*i).mid((*i).lastIndexOf('/')+1) << "\n";
+ ++i;
+ }
+ i = sources.begin();
+ while (i != sources.end()) {
+ //(*filesout) << (*i).mid((*i).lastIndexOf('/')+1) << "\n";
+ ++i;
+ }
+ }
+ //filesout->flush();
+ //files->close();
+#endif
/*
Parse each header file in the set using the appropriate parser and add it
to the big tree.
*/
QSet<CodeParser *> usedParsers;
- QSet<QString>::ConstIterator h = headers.constBegin();
+ int parsed = 0;
+ QMap<QString,QString>::ConstIterator h = headers.constBegin();
while (h != headers.constEnd()) {
- CodeParser *codeParser = CodeParser::parserForHeaderFile(*h);
+ CodeParser *codeParser = CodeParser::parserForHeaderFile(h.key());
if (codeParser) {
- codeParser->parseHeaderFile(config.location(), *h, tree);
+ ++parsed;
+ codeParser->parseHeaderFile(config.location(), h.key(), tree);
usedParsers.insert(codeParser);
+ (*filesout) << (h.key()).mid((h.key()).lastIndexOf('/')+1) << "\n";
}
++h;
}
@@ -368,15 +391,20 @@ static void processQdocconfFile(const QString &fileName)
Parse each source text file in the set using the appropriate parser and
add it to the big tree.
*/
- QSet<QString>::ConstIterator s = sources.constBegin();
+ parsed = 0;
+ QMap<QString,QString>::ConstIterator s = sources.constBegin();
while (s != sources.constEnd()) {
- CodeParser *codeParser = CodeParser::parserForSourceFile(*s);
+ CodeParser *codeParser = CodeParser::parserForSourceFile(s.key());
if (codeParser) {
- codeParser->parseSourceFile(config.location(), *s, tree);
+ ++parsed;
+ codeParser->parseSourceFile(config.location(), s.key(), tree);
usedParsers.insert(codeParser);
+ (*filesout) << s.key().mid((s.key()).lastIndexOf('/')+1) << "\n";
}
++s;
}
+ filesout->flush();
+ files->close();
foreach (CodeParser *codeParser, usedParsers)
codeParser->doneParsingSourceFiles(tree);
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index 0e3286314b..4117c5090d 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -1331,7 +1331,7 @@ ClassNode::ClassNode(InnerNode *parent, const QString& name)
: InnerNode(Class, parent, name)
{
hidden = false;
- abstract = false;
+ abstract_ = false;
qmlelement = 0;
setPageType(ApiPage);
}
@@ -2043,7 +2043,8 @@ QmlClassNode::QmlClassNode(InnerNode *parent,
const QString& name,
ClassNode* cn)
: FakeNode(parent, name, QmlClass, Node::ApiPage),
- abstract(false),
+ abstract_(false),
+ cnodeRequired_(false),
cnode_(cn),
base_(0)
{
@@ -2160,10 +2161,10 @@ bool Node::setQmlModule(const ArgLocPair& arg)
return true;
}
else
- arg.second.warning(tr("Minor version number missing for '\\qmlmodule' or '\\inqmlmodule'; 0 assumed."));
+ arg.second.warning(tr("Minor version number must be included in second arg of '\\qmlmodule' and '\\inqmlmodule'; '.0' assumed."));
}
else
- arg.second.warning(tr("Module version number missing for '\\qmlmodule' or '\\inqmlmodule'; 1.0 assumed."));
+ arg.second.warning(tr("Module version number 'major.minor' must be second arg of '\\qmlmodule' and '\\inqmlmodule'; '1.0' assumed."));
return false;
}
@@ -2305,7 +2306,6 @@ QmlPropertyNode::QmlPropertyNode(QmlPropGroupNode *parent,
designable_(FlagValueDefault),
isdefault_(false),
attached_(attached),
- qproperty_(false),
readOnly_(FlagValueDefault)
{
setPageType(ApiPage);
@@ -2325,7 +2325,6 @@ QmlPropertyNode::QmlPropertyNode(QmlClassNode *parent,
designable_(FlagValueDefault),
isdefault_(false),
attached_(attached),
- qproperty_(false),
readOnly_(FlagValueDefault)
{
setPageType(ApiPage);
@@ -2352,32 +2351,63 @@ QmlPropertyNode::QmlPropertyNode(QmlPropertyNode* parent,
designable_(FlagValueDefault),
isdefault_(false),
attached_(attached),
- qproperty_(false),
readOnly_(FlagValueDefault)
{
setPageType(ApiPage);
}
+#if 0
+ const PropertyNode *correspondingProperty = 0;
+ ClassNode *correspondingClass = static_cast<QmlClassNode*>(qmlPropGroup->parent())->classNode();
+ if (correspondingClass) {
+ correspondingProperty = qmlPropNode->correspondingProperty(tree_);
+ }
+ if (correspondingProperty) {
+ bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
+ qmlPropNode->setReadOnly(!(writableList || correspondingProperty->isWritable()));
+ }
+
+ if (correspondingProperty) {
+ bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
+ qmlPropNode->setReadOnly(!(writableList || correspondingProperty->isWritable()));
+ }
+#endif
/*!
Returns true if a QML property or attached property is
- read-only. The algorithm for figuring this out is long
+ not read-only. The algorithm for figuring this out is long
amd tedious and almost certainly will break. It currently
- doesn't work for qmlproperty bool PropertyChanges::explicit,
- because the tokenizer gets confused on "explicit".
+ doesn't work for the qmlproperty:
+
+ \code
+ bool PropertyChanges::explicit,
+ \endcode
+
+ ...because the tokenizer gets confused on \e{explicit}.
*/
bool QmlPropertyNode::isWritable(Tree* tree)
{
if (readOnly_ != FlagValueDefault)
return !fromFlagValue(readOnly_, false);
- if (qproperty_) {
- PropertyNode* pn = correspondingProperty(tree);
- if (pn)
- return pn->isWritable();
-
- location().warning(tr("Can't detect if QML property %1::%2::%3 is read-only; "
- "writable assumed.")
- .arg(qmlModuleIdentifier()).arg(qmlTypeName()).arg(name()));
+ QmlClassNode* qcn = qmlClassNode();
+ if (qcn) {
+ if (qcn->cppClassRequired()) {
+ if (qcn->classNode()) {
+ PropertyNode* pn = correspondingProperty(tree);
+ if (pn)
+ return pn->isWritable();
+ else
+ location().warning(tr("No Q_PROPERTY for QML property %1::%2::%3 "
+ "in C++ class documented as QML type: "
+ "(property not found in the C++ class or its base classes)")
+ .arg(qmlModuleIdentifier()).arg(qmlTypeName()).arg(name()));
+ }
+ else
+ location().warning(tr("No Q_PROPERTY for QML property %1::%2::%3 "
+ "in C++ class documented as QML type: "
+ "(C++ class not specified or not found).")
+ .arg(qmlModuleIdentifier()).arg(qmlTypeName()).arg(name()));
+ }
}
return true;
}
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 5a67c72133..72b5f6df3f 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -436,8 +436,8 @@ public:
void setServiceName(const QString& value) { sname = value; }
QmlClassNode* qmlElement() { return qmlelement; }
void setQmlElement(QmlClassNode* qcn) { qmlelement = qcn; }
- virtual bool isAbstract() const { return abstract; }
- virtual void setAbstract(bool b) { abstract = b; }
+ virtual bool isAbstract() const { return abstract_; }
+ virtual void setAbstract(bool b) { abstract_ = b; }
PropertyNode* findPropertyNode(const QString& name);
QmlClassNode* findQmlBaseNode();
@@ -446,7 +446,7 @@ private:
QList<RelatedClass> derived;
QList<RelatedClass> ignoredBases;
bool hidden;
- bool abstract;
+ bool abstract_;
QString sname;
QmlClassNode* qmlelement;
};
@@ -543,10 +543,12 @@ public:
virtual void clearCurrentChild();
virtual const ImportList* importList() const { return &importList_; }
virtual void setImportList(const ImportList& il) { importList_ = il; }
- virtual bool isAbstract() const { return abstract; }
- virtual void setAbstract(bool b) { abstract = b; }
+ virtual bool isAbstract() const { return abstract_; }
+ virtual void setAbstract(bool b) { abstract_ = b; }
const FakeNode* qmlBase() const { return base_; }
void resolveInheritance(Tree* tree);
+ void requireCppClass() { cnodeRequired_ = true; }
+ bool cppClassRequired() const { return cnodeRequired_; }
static void addInheritedBy(const QString& base, Node* sub);
static void subclasses(const QString& base, NodeList& subs);
static void terminate();
@@ -560,7 +562,8 @@ public:
static QMap<QString, QmlClassNode*> qmlModuleMemberMap_;
private:
- bool abstract;
+ bool abstract_;
+ bool cnodeRequired_;
ClassNode* cnode_;
FakeNode* base_;
ImportList importList_;
@@ -641,7 +644,6 @@ public:
const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); }
void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); }
const NodeList& qmlPropNodes() const { return qmlPropNodes_; }
- void setQPropertyFlag() { qproperty_ = true; }
private:
QString type_;
@@ -649,7 +651,6 @@ private:
FlagValue designable_;
bool isdefault_;
bool attached_;
- bool qproperty_;
FlagValue readOnly_;
NodeList qmlPropNodes_;
};
diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp
index 19a19373bd..0b6c7baa5b 100644
--- a/src/tools/qdoc/puredocparser.cpp
+++ b/src/tools/qdoc/puredocparser.cpp
@@ -78,8 +78,10 @@ void PureDocParser::parseSourceFile(const Location& location,
Tree *tree)
{
QFile in(filePath);
+ currentFile_ = filePath;
if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Can't open source file '%1' (%2)").arg(filePath).arg(strerror(errno)));
+ currentFile_.clear();
return;
}
createOutputSubdirectory(location, filePath);
@@ -98,6 +100,7 @@ void PureDocParser::parseSourceFile(const Location& location,
processQdocComments();
in.close();
+ currentFile_.clear();
}
/*!
@@ -158,7 +161,7 @@ bool PureDocParser::processQdocComments()
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);
diff --git a/src/tools/qdoc/qmlcodeparser.cpp b/src/tools/qdoc/qmlcodeparser.cpp
index 688087d793..f096a390e8 100644
--- a/src/tools/qdoc/qmlcodeparser.cpp
+++ b/src/tools/qdoc/qmlcodeparser.cpp
@@ -142,8 +142,10 @@ void QmlCodeParser::parseSourceFile(const Location& location,
Tree *tree)
{
QFile in(filePath);
+ currentFile_ = filePath;
if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Cannot open QML file '%1'").arg(filePath));
+ currentFile_.clear();
return;
}
createOutputSubdirectory(location, filePath);
@@ -176,6 +178,7 @@ void QmlCodeParser::parseSourceFile(const Location& location,
<< ": QML syntax error at col " << msg.loc.startColumn
<< ": " << qPrintable(msg.message);
}
+ currentFile_.clear();
}
/*!