qdoc: Refactoring of qdoc data structures

This commit is the beginning of a significant
overhaul of qdoc. A new class, QDocDatabase, is
added, which will eventually encapsulate all the
data structures used by qdoc. In this commit, the
Tree class is made private and only accessible
from QDocDatabase. Several maps structures are
also moved into QDocDatabase from other classes.

Much dead code and unused parameters were removed.
Further simplification will follow.

Change-Id: I237411c50f3ced0d2fc8d3b0fbfdf4e55880f8e9
Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@nokia.com>
bb10
Martin Smith 2012-09-13 11:38:45 +02:00 committed by Qt by Nokia
parent 817a447467
commit 14f7eb86ca
35 changed files with 1814 additions and 2108 deletions

View File

@ -625,26 +625,16 @@ QString CodeMarker::macName(const Node *node, const QString &name)
return QLatin1Char('/') + protect(myName);
}
else {
return plainFullName(node) + QLatin1Char('/') + protect(myName);
return node->plainFullName() + QLatin1Char('/') + protect(myName);
}
}
/*!
Get the list of documentation sections for the children of
the specified QmlClassNode.
Returns an empty list of documentation sections.
*/
QList<Section> CodeMarker::qmlSections(const QmlClassNode* ,
SynopsisStyle )
QList<Section> CodeMarker::qmlSections(const QmlClassNode* , SynopsisStyle )
{
return QList<Section>();
}
const Node* CodeMarker::resolveTarget(const QString& /* target */,
const Tree* ,
const Node* ,
const Node* )
{
return 0;
}
QT_END_NAMESPACE

View File

@ -124,9 +124,6 @@ public:
virtual bool recognizeExtension(const QString& ext) = 0;
virtual bool recognizeLanguage(const QString& lang) = 0;
virtual Atom::Type atomType() const = 0;
virtual QString plainName(const Node *node) = 0;
virtual QString plainFullName(const Node *node,
const Node *relative = 0) = 0;
virtual QString markedUpCode(const QString& code,
const Node *relative,
const Location &location) = 0;
@ -145,12 +142,7 @@ public:
virtual QList<Section> sections(const InnerNode *inner,
SynopsisStyle style,
Status status) = 0;
virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode,
SynopsisStyle style);
virtual const Node* resolveTarget(const QString& target,
const Tree* tree,
const Node* relative,
const Node* self = 0);
virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style);
virtual QStringList macRefsForNode(Node* node);
static void initialize(const Config& config);

View File

@ -48,6 +48,7 @@
#include "tree.h"
#include "config.h"
#include "generator.h"
#include "qdocdatabase.h"
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@ -81,6 +82,7 @@ QMap<QString,QString> CodeParser::nameToTitle;
*/
CodeParser::CodeParser()
{
qdb_ = QDocDatabase::qdocDB();
parsers.prepend(this);
}
@ -114,16 +116,14 @@ QStringList CodeParser::headerFileNameFilter()
return sourceFileNameFilter();
}
void CodeParser::parseHeaderFile(const Location& location,
const QString& filePath,
Tree *tree)
void CodeParser::parseHeaderFile(const Location& location, const QString& filePath)
{
parseSourceFile(location, filePath, tree);
parseSourceFile(location, filePath);
}
void CodeParser::doneParsingHeaderFiles(Tree *tree)
void CodeParser::doneParsingHeaderFiles()
{
doneParsingSourceFiles(tree);
doneParsingSourceFiles();
}
/*!
@ -230,8 +230,7 @@ QSet<QString> CodeParser::commonMetaCommands()
void CodeParser::processCommonMetaCommand(const Location& location,
const QString& command,
const ArgLocPair& arg,
Node* node,
Tree* tree)
Node* node)
{
if (command == COMMAND_COMPAT) {
location.warning(tr("\\compat command used, but Qt3 compatibility is no longer supported"));
@ -241,21 +240,16 @@ void CodeParser::processCommonMetaCommand(const Location& location,
node->setStatus(Node::Deprecated);
}
else if (command == COMMAND_INGROUP) {
tree->addToGroup(node, arg.first);
qdb_->addToGroup(node, arg.first);
}
else if (command == COMMAND_INPUBLICGROUP) {
tree->addToPublicGroup(node, arg.first);
qdb_->addToPublicGroup(node, arg.first);
}
else if (command == COMMAND_INMODULE) {
node->setModuleName(arg.first);
qdb_->addToModule(arg.first,node);
}
else if (command == COMMAND_INQMLMODULE) {
node->setQmlModule(arg);
DocNode* fn = DocNode::lookupQmlModuleNode(tree, arg);
fn->addQmlModuleMember(node);
QString qmid = node->qmlModuleIdentifier();
QmlClassNode* qcn = static_cast<QmlClassNode*>(node);
QmlClassNode::insertQmlModuleMember(qmid, qcn);
qdb_->addToQmlModule(arg.first,node);
}
else if (command == COMMAND_MAINCLASS) {
node->setStatus(Node::Main);

View File

@ -39,15 +39,10 @@
**
****************************************************************************/
/*
codeparser.h
*/
#ifndef CODEPARSER_H
#define CODEPARSER_H
#include <QSet>
#include "node.h"
QT_BEGIN_NAMESPACE
@ -55,7 +50,7 @@ QT_BEGIN_NAMESPACE
class Config;
class Node;
class QString;
class Tree;
class QDocDatabase;
class CodeParser
{
@ -68,12 +63,10 @@ public:
virtual QString language() = 0;
virtual QStringList headerFileNameFilter();
virtual QStringList sourceFileNameFilter() = 0;
virtual void parseHeaderFile(const Location& location,
const QString& filePath, Tree *tree);
virtual void parseSourceFile(const Location& location,
const QString& filePath, Tree *tree) = 0;
virtual void doneParsingHeaderFiles(Tree *tree);
virtual void doneParsingSourceFiles(Tree *tree) = 0;
virtual void parseHeaderFile(const Location& location, const QString& filePath);
virtual void parseSourceFile(const Location& location, const QString& filePath) = 0;
virtual void doneParsingHeaderFiles();
virtual void doneParsingSourceFiles() = 0;
bool isParsingH() const;
bool isParsingCpp() const;
@ -96,11 +89,12 @@ protected:
void processCommonMetaCommand(const Location& location,
const QString& command,
const ArgLocPair& arg,
Node *node, Tree *tree);
Node *node);
static void extractPageLinkAndDesc(const QString& arg,
QString* link,
QString* desc);
QString currentFile_;
QDocDatabase* qdb_;
private:
static QString currentSubDir_;

View File

@ -116,38 +116,6 @@ Atom::Type CppCodeMarker::atomType() const
return Atom::Code;
}
/*!
Returns the \a node name, or "()" if \a node is a
Node::Function node.
*/
QString CppCodeMarker::plainName(const Node *node)
{
QString name = node->name();
if (node->type() == Node::Function)
name += QLatin1String("()");
return name;
}
QString CppCodeMarker::plainFullName(const Node *node, const Node *relative)
{
if (node->name().isEmpty()) {
return QLatin1String("global");
}
else {
QString fullName;
while (node) {
fullName.prepend(plainName(node));
if (node->parent() == relative ||
node->parent()->subType() == Node::Collision ||
node->parent()->name().isEmpty())
break;
fullName.prepend(QLatin1String("::"));
node = node->parent();
}
return fullName;
}
}
QString CppCodeMarker::markedUpCode(const QString &code,
const Node *relative,
const Location &location)
@ -834,40 +802,6 @@ QList<Section> CppCodeMarker::sections(const InnerNode *inner,
return sections;
}
/*!
Search the \a tree for a node named \a target
*/
const Node *CppCodeMarker::resolveTarget(const QString& target,
const Tree* tree,
const Node* relative,
const Node* self)
{
const Node* node = 0;
if (target.endsWith("()")) {
QString funcName = target;
funcName.chop(2);
QStringList path = funcName.split("::");
const FunctionNode* fn = tree->findFunctionNode(path, relative, Tree::SearchBaseClasses);
if (fn) {
/*
Why is this case not accepted?
*/
if (fn->metaness() != FunctionNode::MacroWithoutParams)
node = fn;
}
}
else if (target.contains(QLatin1Char('#'))) {
// This error message is never printed; I think we can remove the case.
qDebug() << "qdoc: target case not handled:" << target;
}
else {
QStringList path = target.split("::");
int flags = Tree::SearchBaseClasses | Tree::SearchEnumValues | Tree::NonFunction;
node = tree->findNode(path, relative, flags, self);
}
return node;
}
static const char * const typeTable[] = {
"bool", "char", "double", "float", "int", "long", "short",
"signed", "unsigned", "uint", "ulong", "ushort", "uchar", "void",

View File

@ -60,8 +60,6 @@ public:
virtual bool recognizeExtension(const QString& ext);
virtual bool recognizeLanguage(const QString& lang);
virtual Atom::Type atomType() const;
virtual QString plainName(const Node *node);
virtual QString plainFullName(const Node *node, const Node *relative);
virtual QString markedUpCode(const QString& code,
const Node *relative,
const Location &location);
@ -78,12 +76,7 @@ public:
virtual QList<Section> sections(const InnerNode *innerNode,
SynopsisStyle style,
Status status);
virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode,
SynopsisStyle style);
virtual const Node* resolveTarget(const QString& target,
const Tree* tree,
const Node* relative,
const Node* self = 0);
virtual QList<Section> qmlSections(const QmlClassNode* qmlClassNode, SynopsisStyle style);
private:
QString addMarkUp(const QString& protectedCode,

View File

@ -50,7 +50,7 @@
#include "config.h"
#include "cppcodeparser.h"
#include "tokenizer.h"
#include "tree.h"
#include "qdocdatabase.h"
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@ -60,54 +60,6 @@ QT_BEGIN_NAMESPACE
QStringList CppCodeParser::exampleFiles;
QStringList CppCodeParser::exampleDirs;
/*
This is used for fuzzy matching only, which in turn is only used
for Qt Jambi.
*/
static QString cleanType(const QString &type, Tree* tree)
{
QString result = type;
result.replace("qlonglong", "long long");
result.replace("qulonglong", "unsigned long long");
result.replace("qreal", "double");
result.replace(QRegExp("\\bu(int|short|char|long)\\b"), "unsigned \\1");
result.replace("QRgb", "unsigned int");
result.replace(" >", ">");
result.remove(" const[]");
result.replace("QStringList<QString>", "QStringList");
result.replace("qint8", "char");
result.replace("qint16", "short");
result.replace("qint32", "int");
result.replace("qint64", "long long");
result.replace("quint8", "unsigned char");
result.replace("quint16", "unsigned short");
result.replace("quint32", "unsigned int");
result.replace("quint64", "unsigned long long");
if (result.contains("QFlags")) {
QRegExp regExp("QFlags<(((?:[^<>]+::)*)([^<>:]+))>");
int pos = 0;
while ((pos = result.indexOf(regExp, pos)) != -1) {
// we assume that the path for the associated enum
// is the same as for the flag typedef
QStringList path = regExp.cap(2).split("::", QString::SkipEmptyParts);
QStringList tmpPath = QStringList(path) << regExp.cap(3);
EnumNode* en = tree->findEnumNode(tmpPath);
if (en && en->flagsType()) {
tmpPath = QStringList(path) << en->flagsType()->name();
result.replace(pos, regExp.matchedLength(), tmpPath.join("::"));
}
++pos;
}
}
if (result.contains("::")) {
// remove needless (and needful) class prefixes
QRegExp regExp("[A-Za-z0-9_]+::");
result.remove(regExp);
}
return result;
}
/*!
The constructor initializes some regular expressions
and calls reset().
@ -115,7 +67,7 @@ static QString cleanType(const QString &type, Tree* tree)
CppCodeParser::CppCodeParser()
: varComment("/\\*\\s*([a-zA-Z_0-9]+)\\s*\\*/"), sep("(?:<[^>]+>)?::")
{
reset(0);
reset();
}
/*!
@ -201,13 +153,11 @@ QStringList CppCodeParser::sourceFileNameFilter()
}
/*!
Parse the C++ header file identified by \a filePath
and add the parsed contents to the big \a tree. The
\a location is used for reporting errors.
Parse the C++ header file identified by \a filePath and add
the parsed contents to the database. The \a location is used
for reporting errors.
*/
void CppCodeParser::parseHeaderFile(const Location& location,
const QString& filePath,
Tree *tree)
void CppCodeParser::parseHeaderFile(const Location& location, const QString& filePath)
{
QFile in(filePath);
currentFile_ = filePath;
@ -218,14 +168,14 @@ void CppCodeParser::parseHeaderFile(const Location& location,
}
createOutputSubdirectory(location, filePath);
reset(tree);
reset();
Location fileLocation(filePath);
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
readToken();
matchDeclList(tree->root());
matchDeclList(qdb_->treeRoot());
if (!fileTokenizer.version().isEmpty())
tree->setVersion(fileTokenizer.version());
qdb_->setVersion(fileTokenizer.version());
in.close();
if (fileLocation.fileName() == "qiterator.h")
@ -235,14 +185,12 @@ void CppCodeParser::parseHeaderFile(const Location& location,
/*!
Get ready to parse the C++ cpp file identified by \a filePath
and add its parsed contents to the big \a tree. \a location is
and add its parsed contents to the database. \a location is
used for reporting errors.
Call matchDocsAndStuff() to do all the parsing and tree building.
*/
void CppCodeParser::parseSourceFile(const Location& location,
const QString& filePath,
Tree *tree)
void CppCodeParser::parseSourceFile(const Location& location, const QString& filePath)
{
QFile in(filePath);
currentFile_ = filePath;
@ -253,7 +201,7 @@ void CppCodeParser::parseSourceFile(const Location& location,
}
createOutputSubdirectory(location, filePath);
reset(tree);
reset();
Location fileLocation(filePath);
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
@ -276,41 +224,29 @@ void CppCodeParser::parseSourceFile(const Location& location,
inheritance links in the tree. But it also initializes a
bunch of stuff.
*/
void CppCodeParser::doneParsingHeaderFiles(Tree *tree)
void CppCodeParser::doneParsingHeaderFiles()
{
tree->resolveInheritance();
qdb_->resolveInheritance();
QMapIterator<QString, QString> i(sequentialIteratorClasses);
while (i.hasNext()) {
i.next();
instantiateIteratorMacro(i.key(),
i.value(),
sequentialIteratorDefinition,
tree);
instantiateIteratorMacro(i.key(), i.value(), sequentialIteratorDefinition);
}
i = mutableSequentialIteratorClasses;
while (i.hasNext()) {
i.next();
instantiateIteratorMacro(i.key(),
i.value(),
mutableSequentialIteratorDefinition,
tree);
instantiateIteratorMacro(i.key(), i.value(), mutableSequentialIteratorDefinition);
}
i = associativeIteratorClasses;
while (i.hasNext()) {
i.next();
instantiateIteratorMacro(i.key(),
i.value(),
associativeIteratorDefinition,
tree);
instantiateIteratorMacro(i.key(), i.value(), associativeIteratorDefinition);
}
i = mutableAssociativeIteratorClasses;
while (i.hasNext()) {
i.next();
instantiateIteratorMacro(i.key(),
i.value(),
mutableAssociativeIteratorDefinition,
tree);
instantiateIteratorMacro(i.key(), i.value(), mutableAssociativeIteratorDefinition);
}
sequentialIteratorDefinition.clear();
mutableSequentialIteratorDefinition.clear();
@ -326,130 +262,15 @@ void CppCodeParser::doneParsingHeaderFiles(Tree *tree)
This is called after all the source files (i.e., not the
header files) have been parsed. It traverses the tree to
resolve property links, normalize overload signatures, and
do other housekeeping of the tree.
do other housekeeping of the database.
*/
void CppCodeParser::doneParsingSourceFiles(Tree *tree)
void CppCodeParser::doneParsingSourceFiles()
{
tree->root()->clearCurrentChildPointers();
tree->root()->normalizeOverloads();
tree->fixInheritance();
tree->resolveProperties();
tree->root()->makeUndocumentedChildrenInternal();
}
/*!
This function searches the \a tree to find a FunctionNode
for a function with the signature \a synopsis. If the
\a relative node is provided, the search begins there. If
\a fuzzy is true, base classes are searched. The function
node is returned, if found.
*/
const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis,
Tree *tree,
Node *relative,
bool fuzzy)
{
QStringList parentPath;
FunctionNode *clone;
FunctionNode *func = 0;
int flags = fuzzy ? int(Tree::SearchBaseClasses) : 0;
reset(tree);
if (makeFunctionNode(synopsis, &parentPath, &clone)) {
func = tree->findFunctionNode(parentPath, clone, relative, flags);
/*
This is necessary because Roberto's parser resolves typedefs.
*/
if (!func && fuzzy) {
func = tree_->findFunctionNode(parentPath +
QStringList(clone->name()),
relative,
flags);
if (!func && clone->name().contains('_')) {
QStringList path = parentPath;
path << clone->name().split('_');
func = tree_->findFunctionNode(path, relative, flags);
}
if (func) {
NodeList overloads = func->parent()->overloads(func->name());
NodeList candidates;
for (int i = 0; i < overloads.count(); ++i) {
FunctionNode *overload = static_cast<FunctionNode *>(overloads.at(i));
if (overload->status() != Node::Compat
&& overload->parameters().count() == clone->parameters().count()
&& !overload->isConst() == !clone->isConst())
candidates << overload;
}
if (candidates.count() == 0)
return 0;
/*
There's only one function with the correct number
of parameters. That must be the one.
*/
if (candidates.count() == 1)
return static_cast<FunctionNode *>(candidates.first());
overloads = candidates;
candidates.clear();
for (int i = 0; i < overloads.count(); ++i) {
FunctionNode *overload = static_cast<FunctionNode *>(overloads.at(i));
QList<Parameter> params1 = overload->parameters();
QList<Parameter> params2 = clone->parameters();
int j;
for (j = 0; j < params1.count(); ++j) {
if (!params2.at(j).name().startsWith(params1.at(j).name()))
break;
}
if (j == params1.count())
candidates << overload;
}
/*
There are several functions with the correct
parameter count, but only one has the correct
parameter names.
*/
if (candidates.count() == 1)
return static_cast<FunctionNode *>(candidates.first());
candidates.clear();
for (int i = 0; i < overloads.count(); ++i) {
FunctionNode *overload = static_cast<FunctionNode *>(overloads.at(i));
QList<Parameter> params1 = overload->parameters();
QList<Parameter> params2 = clone->parameters();
int j;
for (j = 0; j < params1.count(); ++j) {
if (params1.at(j).rightType() != params2.at(j).rightType())
break;
if (cleanType(params1.at(j).leftType(), tree)
!= cleanType(params2.at(j).leftType(), tree))
break;
}
if (j == params1.count())
candidates << overload;
}
/*
There are several functions with the correct
parameter count, but only one has the correct
types, loosely compared.
*/
if (candidates.count() == 1)
return static_cast<FunctionNode *>(candidates.first());
return 0;
}
}
delete clone;
}
return func;
qdb_->treeRoot()->clearCurrentChildPointers();
qdb_->treeRoot()->normalizeOverloads();
qdb_->fixInheritance();
qdb_->resolveProperties();
qdb_->treeRoot()->makeUndocumentedChildrenInternal();
}
/*!
@ -505,18 +326,18 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
if (!activeNamespaces_.isEmpty()) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + parentPath;
func = tree_->findFunctionNode(newPath, clone);
func = qdb_->findFunctionNode(newPath, clone);
if (func)
break;
}
}
// Search the root namespace if no match was found.
if (func == 0)
func = tree_->findFunctionNode(parentPath, clone);
func = qdb_->findFunctionNode(parentPath, clone);
if (func == 0) {
if (parentPath.isEmpty() && !lastPath.isEmpty())
func = tree_->findFunctionNode(lastPath, clone);
if (parentPath.isEmpty() && !lastPath_.isEmpty())
func = qdb_->findFunctionNode(lastPath_, clone);
if (func == 0) {
doc.location().warning(tr("Cannot find '%1' in '\\%2' %3")
.arg(clone->name() + "(...)")
@ -529,13 +350,13 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
else {
doc.location().warning(tr("Missing '%1::' for '%2' in '\\%3'")
.arg(lastPath.join("::"))
.arg(lastPath_.join("::"))
.arg(clone->name() + "()")
.arg(COMMAND_FN));
}
}
else {
lastPath = parentPath;
lastPath_ = parentPath;
}
if (func) {
func->borrowParameterNames(clone);
@ -549,7 +370,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QStringList parentPath;
FunctionNode *func = 0;
if (makeFunctionNode(arg.first, &parentPath, &func, tree_->root())) {
if (makeFunctionNode(arg.first, &parentPath, &func, qdb_->treeRoot())) {
if (!parentPath.isEmpty()) {
doc.startLocation().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_MACRO));
delete func;
@ -569,7 +390,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return func;
}
else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg.first)) {
func = new FunctionNode(tree_->root(), arg.first);
func = new FunctionNode(qdb_->treeRoot(), arg.first);
func->setAccess(Node::Public);
func->setLocation(doc.startLocation());
func->setMetaness(FunctionNode::MacroWithoutParams);
@ -606,7 +427,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
if (!activeNamespaces_.isEmpty()) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + path;
node = tree_->findNodeByNameAndType(newPath, type, subtype, 0);
node = qdb_->findNodeByNameAndType(newPath, type, subtype);
if (node) {
path = newPath;
break;
@ -619,13 +440,13 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
for it in the root namespace.
*/
if (node == 0) {
node = tree_->findNodeByNameAndType(path, type, subtype, 0);
node = qdb_->findNodeByNameAndType(path, type, subtype);
}
if (node == 0) {
doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file")
.arg(arg.first).arg(command));
lastPath = path;
lastPath_ = path;
}
else if (node->isInnerNode()) {
@ -642,39 +463,41 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
}
else if (command == COMMAND_EXAMPLE) {
if (Config::generateExamples) {
ExampleNode* en = new ExampleNode(tree_->root(), arg.first);
ExampleNode* en = new ExampleNode(qdb_->treeRoot(), arg.first);
en->setLocation(doc.startLocation());
createExampleFileNodes(en);
return en;
}
}
else if (command == COMMAND_EXTERNALPAGE) {
DocNode* dn = new DocNode(tree_->root(), arg.first, Node::ExternalPage, Node::ArticlePage);
DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::ExternalPage, Node::ArticlePage);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_FILE) {
DocNode* dn = new DocNode(tree_->root(), arg.first, Node::File, Node::NoPageType);
DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::File, Node::NoPageType);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_GROUP) {
DocNode* dn = new DocNode(tree_->root(), arg.first, Node::Group, Node::OverviewPage);
DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::Group, Node::OverviewPage);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_HEADERFILE) {
DocNode* dn = new DocNode(tree_->root(), arg.first, Node::HeaderFile, Node::ApiPage);
DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::HeaderFile, Node::ApiPage);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_MODULE) {
DocNode* dn = new DocNode(tree_->root(), arg.first, Node::Module, Node::OverviewPage);
DocNode* dn = qdb_->addModule(arg.first);
//DocNode* dn = new DocNode(qdb_->treeRoot(), arg.first, Node::Module, Node::OverviewPage);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_QMLMODULE) {
DocNode* dn = DocNode::lookupQmlModuleNode(tree_, arg);
DocNode* dn = qdb_->addQmlModule(arg.first);
//DocNode* dn = DocNode::lookupQmlModuleNode(qdb_->tree(), arg);
dn->setLocation(doc.startLocation());
return dn;
}
@ -710,12 +533,12 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
If there is no collision, just create a new Page
node and return that one.
*/
NameCollisionNode* ncn = tree_->checkForCollision(args[0]);
NameCollisionNode* ncn = qdb_->checkForCollision(args[0]);
DocNode* dn = 0;
if (ptype == Node::DitaMapPage)
dn = new DitaMapNode(tree_->root(), args[0]);
dn = new DitaMapNode(qdb_->treeRoot(), args[0]);
else
dn = new DocNode(tree_->root(), args[0], Node::Page, ptype);
dn = new DocNode(qdb_->treeRoot(), args[0], Node::Page, ptype);
dn->setLocation(doc.startLocation());
if (ncn) {
ncn->addCollision(dn);
@ -723,7 +546,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return dn;
}
else if (command == COMMAND_DITAMAP) {
DocNode* dn = new DitaMapNode(tree_->root(), arg.first);
DocNode* dn = new DitaMapNode(qdb_->treeRoot(), arg.first);
dn->setLocation(doc.startLocation());
return dn;
}
@ -748,7 +571,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QML in a .qdoc file.
*/
if (names[1] != "0")
classNode = tree_->findClassNode(names[1].split("::"));
classNode = qdb_->findClassNode(names[1].split("::"));
}
/*
@ -762,8 +585,8 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
If there is no collision, just create a new QML class
node and return that one.
*/
NameCollisionNode* ncn = tree_->checkForCollision(names[0]);
QmlClassNode* qcn = new QmlClassNode(tree_->root(), names[0]);
NameCollisionNode* ncn = qdb_->checkForCollision(names[0]);
QmlClassNode* qcn = new QmlClassNode(qdb_->treeRoot(), names[0]);
qcn->setClassNode(classNode);
qcn->setLocation(doc.startLocation());
#if 0
@ -787,7 +610,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
return qcn;
}
else if (command == COMMAND_QMLBASICTYPE) {
QmlBasicTypeNode* n = new QmlBasicTypeNode(tree_->root(), arg.first);
QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->treeRoot(), arg.first);
n->setLocation(doc.startLocation());
return n;
}
@ -799,7 +622,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
QString element;
QString type;
if (splitQmlMethodArg(arg.first,type,module,element)) {
QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element);
QmlClassNode* qmlClass = qdb_->findQmlType(module,element);
if (qmlClass) {
bool attached = false;
Node::Type nodeType = Node::QmlMethod;
@ -956,7 +779,7 @@ Node* CppCodeParser::processTopicCommandGroup(const Doc& doc,
ArgList::ConstIterator argsIter = args.constBegin();
arg = argsIter->first;
if (splitQmlPropertyArg(arg,type,module,element,property)) {
qmlClass = tree_->findQmlClassNode(module,element);
qmlClass = qdb_->findQmlType(module,element);
if (qmlClass) {
qmlPropGroup = new QmlPropGroupNode(qmlClass,property); //,attached);
qmlPropGroup->setLocation(doc.startLocation());
@ -1085,16 +908,16 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
/*
It should be a header file, I think.
*/
n = tree_->findNodeByNameAndType(QStringList(arg), Node::Document, Node::NoSubType, 0);
n = qdb_->findNodeByNameAndType(QStringList(arg), Node::Document, Node::NoSubType);
}
else {
/*
If it wasn't a file, it should be either a class or a namespace.
*/
QStringList newPath = arg.split("::");
n = tree_->findClassNode(newPath);
n = qdb_->findClassNode(newPath);
if (!n)
n = tree_->findNamespaceNode(newPath);
n = qdb_->findNamespaceNode(newPath);
}
if (!n) {
@ -1137,7 +960,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
else if (command == COMMAND_QMLINSTANTIATES) {
if ((node->type() == Node::Document) && (node->subType() == Node::QmlClass)) {
ClassNode* classNode = tree_->findClassNode(arg.split("::"));
ClassNode* classNode = qdb_->findClassNode(arg.split("::"));
if (classNode)
node->setClassNode(classNode);
else
@ -1186,7 +1009,7 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
}
}
else {
processCommonMetaCommand(doc.location(),command,argLocPair,node,tree_);
processCommonMetaCommand(doc.location(),command,argLocPair,node);
}
}
@ -1213,14 +1036,13 @@ void CppCodeParser::processOtherMetaCommands(const Doc& doc, Node *node)
/*!
Resets the C++ code parser to its default initialized state.
*/
void CppCodeParser::reset(Tree *tree)
void CppCodeParser::reset()
{
tree_ = tree;
tokenizer = 0;
tok = 0;
access = Node::Public;
metaness = FunctionNode::Plain;
lastPath.clear();
lastPath_.clear();
moduleName.clear();
}
@ -1741,11 +1563,11 @@ bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass)
if (!matchDataType(&baseClass))
return false;
tree_->addBaseClass(classe,
access,
baseClass.toPath(),
baseClass.toString(),
classe->parent());
qdb_->addBaseClass(classe,
access,
baseClass.toPath(),
baseClass.toString(),
classe->parent());
return true;
}
@ -2026,9 +1848,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent)
}
if (key == "READ")
tree_->addPropertyFunction(property, value, PropertyNode::Getter);
qdb_->addPropertyFunction(property, value, PropertyNode::Getter);
else if (key == "WRITE") {
tree_->addPropertyFunction(property, value, PropertyNode::Setter);
qdb_->addPropertyFunction(property, value, PropertyNode::Setter);
property->setWritable(true);
}
else if (key == "STORED")
@ -2045,9 +1867,9 @@ bool CppCodeParser::matchProperty(InnerNode *parent)
}
}
else if (key == "RESET")
tree_->addPropertyFunction(property, value, PropertyNode::Resetter);
qdb_->addPropertyFunction(property, value, PropertyNode::Resetter);
else if (key == "NOTIFY") {
tree_->addPropertyFunction(property, value, PropertyNode::Notifier);
qdb_->addPropertyFunction(property, value, PropertyNode::Notifier);
} else if (key == "REVISION") {
int revision;
bool ok;
@ -2267,13 +2089,13 @@ bool CppCodeParser::matchDocsAndStuff()
if (matchFunctionDecl(0, &parentPath, &clone)) {
foreach (const QString& usedNamespace_, activeNamespaces_) {
QStringList newPath = usedNamespace_.split("::") + parentPath;
func = tree_->findFunctionNode(newPath, clone);
func = qdb_->findFunctionNode(newPath, clone);
if (func) {
break;
}
}
if (func == 0)
func = tree_->findFunctionNode(parentPath, clone);
func = qdb_->findFunctionNode(parentPath, clone);
if (func) {
func->borrowParameterNames(clone);
@ -2283,8 +2105,7 @@ bool CppCodeParser::matchDocsAndStuff()
delete clone;
}
else {
doc.location().warning(
tr("Cannot tie this documentation to anything"),
doc.location().warning(tr("Cannot tie this documentation to anything"),
tr("I found a /*! ... */ comment, but there was no "
"topic command (e.g., '\\%1', '\\%2') in the "
"comment and no function definition following "
@ -2340,7 +2161,7 @@ bool CppCodeParser::matchDocsAndStuff()
if ((*n)->isInnerNode() &&
((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n);
while (m->parent() != tree_->root())
while (m->parent() != qdb_->treeRoot())
m = m->parent();
if (m == *n)
((InnerNode *)*n)->addInclude((*n)->name());
@ -2369,7 +2190,7 @@ bool CppCodeParser::matchDocsAndStuff()
Signals are implemented in uninteresting files
generated by moc.
*/
node = tree_->findFunctionNode(parentPath, clone);
node = qdb_->findFunctionNode(parentPath, clone);
if (node != 0 && node->metaness() != FunctionNode::Signal)
node->setLocation(clone->location());
delete clone;
@ -2469,8 +2290,7 @@ void CppCodeParser::parseQiteratorDotH(const Location &location,
void CppCodeParser::instantiateIteratorMacro(const QString &container,
const QString &includeFile,
const QString &macroDef,
Tree * /* tree */)
const QString &macroDef)
{
QString resultingCode = macroDef;
resultingCode.replace(QRegExp("\\bC\\b"), container);
@ -2481,7 +2301,7 @@ void CppCodeParser::instantiateIteratorMacro(const QString &container,
Tokenizer stringTokenizer(loc, latin1);
tokenizer = &stringTokenizer;
readToken();
matchDeclList(tree_->root());
matchDeclList(QDocDatabase::qdocDB()->treeRoot());
}
void CppCodeParser::createExampleFileNodes(DocNode *dn)

View File

@ -39,10 +39,6 @@
**
****************************************************************************/
/*
cppcodeparser.h
*/
#ifndef CPPCODEPARSER_H
#define CPPCODEPARSER_H
@ -70,19 +66,10 @@ public:
virtual QString language();
virtual QStringList headerFileNameFilter();
virtual QStringList sourceFileNameFilter();
virtual void parseHeaderFile(const Location& location,
const QString& filePath,
Tree *tree);
virtual void parseSourceFile(const Location& location,
const QString& filePath,
Tree *tree);
virtual void doneParsingHeaderFiles(Tree *tree);
virtual void doneParsingSourceFiles(Tree *tree);
const FunctionNode *findFunctionNode(const QString& synopsis,
Tree *tree,
Node *relative = 0,
bool fuzzy = false);
virtual void parseHeaderFile(const Location& location, const QString& filePath);
virtual void parseSourceFile(const Location& location, const QString& filePath);
virtual void doneParsingHeaderFiles();
virtual void doneParsingSourceFiles();
protected:
virtual QSet<QString> topicCommands();
@ -109,7 +96,7 @@ protected:
void processOtherMetaCommands(const Doc& doc, Node *node);
protected:
void reset(Tree *tree);
void reset();
void readToken();
const Location& location();
QString previousLexeme();
@ -157,19 +144,17 @@ protected:
void parseQiteratorDotH(const Location &location, const QString &filePath);
void instantiateIteratorMacro(const QString &container,
const QString &includeFile,
const QString &macroDef,
Tree *tree);
const QString &macroDef);
void createExampleFileNodes(DocNode *dn);
protected:
QMap<QString, Node::Type> nodeTypeMap;
Tree* tree_;
Tokenizer *tokenizer;
int tok;
Node::Access access;
FunctionNode::Metaness metaness;
QString moduleName;
QStringList lastPath;
QStringList lastPath_;
QRegExp varComment;
QRegExp sep;
QSet<QString> activeNamespaces_;

File diff suppressed because it is too large Load Diff

View File

@ -301,7 +301,7 @@ public:
virtual void terminateGenerator();
virtual QString format();
virtual bool canHandleFormat(const QString& format);
virtual void generateTree(Tree *tree);
virtual void generateTree();
void generateCollisionPages();
QString protectEnc(const QString& string);
@ -310,7 +310,6 @@ public:
static QString sinceTitle(int i) { return sinceTitles[i]; }
protected:
virtual void startText(const Node* relative, CodeMarker* marker);
virtual int generateAtom(const Atom* atom,
const Node* relative,
CodeMarker* marker);
@ -325,17 +324,14 @@ protected:
QString fullQualification(const Node* n);
void writeCharacters(const QString& text);
void writeDerivations(const ClassNode* cn, CodeMarker* marker);
void writeDerivations(const ClassNode* cn);
void writeLocation(const Node* n);
void writeFunctions(const Section& s,
const InnerNode* parent,
CodeMarker* marker,
const QString& attribute = QString());
void writeNestedClasses(const Section& s, const Node* n);
void replaceTypesWithLinks(const Node* n,
const InnerNode* parent,
CodeMarker* marker,
QString& src);
void replaceTypesWithLinks(const Node* n, const InnerNode* parent, QString& src);
void writeParameters(const FunctionNode* fn, const InnerNode* parent, CodeMarker* marker);
void writeEnumerations(const Section& s,
CodeMarker* marker,
@ -353,7 +349,7 @@ protected:
CodeMarker* marker,
const QString& attribute = QString());
void writePropertyParameter(const QString& tag, const NodeList& nlist);
void writeRelatedLinks(const DocNode* dn, CodeMarker* marker);
void writeRelatedLinks(const DocNode* dn);
void writeLink(const Node* node, const QString& tex, const QString& role);
void writeProlog(const InnerNode* inner);
bool writeMetadataElement(const InnerNode* inner,
@ -368,10 +364,6 @@ private:
enum SubTitleSize { SmallSubTitle, LargeSubTitle };
const QPair<QString,QString> anchorForNode(const Node* node);
const Node* findNodeForTarget(const QString& target,
const Node* relative,
CodeMarker* marker,
const Atom* atom = 0);
void generateHeader(const Node* node,
const QString& name,
bool subpage = false);
@ -381,29 +373,23 @@ private:
Doc::Sections sectioningUnit,
int numColumns,
const Node* relative = 0);
void generateTableOfContents(const Node* node,
CodeMarker* marker,
QList<Section>* sections = 0);
void generateLowStatusMembers(const InnerNode* inner,
CodeMarker* marker,
CodeMarker::Status status);
QString generateLowStatusMemberFile(const InnerNode* inner,
CodeMarker* marker,
CodeMarker::Status status);
void generateClassHierarchy(const Node* relative,
CodeMarker* marker,
const NodeMap& classMap);
void generateClassHierarchy(const Node* relative, const NodeMap& classMap);
void generateAnnotatedList(const Node* relative,
CodeMarker* marker,
const NodeMap& nodeMap);
void generateCompactList(const Node* relative,
CodeMarker* marker,
const NodeMap& classMap,
bool includeAlphabet,
QString commonPrefix = QString());
void generateFunctionIndex(const Node* relative, CodeMarker* marker);
void generateFunctionIndex(const Node* relative);
void generateLegaleseList(const Node* relative, CodeMarker* marker);
void generateOverviewList(const Node* relative, CodeMarker* marker);
void generateOverviewList(const Node* relative);
void generateQmlSummary(const Section& section,
const Node* relative,
@ -437,35 +423,19 @@ private:
const Node* relative,
CodeMarker* marker,
CodeMarker::SynopsisStyle style);
void generateSectionInheritedList(const Section& section,
const Node* relative,
CodeMarker* marker);
void writeText(const QString& markedCode,
CodeMarker* marker,
const Node* relative);
void generateSectionInheritedList(const Section& section, const Node* relative);
void writeText(const QString& markedCode, const Node* relative);
void generateFullName(const Node* apparentNode,
const Node* relative,
CodeMarker* marker,
const Node* actualNode = 0);
void generateLink(const Atom* atom,
const Node* relative,
CodeMarker* marker);
void generateFullName(const Node* apparentNode, const Node* relative, const Node* actualNode = 0);
void generateLink(const Atom* atom, CodeMarker* marker);
void generateStatus(const Node* node, CodeMarker* marker);
QString registerRef(const QString& ref);
virtual QString fileBase(const Node *node) const;
QString fileName(const Node *node);
void findAllClasses(const InnerNode *node);
void findAllFunctions(const InnerNode *node);
void findAllLegaleseTexts(const InnerNode *node);
void findAllNamespaces(const InnerNode *node);
static int hOffset(const Node *node);
static bool isThreeColumnEnumValueTable(const Atom *atom);
QString getLink(const Atom *atom,
const Node *relative,
CodeMarker *marker,
const Node **node);
QString getLink(const Atom *atom, const Node *relative, const Node **node);
virtual void generateIndex(const QString& fileBase,
const QString& url,
const QString& title);
@ -485,7 +455,7 @@ private:
QXmlStreamWriter& xmlWriter();
void writeApiDesc(const Node* node, CodeMarker* marker, const QString& title);
void addLink(const QString& href, const QStringRef& text, DitaTag t = DT_xref);
void writeDitaMap(Tree* tree);
void writeDitaMap();
void writeDitaMap(const DitaMapNode* node);
void writeStartTag(DitaTag t);
bool writeEndTag(DitaTag t=DT_NONE);
@ -510,29 +480,21 @@ private:
These flags indicate which elements the generator
is currently outputting.
*/
bool inContents;
bool inDetailedDescription;
bool inLegaleseText;
bool inLink;
bool inObsoleteLink;
bool inSectionHeading;
bool inTableHeader;
bool inTableBody;
bool noLinks;
bool obsoleteLinks;
bool offlineDocs;
bool threeColumnEnumValueTable;
int codeIndent;
int numTableRows;
int divNestingLevel;
int sectionNestingLevel;
int tableColumnCount;
int currentColumn;
QString link;
QStringList sectionNumber;
QRegExp funcLeftParen;
QString style;
QString postHeader;
@ -551,17 +513,6 @@ private:
QMap<QString, QString> refMap;
QMap<QString, QString> name2guidMap;
GuidMaps guidMaps;
QMap<QString, NodeMap > moduleClassMap;
QMap<QString, NodeMap > moduleNamespaceMap;
NodeMap nonCompatClasses;
NodeMap mainClasses;
NodeMap compatClasses;
NodeMap obsoleteClasses;
NodeMap namespaceIndex;
NodeMap serviceClasses;
NodeMap qmlClasses;
QMap<QString, NodeMap > funcIndex;
QMap<Text, const Node*> legaleseTexts;
static int id;
static QString ditaTags[];
QStack<QXmlStreamWriter*> xmlWriterStack;

View File

@ -2918,8 +2918,6 @@ Text Doc::trimmedBriefText(const QString &className) const
if (atom) {
QString briefStr;
QString whats;
bool standardWording = true;
/*
This code is really ugly. The entire \brief business
should be rethought.
@ -2937,21 +2935,9 @@ Text Doc::trimmedBriefText(const QString &className) const
else {
if (!w.isEmpty() && w.first() == "The")
w.removeFirst();
else {
location().warning(
tr("Nonstandard wording in '\\%1' text for '%2' (expected 'The')")
.arg(COMMAND_BRIEF).arg(className));
standardWording = false;
}
if (!w.isEmpty() && (w.first() == className || w.first() == classNameOnly))
w.removeFirst();
else {
location().warning(
tr("Nonstandard wording in '\\%1' text for '%2' (expected '%3')")
.arg(COMMAND_BRIEF).arg(className).arg(className));
standardWording = false;
}
if (!w.isEmpty() && ((w.first() == "class") ||
(w.first() == "function") ||
@ -2960,14 +2946,6 @@ Text Doc::trimmedBriefText(const QString &className) const
(w.first() == "namespace") ||
(w.first() == "header")))
w.removeFirst();
else {
location().warning(
tr("Nonstandard wording in '\\%1' text for '%2' ("
"expected 'class', 'function', 'macro', 'widget', "
"'namespace' or 'header')")
.arg(COMMAND_BRIEF).arg(className));
standardWording = false;
}
if (!w.isEmpty() && (w.first() == "is" || w.first() == "provides"))
w.removeFirst();
@ -2981,18 +2959,11 @@ Text Doc::trimmedBriefText(const QString &className) const
if (whats.endsWith(QLatin1Char('.')))
whats.truncate(whats.length() - 1);
if (whats.isEmpty()) {
location().warning(
tr("Nonstandard wording in '\\%1' text for '%2' (expected more text)")
.arg(COMMAND_BRIEF).arg(className));
standardWording = false;
}
else
if (!whats.isEmpty())
whats[0] = whats[0].toUpper();
// ### move this once \brief is abolished for properties
if (standardWording)
resultText << whats;
resultText << whats;
}
return resultText;
}

View File

@ -50,12 +50,11 @@
#include "doc.h"
#include "editdistance.h"
#include "generator.h"
#include "node.h"
#include "openedlist.h"
#include "quoter.h"
#include "separator.h"
#include "tokenizer.h"
#include "tree.h"
#include "qdocdatabase.h"
QT_BEGIN_NAMESPACE
@ -97,18 +96,33 @@ QString Generator::sinceTitles[] =
QStringList Generator::styleDirs;
QStringList Generator::styleFiles;
/*!
Constructs the generator base class. Prepends the newly
constructed generator to the list of output generators.
Sets a pointer to the QDoc database singleton, which is
available to the generator subclasses.
*/
Generator::Generator()
: amp("&amp;"),
gt("&gt;"),
lt("&lt;"),
quot("&quot;"),
tag("</?@[^>]*>"),
tree_(0)
inLink_(false),
inContents_(false),
inSectionHeading_(false),
inTableHeader_(false),
threeColumnEnumValueTable_(true),
numTableRows_(0)
{
qdb_ = QDocDatabase::qdocDB();
generators.prepend(this);
}
/*!
Destroys the generator after removing it from the list of
output generators.
*/
Generator::~Generator()
{
generators.removeAll(this);
@ -117,14 +131,13 @@ Generator::~Generator()
void Generator::appendFullName(Text& text,
const Node *apparentNode,
const Node *relative,
CodeMarker *marker,
const Node *actualNode)
{
if (actualNode == 0)
actualNode = apparentNode;
text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
<< Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
<< Atom(Atom::String, marker->plainFullName(apparentNode, relative))
<< Atom(Atom::String, apparentNode->plainFullName(relative))
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
@ -141,24 +154,18 @@ void Generator::appendFullName(Text& text,
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
void Generator::appendFullNames(Text& text,
const NodeList& nodes,
const Node* relative,
CodeMarker* marker)
void Generator::appendFullNames(Text& text, const NodeList& nodes, const Node* relative)
{
NodeList::ConstIterator n = nodes.constBegin();
int index = 0;
while (n != nodes.constEnd()) {
appendFullName(text,*n,relative,marker);
appendFullName(text,*n,relative);
text << comma(index++,nodes.count());
++n;
}
}
void Generator::appendSortedNames(Text& text,
const ClassNode *classe,
const QList<RelatedClass> &classes,
CodeMarker *marker)
void Generator::appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes)
{
QList<RelatedClass>::ConstIterator r;
QMap<QString,Text> classMap;
@ -170,7 +177,7 @@ void Generator::appendSortedNames(Text& text,
(*r).node->status() != Node::Internal
&& !(*r).node->doc().isEmpty()) {
Text className;
appendFullName(className, (*r).node, classe, marker);
appendFullName(className, (*r).node, classe);
classMap[className.toString().toLower()] = className;
}
++r;
@ -185,10 +192,7 @@ void Generator::appendSortedNames(Text& text,
}
}
void Generator::appendSortedQmlNames(Text& text,
const Node* base,
const NodeList& subs,
CodeMarker *marker)
void Generator::appendSortedQmlNames(Text& text, const Node* base, const NodeList& subs)
{
QMap<QString,Text> classMap;
int index = 0;
@ -197,7 +201,7 @@ void Generator::appendSortedQmlNames(Text& text,
Text t;
if (!base->isQtQuickNode() || !subs[i]->isQtQuickNode() ||
(base->qmlModuleIdentifier() == subs[i]->qmlModuleIdentifier())) {
appendFullName(t, subs[i], base, marker);
appendFullName(t, subs[i], base);
classMap[t.toString().toLower()] = t;
}
}
@ -265,11 +269,6 @@ void Generator::endSubPage()
delete outStreamStack.pop();
}
void Generator::endText(const Node * /* relative */,
CodeMarker * /* marker */)
{
}
QString Generator::fileBase(const Node *node) const
{
if (node->relates())
@ -371,93 +370,6 @@ QString Generator::fileName(const Node* node) const
return name;
}
/*!
For generating the "New Classes... in x.y" section on the
What's New in Qt x.y" page.
*/
void Generator::findAllSince(const InnerNode *node)
{
NodeList::const_iterator child = node->childNodes().constBegin();
// Traverse the tree, starting at the node supplied.
while (child != node->childNodes().constEnd()) {
QString sinceString = (*child)->since();
if (((*child)->access() != Node::Private) && !sinceString.isEmpty()) {
// Insert a new entry into each map for each new since string found.
NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceString);
if (nsmap == newSinceMaps.end())
nsmap = newSinceMaps.insert(sinceString,NodeMultiMap());
NewClassMaps::iterator ncmap = newClassMaps.find(sinceString);
if (ncmap == newClassMaps.end())
ncmap = newClassMaps.insert(sinceString,NodeMap());
NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceString);
if (nqcmap == newQmlClassMaps.end())
nqcmap = newQmlClassMaps.insert(sinceString,NodeMap());
if ((*child)->type() == Node::Function) {
// Insert functions into the general since map.
FunctionNode *func = static_cast<FunctionNode *>(*child);
if ((func->status() > Node::Obsolete) &&
(func->metaness() != FunctionNode::Ctor) &&
(func->metaness() != FunctionNode::Dtor)) {
nsmap.value().insert(func->name(),(*child));
}
}
else if ((*child)->url().isEmpty()) {
if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
// Insert classes into the since and class maps.
QString className = (*child)->name();
if ((*child)->parent() &&
(*child)->parent()->type() == Node::Namespace &&
!(*child)->parent()->name().isEmpty())
className = (*child)->parent()->name()+"::"+className;
nsmap.value().insert(className,(*child));
ncmap.value().insert(className,(*child));
}
else if ((*child)->subType() == Node::QmlClass) {
// Insert QML elements into the since and element maps.
QString className = (*child)->name();
if ((*child)->parent() &&
(*child)->parent()->type() == Node::Namespace &&
!(*child)->parent()->name().isEmpty())
className = (*child)->parent()->name()+"::"+className;
nsmap.value().insert(className,(*child));
nqcmap.value().insert(className,(*child));
}
else if ((*child)->type() == Node::QmlProperty) {
// Insert QML properties into the since map.
QString propertyName = (*child)->name();
nsmap.value().insert(propertyName,(*child));
}
}
else {
// Insert external documents into the general since map.
QString name = (*child)->name();
if ((*child)->parent() &&
(*child)->parent()->type() == Node::Namespace &&
!(*child)->parent()->name().isEmpty())
name = (*child)->parent()->name()+"::"+name;
nsmap.value().insert(name,(*child));
}
// Find child nodes with since commands.
if ((*child)->isInnerNode()) {
findAllSince(static_cast<InnerNode *>(*child));
}
}
++child;
}
}
QMap<QString, QString>& Generator::formattingLeftMap()
{
return fmtLeftMaps[format()];
@ -628,26 +540,6 @@ QString Generator::fullDocumentLocation(const Node *node, bool subdir)
return fdl + parentName.toLower() + anchorRef;
}
QString Generator::fullName(const Node *node,
const Node *relative,
CodeMarker *marker) const
{
if (node->type() == Node::Document) {
const DocNode* fn = static_cast<const DocNode *>(node);
// Only print modulename::type on collision pages.
if (!fn->qmlModuleIdentifier().isEmpty() && relative != 0 && relative->isCollisionNode())
return fn->qmlModuleIdentifier() + "::" + fn->title();
return fn->title();
}
else if (node->type() == Node::Class &&
!(static_cast<const ClassNode *>(node))->serviceName().isEmpty())
return (static_cast<const ClassNode *>(node))->serviceName();
else
return marker->plainFullName(node, relative);
}
void Generator::generateAlsoList(const Node *node, CodeMarker *marker)
{
QList<Text> alsoList = node->doc().alsoList();
@ -747,8 +639,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
if (node->doc().isEmpty()) {
if (!quiet && !node->isReimp()) { // ### might be unnecessary
node->location().warning(tr("No documentation for '%1'")
.arg(marker->plainFullName(node)));
node->location().warning(tr("No documentation for '%1'").arg(node->plainFullName()));
}
}
else {
@ -785,15 +676,12 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
if (!best.isEmpty() && !documentedItems.contains(best))
details = tr("Maybe you meant '%1'?").arg(best);
node->doc().location().warning(
tr("No such enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node)),
details);
node->doc().location().warning(tr("No such enum item '%1' in %2").arg(*a).arg(node->plainFullName()), details);
if (*a == "Void")
qDebug() << "VOID:" << node->name() << definedItems;
}
else if (!documentedItems.contains(*a)) {
node->doc().location().warning(
tr("Undocumented enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node)));
node->doc().location().warning(tr("Undocumented enum item '%1' in %2").arg(*a).arg(node->plainFullName()));
}
++a;
}
@ -828,7 +716,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
details = tr("Maybe you meant '%1'?").arg(best);
node->doc().location().warning(
tr("No such parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node)),
tr("No such parameter '%1' in %2").arg(*a).arg(node->plainFullName()),
details);
}
else if (!(*a).isEmpty() && !documentedParams.contains(*a)) {
@ -849,7 +737,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
if (needWarning && !func->isReimp())
node->doc().location().warning(
tr("Undocumented parameter '%1' in %2")
.arg(*a).arg(marker->plainFullName(node)));
.arg(*a).arg(node->plainFullName()));
}
++a;
}
@ -974,7 +862,7 @@ void Generator::generateInheritedBy(const ClassNode *classe, CodeMarker *marker)
<< "Inherited by: "
<< Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
appendSortedNames(text, classe, classe->derivedClasses(), marker);
appendSortedNames(text, classe, classe->derivedClasses());
text << Atom::ParaRight;
generateText(text, classe, marker);
}
@ -1111,7 +999,7 @@ void Generator::generateQmlInheritedBy(const QmlClassNode* qcn,
if (!subs.isEmpty()) {
Text text;
text << Atom::ParaLeft << "Inherited by ";
appendSortedQmlNames(text,qcn,subs,marker);
appendSortedQmlNames(text,qcn,subs);
text << Atom::ParaRight;
generateText(text, qcn, marker);
}
@ -1138,7 +1026,7 @@ bool Generator::generateQmlText(const Text& text,
bool result = false;
if (atom != 0) {
startText(relative, marker);
initializeTextOutput();
while (atom) {
if (atom->type() != Atom::QmlText)
atom = atom->next();
@ -1151,7 +1039,6 @@ bool Generator::generateQmlText(const Text& text,
}
}
}
endText(relative, marker);
result = true;
}
return result;
@ -1269,13 +1156,12 @@ bool Generator::generateText(const Text& text,
bool result = false;
if (text.firstAtom() != 0) {
int numAtoms = 0;
startText(relative, marker);
initializeTextOutput();
generateAtomList(text.firstAtom(),
relative,
marker,
true,
numAtoms);
endText(relative, marker);
result = true;
}
return result;
@ -1366,7 +1252,7 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
if (nonreentrant.isEmpty()) {
if (!threadsafe.isEmpty()) {
text << ", but ";
appendFullNames(text,threadsafe,innerNode,marker);
appendFullNames(text,threadsafe,innerNode);
singularPlural(text,threadsafe);
text << " also " << tlink << ".";
}
@ -1375,13 +1261,13 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
}
else {
text << ", except for ";
appendFullNames(text,nonreentrant,innerNode,marker);
appendFullNames(text,nonreentrant,innerNode);
text << ", which";
singularPlural(text,nonreentrant);
text << " nonreentrant.";
if (!threadsafe.isEmpty()) {
text << " ";
appendFullNames(text,threadsafe,innerNode,marker);
appendFullNames(text,threadsafe,innerNode);
singularPlural(text,threadsafe);
text << " " << tlink << ".";
}
@ -1391,7 +1277,7 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
if (!nonreentrant.isEmpty() || !reentrant.isEmpty()) {
text << ", except for ";
if (!reentrant.isEmpty()) {
appendFullNames(text,reentrant,innerNode,marker);
appendFullNames(text,reentrant,innerNode);
text << ", which";
singularPlural(text,reentrant);
text << " only " << rlink;
@ -1399,7 +1285,7 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
text << ", and ";
}
if (!nonreentrant.isEmpty()) {
appendFullNames(text,nonreentrant,innerNode,marker);
appendFullNames(text,nonreentrant,innerNode);
text << ", which";
singularPlural(text,nonreentrant);
text << " nonreentrant.";
@ -1422,12 +1308,11 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
}
/*!
This function is recursive.
Traverses the database recursivly to generate all the documentation.
*/
void Generator::generateTree(Tree *tree)
void Generator::generateTree()
{
tree_ = tree;
generateInnerNode(tree->root());
generateInnerNode(qdb_->treeRoot());
}
Generator *Generator::generatorForFormat(const QString& format)
@ -1458,7 +1343,7 @@ QString Generator::getCollisionLink(const Atom* atom)
if (!atom->string().contains("::"))
return link;
QStringList path = atom->string().split("::");
NameCollisionNode* ncn = tree_->findCollisionNode(path[0]);
NameCollisionNode* ncn = qdb_->findCollisionNode(path[0]);
if (ncn) {
QString label;
if (atom->next() && atom->next()->next()) {
@ -1914,9 +1799,19 @@ int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
return skipAhead;
}
void Generator::startText(const Node * /* relative */,
CodeMarker * /* marker */)
/*!
Resets the variables used during text output.
*/
void Generator::initializeTextOutput()
{
inLink_ = false;
inContents_ = false;
inSectionHeading_ = false;
inTableHeader_ = false;
numTableRows_ = 0;
threeColumnEnumValueTable_ = true;
link_.clear();
sectionNumber_.clear();
}
void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)

View File

@ -39,10 +39,6 @@
**
****************************************************************************/
/*
generator.h
*/
#ifndef GENERATOR_H
#define GENERATOR_H
@ -60,22 +56,14 @@
QT_BEGIN_NAMESPACE
typedef QMap<QString, NodeMap> NewClassMaps;
typedef QMap<QString, NodeMultiMap> NewSinceMaps;
typedef QMap<QString, const Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
typedef QMap<Node*, NodeMultiMap> ParentMaps;
class ClassNode;
class Config;
class CodeMarker;
class DocNode;
class FunctionNode;
class InnerNode;
class Location;
class NamespaceNode;
class Node;
class Tree;
class QDocDatabase;
class Generator
{
@ -85,7 +73,7 @@ public:
virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
virtual QString format() = 0;
virtual void generateTree(Tree *tree);
virtual void generateTree();
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
@ -102,12 +90,8 @@ public:
protected:
virtual void beginSubPage(const InnerNode* node, const QString& fileName);
virtual void endSubPage();
virtual void endText(const Node *relative, CodeMarker *marker);
virtual QString fileBase(const Node* node) const;
virtual QString fileExtension() const = 0;
virtual QString fullName(const Node *node,
const Node *relative,
CodeMarker *marker) const;
virtual void generateAlsoList(const Node *node, CodeMarker *marker);
virtual int generateAtom(const Atom *atom,
const Node *relative,
@ -131,8 +115,7 @@ protected:
const Node *relative,
CodeMarker *marker);
virtual QString imageFileName(const Node *relative, const QString& fileBase);
virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
virtual void startText(const Node *relative, CodeMarker *marker);
virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
virtual QString typeString(const Node *node);
static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType);
@ -142,8 +125,8 @@ protected:
static QString trimmedTrailing(const QString &string);
static QString sinceTitles[];
void initializeTextOutput();
QString fileName(const Node* node) const;
void findAllSince(const InnerNode *node);
QMap<QString, QString> &formattingLeftMap();
QMap<QString, QString> &formattingRightMap();
const Atom* generateAtomList(const Atom *atom,
@ -175,10 +158,7 @@ protected:
QString plainCode(const QString& markedCode);
void setImageFileExtensions(const QStringList& extensions);
void unknownAtom(const Atom *atom);
void appendSortedQmlNames(Text& text,
const Node* base,
const NodeList& subs,
CodeMarker *marker);
void appendSortedQmlNames(Text& text, const Node* base, const NodeList& subs);
QList<NameCollisionNode*> collisionNodes;
QMap<QString, QStringList> editionGroupMap;
@ -187,9 +167,6 @@ protected:
QTextCodec* outputCodec;
QString outputEncoding;
QStack<QTextStream*> outStreamStack;
NewClassMaps newClassMaps;
NewClassMaps newQmlClassMaps;
NewSinceMaps newSinceMaps;
private:
static QString baseDir_;
@ -214,22 +191,14 @@ private:
void appendFullName(Text& text,
const Node *apparentNode,
const Node *relative,
CodeMarker *marker,
const Node *actualNode = 0);
void appendFullName(Text& text,
const Node *apparentNode,
const QString& fullName,
const Node *actualNode);
void appendFullNames(Text& text,
const NodeList& nodes,
const Node* relative,
CodeMarker* marker);
void appendSortedNames(Text& text,
const ClassNode *classe,
const QList<RelatedClass> &classes,
CodeMarker *marker);
void generateReimplementedFrom(const FunctionNode *func,
CodeMarker *marker);
void appendFullNames(Text& text, const NodeList& nodes, const Node* relative);
void appendSortedNames(Text& text, const ClassNode *classe, const QList<RelatedClass> &classes);
void generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker);
QString amp;
QString gt;
@ -238,7 +207,15 @@ private:
QRegExp tag;
protected:
Tree* tree_;
QDocDatabase* qdb_;
bool inLink_;
bool inContents_;
bool inSectionHeading_;
bool inTableHeader_;
bool threeColumnEnumValueTable_;
int numTableRows_;
QString link_;
QString sectionNumber_;
};
QT_END_NAMESPACE

View File

@ -49,7 +49,8 @@
#include "htmlgenerator.h"
#include "config.h"
#include "node.h"
#include "tree.h"
#include "qdocdatabase.h"
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@ -58,6 +59,13 @@ HelpProjectWriter::HelpProjectWriter(const Config &config,
Generator* g)
: gen_(g)
{
/*
Get the pointer to the singleton for the qdoc database and
store it locally. This replaces all the local accesses to
the node tree, which are now private.
*/
qdb_ = QDocDatabase::qdocDB();
// The output directory should already have been checked by the calling
// generator.
outputDir = config.getOutputDir();
@ -455,9 +463,8 @@ void HelpProjectWriter::generateSections(HelpProject &project,
}
}
void HelpProjectWriter::generate(const Tree *t)
void HelpProjectWriter::generate()
{
this->tree = t;
for (int i = 0; i < projects.size(); ++i)
generateProject(projects[i]);
}
@ -581,9 +588,9 @@ void HelpProjectWriter::generateProject(HelpProject &project)
{
const Node *rootNode;
if (!project.indexRoot.isEmpty())
rootNode = tree->findDocNodeByTitle(project.indexRoot);
rootNode = qdb_->findDocNodeByTitle(project.indexRoot);
else
rootNode = tree->root();
rootNode = qdb_->treeRoot();
if (!rootNode)
return;
@ -624,9 +631,9 @@ void HelpProjectWriter::generateProject(HelpProject &project)
writer.writeStartElement("toc");
writer.writeStartElement("section");
const Node* node = tree->findDocNodeByTitle(project.indexTitle);
const Node* node = qdb_->findDocNodeByTitle(project.indexTitle);
if (node == 0)
node = tree->findNode(QStringList("index.html"));
node = qdb_->findNode(QStringList("index.html"));
QString indexPath;
if (node)
indexPath = gen_->fullDocumentLocation(node,true);
@ -643,7 +650,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (subproject.type == QLatin1String("manual")) {
const DocNode *indexPage = tree->findDocNodeByTitle(subproject.indexTitle);
const DocNode *indexPage = qdb_->findDocNodeByTitle(subproject.indexTitle);
if (indexPage) {
Text indexBody = indexPage->doc().body();
const Atom *atom = indexBody.firstAtom();
@ -670,7 +677,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (sectionStack.top() > 0)
writer.writeEndElement(); // section
const DocNode *page = tree->findDocNodeByTitle(atom->string());
const DocNode *page = qdb_->findDocNodeByTitle(atom->string());
writer.writeStartElement("section");
QString indexPath = gen_->fullDocumentLocation(page,true);
writer.writeAttribute("ref", indexPath);
@ -697,7 +704,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (!name.isEmpty()) {
writer.writeStartElement("section");
QString indexPath = gen_->fullDocumentLocation(tree->findDocNodeByTitle(subproject.indexTitle),true);
QString indexPath = gen_->fullDocumentLocation(qdb_->findDocNodeByTitle(subproject.indexTitle),true);
writer.writeAttribute("ref", indexPath);
writer.writeAttribute("title", subproject.title);
project.files.insert(indexPath);
@ -717,7 +724,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
if (!nextTitle.isEmpty() &&
node->links().value(Node::ContentsLink).first.isEmpty()) {
DocNode *nextPage = const_cast<DocNode *>(tree->findDocNodeByTitle(nextTitle));
DocNode *nextPage = const_cast<DocNode *>(qdb_->findDocNodeByTitle(nextTitle));
// Write the contents node.
writeNode(project, writer, node);
@ -727,7 +734,7 @@ void HelpProjectWriter::generateProject(HelpProject &project)
nextTitle = nextPage->links().value(Node::NextLink).first;
if (nextTitle.isEmpty() || visited.contains(nextTitle))
break;
nextPage = const_cast<DocNode *>(tree->findDocNodeByTitle(nextTitle));
nextPage = const_cast<DocNode *>(qdb_->findDocNodeByTitle(nextTitle));
visited.insert(nextTitle);
}
break;

View File

@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
class Tree;
class QDocDatabase;
class Generator;
typedef QPair<QString, const Node*> QStringNodePair;
@ -92,7 +92,7 @@ public:
Generator* g);
void addExtraFile(const QString &file);
void addExtraFiles(const QSet<QString> &files);
void generate(const Tree *t);
void generate();
private:
void generateProject(HelpProject &project);
@ -105,7 +105,7 @@ private:
void writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node);
void readSelectors(SubProject &subproject, const QStringList &selectors);
const Tree *tree;
QDocDatabase* qdb_;
Generator* gen_;
QString outputDir;

File diff suppressed because it is too large Load Diff

View File

@ -86,7 +86,7 @@ public:
virtual void initializeGenerator(const Config& config);
virtual void terminateGenerator();
virtual QString format();
virtual void generateTree(Tree *tree);
virtual void generateTree();
void generateCollisionPages();
void generateManifestFiles();
@ -96,7 +96,6 @@ public:
static QString sinceTitle(int i) { return sinceTitles[i]; }
protected:
virtual void startText(const Node *relative, CodeMarker *marker);
virtual int generateAtom(const Atom *atom,
const Node *relative,
CodeMarker *marker);
@ -119,10 +118,6 @@ private:
};
const QPair<QString,QString> anchorForNode(const Node *node);
const Node *findNodeForTarget(const QString &target,
const Node *relative,
CodeMarker *marker,
const Atom *atom = 0);
void generateBreadCrumbs(const QString& title,
const Node *node,
CodeMarker *marker);
@ -149,21 +144,18 @@ private:
QString generateLowStatusMemberFile(const InnerNode *inner,
CodeMarker *marker,
CodeMarker::Status status);
void generateClassHierarchy(const Node *relative,
CodeMarker *marker,
const NodeMap &classMap);
void generateClassHierarchy(const Node *relative, const NodeMap &classMap);
void generateAnnotatedList(const Node *relative,
CodeMarker *marker,
const NodeMap &nodeMap,
bool allOdd = false);
void generateCompactList(const Node *relative,
CodeMarker *marker,
const NodeMap &classMap,
bool includeAlphabet,
QString commonPrefix = QString());
void generateFunctionIndex(const Node *relative, CodeMarker *marker);
void generateFunctionIndex(const Node *relative);
void generateLegaleseList(const Node *relative, CodeMarker *marker);
void generateOverviewList(const Node *relative, CodeMarker *marker);
void generateOverviewList(const Node *relative);
void generateSectionList(const Section& section,
const Node *relative,
CodeMarker *marker,
@ -192,50 +184,32 @@ private:
CodeMarker::SynopsisStyle style,
bool alignNames = false,
const QString* prefix = 0);
void generateSectionInheritedList(const Section& section,
const Node *relative,
CodeMarker *marker);
void generateSectionInheritedList(const Section& section, const Node *relative);
QString highlightedCode(const QString& markedCode,
CodeMarker* marker,
const Node* relative,
bool alignNames = false,
const Node* self = 0);
void generateFullName(const Node *apparentNode,
const Node *relative,
CodeMarker *marker,
const Node *actualNode = 0);
void generateFullName(const Node *apparentNode, const Node *relative, const Node *actualNode = 0);
void generateDetailedMember(const Node *node,
const InnerNode *relative,
CodeMarker *marker);
void generateLink(const Atom *atom,
const Node *relative,
CodeMarker *marker);
void generateLink(const Atom *atom, CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker);
QString registerRef(const QString& ref);
virtual QString fileBase(const Node *node) const;
QString fileName(const Node *node);
void findAllClasses(const InnerNode *node);
void findAllFunctions(const InnerNode *node);
void findAllLegaleseTexts(const InnerNode *node);
void findAllNamespaces(const InnerNode *node);
static int hOffset(const Node *node);
static bool isThreeColumnEnumValueTable(const Atom *atom);
QString getLink(const Atom *atom,
const Node *relative,
CodeMarker *marker,
const Node** node);
QString getLink(const Atom *atom, const Node *relative, const Node** node);
virtual void generateIndex(const QString &fileBase,
const QString &url,
const QString &title);
#ifdef GENERATE_MAC_REFS
void generateMacRef(const Node *node, CodeMarker *marker);
#endif
void beginLink(const QString &link,
const Node *node,
const Node *relative,
CodeMarker *marker);
void beginLink(const QString &link, const Node *node, const Node *relative);
void endLink();
void generateExtractionMark(const Node *node, ExtractionMarkType markType);
void reportOrphans(const InnerNode* parent);
@ -249,15 +223,7 @@ private:
QMap<QString, QString> refMap;
int codeIndent;
HelpProjectWriter *helpProjectWriter;
bool inLink;
bool inObsoleteLink;
bool inContents;
bool inSectionHeading;
bool inTableHeader;
int numTableRows;
bool threeColumnEnumValueTable;
QString link;
QStringList sectionNumber;
QRegExp funcLeftParen;
QString style;
QString headerScripts;
@ -277,17 +243,6 @@ private:
QStringList stylesheets;
QStringList customHeadElements;
bool obsoleteLinks;
QMap<QString, NodeMap > moduleClassMap;
QMap<QString, NodeMap > moduleNamespaceMap;
NodeMap nonCompatClasses;
NodeMap mainClasses;
NodeMap compatClasses;
NodeMap obsoleteClasses;
NodeMap namespaceIndex;
NodeMap serviceClasses;
NodeMap qmlClasses;
QMap<QString, NodeMap > funcIndex;
QMap<Text, const Node *> legaleseTexts;
QStack<QXmlStreamWriter*> xmlWriterStack;
static int id;
public:

View File

@ -39,10 +39,6 @@
**
****************************************************************************/
/*
main.cpp
*/
#include <qglobal.h>
#include <stdlib.h>
#include "codemarker.h"
@ -57,14 +53,12 @@
#include "puredocparser.h"
#include "tokenizer.h"
#include "tree.h"
#include "qdocdatabase.h"
#include "jscodemarker.h"
#include "qmlcodemarker.h"
#include "qmlcodeparser.h"
#include <qdatetime.h>
#include <qdebug.h>
#include "qtranslator.h"
#ifndef QT_BOOTSTRAPPED
# include "qcoreapplication.h"
@ -105,7 +99,6 @@ static bool obsoleteLinks = false;
static QStringList defines;
static QStringList dependModules;
static QStringList indexDirs;
static QHash<QString, Tree *> trees;
/*!
Print the help message to \c stdout.
@ -240,12 +233,13 @@ static void processQdocconfFile(const QString &fileName)
Location langLocation = config.lastLocation();
/*
Initialize the tree where all the parsed sources will be stored.
The tree gets built as the source files are parsed, and then the
documentation output is generated by traversing the tree.
Initialize the qdoc database, where all the parsed source files
will be stored. The database includes a tree of nodes, which gets
built as the source files are parsed. The documentation output is
generated by traversing that tree.
*/
Tree *tree = new Tree;
tree->setVersion(config.getString(CONFIG_VERSION));
QDocDatabase* qdb = QDocDatabase::qdocDB();
qdb->setVersion(config.getString(CONFIG_VERSION));
/*
By default, the only output format is HTML.
@ -327,7 +321,7 @@ static void processQdocconfFile(const QString &fileName)
<< "There will probably be errors for missing links.";
}
}
tree->readIndexes(indexFiles);
qdb->readIndexes(indexFiles);
QSet<QString> excludedDirs;
QSet<QString> excludedFiles;
@ -390,14 +384,14 @@ static void processQdocconfFile(const QString &fileName)
CodeParser *codeParser = CodeParser::parserForHeaderFile(h.key());
if (codeParser) {
++parsed;
codeParser->parseHeaderFile(config.location(), h.key(), tree);
codeParser->parseHeaderFile(config.location(), h.key());
usedParsers.insert(codeParser);
}
++h;
}
foreach (CodeParser *codeParser, usedParsers)
codeParser->doneParsingHeaderFiles(tree);
codeParser->doneParsingHeaderFiles();
usedParsers.clear();
/*
@ -410,24 +404,21 @@ static void processQdocconfFile(const QString &fileName)
CodeParser *codeParser = CodeParser::parserForSourceFile(s.key());
if (codeParser) {
++parsed;
codeParser->parseSourceFile(config.location(), s.key(), tree);
codeParser->parseSourceFile(config.location(), s.key());
usedParsers.insert(codeParser);
}
++s;
}
foreach (CodeParser *codeParser, usedParsers)
codeParser->doneParsingSourceFiles(tree);
codeParser->doneParsingSourceFiles();
/*
Now the big tree has been built from all the header and
source files. Resolve all the class names, function names,
targets, URLs, links, and other stuff that needs resolving.
*/
tree->resolveGroups();
tree->resolveTargets(tree->root());
tree->resolveCppToQmlLinks();
tree->resolveQmlInheritance();
qdb->resolveIssues();
/*
The tree is built and all the stuff that needed resolving
@ -440,21 +431,18 @@ static void processQdocconfFile(const QString &fileName)
Generator* generator = Generator::generatorForFormat(*of);
if (generator == 0)
outputFormatsLocation.fatal(tr("Unknown output format '%1'").arg(*of));
generator->generateTree(tree);
generator->generateTree();
++of;
}
/*
Generate the XML tag file, if it was requested.
*/
QString tagFile = config.getString(CONFIG_TAGFILE);
if (!tagFile.isEmpty()) {
tree->generateTagFile(tagFile);
}
qdb->generateTagFile(config.getString(CONFIG_TAGFILE));
//Generator::writeOutFileNames();
tree->setVersion(QString());
QDocDatabase::qdocDB()->setVersion(QString());
Generator::terminate();
CodeParser::terminate();
CodeMarker::terminate();
@ -467,11 +455,11 @@ static void processQdocconfFile(const QString &fileName)
qDeleteAll(translators);
#endif
#ifdef DEBUG_SHUTDOWN_CRASH
qDebug() << "main(): Delete tree";
qDebug() << "main(): Delete qdoc database";
#endif
delete tree;
QDocDatabase::destroyQdocDB();
#ifdef DEBUG_SHUTDOWN_CRASH
qDebug() << "main(): Tree deleted";
qDebug() << "main(): qdoc database deleted";
#endif
}
@ -584,7 +572,6 @@ int main(int argc, char **argv)
processQdocconfFile(qf);
}
qDeleteAll(trees);
return EXIT_SUCCESS;
}

View File

@ -44,6 +44,7 @@
#include "codemarker.h"
#include "codeparser.h"
#include <QUuid>
#include "qdocdatabase.h"
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@ -84,6 +85,63 @@ Node::~Node()
relatesTo_->removeRelated(this);
}
/*!
Returns this node's name member. Appends "()" to the returned
name, if this node is a function node.
*/
QString Node::plainName() const
{
if (type() == Node::Function)
return name_ + QLatin1String("()");
return name_;
}
/*!
Constructs and returns the node's fully qualified name by
recursively ascending the parent links and prepending each
parent name + "::". Breaks out when the parent pointer is
\a relative. Almost all calls to this function pass 0 for
\a relative.
*/
QString Node::plainFullName(const Node* relative) const
{
if (name_.isEmpty())
return QLatin1String("global");
QString fullName;
const Node* node = this;
while (node) {
fullName.prepend(node->plainName());
if (node->parent() == relative || node->parent()->subType() == Node::Collision ||
node->parent()->name().isEmpty())
break;
fullName.prepend(QLatin1String("::"));
node = node->parent();
}
return fullName;
}
/*!
Constructs and returns this node's full name. The \a relative
node is either null or is a collision node.
*/
QString Node::fullName(const Node* relative) const
{
if (type() == Node::Document) {
const DocNode* dn = static_cast<const DocNode*>(this);
// Only print modulename::type on collision pages.
if (!dn->qmlModuleIdentifier().isEmpty() && relative != 0 && relative->isCollisionNode())
return dn->qmlModuleIdentifier() + "::" + dn->title();
return dn->title();
}
else if (type() == Node::Class) {
const ClassNode* cn = static_cast<const ClassNode*>(this);
if (!cn->serviceName().isEmpty())
return cn->serviceName();
}
return plainFullName(relative);
}
/*!
Sets this Node's Doc to \a doc. If \a replace is false and
this Node already has a Doc, a warning is reported that the
@ -394,7 +452,7 @@ void Node::setLink(LinkType linkType, const QString &link, const QString &desc)
QPair<QString,QString> linkPair;
linkPair.first = link;
linkPair.second = desc;
linkMap[linkType] = linkPair;
linkMap_[linkType] = linkPair;
}
/*!
@ -594,6 +652,76 @@ InnerNode::~InnerNode()
removeFromRelated();
}
/*!
Returns true if this node's members coolection is not empty.
*/
bool InnerNode::hasMembers() const
{
return !members_.isEmpty();
}
/*!
Returns true if this node's members collection contains at
least one namespace node.
*/
bool InnerNode::hasNamespaces() const
{
if (!members_.isEmpty()) {
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isNamespace())
return true;
++i;
}
}
return false;
}
/*!
Returns true if this node's members collection contains at
least one class node.
*/
bool InnerNode::hasClasses() const
{
if (!members_.isEmpty()) {
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isClass())
return true;
++i;
}
}
return false;
}
/*!
Loads \a out with all this node's member nodes that are namespace nodes.
*/
void InnerNode::getMemberNamespaces(NodeMap& out)
{
out.clear();
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isNamespace())
out.insert((*i)->name(),(*i));
++i;
}
}
/*!
Loads \a out with all this node's member nodes that are class nodes.
*/
void InnerNode::getMemberClasses(NodeMap& out)
{
out.clear();
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isClass())
out.insert((*i)->name(),(*i));
++i;
}
}
/*!
Find the node in this node's children that has the
given \a name. If this node is a QML class node, be
@ -606,8 +734,8 @@ Node *InnerNode::findChildNodeByName(const QString& name)
if (node && node->subType() != QmlPropertyGroup)
return node;
if ((type() == Document) && (subType() == QmlClass)) {
for (int i=0; i<children.size(); ++i) {
Node* n = children.at(i);
for (int i=0; i<children_.size(); ++i) {
Node* n = children_.at(i);
if (n->subType() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
if (node)
@ -630,8 +758,8 @@ void InnerNode::findNodes(const QString& name, QList<Node*>& n)
*/
if (nodes.isEmpty()) {
if ((type() == Document) && (subType() == QmlClass)) {
for (int i=0; i<children.size(); ++i) {
node = children.at(i);
for (int i=0; i<children_.size(); ++i) {
node = children_.at(i);
if (node->subType() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) {
@ -695,8 +823,8 @@ Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
}
}
if (qml && (type() == Document) && (subType() == QmlClass)) {
for (int i=0; i<children.size(); ++i) {
Node* node = children.at(i);
for (int i=0; i<children_.size(); ++i) {
Node* node = children_.at(i);
if (node->subType() == QmlPropertyGroup) {
node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node)
@ -931,7 +1059,7 @@ void InnerNode::removeFromRelated()
*/
void InnerNode::deleteChildren()
{
NodeList childrenCopy = children; // `children` will be changed in ~Node()
NodeList childrenCopy = children_; // `children_` will be changed in ~Node()
qDeleteAll(childrenCopy);
}
@ -994,7 +1122,7 @@ const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
*/
const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
{
foreach (const Node *node, enumChildren) {
foreach (const Node *node, enumChildren_) {
const EnumNode *enume = static_cast<const EnumNode *>(node);
if (enume->hasItem(enumValue))
return enume;
@ -1055,7 +1183,7 @@ InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name)
*/
void InnerNode::addInclude(const QString& include)
{
inc.append(include);
includes_.append(include);
}
/*!
@ -1063,7 +1191,7 @@ void InnerNode::addInclude(const QString& include)
*/
void InnerNode::setIncludes(const QStringList& includes)
{
inc = includes;
includes_ = includes;
}
/*!
@ -1107,7 +1235,7 @@ bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2)
*/
void InnerNode::addChild(Node *child)
{
children.append(child);
children_.append(child);
if ((child->type() == Function) || (child->type() == QmlMethod)) {
FunctionNode *func = (FunctionNode *) child;
if (!primaryFunctionMap.contains(func->name())) {
@ -1120,7 +1248,7 @@ void InnerNode::addChild(Node *child)
}
else {
if (child->type() == Enum)
enumChildren.append(child);
enumChildren_.append(child);
childMap.insertMulti(child->name(), child);
}
}
@ -1129,8 +1257,8 @@ void InnerNode::addChild(Node *child)
*/
void InnerNode::removeChild(Node *child)
{
children.removeAll(child);
enumChildren.removeAll(child);
children_.removeAll(child);
enumChildren_.removeAll(child);
if (child->type() == Function) {
QMap<QString, Node *>::Iterator prim =
primaryFunctionMap.find(child->name());
@ -1169,8 +1297,8 @@ void InnerNode::removeChild(Node *child)
*/
QString Node::moduleName() const
{
if (!mod.isEmpty())
return mod;
if (!moduleName_.isEmpty())
return moduleName_;
QString path = location().filePath();
QString pattern = QString("src") + QDir::separator();
@ -1423,8 +1551,6 @@ QmlClassNode* ClassNode::findQmlBaseNode()
return result;
}
QMap<QString, DocNode*> DocNode::qmlModuleMap_;
/*!
\class DocNode
*/
@ -1522,48 +1648,6 @@ QString DocNode::subTitle() const
return QString();
}
/*!
The QML module map contains an entry for each QML module
identifier. A QML module identifier is constucted from the
QML module name and the module's major version number, like
this: \e {<module-name><major-version>}
If the QML module map does not contain the module identifier
\a qmid, insert the QML module node \a fn mapped to \a qmid.
*/
void DocNode::insertQmlModuleNode(const QString& qmid, DocNode* fn)
{
if (!qmlModuleMap_.contains(qmid))
qmlModuleMap_.insert(qmid,fn);
}
/*!
Returns a pointer to the QML module node (DocNode) that is
mapped to the QML module identifier constructed from \a arg.
If that QML module node does not yet exist, it is constructed
and inserted into the QML module map mapped to the QML module
identifier constructed from \a arg.
*/
DocNode* DocNode::lookupQmlModuleNode(Tree* tree, const ArgLocPair& arg)
{
QStringList dotSplit;
QStringList blankSplit = arg.first.split(QLatin1Char(' '));
QString qmid = blankSplit[0];
if (blankSplit.size() > 1) {
dotSplit = blankSplit[1].split(QLatin1Char('.'));
qmid += dotSplit[0];
}
DocNode* fn = 0;
if (qmlModuleMap_.contains(qmid))
fn = qmlModuleMap_.value(qmid);
if (!fn) {
fn = new DocNode(tree->root(), arg.first, Node::QmlModule, Node::OverviewPage);
fn->setQmlModule(arg);
insertQmlModuleNode(qmid,fn);
}
return fn;
}
/*!
Returns true if this QML type or property group contains a
property named \a name.
@ -2001,7 +2085,6 @@ QString PropertyNode::qualifiedDataType() const
bool QmlClassNode::qmlOnly = false;
QMultiMap<QString,Node*> QmlClassNode::inheritedBy;
QMap<QString, QmlClassNode*> QmlClassNode::qmlModuleMemberMap_;
/*!
Constructs a Qml class node (i.e. a Document node with the
@ -2038,40 +2121,8 @@ QmlClassNode::~QmlClassNode()
void QmlClassNode::terminate()
{
inheritedBy.clear();
qmlModuleMemberMap_.clear();
}
/*!
Insert the QML type node \a qcn into the static QML module
member map. The key is \a qmid + "::" + qcn->name().
*/
void QmlClassNode::insertQmlModuleMember(const QString& qmid, QmlClassNode* qcn)
{
qmlModuleMemberMap_.insert(qmid + "::" + qcn->name(), qcn);
}
/*!
Lookup the QML type node identified by the Qml module id
\a qmid and QML type \a name, and return a pointer to the
node. The key is \a qmid + "::" + qcn->name().
*/
QmlClassNode* QmlClassNode::lookupQmlTypeNode(const QString& qmid, const QString& name)
{
return qmlModuleMemberMap_.value(qmid + "::" + name);
}
#if 0
/*!
The base file name for this kind of node has "qml_"
prepended to it.
But not yet. Still testing.
*/
QString QmlClassNode::fileBase() const
{
return Node::fileBase();
}
#endif
/*!
Record the fact that QML class \a base is inherited by
QML class \a sub.
@ -2102,7 +2153,7 @@ void QmlClassNode::subclasses(const QString& base, NodeList& subs)
is returned is the concatenation of the QML module name
and its version number. e.g., if an element or component
is defined to be in the QML module QtQuick 1, its module
identifier is "QtQuick1". See setQmlModule().
identifier is "QtQuick1". See setQmlModuleInfo().
*/
/*!
@ -2114,10 +2165,10 @@ void QmlClassNode::subclasses(const QString& base, NodeList& subs)
true is returned. If any of the three is not found or is not
correct, false is returned.
*/
bool Node::setQmlModule(const ArgLocPair& arg)
bool Node::setQmlModuleInfo(const QString& arg)
{
QStringList dotSplit;
QStringList blankSplit = arg.first.split(QLatin1Char(' '));
QStringList blankSplit = arg.split(QLatin1Char(' '));
qmlModuleName_ = blankSplit[0];
qmlModuleVersionMajor_ = "1";
qmlModuleVersionMinor_ = "0";
@ -2164,56 +2215,6 @@ void QmlClassNode::clearCurrentChild()
}
}
/*!
Most QML elements don't have an \\inherits command in their
\\qmlclass command. This leaves qdoc bereft, when it tries
to output the line in the documentation that specifies the
QML element that a QML element inherits.
*/
void QmlClassNode::resolveInheritance(Tree* tree)
{
if (!links().empty() && links().contains(Node::InheritsLink)) {
QPair<QString,QString> linkPair;
linkPair = links()[Node::InheritsLink];
QStringList strList = linkPair.first.split("::");
Node* n = tree->findQmlClassNode(strList);
if (n) {
base_ = static_cast<DocNode*>(n);
if (base_ && base_->subType() == Node::QmlClass) {
return;
}
}
if (base_ && base_->subType() == Node::Collision) {
const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(base_);
const NodeList& children = ncn->childNodes();
for (int i=0; i<importList_.size(); ++i) {
QString qmid = importList_.at(i).first + importList_.at(i).second;
for (int j=0; j<children.size(); ++j) {
if (qmid == children.at(j)->qmlModuleIdentifier()) {
base_ = static_cast<DocNode*>(children.at(j));
return;
}
}
}
QString qmid = qmlModuleIdentifier();
for (int k=0; k<children.size(); ++k) {
if (qmid == children.at(k)->qmlModuleIdentifier()) {
base_ = static_cast<QmlClassNode*>(children.at(k));
return;
}
}
}
if (base_)
return;
}
if (cnode_) {
QmlClassNode* qcn = cnode_->findQmlBaseNode();
if (qcn != 0)
base_ = qcn;
}
return;
}
/*!
Constructs a Qml basic type node (i.e. a Document node with
the subtype QmlBasicType. The new node has the given
@ -2332,7 +2333,7 @@ QmlPropertyNode::QmlPropertyNode(QmlPropertyNode* parent,
...because the tokenizer gets confused on \e{explicit}.
*/
bool QmlPropertyNode::isWritable(Tree* tree)
bool QmlPropertyNode::isWritable(QDocDatabase* qdb)
{
if (readOnly_ != FlagValueDefault)
return !fromFlagValue(readOnly_, false);
@ -2341,7 +2342,7 @@ bool QmlPropertyNode::isWritable(Tree* tree)
if (qcn) {
if (qcn->cppClassRequired()) {
if (qcn->classNode()) {
PropertyNode* pn = correspondingProperty(tree);
PropertyNode* pn = correspondingProperty(qdb);
if (pn)
return pn->isWritable();
else
@ -2364,7 +2365,7 @@ bool QmlPropertyNode::isWritable(Tree* tree)
Returns a pointer this QML property's corresponding C++
property, if it has one.
*/
PropertyNode* QmlPropertyNode::correspondingProperty(Tree *tree)
PropertyNode* QmlPropertyNode::correspondingProperty(QDocDatabase* qdb)
{
PropertyNode* pn;
@ -2383,7 +2384,7 @@ PropertyNode* QmlPropertyNode::correspondingProperty(Tree *tree)
// the property group, <group>.<property>.
QStringList path(extractClassName(pn->qualifiedDataType()));
Node* nn = tree->findClassNode(path);
Node* nn = qdb->findClassNode(path);
if (nn) {
ClassNode* cn = static_cast<ClassNode*>(nn);
PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
@ -2455,7 +2456,7 @@ void NameCollisionNode::addCollision(InnerNode* child)
if (child->parent())
child->parent()->removeChild(child);
child->setParent((InnerNode*)this);
children.append(child);
children_.append(child);
}
}
@ -2844,4 +2845,34 @@ QString Node::idForNode() const
return str;
}
/*!
Prints the inner node's list of children.
For debugging only.
*/
void InnerNode::printChildren(const QString& title)
{
qDebug() << title << name() << children_.size();
if (children_.size() > 0) {
for (int i=0; i<children_.size(); ++i) {
Node* n = children_.at(i);
qDebug() << " CHILD:" << n->name() << n->nodeTypeString() << n->nodeSubtypeString();
}
}
}
/*!
Prints the inner node's list of members.
For debugging only.
*/
void InnerNode::printMembers(const QString& title)
{
qDebug() << title << name() << members_.size();
if (members_.size() > 0) {
for (int i=0; i<members_.size(); ++i) {
Node* n = members_.at(i);
qDebug() << " MEMBER:" << n->name() << n->nodeTypeString() << n->nodeSubtypeString();
}
}
}
QT_END_NAMESPACE

View File

@ -39,10 +39,6 @@
**
****************************************************************************/
/*
node.h
*/
#ifndef NODE_H
#define NODE_H
@ -61,11 +57,11 @@ QT_BEGIN_NAMESPACE
class Node;
class ClassNode;
class InnerNode;
class ClassNode;
class ExampleNode;
class QmlClassNode;
class Tree;
class QDocDatabase;
typedef QList<Node*> NodeList;
typedef QMap<QString, const Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
@ -164,6 +160,10 @@ public:
virtual ~Node();
QString plainName() const;
QString plainFullName(const Node* relative = 0) const;
QString fullName(const Node* relative=0) const;
void setAccess(Access access) { access_ = access; }
void setLocation(const Location& location) { loc = location; }
void setDoc(const Doc& doc, bool replace = false);
@ -171,7 +171,7 @@ public:
void setThreadSafeness(ThreadSafeness safeness) { safeness_ = safeness; }
void setSince(const QString &since);
void setRelates(InnerNode* pseudoParent);
void setModuleName(const QString &module) { mod = module; }
void setModuleName(const QString &name) { moduleName_ = name; }
void setLink(LinkType linkType, const QString &link, const QString &desc);
void setUrl(const QString &url);
void setTemplateStuff(const QString &templateStuff) { templateStuff_ = templateStuff; }
@ -185,15 +185,22 @@ public:
virtual bool isLeaf() const { return false; }
virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; }
virtual bool isNamespace() const { return false; }
virtual bool isClass() const { return false; }
virtual bool isQmlNode() const { return false; }
virtual bool isQtQuickNode() const { return false; }
virtual bool isAbstract() const { return false; }
virtual bool isQmlPropertyGroup() const { return false; }
virtual bool isCollisionNode() const { return false; }
virtual bool isAttached() const { return false; }
virtual bool hasMembers() const { return false; }
virtual bool hasNamespaces() const { return false; }
virtual bool hasClasses() const { return false; }
virtual void setAbstract(bool ) { }
virtual QString title() const { return QString(); }
virtual bool hasProperty(const QString& ) const { return false; }
virtual void getMemberNamespaces(NodeMap& ) { }
virtual void getMemberClasses(NodeMap& ) { }
bool isInternal() const;
bool isIndexNode() const { return indexNodeFlag_; }
Type type() const { return nodeType_; }
@ -201,13 +208,11 @@ public:
InnerNode* parent() const { return parent_; }
InnerNode* relates() const { return relatesTo_; }
const QString& name() const { return name_; }
QMap<LinkType, QPair<QString,QString> > links() const { return linkMap; }
const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
QString moduleName() const;
QString url() const;
virtual QString nameForLists() const { return name_; }
virtual QString outputFileName() const { return QString(); }
virtual void addGroupMember(Node* ) { }
virtual void addQmlModuleMember(Node* ) { }
Access access() const { return access_; }
QString accessString() const;
@ -233,12 +238,10 @@ public:
virtual QString qmlModuleName() const { return qmlModuleName_; }
virtual QString qmlModuleVersion() const { return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_; }
virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersionMajor_; }
virtual bool setQmlModule(const ArgLocPair& );
virtual bool setQmlModuleInfo(const QString& );
virtual ClassNode* classNode() { return 0; }
virtual void setClassNode(ClassNode* ) { }
virtual void clearCurrentChild() { }
virtual const ImportList* importList() const { return 0; }
virtual void setImportList(const ImportList& ) { }
virtual const Node* applyModuleIdentifier(const Node* ) const { return 0; }
virtual QString idNumber() { return "0"; }
QmlClassNode* qmlClassNode();
@ -274,8 +277,8 @@ private:
QString name_;
Location loc;
Doc d;
QMap<LinkType, QPair<QString, QString> > linkMap;
QString mod;
QMap<LinkType, QPair<QString, QString> > linkMap_;
QString moduleName_;
QString url_;
QString sinc;
QString templateStuff_;
@ -292,10 +295,6 @@ class FunctionNode;
class EnumNode;
class NameCollisionNode;
typedef QList<Node*> NodeList;
typedef QMap<QString, const Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
class InnerNode : public Node
{
public:
@ -324,12 +323,21 @@ public:
const FunctionNode* findFunctionNode(const QString& name) const;
const FunctionNode* findFunctionNode(const FunctionNode* clone) const;
const EnumNode* findEnumNodeForValue(const QString &enumValue) const;
const NodeList & childNodes() const { return children; }
const NodeList & childNodes() const { return children_; }
const NodeList & relatedNodes() const { return related_; }
int count() const { return children.size(); }
void addMember(Node* node) { members_.append(node); }
const NodeList& members() const { return members_; }
virtual bool hasMembers() const;
virtual bool hasNamespaces() const;
virtual bool hasClasses() const;
virtual void getMemberNamespaces(NodeMap& out);
virtual void getMemberClasses(NodeMap& out);
int count() const { return children_.size(); }
int overloadNumber(const FunctionNode* func) const;
NodeList overloads(const QString &funcName) const;
const QStringList& includes() const { return inc; }
const QStringList& includes() const { return includes_; }
QStringList primaryKeys();
QStringList secondaryKeys();
@ -340,6 +348,9 @@ public:
virtual void setOutputFileName(const QString& f) { outputFileName_ = f; }
virtual QString outputFileName() const { return outputFileName_; }
void printChildren(const QString& title);
void printMembers(const QString& title);
protected:
InnerNode(Type type, InnerNode* parent, const QString& name);
@ -354,9 +365,10 @@ private:
QString outputFileName_;
QStringList pageKeywds;
QStringList inc;
NodeList children;
NodeList enumChildren;
QStringList includes_;
NodeList children_;
NodeList members_;
NodeList enumChildren_;
NodeList related_;
QMap<QString, Node*> childMap;
QMap<QString, Node*> primaryFunctionMap;
@ -382,6 +394,7 @@ class NamespaceNode : public InnerNode
public:
NamespaceNode(InnerNode* parent, const QString& name);
virtual ~NamespaceNode() { }
virtual bool isNamespace() const { return true; }
};
class ClassNode;
@ -409,6 +422,7 @@ class ClassNode : public InnerNode
public:
ClassNode(InnerNode* parent, const QString& name);
virtual ~ClassNode() { }
virtual bool isClass() const { return true; }
void addBaseClass(Access access,
ClassNode* node,
@ -453,31 +467,21 @@ public:
void setTitle(const QString &title) { title_ = title; }
void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
virtual void addGroupMember(Node* node) { nodeList.append(node); }
virtual void addQmlModuleMember(Node* node) { nodeList.append(node); }
SubType subType() const { return nodeSubtype_; }
virtual QString title() const;
virtual QString fullTitle() const;
virtual QString subTitle() const;
virtual QString imageFileName() const { return QString(); }
const NodeList& groupMembers() const { return nodeList; }
const NodeList& qmlModuleMembers() const { return nodeList; }
virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { }
virtual bool isQmlPropertyGroup() const { return (nodeSubtype_ == QmlPropertyGroup); }
virtual bool hasProperty(const QString& ) const;
static void insertQmlModuleNode(const QString& qmid, DocNode* fn);
static DocNode* lookupQmlModuleNode(Tree* tree, const ArgLocPair& arg);
protected:
SubType nodeSubtype_;
QString title_;
QString subtitle_;
NodeList nodeList; // used for groups and QML modules.
static QMap<QString, DocNode*> qmlModuleMap_;
};
class NameCollisionNode : public DocNode
@ -529,25 +533,21 @@ public:
virtual void setClassNode(ClassNode* cn) { cnode_ = cn; }
virtual void setCurrentChild();
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; }
const ImportList& importList() const { return importList_; }
void setImportList(const ImportList& il) { importList_ = il; }
const DocNode* qmlBase() const { return base_; }
void resolveInheritance(Tree* tree);
void setQmlBase(DocNode* b) { base_ = b; }
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();
static void insertQmlModuleMember(const QString& qmid, QmlClassNode* qcn);
static QmlClassNode* lookupQmlTypeNode(const QString& qmid, const QString& name);
public:
static bool qmlOnly;
static QMultiMap<QString,Node*> inheritedBy;
static QMap<QString, QmlClassNode*> qmlModuleMemberMap_;
private:
bool abstract_;
@ -616,7 +616,7 @@ public:
bool isDefault() const { return isdefault_; }
bool isStored() const { return fromFlagValue(stored_,true); }
bool isDesignable() const { return fromFlagValue(designable_,false); }
bool isWritable(Tree* tree);
bool isWritable(QDocDatabase* qdb);
bool isReadOnly() const { return fromFlagValue(readOnly_,false); }
virtual bool isAttached() const { return attached_; }
virtual bool isQmlNode() const { return true; }
@ -627,7 +627,7 @@ public:
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
virtual bool hasProperty(const QString& name) const;
PropertyNode* correspondingProperty(Tree* tree);
PropertyNode* correspondingProperty(QDocDatabase* qdb);
const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); }
void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); }

View File

@ -71,16 +71,6 @@ Atom::Type PlainCodeMarker::atomType() const
return Atom::Code;
}
QString PlainCodeMarker::plainName( const Node * /* node */ )
{
return QString();
}
QString PlainCodeMarker::plainFullName(const Node * /* node */, const Node * /* relative */)
{
return QString();
}
QString PlainCodeMarker::markedUpCode( const QString& code,
const Node * /* relative */,
const Location & /* location */ )

View File

@ -60,8 +60,6 @@ public:
bool recognizeExtension( const QString& ext );
bool recognizeLanguage( const QString& lang );
Atom::Type atomType() const;
QString plainName( const Node *node );
QString plainFullName( const Node *node, const Node *relative );
QString markedUpCode( const QString& code, const Node *relative, const Location &location );
QString markedUpSynopsis( const Node *node, const Node *relative,
SynopsisStyle style );

View File

@ -49,33 +49,42 @@
#include "codechunk.h"
#include "config.h"
#include "tokenizer.h"
#include "tree.h"
#include <qdebug.h>
#include "qdocdatabase.h"
#include "puredocparser.h"
QT_BEGIN_NAMESPACE
/*!
Constructs the pure doc parser.
*/
PureDocParser::PureDocParser()
{
}
/*!
Destroys the pure doc parser.
*/
PureDocParser::~PureDocParser()
{
}
/*!
Returns a list of the kinds of files that the pure doc
parser is meant to parse. The elements of the list are
file suffixes.
*/
QStringList PureDocParser::sourceFileNameFilter()
{
return QStringList() << "*.qdoc" << "*.qtx" << "*.qtt" << "*.js";
}
/*!
Parse the source file identified by \a filePath and add its
parsed contents to the big \a tree. \a location is used for
Parses the source file identified by \a filePath and adds its
parsed contents to the database. The \a location is used for
reporting errors.
*/
void PureDocParser::parseSourceFile(const Location& location,
const QString& filePath,
Tree *tree)
void PureDocParser::parseSourceFile(const Location& location, const QString& filePath)
{
QFile in(filePath);
currentFile_ = filePath;
@ -86,7 +95,7 @@ void PureDocParser::parseSourceFile(const Location& location,
}
createOutputSubdirectory(location, filePath);
reset(tree);
reset();
Location fileLocation(filePath);
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
@ -181,6 +190,7 @@ bool PureDocParser::processQdocComments()
}
}
Node* treeRoot = QDocDatabase::qdocDB()->treeRoot();
NodeList::Iterator n = nodes.begin();
QList<Doc>::Iterator d = docs.begin();
while (n != nodes.end()) {
@ -188,7 +198,7 @@ bool PureDocParser::processQdocComments()
(*n)->setDoc(*d);
if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n);
while (m->parent() != tree_->root())
while (m->parent() && m->parent() != treeRoot)
m = m->parent();
if (m == *n)
((InnerNode *)*n)->addInclude((*n)->name());

View File

@ -65,7 +65,7 @@ public:
virtual ~PureDocParser();
virtual QStringList sourceFileNameFilter();
virtual void parseSourceFile(const Location& location, const QString& filePath, Tree* tree);
virtual void parseSourceFile(const Location& location, const QString& filePath);
private:
bool processQdocComments();

View File

@ -42,6 +42,7 @@ HEADERS += atom.h \
openedlist.h \
plaincodemarker.h \
puredocparser.h \
qdocdatabase.h \
quoter.h \
separator.h \
text.h \
@ -67,6 +68,7 @@ SOURCES += atom.cpp \
openedlist.cpp \
plaincodemarker.cpp \
puredocparser.cpp \
qdocdatabase.cpp \
quoter.cpp \
separator.cpp \
text.cpp \

View File

@ -0,0 +1,638 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "tree.h"
#include "qdocdatabase.h"
#include <qdebug.h>
QT_BEGIN_NAMESPACE
static NodeMap emptyNodeMap_;
static NodeMultiMap emptyNodeMultiMap_;
/*! \class QDocDatabase
*/
QDocDatabase* QDocDatabase::qdocDB_ = NULL;
/*!
Constructs the singleton qdoc database object.
It constructs a singleton Tree object with this
qdoc database pointer.
*/
QDocDatabase::QDocDatabase()
{
tree_ = new Tree(this);
}
/*!
Destroys the qdoc database object. This requires deleting
the tree of nodes, which deletes each node.
*/
QDocDatabase::~QDocDatabase()
{
masterMap_.clear();
delete tree_;
}
/*! \fn Tree* QDocDatabase::tree()
Returns the pointer to the tree. This function is for compatibility
with the current qdoc. It will be removed when the QDocDatabase class
replaces the current structures.
*/
/*!
Creates the singleton. Allows only one instance of the class
to be created. Returns a pointer to the singleton.
*/
QDocDatabase* QDocDatabase::qdocDB()
{
if (!qdocDB_)
qdocDB_ = new QDocDatabase;
return qdocDB_;
}
/*!
Destroys the singleton.
*/
void QDocDatabase::destroyQdocDB()
{
if (qdocDB_) {
delete qdocDB_;
qdocDB_ = 0;
}
}
/*!
\fn const DocNodeMap& QDocDatabase::modules() const
Returns a const reference to the collection of all
module nodes.
*/
/*!
\fn const DocNodeMap& QDocDatabase::qmlModules() const
Returns a const reference to the collection of all
QML module nodes.
*/
/*!
Looks up the module node named \a name in the collection
of all module nodes. If a match is found, a pointer to the
node is returned. Otherwise, a new module node named \a name
is created and inserted into the collection, and the pointer
to that node is returned.
*/
DocNode* QDocDatabase::addModule(const QString& name)
{
return findModule(name,true);
}
/*!
Looks up the QML module node named \a name in the collection
of all QML module nodes. If a match is found, a pointer to the
node is returned. Otherwise, a new QML module node named \a name
is created and inserted into the collection, and the pointer
to that node is returned.
*/
DocNode* QDocDatabase::addQmlModule(const QString& name)
{
return findQmlModule(name,true);
}
/*!
Looks up the C++ module named \a moduleName. If it isn't
there, create it. Then append \a node to the module's child
list. The parent of \a node is not changed by this function.
Returns the module node.
*/
DocNode* QDocDatabase::addToModule(const QString& moduleName, Node* node)
{
DocNode* dn = findModule(moduleName,true);
dn->addMember(node);
node->setModuleName(moduleName);
return dn;
}
/*!
Looks up the QML module named \a qmlModuleName. If it isn't
there, create it. Then append \a node to the module's child
list. The parent of \a node is not changed by this function.
Returns a pointer to the QML module node.
*/
DocNode* QDocDatabase::addToQmlModule(const QString& qmlModuleName, Node* node)
{
DocNode* dn = findQmlModule(qmlModuleName,true);
dn->addMember(node);
node->setQmlModuleInfo(qmlModuleName);
if (node->subType() == Node::QmlClass) {
QString t = node->qmlModuleIdentifier() + "::" + node->name();
QmlClassNode* n = static_cast<QmlClassNode*>(node);
if (!qmlTypeMap_.contains(t))
qmlTypeMap_.insert(t,n);
if (!masterMap_.contains(t))
masterMap_.insert(t,node);
if (!masterMap_.contains(node->name(),node))
masterMap_.insert(node->name(),node);
}
return dn;
}
/*!
Find the module node named \a name and return a pointer
to it. If a matching node is not found and \a addIfNotFound
is true, add a new module node named \a name and return
a pointer to that one. Otherwise, return 0.
If a new module node is added, its parent is the tree root,
but the new module node is not added to the child list of the
tree root.
*/
DocNode* QDocDatabase::findModule(const QString& name, bool addIfNotFound)
{
DocNodeMap::const_iterator i = modules_.find(name);
if (i != modules_.end()) {
return i.value();
}
if (addIfNotFound) {
DocNode* dn = new DocNode(tree_->root(), name, Node::Module, Node::OverviewPage);
modules_.insert(name,dn);
if (!masterMap_.contains(name,dn))
masterMap_.insert(name,dn);
return dn;
}
return 0;
}
/*!
Find the QML module node named \a name and return a pointer
to it. If a matching node is not found and \a addIfNotFound
is true, add a new QML module node named \a name and return
a pointer to that one. Otherwise, return 0.
If a new QML module node is added, its parent is the tree root,
but the new QML module node is not added to the child list of
the tree root.
*/
DocNode* QDocDatabase::findQmlModule(const QString& name, bool addIfNotFound)
{
QStringList dotSplit;
QStringList blankSplit = name.split(QLatin1Char(' '));
QString qmid = blankSplit[0];
if (blankSplit.size() > 1) {
dotSplit = blankSplit[1].split(QLatin1Char('.'));
qmid += dotSplit[0];
}
DocNode* dn = 0;
if (qmlModules_.contains(qmid))
dn = qmlModules_.value(qmid);
else if (addIfNotFound) {
dn = new DocNode(tree_->root(), name, Node::QmlModule, Node::OverviewPage);
dn->setQmlModuleInfo(name);
qmlModules_.insert(qmid,dn);
masterMap_.insert(qmid,dn);
masterMap_.insert(dn->name(),dn);
}
return dn;
}
/*!
Looks up the QML type node identified by the Qml module id
\a qmid and QML type \a name and returns a pointer to the
QML type node. The key is \a qmid + "::" + \a name.
If the QML module id is empty, it looks up the QML type by
\a name only.
*/
QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name) const
{
if (!qmid.isEmpty())
return qmlTypeMap_.value(qmid + "::" + name);
QStringList path(name);
Node* n = tree_->findNodeByNameAndType(path, Node::Document, Node::QmlClass, 0, true);
if (n) {
if (n->subType() == Node::QmlClass)
return static_cast<QmlClassNode*>(n);
else if (n->subType() == Node::Collision) {
NameCollisionNode* ncn;
ncn = static_cast<NameCollisionNode*>(n);
return static_cast<QmlClassNode*>(ncn->findAny(Node::Document,Node::QmlClass));
}
}
return 0;
}
/*!
For debugging only.
*/
void QDocDatabase::printModules() const
{
DocNodeMap::const_iterator i = modules_.begin();
while (i != modules_.end()) {
qDebug() << " " << i.key();
++i;
}
}
/*!
For debugging only.
*/
void QDocDatabase::printQmlModules() const
{
DocNodeMap::const_iterator i = qmlModules_.begin();
while (i != qmlModules_.end()) {
qDebug() << " " << i.key();
++i;
}
}
/*!
Traverses the database to construct useful data structures
for use when outputting certain significant collections of
things, C++ classes, QML types, "since" lists, and other
stuff.
*/
void QDocDatabase::buildCollections()
{
nonCompatClasses_.clear();
mainClasses_.clear();
compatClasses_.clear();
obsoleteClasses_.clear();
funcIndex_.clear();
legaleseTexts_.clear();
serviceClasses_.clear();
qmlClasses_.clear();
findAllClasses(treeRoot());
findAllFunctions(treeRoot());
findAllLegaleseTexts(treeRoot());
findAllNamespaces(treeRoot());
findAllSince(treeRoot());
}
/*!
Finds all the C++ class nodes and QML type nodes and
sorts them into maps.
*/
void QDocDatabase::findAllClasses(const InnerNode* node)
{
NodeList::const_iterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
QString className = (*c)->name();
if ((*c)->parent() &&
(*c)->parent()->type() == Node::Namespace &&
!(*c)->parent()->name().isEmpty())
className = (*c)->parent()->name()+"::"+className;
if (!(static_cast<const ClassNode *>(*c))->hideFromMainList()) {
if ((*c)->status() == Node::Compat) {
compatClasses_.insert(className, *c);
}
else if ((*c)->status() == Node::Obsolete) {
obsoleteClasses_.insert(className, *c);
}
else {
nonCompatClasses_.insert(className, *c);
if ((*c)->status() == Node::Main)
mainClasses_.insert(className, *c);
}
}
QString serviceName = (static_cast<const ClassNode *>(*c))->serviceName();
if (!serviceName.isEmpty())
serviceClasses_.insert(serviceName, *c);
}
else if ((*c)->type() == Node::Document &&
(*c)->subType() == Node::QmlClass &&
!(*c)->doc().isEmpty()) {
QString qmlTypeName = (*c)->name();
if (qmlTypeName.startsWith(QLatin1String("QML:")))
qmlClasses_.insert(qmlTypeName.mid(4),*c);
else
qmlClasses_.insert(qmlTypeName,*c);
}
else if ((*c)->isInnerNode()) {
findAllClasses(static_cast<InnerNode*>(*c));
}
}
++c;
}
}
/*!
Finds all the function nodes
*/
void QDocDatabase::findAllFunctions(const InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
findAllFunctions(static_cast<const InnerNode*>(*c));
}
else if ((*c)->type() == Node::Function) {
const FunctionNode* func = static_cast<const FunctionNode*>(*c);
if ((func->status() > Node::Obsolete) &&
!func->isInternal() &&
(func->metaness() != FunctionNode::Ctor) &&
(func->metaness() != FunctionNode::Dtor)) {
funcIndex_[(*c)->name()].insert((*c)->parent()->fullDocumentName(), *c);
}
}
}
++c;
}
}
/*!
Finds all the nodes containing legalese text and puts them
in a map.
*/
void QDocDatabase::findAllLegaleseTexts(const InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if (!(*c)->doc().legaleseText().isEmpty())
legaleseTexts_.insertMulti((*c)->doc().legaleseText(), *c);
if ((*c)->isInnerNode())
findAllLegaleseTexts(static_cast<const InnerNode *>(*c));
}
++c;
}
}
/*!
Finds all the namespace nodes and puts them in an index.
*/
void QDocDatabase::findAllNamespaces(const InnerNode* node)
{
NodeList::ConstIterator c = node->childNodes().constBegin();
while (c != node->childNodes().constEnd()) {
if ((*c)->access() != Node::Private) {
if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
findAllNamespaces(static_cast<const InnerNode *>(*c));
if ((*c)->type() == Node::Namespace) {
const NamespaceNode* nspace = static_cast<const NamespaceNode *>(*c);
// Ensure that the namespace's name is not empty (the root
// namespace has no name).
if (!nspace->name().isEmpty()) {
namespaceIndex_.insert(nspace->name(), *c);
}
}
}
}
++c;
}
}
/*!
Finds all the nodes where a \e{since} command appeared in the
qdoc comment and sorts them into maps according to the kind of
node.
This function is used for generating the "New Classes... in x.y"
section on the \e{What's New in Qt x.y} page.
*/
void QDocDatabase::findAllSince(const InnerNode* node)
{
NodeList::const_iterator child = node->childNodes().constBegin();
while (child != node->childNodes().constEnd()) {
QString sinceString = (*child)->since();
// Insert a new entry into each map for each new since string found.
if (((*child)->access() != Node::Private) && !sinceString.isEmpty()) {
NodeMultiMapMap::iterator nsmap = newSinceMaps_.find(sinceString);
if (nsmap == newSinceMaps_.end())
nsmap = newSinceMaps_.insert(sinceString,NodeMultiMap());
NodeMapMap::iterator ncmap = newClassMaps_.find(sinceString);
if (ncmap == newClassMaps_.end())
ncmap = newClassMaps_.insert(sinceString,NodeMap());
NodeMapMap::iterator nqcmap = newQmlTypeMaps_.find(sinceString);
if (nqcmap == newQmlTypeMaps_.end())
nqcmap = newQmlTypeMaps_.insert(sinceString,NodeMap());
if ((*child)->type() == Node::Function) {
// Insert functions into the general since map.
FunctionNode *func = static_cast<FunctionNode *>(*child);
if ((func->status() > Node::Obsolete) &&
(func->metaness() != FunctionNode::Ctor) &&
(func->metaness() != FunctionNode::Dtor)) {
nsmap.value().insert(func->name(),(*child));
}
}
else if ((*child)->url().isEmpty()) {
if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
// Insert classes into the since and class maps.
QString className = (*child)->name();
if ((*child)->parent() && (*child)->parent()->type() == Node::Namespace &&
!(*child)->parent()->name().isEmpty()) {
className = (*child)->parent()->name()+"::"+className;
}
nsmap.value().insert(className,(*child));
ncmap.value().insert(className,(*child));
}
else if ((*child)->subType() == Node::QmlClass) {
// Insert QML elements into the since and element maps.
QString className = (*child)->name();
if ((*child)->parent() && (*child)->parent()->type() == Node::Namespace &&
!(*child)->parent()->name().isEmpty()) {
className = (*child)->parent()->name()+"::"+className;
}
nsmap.value().insert(className,(*child));
nqcmap.value().insert(className,(*child));
}
else if ((*child)->type() == Node::QmlProperty) {
// Insert QML properties into the since map.
QString propertyName = (*child)->name();
nsmap.value().insert(propertyName,(*child));
}
}
else {
// Insert external documents into the general since map.
QString name = (*child)->name();
if ((*child)->parent() && (*child)->parent()->type() == Node::Namespace &&
!(*child)->parent()->name().isEmpty()) {
name = (*child)->parent()->name()+"::"+name;
}
nsmap.value().insert(name,(*child));
}
// Recursively find child nodes with since commands.
if ((*child)->isInnerNode()) {
findAllSince(static_cast<InnerNode *>(*child));
}
}
++child;
}
}
/*!
Find the \a key in the map of new class maps, and return a
reference to the value, which is a NodeMap. If \a key is not
found, return a reference to an empty NodeMap.
*/
const NodeMap& QDocDatabase::getClassMap(const QString& key) const
{
NodeMapMap::const_iterator i = newClassMaps_.constFind(key);
if (i != newClassMaps_.constEnd())
return i.value();
return emptyNodeMap_;
}
/*!
Find the \a key in the map of new QML type maps, and return a
reference to the value, which is a NodeMap. If the \a key is not
found, return a reference to an empty NodeMap.
*/
const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const
{
NodeMapMap::const_iterator i = newQmlTypeMaps_.constFind(key);
if (i != newQmlTypeMaps_.constEnd())
return i.value();
return emptyNodeMap_;
}
/*!
Find the \a key in the map of new \e {since} maps, and return
a reference to the value, which is a NodeMultiMap. If \a key
is not found, return a reference to an empty NodeMultiMap.
*/
const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key) const
{
NodeMultiMapMap::const_iterator i = newSinceMaps_.constFind(key);
if (i != newSinceMaps_.constEnd())
return i.value();
return emptyNodeMultiMap_;
}
/*!
Performs several housekeeping algorithms that create
certain data structures and resolve lots of links, prior
to generating documentation.
*/
void QDocDatabase::resolveIssues() {
tree_->resolveGroups();
tree_->resolveTargets(tree_->root());
tree_->resolveCppToQmlLinks();
}
/*!
Look up group \a name in the map of groups. If found, populate
the node map \a group with the classes in the group that are
not marked internal or private.
*/
void QDocDatabase::getGroup(const QString& name, NodeMap& group) const
{
group.clear();
NodeList values = tree_->groups().values(name);
for (int i=0; i<values.size(); ++i) {
const Node* n = values.at(i);
if ((n->status() != Node::Internal) && (n->access() != Node::Private)) {
group.insert(n->nameForLists(),n);
}
}
}
/*!
Searches the \a database for a node named \a target and returns
a pointer to it if found.
*/
const Node* QDocDatabase::resolveTarget(const QString& target,
const Node* relative,
const Node* self)
{
const Node* node = 0;
if (target.endsWith("()")) {
QString funcName = target;
funcName.chop(2);
QStringList path = funcName.split("::");
const FunctionNode* fn = tree_->findFunctionNode(path, relative, Tree::SearchBaseClasses);
if (fn) {
/*
Why is this case not accepted?
*/
if (fn->metaness() != FunctionNode::MacroWithoutParams)
node = fn;
}
}
else if (target.contains(QLatin1Char('#'))) {
// This error message is never printed; I think we can remove the case.
qDebug() << "qdoc: target case not handled:" << target;
}
else {
QStringList path = target.split("::");
int flags = Tree::SearchBaseClasses | Tree::SearchEnumValues | Tree::NonFunction;
node = tree_->findNode(path, relative, flags, self);
}
return node;
}
/*!
zzz
Is the atom necessary?
*/
const Node* QDocDatabase::findNodeForTarget(const QString& target,
const Node* relative,
const Atom* atom)
{
const Node* node = 0;
if (target.isEmpty())
node = relative;
else if (target.endsWith(".html"))
node = tree_->root()->findChildNodeByNameAndType(target, Node::Document);
else {
node = resolveTarget(target, relative);
if (!node)
node = tree_->findDocNodeByTitle(target, relative);
if (!node && atom) {
qDebug() << "USING ATOM!";
node = tree_->findUnambiguousTarget(target, *const_cast<Atom**>(&atom), relative);
}
}
return node;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,198 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDOCDATABASE_H
#define QDOCDATABASE_H
#include <QString>
#include <QMultiMap>
#include "tree.h"
QT_BEGIN_NAMESPACE
typedef QMap<QString, DocNode*> DocNodeMap;
typedef QMap<QString, QmlClassNode*> QmlTypeMap;
typedef QMap<QString, NodeMap> NodeMapMap;
typedef QMap<QString, NodeMultiMap> NodeMultiMapMap;
typedef QMultiMap<QString, Node*> QDocMultiMap;
typedef QMap<Text, const Node*> TextToNodeMap;
class QDocDatabase
{
public:
static QDocDatabase* qdocDB();
static void destroyQdocDB();
~QDocDatabase();
const DocNodeMap& modules() const { return modules_; }
const DocNodeMap& qmlModules() const { return qmlModules_; }
DocNode* addModule(const QString& name);
DocNode* addQmlModule(const QString& name);
DocNode* addToModule(const QString& name, Node* node);
DocNode* addToQmlModule(const QString& moduleName, Node* node);
DocNode* findModule(const QString& qmlModuleName, bool addIfNotFound = false);
DocNode* findQmlModule(const QString& name, bool addIfNotFound = false);
QmlClassNode* findQmlType(const QString& qmid, const QString& name) const;
void findAllClasses(const InnerNode *node);
void findAllFunctions(const InnerNode *node);
void findAllLegaleseTexts(const InnerNode *node);
void findAllNamespaces(const InnerNode *node);
void findAllSince(const InnerNode *node);
void buildCollections();
// special collection access functions
NodeMap& getCppClasses() { return nonCompatClasses_; }
NodeMap& getMainClasses() { return mainClasses_; }
NodeMap& getCompatibilityClasses() { return compatClasses_; }
NodeMap& getObsoleteClasses() { return obsoleteClasses_; }
NodeMap& getNamespaces() { return namespaceIndex_; }
NodeMap& getServiceClasses() { return serviceClasses_; }
NodeMap& getQmlTypes() { return qmlClasses_; }
NodeMapMap& getFunctionIndex() { return funcIndex_; }
TextToNodeMap& getLegaleseTexts() { return legaleseTexts_; }
const NodeMultiMap& groups() const { return tree_->groups(); }
const NodeList getGroup(const QString& name) const { return tree_->groups().values(name); }
void getGroup(const QString& name, NodeMap& group) const;
const NodeMap& getClassMap(const QString& key) const;
const NodeMap& getQmlTypeMap(const QString& key) const;
const NodeMultiMap& getSinceMap(const QString& key) const;
const Node* resolveTarget(const QString& target, const Node* relative, const Node* self=0);
const Node* findNodeForTarget(const QString& target, const Node* relative, const Atom* atom=0);
/* convenience functions
Many of these will be either eliminated or replaced.
*/
Tree* tree() { return tree_; }
QString version() const { return tree_->version(); }
NamespaceNode* treeRoot() { return tree_->root(); }
void setVersion(const QString& version) { tree_->setVersion(version); }
void resolveInheritance() { tree_->resolveInheritance(); }
void readIndexes(const QStringList& indexFiles) { tree_->readIndexes(indexFiles); }
void resolveIssues();
void generateTagFile(const QString& name) { if (!name.isEmpty()) tree_->generateTagFile(name); }
void addToGroup(Node* node, const QString& group) { tree_->addToGroup(node, group); }
void addToPublicGroup(Node* node, const QString& group) { tree_->addToPublicGroup(node, group); }
void fixInheritance() { tree_->fixInheritance(); }
void resolveProperties() { tree_->resolveProperties(); }
const Node* findNode(const QStringList& path) { return tree_->findNode(path); }
ClassNode* findClassNode(const QStringList& path) { return tree_->findClassNode(path); }
NamespaceNode* findNamespaceNode(const QStringList& path) { return tree_->findNamespaceNode(path); }
DocNode* findGroupNode(const QStringList& path) { return tree_->findGroupNode(path); }
NameCollisionNode* findCollisionNode(const QString& name) const {
return tree_->findCollisionNode(name);
}
const DocNode* findDocNodeByTitle(const QString& title, const Node* relative=0) const {
return tree_->findDocNodeByTitle(title, relative);
}
const Node* findUnambiguousTarget(const QString& target, Atom* &atom, const Node* relative) const {
return tree_->findUnambiguousTarget(target, atom, relative);
}
Atom* findTarget(const QString& target, const Node* node) const {
return tree_->findTarget(target, node);
}
void generateIndex(const QString& fileName,
const QString& url,
const QString& title,
Generator* g,
bool generateInternalNodes = false) {
tree_->generateIndex(fileName, url, title, g, generateInternalNodes);
}
FunctionNode* findFunctionNode(const QStringList& parentPath, const FunctionNode* clone) {
return tree_->findFunctionNode(parentPath, clone);
}
Node* findNodeByNameAndType(const QStringList& path, Node::Type type, Node::SubType subtype){
return tree_->findNodeByNameAndType(path, type, subtype, 0);
}
NameCollisionNode* checkForCollision(const QString& name) const {
return tree_->checkForCollision(name);
}
void addBaseClass(ClassNode* subclass,
Node::Access access,
const QStringList& basePath,
const QString& dataTypeWithTemplateArgs,
InnerNode* parent) {
tree_->addBaseClass(subclass, access, basePath, dataTypeWithTemplateArgs, parent);
}
void addPropertyFunction(PropertyNode* property,
const QString& funcName,
PropertyNode::FunctionRole funcRole) {
tree_->addPropertyFunction(property, funcName, funcRole);
}
/* debugging functions */
void printModules() const;
void printQmlModules() const;
private:
QDocDatabase();
QDocDatabase(QDocDatabase const& ) { }; // copy constructor is private
QDocDatabase& operator=(QDocDatabase const& ); // assignment operator is private
private:
static QDocDatabase* qdocDB_;
QDocMultiMap masterMap_;
Tree* tree_;
DocNodeMap modules_;
DocNodeMap qmlModules_;
QmlTypeMap qmlTypeMap_;
NodeMap nonCompatClasses_;
NodeMap mainClasses_;
NodeMap compatClasses_;
NodeMap obsoleteClasses_;
NodeMap namespaceIndex_;
NodeMap serviceClasses_;
NodeMap qmlClasses_;
NodeMapMap newClassMaps_;
NodeMapMap newQmlTypeMaps_;
NodeMultiMapMap newSinceMaps_;
NodeMapMap funcIndex_;
TextToNodeMap legaleseTexts_;
};
QT_END_NAMESPACE
#endif

View File

@ -108,38 +108,6 @@ Atom::Type QmlCodeMarker::atomType() const
return Atom::Qml;
}
/*!
Returns the name of the \a node. Method names include are returned with a
trailing set of parentheses.
*/
QString QmlCodeMarker::plainName(const Node *node)
{
QString name = node->name();
if (node->type() == Node::QmlMethod)
name += "()";
return name;
}
QString QmlCodeMarker::plainFullName(const Node *node, const Node *relative)
{
if (node->name().isEmpty()) {
return "global";
}
else {
QString fullName;
while (node) {
fullName.prepend(plainName(node));
if (node->parent() == relative ||
node->parent()->subType() == Node::Collision ||
node->parent()->name().isEmpty())
break;
fullName.prepend("::");
node = node->parent();
}
return fullName;
}
}
QString QmlCodeMarker::markedUpCode(const QString &code,
const Node *relative,
const Location &location)

View File

@ -61,8 +61,6 @@ public:
virtual bool recognizeExtension(const QString &ext);
virtual bool recognizeLanguage(const QString &language);
virtual Atom::Type atomType() const;
virtual QString plainName(const Node *node);
virtual QString plainFullName(const Node *node, const Node *relative);
virtual QString markedUpCode(const QString &code,
const Node *relative,
const Location &location);

View File

@ -45,10 +45,8 @@
#include "qqmljsast_p.h"
#include "qqmljsastvisitor_p.h"
#include "qmlcodeparser.h"
#include "node.h"
#include "tree.h"
#include "config.h"
#include "qmlvisitor.h"
#include <qdebug.h>
@ -84,10 +82,16 @@ QT_BEGIN_NAMESPACE
#define COMMAND_QMLBASICTYPE Doc::alias("qmlbasictype")
#define COMMAND_QMLMODULE Doc::alias("qmlmodule")
/*!
Constructs the QML code parser.
*/
QmlCodeParser::QmlCodeParser()
{
}
/*!
Destroys the QML code parser.
*/
QmlCodeParser::~QmlCodeParser()
{
}
@ -107,7 +111,8 @@ void QmlCodeParser::initializeParser(const Config &config)
}
/*!
Deletes the lexer and parser created by the constructor.
Terminates the QML code parser. Deletes the lexer and parser
created by the constructor.
*/
void QmlCodeParser::terminateParser()
{
@ -124,7 +129,8 @@ QString QmlCodeParser::language()
}
/*!
Returns a filter string of "*.qml".
Returns a string list containing "*.qml". This is the only
file type parsed by the QMLN parser.
*/
QStringList QmlCodeParser::sourceFileNameFilter()
{
@ -132,16 +138,13 @@ QStringList QmlCodeParser::sourceFileNameFilter()
}
/*!
Parses the source file at \a filePath, creating nodes as
needed and inserting them into the \a tree. \a location is
used for error reporting.
Parses the source file at \a filePath and inserts the contents
into the database. The \a location is used for error reporting.
If it can't open the file at \a filePath, it reports an
error and returns without doing anything.
If it can't open the file at \a filePath, it reports an error
and returns without doing anything.
*/
void QmlCodeParser::parseSourceFile(const Location& location,
const QString& filePath,
Tree *tree)
void QmlCodeParser::parseSourceFile(const Location& location, const QString& filePath)
{
QFile in(filePath);
currentFile_ = filePath;
@ -170,7 +173,6 @@ void QmlCodeParser::parseSourceFile(const Location& location,
QmlDocVisitor visitor(filePath,
newCode,
&engine,
tree,
metacommandsAllowed,
topicCommandsAllowed);
QQmlJS::AST::Node::accept(ast, &visitor);
@ -184,10 +186,10 @@ void QmlCodeParser::parseSourceFile(const Location& location,
}
/*!
This function is called when the parser finishes parsing
the file, but in this case the function does nothing.
Performs cleanup after qdoc is done parsing all the QML files.
Currently, no cleanup is required.
*/
void QmlCodeParser::doneParsingSourceFiles(Tree *)
void QmlCodeParser::doneParsingSourceFiles()
{
}

View File

@ -70,9 +70,8 @@ public:
virtual void terminateParser();
virtual QString language();
virtual QStringList sourceFileNameFilter();
virtual void parseSourceFile(const Location& location,
const QString& filePath, Tree *tree);
virtual void doneParsingSourceFiles(Tree *tree);
virtual void parseSourceFile(const Location& location, const QString& filePath);
virtual void doneParsingSourceFiles();
/* Copied from src/declarative/qml/qdeclarativescriptparser.cpp */
void extractPragmas(QString &script);

View File

@ -49,6 +49,7 @@
#include "node.h"
#include "codeparser.h"
#include "qmlvisitor.h"
#include "qdocdatabase.h"
QT_BEGIN_NAMESPACE
@ -84,7 +85,6 @@ QT_BEGIN_NAMESPACE
QmlDocVisitor::QmlDocVisitor(const QString &filePath,
const QString &code,
QQmlJS::Engine *engine,
Tree *tree,
QSet<QString> &commands,
QSet<QString> &topics)
: nestingLevel(0)
@ -93,10 +93,9 @@ QmlDocVisitor::QmlDocVisitor(const QString &filePath,
this->name = QFileInfo(filePath).baseName();
document = code;
this->engine = engine;
this->tree = tree;
this->commands = commands;
this->topics = topics;
current = tree->root();
current = QDocDatabase::qdocDB()->treeRoot();
}
/*!
@ -235,6 +234,8 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
Node* node,
Doc& doc)
{
QDocDatabase* qdb = QDocDatabase::qdocDB();
const TopicList& topicsUsed = doc.topicsUsed();
if (topicsUsed.size() > 0) {
if (node->type() == Node::QmlProperty) {
@ -317,12 +318,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
node->setStatus(Node::Deprecated);
}
else if (command == COMMAND_INQMLMODULE) {
node->setQmlModule(args[0]);
DocNode* dn = DocNode::lookupQmlModuleNode(tree, args[0]);
dn->addQmlModuleMember(node);
QString qmid = node->qmlModuleIdentifier();
QmlClassNode* qcn = static_cast<QmlClassNode*>(node);
QmlClassNode::insertQmlModuleMember(qmid, qcn);
qdb->addToQmlModule(args[0].first,node);
}
else if (command == COMMAND_QMLINHERITS) {
if (node->name() == args[0].first)
@ -349,7 +345,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
else if ((command == COMMAND_INGROUP) && !args.isEmpty()) {
ArgList::ConstIterator argsIter = args.constBegin();
while (argsIter != args.constEnd()) {
tree->addToGroup(node, argsIter->first);
QDocDatabase::qdocDB()->addToGroup(node, argsIter->first);
++argsIter;
}
}
@ -380,10 +376,10 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
}
/*!
Begin the visit of the object \a definition, recording it in a tree
structure. Increment the object nesting level, which is used to
test whether we are at the public API level. The public level is
level 1.
Begin the visit of the object \a definition, recording it in the
qdoc database. Increment the object nesting level, which is used
to test whether we are at the public API level. The public level
is level 1.
*/
bool QmlDocVisitor::visit(QQmlJS::AST::UiObjectDefinition *definition)
{

View File

@ -70,7 +70,6 @@ public:
QmlDocVisitor(const QString &filePath,
const QString &code,
QQmlJS::Engine *engine,
Tree *tree,
QSet<QString> &commands,
QSet<QString> &topics);
virtual ~QmlDocVisitor();

View File

@ -51,6 +51,7 @@
#include "node.h"
#include "text.h"
#include "tree.h"
#include "qdocdatabase.h"
#include <limits.h>
#include <qdebug.h>
@ -103,14 +104,20 @@ public:
\class Tree
This class constructs and maintains a tree of instances of
Node and its many subclasses.
the subclasses of Node.
This class is now private. Only class QDocDatabase has access.
Please don't change this. If you must access class Tree, do it
though the pointer to the singleton QDocDatabase.
*/
/*!
The default constructor is the only constructor.
Constructs the singleton tree. \a qdb is the pointer to the
qdoc database that is constructing the tree. This might not
be necessary, and it might be removed later.
*/
Tree::Tree()
: roo(0, QString())
Tree::Tree(QDocDatabase* qdb)
: qdb_(qdb), root_(0, QString())
{
priv = new TreePrivate;
}
@ -180,8 +187,8 @@ const Node* Tree::findNode(const QStringList& path,
If the anser is yes, the reference identifies a QML
class node.
*/
if (qml && path.size() >= 2) {
QmlClassNode* qcn = QmlClassNode::lookupQmlTypeNode(path[0], path[1]);
if (qml && path.size() >= 2 && !path[0].isEmpty()) {
QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
if (qcn) {
node = qcn;
if (path.size() == 2)
@ -227,30 +234,27 @@ const Node* Tree::findNode(const QStringList& path,
}
/*!
Find the QML class node for the specified \a module and \a name
identifiers. The \a module identifier may be empty. If the module
identifier is empty, then begin by finding the DocNode that has
the specified \a name. If that DocNode is a QML class, return it.
If it is a collision node, return its current child, if the current
child is a QML class. If the collision node does not have a child
that is a QML class node, return 0.
Find the Qml type node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Qml type node named \a path is
acceptible. If one is not found, 0 is returned.
*/
QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name)
QmlClassNode* Tree::findQmlTypeNode(const QStringList& path)
{
if (module.isEmpty()) {
Node* n = findQmlClassNode(QStringList(name));
if (n) {
if (n->subType() == Node::QmlClass)
return static_cast<QmlClassNode*>(n);
else if (n->subType() == Node::Collision) {
NameCollisionNode* ncn;
ncn = static_cast<NameCollisionNode*>(n);
return static_cast<QmlClassNode*>(ncn->findAny(Node::Document,Node::QmlClass));
}
}
return 0;
/*
If the path contains one or two double colons ("::"),
check first to see if the first two path strings refer
to a QML element. If they do, path[0] will be the QML
module identifier, and path[1] will be the QML type.
If the anser is yes, the reference identifies a QML
class node.
*/
if (path.size() >= 2 && !path[0].isEmpty()) {
QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
if (qcn)
return qcn;
}
return QmlClassNode::lookupQmlTypeNode(module, name);
return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, root(), Node::Document, Node::QmlClass));
}
/*!
@ -327,8 +331,8 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path,
it is a reference to a QML method, first look up the
QML class node in the QML module map.
*/
if (path.size() == 3) {
QmlClassNode* qcn = QmlClassNode::lookupQmlTypeNode(path[0], path[1]);
if (path.size() == 3 && !path[0].isEmpty()) {
QmlClassNode* qcn = qdb_->findQmlType(path[0], path[1]);
if (qcn) {
return static_cast<const FunctionNode*>(qcn->findFunctionNode(path[2]));
}
@ -415,12 +419,9 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& parentPath,
int findFlags) const
{
const Node* parent = findNode(parentPath, relative, findFlags);
if (parent == 0 || !parent->isInnerNode()) {
if (parent == 0 || !parent->isInnerNode())
return 0;
}
else {
return ((InnerNode*)parent)->findFunctionNode(clone);
}
return ((InnerNode*)parent)->findFunctionNode(clone);
}
//findNode(parameter.leftType().split("::"), 0, SearchBaseClasses|NonFunction);
@ -596,7 +597,7 @@ void Tree::addToGroup(Node* node, const QString& group)
/*!
Returns the group map.
*/
NodeMultiMap Tree::groups() const
const NodeMultiMap& Tree::groups() const
{
return priv->groupMap;
}
@ -745,9 +746,9 @@ void Tree::resolveGroups()
if (i.value()->access() == Node::Private)
continue;
Node* n = findGroupNode(QStringList(i.key()));
DocNode* n = findGroupNode(QStringList(i.key()));
if (n)
n->addGroupMember(i.value());
n->addMember(i.value());
}
}
@ -813,7 +814,7 @@ void Tree::resolveTargets(InnerNode* root)
void Tree::resolveCppToQmlLinks()
{
foreach (Node* child, roo.childNodes()) {
foreach (Node* child, root_.childNodes()) {
if (child->type() == Node::Document && child->subType() == Node::QmlClass) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(child);
ClassNode* cn = const_cast<ClassNode*>(qcn->classNode());
@ -823,35 +824,6 @@ void Tree::resolveCppToQmlLinks()
}
}
/*!
For each QML class node in the tree, determine whether
it inherits a QML base class and, if so, which one, and
store that pointer in the QML class node's state.
*/
void Tree::resolveQmlInheritance()
{
foreach (Node* child, roo.childNodes()) {
if (child->type() == Node::Document) {
if (child->subType() == Node::QmlClass) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(child);
qcn->resolveInheritance(this);
}
else if (child->subType() == Node::Collision) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(child);
foreach (Node* child, ncn->childNodes()) {
if (child->type() == Node::Document) {
if (child->subType() == Node::QmlClass) {
QmlClassNode* qcn = static_cast<QmlClassNode*>(child);
qcn->resolveInheritance(this);
}
}
}
}
}
}
}
/*!
*/
void Tree::fixInheritance(NamespaceNode* rootNode)
@ -1635,7 +1607,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer,
QmlPropertyNode* qpn = static_cast<QmlPropertyNode*>(node);
writer.writeAttribute("type", qpn->dataType());
writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false");
writer.writeAttribute("writable", qpn->isWritable(this) ? "true" : "false");
writer.writeAttribute("writable", qpn->isWritable(qdb_) ? "true" : "false");
}
break;
case Node::Property:
@ -2399,42 +2371,13 @@ ClassNode* Tree::findClassNode(const QStringList& path, Node* start)
}
/*!
Find the Qml class node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Qml class node named \a path is
acceptible. If one is not found, 0 is returned.
Find the Namespace node named \a path. Begin the search at
the root of the tree. Only a Namespace node named \a path
is acceptible. If one is not found, 0 is returned.
*/
QmlClassNode* Tree::findQmlClassNode(const QStringList& path, Node* start)
NamespaceNode* Tree::findNamespaceNode(const QStringList& path)
{
/*
If the path contains one or two double colons ("::"),
check first to see if the first two path strings refer
to a QML element. If they do, path[0] will be the QML
module identifier, and path[1] will be the QML type.
If the anser is yes, the reference identifies a QML
class node.
*/
if (path.size() >= 2) {
QmlClassNode* qcn = QmlClassNode::lookupQmlTypeNode(path[0], path[1]);
if (qcn)
return qcn;
}
if (!start)
start = const_cast<NamespaceNode*>(root());
return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, start, Node::Document, Node::QmlClass));
}
/*!
Find the Namespace node named \a path. Begin the search at the
\a start node. If the \a start node is 0, begin the search
at the root of the tree. Only a Namespace node named \a path is
acceptible. If one is not found, 0 is returned.
*/
NamespaceNode* Tree::findNamespaceNode(const QStringList& path, Node* start)
{
if (!start)
start = const_cast<NamespaceNode*>(root());
Node* start = const_cast<NamespaceNode*>(root());
return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
}

View File

@ -55,21 +55,24 @@ QT_BEGIN_NAMESPACE
class Generator;
class QStringList;
class TreePrivate;
class QDocDatabase;
class Tree
{
public:
private:
friend class QDocDatabase;
enum FindFlag { SearchBaseClasses = 0x1,
SearchEnumValues = 0x2,
NonFunction = 0x4 };
Tree();
Tree(QDocDatabase* qdb);
~Tree();
EnumNode* findEnumNode(const QStringList& path, Node* start = 0);
ClassNode* findClassNode(const QStringList& path, Node* start = 0);
QmlClassNode* findQmlClassNode(const QStringList& path, Node* start = 0);
NamespaceNode* findNamespaceNode(const QStringList& path, Node* start = 0);
QmlClassNode* findQmlTypeNode(const QStringList& path);
NamespaceNode* findNamespaceNode(const QStringList& path);
DocNode* findGroupNode(const QStringList& path, Node* start = 0);
DocNode* findQmlModuleNode(const QStringList& path, Node* start = 0);
@ -91,15 +94,12 @@ public:
int findFlags = 0,
const Node* self=0) const;
private:
const Node* findNode(const QStringList& path,
const Node* start,
int findFlags,
const Node* self,
bool qml) const;
public:
QmlClassNode* findQmlClassNode(const QString& module, const QString& name);
NameCollisionNode* checkForCollision(const QString& name) const;
NameCollisionNode* findCollisionNode(const QString& name) const;
FunctionNode *findFunctionNode(const QStringList &path,
@ -113,14 +113,14 @@ public:
Node::Access access,
const QStringList &basePath,
const QString &dataTypeWithTemplateArgs,
InnerNode *parent = 0);
InnerNode *parent);
void addPropertyFunction(PropertyNode *property,
const QString &funcName,
PropertyNode::FunctionRole funcRole);
void addToGroup(Node *node, const QString &group);
void addToPublicGroup(Node *node, const QString &group);
void addToQmlModule(Node* node);
NodeMultiMap groups() const;
const NodeMultiMap& groups() const;
QMultiMap<QString,QString> publicGroups() const;
void resolveInheritance(NamespaceNode *rootNode = 0);
void resolveProperties();
@ -129,7 +129,7 @@ public:
void resolveCppToQmlLinks();
void fixInheritance(NamespaceNode *rootNode = 0);
void setVersion(const QString &version) { vers = version; }
NamespaceNode *root() { return &roo; }
NamespaceNode *root() { return &root_; }
QString version() const { return vers; }
const FunctionNode *findFunctionNode(const QStringList &path,
@ -142,7 +142,7 @@ public:
const DocNode *findDocNodeByTitle(const QString &title, const Node* relative = 0) const;
const Node *findUnambiguousTarget(const QString &target, Atom *&atom, const Node* relative) const;
Atom *findTarget(const QString &target, const Node *node) const;
const NamespaceNode *root() const { return &roo; }
const NamespaceNode *root() const { return &root_; }
void readIndexes(const QStringList &indexFiles);
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
@ -157,9 +157,7 @@ public:
const InnerNode *inner);
void generateTagFile(const QString &fileName);
void addExternalLink(const QString &url, const Node *relative);
void resolveQmlInheritance();
private:
void resolveInheritance(int pass, ClassNode *classe);
FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe,
FunctionNode *clone);
@ -172,7 +170,8 @@ private:
void resolveIndex();
private:
NamespaceNode roo;
QDocDatabase* qdb_;
NamespaceNode root_;
QString vers;
Generator* gen_;
TreePrivate *priv;