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 <casper.vandonderen@nokia.com>
This commit is contained in:
parent
9e1a9878aa
commit
14b0722166
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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>";
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
Loading…
Reference in New Issue
Block a user