}
case Node::Namespace:
case Node::Fake:
- case Node::Target:
default:
return QStringList();
}
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("()")) {
- const FunctionNode *func;
QString funcName = target;
funcName.chop(2);
-
QStringList path = funcName.split("::");
- if ((func = tree->findFunctionNode(path,
- relative,
- Tree::SearchBaseClasses))
- && func->metaness() != FunctionNode::MacroWithoutParams)
- return func;
+ 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 doesn't belong here; get rid of TargetNode hack
- int hashAt = target.indexOf(QLatin1Char('#'));
- QString link = target.left(hashAt);
- QString ref = target.mid(hashAt + 1);
- const Node *node;
- if (link.isEmpty()) {
- node = relative;
- }
- else {
- QStringList path(link);
- node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses);
- }
- if (node && node->isInnerNode()) {
- const Atom *atom = node->doc().body().firstAtom();
- while (atom) {
- if (atom->type() == Atom::Target && atom->string() == ref) {
- Node *parentNode = const_cast<Node *>(node);
- return new TargetNode(static_cast<InnerNode*>(parentNode),
- ref);
- }
- atom = atom->next();
- }
- }
+ // 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("::");
- const Node *node;
- int flags = Tree::SearchBaseClasses |
- Tree::SearchEnumValues |
- Tree::NonFunction;
- if ((node = tree->findNode(path,
- relative,
- flags,
- self)))
- return node;
+ int flags = Tree::SearchBaseClasses | Tree::SearchEnumValues | Tree::NonFunction;
+ node = tree->findNode(path, relative, flags, self);
}
- return 0;
+ return node;
}
static const char * const typeTable[] = {
#define COMMAND_PROPERTY Doc::alias("property")
#define COMMAND_REIMP Doc::alias("reimp")
#define COMMAND_RELATES Doc::alias("relates")
-#define COMMAND_SERVICE Doc::alias("service")
#define COMMAND_STARTPAGE Doc::alias("startpage")
#define COMMAND_TYPEDEF Doc::alias("typedef")
#define COMMAND_VARIABLE Doc::alias("variable")
This is used for fuzzy matching only, which in turn is only used
for Qt Jambi.
*/
-static QString cleanType(const QString &type, const Tree *tree)
+static QString cleanType(const QString &type, Tree* tree)
{
QString result = type;
result.replace("qlonglong", "long long");
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);
- const EnumNode *enume = static_cast<const EnumNode *>(
- tree->findNode(QStringList(path) << regExp.cap(3),
- Node::Enum));
- if (enume && enume->flagsType())
- result.replace(pos, regExp.matchedLength(),
- (QStringList(path) << enume->flagsType()->name()).join("::"));
+ 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;
}
}
{
CodeParser::initializeParser(config);
+ /*
+ All these can appear in a C++ namespace. Don't add
+ anything that can't be in a C++ namespace.
+ */
nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace);
nodeTypeMap.insert(COMMAND_CLASS, Node::Class);
- nodeTypeMap.insert(COMMAND_SERVICE, Node::Class);
nodeTypeMap.insert(COMMAND_ENUM, Node::Enum);
nodeTypeMap.insert(COMMAND_TYPEDEF, Node::Typedef);
nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property);
Tokenizer fileTokenizer(fileLocation, in);
tokenizer = &fileTokenizer;
readToken();
- usedNamespaces.clear();
+
+ /*
+ The set of active namespaces is cleared before parsing
+ each source file. The word "source" here means cpp file.
+ */
+ activeNamespaces_.clear();
+
matchDocsAndStuff();
in.close();
}
This is necessary because Roberto's parser resolves typedefs.
*/
if (!func && fuzzy) {
- func = tre->findFunctionNode(parentPath +
+ func = tree_->findFunctionNode(parentPath +
QStringList(clone->name()),
relative,
flags);
if (!func && clone->name().contains('_')) {
QStringList path = parentPath;
path << clone->name().split('_');
- func = tre->findFunctionNode(path, relative, flags);
+ func = tree_->findFunctionNode(path, relative, flags);
}
if (func) {
<< COMMAND_NAMESPACE
<< COMMAND_PAGE
<< COMMAND_PROPERTY
- << COMMAND_SERVICE
<< COMMAND_TYPEDEF
<< COMMAND_VARIABLE
<< COMMAND_QMLCLASS
doc.location().warning(tr("Invalid syntax in '\\%1'").arg(COMMAND_FN));
}
else {
- if (!usedNamespaces.isEmpty()) {
- foreach (const QString &usedNamespace, usedNamespaces) {
- QStringList newPath = usedNamespace.split("::") + parentPath;
- func = tre->findFunctionNode(newPath, clone);
+ if (!activeNamespaces_.isEmpty()) {
+ foreach (const QString& usedNamespace_, activeNamespaces_) {
+ QStringList newPath = usedNamespace_.split("::") + parentPath;
+ func = tree_->findFunctionNode(newPath, clone);
if (func)
break;
}
}
// Search the root namespace if no match was found.
if (func == 0)
- func = tre->findFunctionNode(parentPath, clone);
+ func = tree_->findFunctionNode(parentPath, clone);
if (func == 0) {
if (parentPath.isEmpty() && !lastPath.isEmpty())
- func = tre->findFunctionNode(lastPath, clone);
+ func = tree_->findFunctionNode(lastPath, clone);
if (func == 0) {
doc.location().warning(tr("Cannot find '%1' in '\\%2'")
.arg(clone->name() + "(...)")
QStringList parentPath;
FunctionNode *func = 0;
- if (makeFunctionNode(arg, &parentPath, &func, tre->root())) {
+ if (makeFunctionNode(arg, &parentPath, &func, tree_->root())) {
if (!parentPath.isEmpty()) {
doc.location().warning(tr("Invalid syntax in '\\%1'")
.arg(COMMAND_MACRO));
return func;
}
else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg)) {
- func = new FunctionNode(tre->root(), arg);
+ func = new FunctionNode(tree_->root(), arg);
func->setAccess(Node::Public);
func->setLocation(doc.location());
func->setMetaness(FunctionNode::MacroWithoutParams);
}
else if (nodeTypeMap.contains(command)) {
/*
- The command was neither "fn" nor "macro" .
+ We should only get in here if the command refers to
+ something that can appear in a C++ namespace,
+ i.e. a class, another namespace, an enum, a typedef,
+ a property or a variable. I think these are handled
+ this way to allow the writer to refer to the entity
+ without including the namespace qualifier.
*/
- // ### split(QLatin1Char(' ')) hack is there to support header file syntax
+ Node::Type type = nodeTypeMap[command];
+ Node::SubType subtype = Node::NoSubType;
+ if (type == Node::Fake)
+ subtype = Node::QmlClass;
+
QStringList paths = arg.split(QLatin1Char(' '));
QStringList path = paths[0].split("::");
Node *node = 0;
- if (!usedNamespaces.isEmpty()) {
- foreach (const QString &usedNamespace, usedNamespaces) {
- QStringList newPath = usedNamespace.split("::") + path;
- node = tre->findNode(newPath, nodeTypeMap[command]);
+
+ /*
+ If the command refers to something that can be in a
+ C++ namespace, search for it first in all the known
+ C++ namespaces.
+ */
+ if (!activeNamespaces_.isEmpty()) {
+ foreach (const QString& usedNamespace_, activeNamespaces_) {
+ QStringList newPath = usedNamespace_.split("::") + path;
+ node = tree_->findNodeByNameAndType(newPath, type, subtype, 0);
if (node) {
path = newPath;
break;
}
}
}
- // Search the root namespace if no match was found.
- if (node == 0)
- node = tre->findNode(path, nodeTypeMap[command]);
+
+ /*
+ If the node was not found in a C++ namespace, search
+ for it in the root namespace.
+ */
+ if (node == 0) {
+ node = tree_->findNodeByNameAndType(path, type, subtype, 0);
+ }
if (node == 0) {
doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file")
lastPath = path;
}
- else if (command == COMMAND_SERVICE) {
- // If the command is "\service", then we need to tag the
- // class with the actual service name.
- QStringList args = arg.split(QLatin1Char(' '));
- if (args.size() > 1) {
- ClassNode *cnode = static_cast<ClassNode *>(node);
- cnode->setServiceName(args[1]);
- cnode->setHideFromMainList(true);
- }
- }
else if (node->isInnerNode()) {
+ /*
+ This treets a class as a namespace.
+ */
if (path.size() > 1) {
path.pop_back();
- usedNamespaces.insert(path.join("::"));
+ QString ns = path.join("::");
+ activeNamespaces_.insert(ns);
}
}
-#if 0
- /*
- This code apparently does nothing. After further
- investigation to verify it is useless, it will
- be removed.
- */
- if (command == COMMAND_CLASS) {
- if (paths.size() > 1) {
- if (!paths[1].endsWith(".h")) {
- ClassNode* cnode = static_cast<ClassNode*>(node);
- cnode->setQmlElement(paths[1]);
- }
- }
- }
-#endif
return node;
}
else if (command == COMMAND_EXAMPLE) {
- if (Config::generateExamples) {
- ExampleNode* en = new ExampleNode(tre->root(), arg);
- createExampleFileNodes(en);
- return en;
- }
+ ExampleNode* en = new ExampleNode(tree_->root(), arg);
+ createExampleFileNodes(en);
+ return en;
}
else if (command == COMMAND_EXTERNALPAGE) {
- return new FakeNode(tre->root(), arg, Node::ExternalPage, Node::ArticlePage);
+ return new FakeNode(tree_->root(), arg, Node::ExternalPage, Node::ArticlePage);
}
else if (command == COMMAND_FILE) {
- return new FakeNode(tre->root(), arg, Node::File, Node::NoPageType);
+ return new FakeNode(tree_->root(), arg, Node::File, Node::NoPageType);
}
else if (command == COMMAND_GROUP) {
- return new FakeNode(tre->root(), arg, Node::Group, Node::OverviewPage);
+ return new FakeNode(tree_->root(), arg, Node::Group, Node::OverviewPage);
}
else if (command == COMMAND_HEADERFILE) {
- return new FakeNode(tre->root(), arg, Node::HeaderFile, Node::ApiPage);
+ return new FakeNode(tree_->root(), arg, Node::HeaderFile, Node::ApiPage);
}
else if (command == COMMAND_MODULE) {
- return new FakeNode(tre->root(), arg, Node::Module, Node::OverviewPage);
+ return new FakeNode(tree_->root(), arg, Node::Module, Node::OverviewPage);
}
else if (command == COMMAND_QMLMODULE) {
- return new FakeNode(tre->root(), arg, Node::QmlModule, Node::OverviewPage);
+ return new FakeNode(tree_->root(), arg, Node::QmlModule, Node::OverviewPage);
}
else if (command == COMMAND_PAGE) {
Node::PageType ptype = Node::ArticlePage;
If there is no collision, just create a new Page
node and return that one.
*/
- NameCollisionNode* ncn = tre->checkForCollision(args[0]);
+ NameCollisionNode* ncn = tree_->checkForCollision(args[0]);
FakeNode* fn = 0;
if (ptype == Node::DitaMapPage)
- fn = new DitaMapNode(tre->root(), args[0]);
+ fn = new DitaMapNode(tree_->root(), args[0]);
else
- fn = new FakeNode(tre->root(), args[0], Node::Page, ptype);
+ fn = new FakeNode(tree_->root(), args[0], Node::Page, ptype);
if (ncn) {
ncn->addCollision(fn);
}
return fn;
}
else if (command == COMMAND_DITAMAP) {
- FakeNode* fn = new DitaMapNode(tre->root(), arg);
+ FakeNode* fn = new DitaMapNode(tree_->root(), arg);
return fn;
}
else if (command == COMMAND_QMLCLASS) {
- const ClassNode* classNode = 0;
+ ClassNode* classNode = 0;
QStringList names = arg.split(QLatin1Char(' '));
- if (names.size() > 1) {
- Node* n = tre->findNode(names[1].split("::"),Node::Class);
- if (n) {
- classNode = static_cast<const ClassNode*>(n);
- }
- }
+ if (names.size() > 1)
+ classNode = tree_->findClassNode(names[1].split("::"));
+
/*
Search for a node with the same name. If there is one,
then there is a collision, so create a collision node
If there is no collision, just create a new QML class
node and return that one.
*/
- NameCollisionNode* ncn = tre->checkForCollision(names[0]);
- QmlClassNode* qcn = new QmlClassNode(tre->root(), names[0], classNode);
- if (ncn) {
+ NameCollisionNode* ncn = tree_->checkForCollision(names[0]);
+ QmlClassNode* qcn = new QmlClassNode(tree_->root(), names[0], classNode);
+ if (ncn)
ncn->addCollision(qcn);
- }
return qcn;
}
else if (command == COMMAND_QMLBASICTYPE) {
- return new QmlBasicTypeNode(tre->root(), arg);
+ return new QmlBasicTypeNode(tree_->root(), arg);
}
else if ((command == COMMAND_QMLSIGNAL) ||
(command == COMMAND_QMLMETHOD) ||
QString element;
QString type;
if (splitQmlMethodArg(doc,arg,type,module,element)) {
- QmlClassNode* qmlClass = tre->findQmlClassNode(module,element);
+ QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element);
if (qmlClass) {
if (command == COMMAND_QMLSIGNAL)
return makeFunctionNode(doc,arg,qmlClass,Node::QmlSignal,false,COMMAND_QMLSIGNAL);
bool attached = (command == COMMAND_QMLATTACHEDPROPERTY);
QStringList::ConstIterator arg = args.begin();
if (splitQmlPropertyArg(doc,(*arg),type,module,element,property)) {
- QmlClassNode* qmlClass = tre->findQmlClassNode(module,element);
+ QmlClassNode* qmlClass = tree_->findQmlClassNode(module,element);
if (qmlClass) {
qmlPropGroup = new QmlPropGroupNode(qmlClass,property,attached);
}
}
if (qmlPropGroup) {
- const ClassNode *correspondingClass = static_cast<const QmlClassNode*>(qmlPropGroup->parent())->classNode();
+ ClassNode *correspondingClass = static_cast<QmlClassNode*>(qmlPropGroup->parent())->classNode();
QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup,property,type,attached);
const PropertyNode *correspondingProperty = 0;
if (correspondingClass) {
- correspondingProperty = qmlPropNode->correspondingProperty(tre);
+ correspondingProperty = qmlPropNode->correspondingProperty(tree_);
}
if (correspondingProperty) {
bool writableList = type.startsWith("list") && correspondingProperty->dataType().endsWith('*');
}
}
else if (command == COMMAND_RELATES) {
- InnerNode *pseudoParent;
+ /*
+ Find the node that this node relates to.
+ */
+ Node* n = 0;
if (arg.startsWith(QLatin1Char('<')) || arg.startsWith('"')) {
- pseudoParent =
- static_cast<InnerNode *>(tre->findNode(QStringList(arg),
- Node::Fake));
+ /*
+ It should be a header file, I think.
+ */
+ n = tree_->findNodeByNameAndType(QStringList(arg), Node::Fake, Node::NoSubType, 0);
}
else {
+ /*
+ If it wasn't a file, it should be either a class or a namespace.
+ */
QStringList newPath = arg.split("::");
- pseudoParent =
- static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
- Node::Class));
- if (!pseudoParent)
- pseudoParent =
- static_cast<InnerNode*>(tre->findNode(QStringList(newPath),
- Node::Namespace));
- }
- if (!pseudoParent) {
- doc.location().warning(tr("Cannot find '%1' in '\\%2'")
- .arg(arg).arg(COMMAND_RELATES));
+ n = tree_->findClassNode(QStringList(newPath));
+ if (!n)
+ n = tree_->findNamespaceNode(QStringList(newPath));
+ }
+
+ if (!n) {
+ /*
+ Didn't ind it. Error...
+ */
+ doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
}
else {
- node->setRelates(pseudoParent);
+ /*
+ Found it. This node relates to it.
+ */
+ node->setRelates(static_cast<InnerNode*>(n));
}
}
else if (command == COMMAND_CONTENTSPAGE) {
}
}
else {
- processCommonMetaCommand(doc.location(),command,arg,node,tre);
+ processCommonMetaCommand(doc.location(),command,arg,node,tree_);
}
}
*/
void CppCodeParser::reset(Tree *tree)
{
- tre = tree;
+ tree_ = tree;
tokenizer = 0;
tok = 0;
access = Node::Public;
if (!matchDataType(&baseClass))
return false;
- tre->addBaseClass(classe,
+ tree_->addBaseClass(classe,
access,
baseClass.toPath(),
baseClass.toString(),
So far, so good. We have 'namespace Foo {'.
*/
QString namespaceName = previousLexeme();
- NamespaceNode *namespasse = 0;
+ NamespaceNode* ns = 0;
if (parent) {
- namespasse = static_cast<NamespaceNode*>(parent->findNode(namespaceName, Node::Namespace));
+ ns = static_cast<NamespaceNode*>(parent->findChildNodeByNameAndType(namespaceName, Node::Namespace));
}
- if (!namespasse) {
- namespasse = new NamespaceNode(parent, namespaceName);
- namespasse->setAccess(access);
- namespasse->setLocation(location());
+ if (!ns) {
+ ns = new NamespaceNode(parent, namespaceName);
+ ns->setAccess(access);
+ ns->setLocation(location());
}
readToken(); // skip '{'
- bool matched = matchDeclList(namespasse);
+ bool matched = matchDeclList(ns);
return matched && match(Tok_RightBrace);
}
/*
So far, so good. We have 'using namespace Foo;'.
*/
- usedNamespaces.insert(name);
+ activeNamespaces_.insert(name);
return true;
}
if (!match(Tok_Semicolon))
return false;
- if (parent && !parent->findNode(name, Node::Typedef)) {
- TypedefNode *typedeffe = new TypedefNode(parent, name);
- typedeffe->setAccess(access);
- typedeffe->setLocation(location());
+ if (parent && !parent->findChildNodeByNameAndType(name, Node::Typedef)) {
+ TypedefNode* td = new TypedefNode(parent, name);
+ td->setAccess(access);
+ td->setLocation(location());
}
return true;
}
}
if (key == "READ")
- tre->addPropertyFunction(property, value, PropertyNode::Getter);
+ tree_->addPropertyFunction(property, value, PropertyNode::Getter);
else if (key == "WRITE") {
- tre->addPropertyFunction(property, value, PropertyNode::Setter);
+ tree_->addPropertyFunction(property, value, PropertyNode::Setter);
property->setWritable(true);
}
else if (key == "STORED")
}
}
else if (key == "RESET")
- tre->addPropertyFunction(property, value, PropertyNode::Resetter);
+ tree_->addPropertyFunction(property, value, PropertyNode::Resetter);
else if (key == "NOTIFY") {
- tre->addPropertyFunction(property, value, PropertyNode::Notifier);
+ tree_->addPropertyFunction(property, value, PropertyNode::Notifier);
} else if (key == "REVISION") {
int revision;
bool ok;
if (match(Tok_LeftParen) && match(Tok_Ident)) {
QString flagsType = previousLexeme();
if (match(Tok_Comma) && match(Tok_Ident)) {
- QString enumType = previousLexeme();
+ QString name = previousLexeme();
TypedefNode *flagsNode = new TypedefNode(parent, flagsType);
flagsNode->setAccess(access);
flagsNode->setLocation(location());
- EnumNode *enumNode =
- static_cast<EnumNode*>(parent->findNode(enumType,
- Node::Enum));
- if (enumNode)
- enumNode->setFlagsType(flagsNode);
+ EnumNode* en = static_cast<EnumNode*>(parent->findChildNodeByNameAndType(name, Node::Enum));
+ if (en)
+ en->setFlagsType(flagsNode);
}
}
match(Tok_RightParen);
FunctionNode *func = 0;
if (matchFunctionDecl(0, &parentPath, &clone)) {
- foreach (const QString &usedNamespace, usedNamespaces) {
- QStringList newPath = usedNamespace.split("::") + parentPath;
- func = tre->findFunctionNode(newPath, clone);
+ foreach (const QString& usedNamespace_, activeNamespaces_) {
+ QStringList newPath = usedNamespace_.split("::") + parentPath;
+ func = tree_->findFunctionNode(newPath, clone);
if (func)
break;
}
if (func == 0)
- func = tre->findFunctionNode(parentPath, clone);
+ func = tree_->findFunctionNode(parentPath, clone);
if (func) {
func->borrowParameterNames(clone);
if ((*n)->isInnerNode() &&
((InnerNode *)*n)->includes().isEmpty()) {
InnerNode *m = static_cast<InnerNode *>(*n);
- while (m->parent() != tre->root())
+ while (m->parent() != tree_->root())
m = m->parent();
if (m == *n)
((InnerNode *)*n)->addInclude((*n)->name());
Signals are implemented in uninteresting files
generated by moc.
*/
- node = tre->findFunctionNode(parentPath, clone);
+ node = tree_->findFunctionNode(parentPath, clone);
if (node != 0 && node->metaness() != FunctionNode::Signal)
node->setLocation(clone->location());
delete clone;
Tokenizer stringTokenizer(loc, latin1);
tokenizer = &stringTokenizer;
readToken();
- matchDeclList(tre->root());
+ matchDeclList(tree_->root());
}
void CppCodeParser::createExampleFileNodes(FakeNode *fake)
void createExampleFileNodes(FakeNode *fake);
QMap<QString, Node::Type> nodeTypeMap;
- Tree *tre;
+ Tree* tree_;
Tokenizer *tokenizer;
int tok;
Node::Access access;
QString mutableSequentialIteratorDefinition;
QString associativeIteratorDefinition;
QString mutableAssociativeIteratorDefinition;
- QSet<QString> usedNamespaces;
+ QSet<QString> activeNamespaces_;
QMap<QString, QString> sequentialIteratorClasses;
QMap<QString, QString> mutableSequentialIteratorClasses;
QMap<QString, QString> associativeIteratorClasses;
sectionNestingLevel(0),
tableColumnCount(0),
funcLeftParen("\\S(\\()"),
- tree_(0),
nodeTypeMaps(Node::LastType,0),
nodeSubtypeMaps(Node::LastSubtype,0),
pageTypeMaps(Node::OnBeyondZebra,0)
This is where the DITA XML files are written.
\note The file is created in PageGenerator::generateTree().
*/
-void DitaXmlGenerator::generateTree(const Tree *tree)
+void DitaXmlGenerator::generateTree(Tree *tree)
{
tree_ = tree;
nonCompatClasses.clear();
findAllSince(tree->root());
Generator::generateTree(tree);
+ generateCollisionPages();
writeDitaMap(tree);
}
const Node *node = 0;
QString myLink = getLink(atom, relative, marker, &node);
if (myLink.isEmpty()) {
- relative->doc().location().warning(tr("Can't link to '%1' in %2")
- .arg(atom->string())
- .arg(marker->plainFullName(relative)));
+ myLink = getCollisionLink(atom);
+ }
+ if (myLink.isEmpty()) {
+ relative->doc().location().warning(tr("Can't link to '%1'")
+ .arg(atom->string()));
}
else if (!inSectionHeading) {
beginLink(myLink);
}
-#if 0
- else {
- //xmlWriter().writeCharacters(atom->string());
- //qDebug() << "MYLINK:" << myLink << outFileName() << atom->string();
- }
-#endif
skipAhead = 1;
}
break;
for marking up the code. I don't know what that means exactly.
*/
void
-DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* marker)
+DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
{
QList<Section>::ConstIterator s;
writeEndTag(); // </cxxClass>
}
else if ((inner->type() == Node::Fake) && (inner->subType() == Node::QmlClass)) {
- const QmlClassNode* qcn = const_cast<QmlClassNode*>(static_cast<const QmlClassNode*>(inner));
- const ClassNode* cn = qcn->classNode();
+ QmlClassNode* qcn = const_cast<QmlClassNode*>(static_cast<const QmlClassNode*>(inner));
+ ClassNode* cn = qcn->classNode();
rawTitle = marker->plainName(inner);
fullTitle = marker->plainFullName(inner);
title = rawTitle + " Element";
Generate the DITA page for a qdoc file that doesn't map
to an underlying c++ file.
*/
-void DitaXmlGenerator::generateFakeNode(const FakeNode* fake, CodeMarker* marker)
+void DitaXmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker)
{
/*
If the fake node is a page node, and if the page type
case Node::ExternalPage: // not used
outputclass = "externalpage";
break;
+ case Node::Collision:
+ outputclass = "collision";
+ break;
default:
outputclass = "page";
}
else if (!isGroupPage) {
// If we encounter a page that belongs to a group then
// we add that page to the list for that group.
- const FakeNode* groupNode =
- static_cast<const FakeNode*>(tree_->root()->findNode(group, Node::Fake));
- if (groupNode)
- fakeNodeMap[groupNode].insert(sortKey, fakeNode);
- //else
- // uncategorizedNodeMap.insert(sortKey, fakeNode);
- }// else
- // uncategorizedNodeMap.insert(sortKey, fakeNode);
- }// else
- // uncategorizedNodeMap.insert(sortKey, fakeNode);
+ const FakeNode* gn = tree_->findGroupNode(QStringList(group));
+ if (gn)
+ fakeNodeMap[gn].insert(sortKey, fakeNode);
+ }
+ }
}
}
return node->guid();
case Node::Variable:
return node->guid();
- case Node::Target:
- return node->guid();
}
return QString();
}
node = relative;
}
else if (target.endsWith(".html")) {
- node = tree_->root()->findNode(target, Node::Fake);
+ node = tree_->root()->findChildNodeByNameAndType(target, Node::Fake);
}
else if (marker) {
node = marker->resolveTarget(target, tree_, relative);
*node = relative;
}
else if (first.endsWith(".html")) {
- *node = tree_->root()->findNode(first, Node::Fake);
+ *node = tree_->root()->findChildNodeByNameAndType(first, Node::Fake);
}
else {
*node = marker->resolveTarget(first, tree_, relative);
return link;
}
-/*!
- This function can be called if getLink() returns an empty
- string.
- */
-QString DitaXmlGenerator::getDisambiguationLink(const Atom *, CodeMarker *)
-{
- qDebug() << "Unimplemented function called: "
- << "QString DitaXmlGenerator::getDisambiguationLink()";
- return QString();
-}
-
void DitaXmlGenerator::generateIndex(const QString& fileBase,
const QString& url,
const QString& title)
Outputs the DITA detailed documentation for a section
on a QML element reference page.
*/
-void DitaXmlGenerator::generateDetailedQmlMember(const Node* node,
+void DitaXmlGenerator::generateDetailedQmlMember(Node* node,
const InnerNode* relative,
CodeMarker* marker)
{
QString marked;
- const QmlPropertyNode* qpn = 0;
+ QmlPropertyNode* qpn = 0;
if (node->subType() == Node::QmlPropertyGroup) {
const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node);
NodeList::ConstIterator p = qpgn->childNodes().begin();
writeStartTag(DT_ul);
while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) {
- qpn = static_cast<const QmlPropertyNode*>(*p);
+ qpn = static_cast<QmlPropertyNode*>(*p);
writeStartTag(DT_li);
writeGuidAttribute((Node*)qpn);
QString attr;
writeEndTag(); // </ul>
}
else if (node->type() == Node::QmlProperty) {
- qpn = static_cast<const QmlPropertyNode*>(node);
+ qpn = static_cast<QmlPropertyNode*>(node);
/*
If the QML property node has a single subproperty,
override, replace qpn with that override node and
if (qpn->qmlPropNodes().size() == 1) {
Node* n = qpn->qmlPropNodes().at(0);
if (n->type() == Node::QmlProperty)
- qpn = static_cast<const QmlPropertyNode*>(n);
+ qpn = static_cast<QmlPropertyNode*>(n);
}
/*
Now qpn either has no overrides, or it has more
If there is no class node, or if the class node status
is set to Node::Internal, do nothing.
*/
-void DitaXmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn,
- CodeMarker* marker)
+void DitaXmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker)
{
- const ClassNode* cn = qcn->classNode();
+ ClassNode* cn = qcn->classNode();
if (cn && (cn->status() != Node::Internal)) {
writeStartTag(DT_p);
xmlWriter().writeAttribute("outputclass","instantiates");
If there is no QML element, or if the class node status
is set to Node::Internal, do nothing.
*/
-void DitaXmlGenerator::generateInstantiatedBy(const ClassNode* cn,
- CodeMarker* marker)
+void DitaXmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker)
{
if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) {
const QmlClassNode* qcn = cn->qmlElement();
Recursive writing of DITA XML files from the root \a node.
*/
void
-DitaXmlGenerator::generateInnerNode(const InnerNode* node)
+DitaXmlGenerator::generateInnerNode(InnerNode* node)
{
if (!node->url().isNull())
return;
if (node->type() == Node::Fake) {
- const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ FakeNode* fakeNode = static_cast<FakeNode*>(node);
if (fakeNode->subType() == Node::ExternalPage)
return;
if (fakeNode->subType() == Node::Image)
CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
if (node->parent() != 0) {
- if (!node->name().endsWith(".ditamap"))
- beginSubPage(node, fileName(node));
- if (node->type() == Node::Namespace || node->type() == Node::Class) {
- generateClassLikeNode(node, marker);
+ /*
+ Skip name collision nodes here and process them
+ later in generateCollisionPages(). Each one is
+ appended to a list for later.
+ */
+ if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
+ NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
+ collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
}
- else if (node->type() == Node::Fake) {
- if (node->subType() == Node::HeaderFile)
- generateClassLikeNode(node, marker);
- else if (node->subType() == Node::QmlClass)
+ else {
+ if (!node->name().endsWith(".ditamap"))
+ beginSubPage(node, fileName(node));
+ if (node->type() == Node::Namespace || node->type() == Node::Class) {
generateClassLikeNode(node, marker);
- else
- generateFakeNode(static_cast<const FakeNode*>(node), marker);
+ }
+ else if (node->type() == Node::Fake) {
+ if (node->subType() == Node::HeaderFile)
+ generateClassLikeNode(node, marker);
+ else if (node->subType() == Node::QmlClass)
+ generateClassLikeNode(node, marker);
+ else
+ generateFakeNode(static_cast<FakeNode*>(node), marker);
+ }
+ if (!node->name().endsWith(".ditamap"))
+ endSubPage();
}
- if (!node->name().endsWith(".ditamap"))
- endSubPage();
}
NodeList::ConstIterator c = node->childNodes().begin();
while (c != node->childNodes().end()) {
if ((*c)->isInnerNode() && (*c)->access() != Node::Private)
- generateInnerNode((const InnerNode*) *c);
+ generateInnerNode((InnerNode*)*c);
++c;
}
}
break;
case Node::Variable:
break;
- case Node::Target:
- break;
case Node::QmlProperty:
break;
case Node::QmlSignal:
Creates the DITA map for the qdoc run. The map is written
to the file \e{qt.ditamap" in the DITA XML output directory.
*/
-void DitaXmlGenerator::writeDitaMap(const Tree *tree)
+void DitaXmlGenerator::writeDitaMap(Tree *tree)
{
QString doctype;
return text;
}
+/*!
+ We delayed generation of the collision pages until now, after
+ all the other pages have been generated. We do this because we might
+ encounter a link command that tries to link to a target on a QML
+ type page, but the link doesn't specify the module identifer
+ for the QML type, and the QML type name without a module
+ identifier is ambiguous. When such a link is found, qdoc can't find
+ the target, so it appends the target to the NameCollisionNode. After
+ the tree has been traversed and all these ambiguous links have been
+ added to the name collision nodes, this function is called. The list
+ of collision nodes is traversed here, and the collision page for
+ each collision is generated. The collision page will not only
+ disambiguate links to the QML type pages, but it will also disambiguate
+ links to properties, section headers, etc.
+ */
+void DitaXmlGenerator::generateCollisionPages()
+{
+ if (collisionNodes.isEmpty())
+ return;
+
+ for (int i=0; i<collisionNodes.size(); ++i) {
+ NameCollisionNode* ncn = collisionNodes.at(i);
+ if (!ncn)
+ continue;
+
+ NodeList collisions;
+ const NodeList& nl = ncn->childNodes();
+ if (!nl.isEmpty()) {
+ NodeList::ConstIterator it = nl.begin();
+ while (it != nl.end()) {
+ if (!(*it)->isInternal())
+ collisions.append(*it);
+ ++it;
+ }
+ }
+ if (collisions.size() <= 1)
+ continue;
+
+ ncn->clearCurrentChild();
+ beginSubPage(ncn, Generator::fileName(ncn));
+ QString fullTitle = ncn->fullTitle();
+ QString ditaTitle = fullTitle;
+ CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
+ if (ncn->isQmlNode()) {
+ // Replace the marker with a QML code marker.
+ if (ncn->isQmlNode())
+ marker = CodeMarker::markerForLanguage(QLatin1String("QML"));
+ }
+
+ generateHeader(ncn, ditaTitle);
+ writeProlog(ncn);
+ writeStartTag(DT_body);
+ enterSection(QString(),QString());
+
+ NodeMap nm;
+ for (int i=0; i<collisions.size(); ++i) {
+ Node* n = collisions.at(i);
+ QString t;
+ if (!n->qmlModuleIdentifier().isEmpty())
+ t = n->qmlModuleIdentifier() + " ";
+ t += protectEnc(fullTitle);
+ nm.insertMulti(t,n);
+ }
+ generateAnnotatedList(ncn, marker, nm);
+
+ QList<QString> targets;
+ if (!ncn->linkTargets().isEmpty()) {
+ QMap<QString,QString>::ConstIterator t = ncn->linkTargets().begin();
+ while (t != ncn->linkTargets().end()) {
+ int count = 0;
+ for (int i=0; i<collisions.size(); ++i) {
+ InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
+ if (n->findChildNodeByName(t.key())) {
+ ++count;
+ if (count > 1) {
+ targets.append(t.key());
+ break;
+ }
+ }
+ }
+ ++t;
+ }
+ }
+ if (!targets.isEmpty()) {
+ QList<QString>::ConstIterator t = targets.begin();
+ while (t != targets.end()) {
+ writeStartTag(DT_p);
+ writeGuidAttribute(Doc::canonicalTitle(*t));
+ xmlWriter().writeAttribute("outputclass","h2");
+ writeCharacters(protectEnc(*t));
+ writeEndTag(); // </p>
+ writeStartTag(DT_ul);
+ for (int i=0; i<collisions.size(); ++i) {
+ InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
+ Node* p = n->findChildNodeByName(*t);
+ if (p) {
+ QString link = linkForNode(p,0);
+ QString label;
+ if (!n->qmlModuleIdentifier().isEmpty())
+ label = n->qmlModuleIdentifier() + "::";
+ label += n->name() + "::" + p->name();
+ writeStartTag(DT_li);
+ writeStartTag(DT_xref);
+ xmlWriter().writeAttribute("href", link);
+ writeCharacters(protectEnc(label));
+ writeEndTag(); // </xref>
+ writeEndTag(); // </li>
+ }
+ }
+ writeEndTag(); // </ul>
+ ++t;
+ }
+ }
+ leaveSection(); // </section>
+ writeEndTag(); // </body>
+ endSubPage();
+ }
+}
+
+
QT_END_NAMESPACE
virtual void terminateGenerator();
virtual QString format();
virtual bool canHandleFormat(const QString& format);
- virtual void generateTree(const Tree *tree);
- virtual void generateDisambiguationPages() { }
+ virtual void generateTree(Tree *tree);
+ void generateCollisionPages();
QString protectEnc(const QString& string);
static QString protect(const QString& string, const QString& encoding = "ISO-8859-1");
virtual int generateAtom(const Atom* atom,
const Node* relative,
CodeMarker* marker);
- virtual void generateClassLikeNode(const InnerNode* inner, CodeMarker* marker);
- virtual void generateFakeNode(const FakeNode* fake, CodeMarker* marker);
+ virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
+ virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker);
virtual QString fileExtension(const Node* node) const;
virtual QString guidForNode(const Node* node);
virtual QString linkForNode(const Node* node, const Node* relative);
const Node* relative,
CodeMarker* marker,
bool summary);
- void generateDetailedQmlMember(const Node* node,
+ void generateDetailedQmlMember(Node* node,
const InnerNode* relative,
CodeMarker* marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
- void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
+ void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
+ void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
void generateSection(const NodeList& nl,
const Node* relative,
const Node *relative,
CodeMarker *marker,
const Node **node);
- QString getDisambiguationLink(const Atom* atom, CodeMarker* marker);
virtual void generateIndex(const QString& fileBase,
const QString& url,
const QString& title);
GuidMap* lookupGuidMap(const QString& fileName);
virtual void beginSubPage(const InnerNode* node, const QString& fileName);
virtual void endSubPage();
- virtual void generateInnerNode(const InnerNode* node);
+ virtual void generateInnerNode(InnerNode* node);
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(const Tree* tree);
+ void writeDitaMap(Tree* tree);
void writeDitaMap(const DitaMapNode* node);
void writeStartTag(DitaTag t);
bool writeEndTag(DitaTag t=DT_NONE);
QStringList vrm;
QStringList stylesheets;
QStringList customHeadElements;
- const Tree* tree_;
QMap<QString, QString> refMap;
QMap<QString, QString> name2guidMap;
GuidMaps guidMaps;
gt(">"),
lt("<"),
quot("""),
- tag("</?@[^>]*>")
+ tag("</?@[^>]*>"),
+ tree_(0)
{
generators.prepend(this);
}
{
if (node->type() == Node::Fake) {
const FakeNode* fn = static_cast<const FakeNode *>(node);
-#if 0
+
// Removed for QTBUG-22870
+ // Unremoved by mws 30/03/12
if (!fn->qmlModuleIdentifier().isEmpty())
- return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title();
-#endif
+ return fn->qmlModuleIdentifier() + "::" + fn->title();
+
return fn->title();
}
else if (node->type() == Node::Class &&
}
}
-void Generator::generateClassLikeNode(const InnerNode * /* classe */,
- CodeMarker * /* marker */)
+void Generator::generateClassLikeNode(InnerNode* /* classe */, CodeMarker* /* marker */)
{
}
generateFileList(fake, marker, Node::Image, QString("Images:"));
}
-void Generator::generateFakeNode(const FakeNode * /* fake */,
- CodeMarker * /* marker */)
+void Generator::generateFakeNode(FakeNode* /* fake */, CodeMarker* /* marker */)
{
}
Recursive writing of HTML files from the root \a node.
\note NameCollisionNodes are skipped here and processed
- later. See HtmlGenerator::generateDisambiguationPages()
- for more on this.
+ later. See HtmlGenerator::generateCollisionPages() for
+ more on this.
*/
-void Generator::generateInnerNode(const InnerNode* node)
+void Generator::generateInnerNode(InnerNode* node)
{
if (!node->url().isNull())
return;
if (node->type() == Node::Fake) {
- const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ FakeNode* fakeNode = static_cast<FakeNode*>(node);
if (fakeNode->subType() == Node::ExternalPage)
return;
if (fakeNode->subType() == Node::Image)
if (node->parent() != 0) {
/*
Skip name collision nodes here and process them
- later in generateDisambiguationPages(). Each one
- is appended to a list for later.
+ later in generateCollisionPages(). Each one is
+ appended to a list for later.
*/
if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
+ NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
}
else {
generateClassLikeNode(node, marker);
}
else if (node->type() == Node::Fake) {
- generateFakeNode(static_cast<const FakeNode *>(node), marker);
+ generateFakeNode(static_cast<FakeNode*>(node), marker);
}
endSubPage();
}
NodeList::ConstIterator c = node->childNodes().begin();
while (c != node->childNodes().end()) {
if ((*c)->isInnerNode() && (*c)->access() != Node::Private) {
- generateInnerNode((const InnerNode *) *c);
+ generateInnerNode((InnerNode*)*c);
}
++c;
}
/*!
This function is recursive.
*/
-void Generator::generateTree(const Tree *tree)
+void Generator::generateTree(Tree *tree)
{
+ tree_ = tree;
generateInnerNode(tree->root());
}
}
/*!
+ This function can be called if getLink() returns an empty
+ string. It tests the \a atom string to see if it is a link
+ of the form <element> :: <name>, where <element> is a QML
+ element or component without a module qualifier. If so, it
+ constructs a link to the <name> clause on the disambiguation
+ page for <element> and returns that link string. It also
+ adds the <name> as a target in the NameCollisionNode for
+ <element>. These clauses are then constructed when the
+ disambiguation page is actually generated.
+ */
+QString Generator::getCollisionLink(const Atom* atom)
+{
+ QString link;
+ if (!atom->string().contains("::"))
+ return link;
+ QStringList path = atom->string().split("::");
+ NameCollisionNode* ncn = tree_->findCollisionNode(path[0]);
+ if (ncn) {
+ QString label;
+ if (atom->next() && atom->next()->next()) {
+ if (atom->next()->type() == Atom::FormattingLeft &&
+ atom->next()->next()->type() == Atom::String)
+ label = atom->next()->next()->string();
+ }
+ ncn->addLinkTarget(path[1],label);
+ link = fileName(ncn);
+ link += QLatin1Char('#');
+ link += Doc::canonicalTitle(path[1]);
+ }
+ return link;
+}
+
+
+/*!
Looks up the tag \a t in the map of metadata values for the
current topic in \a inner. If a value for the tag is found,
the value is returned.
virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
virtual QString format() = 0;
- virtual void generateTree(const Tree *tree);
+ virtual void generateTree(Tree *tree);
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
const Node *relative,
CodeMarker *marker);
virtual void generateBody(const Node *node, CodeMarker *marker);
- virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
- virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
+ virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
+ virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker);
virtual void generateInheritedBy(const ClassNode *classe,
CodeMarker *marker);
virtual void generateInherits(const ClassNode *classe,
CodeMarker *marker);
- virtual void generateInnerNode(const InnerNode *node);
+ virtual void generateInnerNode(InnerNode* node);
virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
void generateSince(const Node *node, CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker);
void generateThreadSafeness(const Node *node, CodeMarker *marker);
+ QString getCollisionLink(const Atom* atom);
QString getMetadataElement(const InnerNode* inner, const QString& t);
QStringList getMetadataElements(const InnerNode* inner, const QString& t);
QString indent(int level, const QString& markedCode);
QString lt;
QString quot;
QRegExp tag;
+
+ protected:
+ Tree* tree_;
};
QT_END_NAMESPACE
typeHash["function"] = Node::Function;
typeHash["property"] = Node::Property;
typeHash["variable"] = Node::Variable;
- typeHash["target"] = Node::Target;
-#ifdef QDOC_QML
typeHash["qmlproperty"] = Node::QmlProperty;
typeHash["qmlsignal"] = Node::QmlSignal;
typeHash["qmlsignalhandler"] = Node::QmlSignalHandler;
typeHash["qmlmethod"] = Node::QmlMethod;
-#endif
QHash<QString, Node::SubType> subTypeHash;
subTypeHash["example"] = Node::Example;
subTypeHash["module"] = Node::Module;
subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage;
-#ifdef QDOC_QML
subTypeHash["qmlclass"] = Node::QmlClass;
subTypeHash["qmlpropertygroup"] = Node::QmlPropertyGroup;
subTypeHash["qmlbasictype"] = Node::QmlBasicType;
-#endif
QSet<Node::SubType> allSubTypes = QSet<Node::SubType>::fromList(subTypeHash.values());
numTableRows(0),
threeColumnEnumValueTable(true),
funcLeftParen("\\S(\\()"),
- myTree(0),
obsoleteLinks(false)
{
}
\note The HTML file generation is done in the base class,
PageGenerator::generateTree().
*/
-void HtmlGenerator::generateTree(const Tree *tree)
+void HtmlGenerator::generateTree(Tree *tree)
{
- myTree = tree;
+ tree_ = tree;
nonCompatClasses.clear();
mainClasses.clear();
compatClasses.clear();
legaleseTexts.clear();
serviceClasses.clear();
qmlClasses.clear();
+
findAllClasses(tree->root());
findAllFunctions(tree->root());
findAllLegaleseTexts(tree->root());
findAllSince(tree->root());
Generator::generateTree(tree);
- reportOrphans(tree->root());
- generateDisambiguationPages();
+ //reportOrphans(tree->root());
+ generateCollisionPages();
QString fileBase = project.toLower().simplified().replace(" ", "-");
generateIndex(fileBase, projectUrl, projectDescription);
- helpProjectWriter->generate(myTree);
+ helpProjectWriter->generate(tree_);
generateManifestFiles();
}
break;
case Atom::AnnotatedList:
{
- QList<Node*> values = myTree->groups().values(atom->string());
+ QList<Node*> values = tree_->groups().values(atom->string());
NodeMap nodeMap;
for (int i = 0; i < values.size(); ++i) {
const Node* n = values.at(i);
// Add additional groups and remove groups of classes that
// should be excluded from the edition.
- QMultiMap <QString, Node *> groups = myTree->groups();
+ QMultiMap <QString, Node *> groups = tree_->groups();
foreach (const QString &groupName, editionGroupMap[editionName]) {
QList<Node *> groupClasses;
if (groupName.startsWith(QLatin1Char('-'))) {
const Node *node = 0;
QString myLink = getLink(atom, relative, marker, &node);
if (myLink.isEmpty()) {
- myLink = getDisambiguationLink(atom, marker);
+ myLink = getCollisionLink(atom);
if (myLink.isEmpty()) {
relative->doc().location().warning(tr("Can't create link to '%1'")
.arg(atom->string()));
/*!
Generate a reference page for a C++ class.
*/
-void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
- CodeMarker *marker)
+void HtmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
{
QList<Section> sections;
QList<Section>::ConstIterator s;
- const ClassNode *classe = 0;
+ ClassNode* classe = 0;
QString title;
QString rawTitle;
title = rawTitle + " Namespace";
}
else if (inner->type() == Node::Class) {
- classe = static_cast<const ClassNode *>(inner);
+ classe = static_cast<ClassNode*>(inner);
rawTitle = marker->plainName(inner);
fullTitle = marker->plainFullName(inner);
title = rawTitle + " Class";
disambiguate links to the component pages, but it will also disambiguate
links to properties, section headers, etc.
*/
-void HtmlGenerator::generateDisambiguationPages()
+void HtmlGenerator::generateCollisionPages()
{
if (collisionNodes.isEmpty())
return;
+
for (int i=0; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i);
+ if (!ncn)
+ continue;
+
+ NodeList collisions;
+ const NodeList& nl = ncn->childNodes();
+ if (!nl.isEmpty()) {
+ NodeList::ConstIterator it = nl.begin();
+ while (it != nl.end()) {
+ if (!(*it)->isInternal())
+ collisions.append(*it);
+ ++it;
+ }
+ }
+ if (collisions.size() <= 1)
+ continue;
+
ncn->clearCurrentChild();
beginSubPage(ncn, Generator::fileName(ncn));
- QString fullTitle = "Name Collision: " + ncn->fullTitle();
+ QString fullTitle = ncn->fullTitle();
QString htmlTitle = fullTitle;
CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
if (ncn->isQmlNode()) {
generateHeader(htmlTitle, ncn, marker);
if (!fullTitle.isEmpty())
out() << "<h1 class=\"title\">" << protectEnc(fullTitle) << "</h1>\n";
- const NodeList& nl = ncn->childNodes();
+
NodeMap nm;
- NodeList::ConstIterator it = nl.begin();
- while (it != nl.end()) {
- QString t = (*it)->qmlModuleIdentifier() + " " + protectEnc(fullTitle);
- nm.insertMulti(t,(*it));
- ++it;
+ for (int i=0; i<collisions.size(); ++i) {
+ Node* n = collisions.at(i);
+ QString t;
+ if (!n->qmlModuleIdentifier().isEmpty())
+ t = n->qmlModuleIdentifier() + "::";
+ t += protectEnc(fullTitle);
+ nm.insertMulti(t,n);
}
generateAnnotatedList(ncn, marker, nm, true);
- const QMap<QString,QString>& targets = ncn->linkTargets();
+ QList<QString> targets;
+ if (!ncn->linkTargets().isEmpty()) {
+ QMap<QString,QString>::ConstIterator t = ncn->linkTargets().begin();
+ while (t != ncn->linkTargets().end()) {
+ int count = 0;
+ for (int i=0; i<collisions.size(); ++i) {
+ InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
+ if (n->findChildNodeByName(t.key())) {
+ ++count;
+ if (count > 1) {
+ targets.append(t.key());
+ break;
+ }
+ }
+ }
+ ++t;
+ }
+ }
if (!targets.isEmpty()) {
- QMap<QString,QString>::ConstIterator t = targets.begin();
+ QList<QString>::ConstIterator t = targets.begin();
while (t != targets.end()) {
- out() << "<a name=\"" << Doc::canonicalTitle(t.key()) << "\"></a>";
- out() << "<h2 class=\"title\">" << protectEnc(t.key()) << "</h2>\n";
+ out() << "<a name=\"" << Doc::canonicalTitle(*t) << "\"></a>";
+ out() << "<h2 class=\"title\">" << protectEnc(*t) << "</h2>\n";
out() << "<ul>\n";
- it = nl.begin();
- while (it != nl.end()) {
- InnerNode* n = static_cast<InnerNode*>(*it);
- Node* p = n->findNode(t.key());
+ for (int i=0; i<collisions.size(); ++i) {
+ InnerNode* n = static_cast<InnerNode*>(collisions.at(i));
+ Node* p = n->findChildNodeByName(*t);
if (p) {
QString link = linkForNode(p,0);
- QString label = n->qmlModuleIdentifier() + "::" + n->name() + "::" + p->name();
+ QString label;
+ if (!n->qmlModuleIdentifier().isEmpty())
+ label = n->qmlModuleIdentifier() + "::";
+ label += n->name() + "::" + p->name();
out() << "<li>";
out() << "<a href=\"" << link << "\">";
out() << protectEnc(label) << "</a>";
out() << "</li>\n";
}
- ++it;
}
out() << "</ul>\n";
++t;
Generate the HTML page for an entity that doesn't map
to any underlying parsable C++ class or QML component.
*/
-void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
+void HtmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker)
{
/*
If the fake node is a page node, and if the page type
Generate the TOC for the new doc format.
Don't generate a TOC for the home page.
*/
- const QmlClassNode* qml_cn = 0;
+ QmlClassNode* qml_cn = 0;
if (fake->subType() == Node::QmlClass) {
- qml_cn = static_cast<const QmlClassNode*>(fake);
+ qml_cn = static_cast<QmlClassNode*>(fake);
sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
generateTableOfContents(fake,marker,§ions);
}
else if (fake->subType() == Node::QmlClass) {
const_cast<FakeNode*>(fake)->setCurrentChild();
- const ClassNode* cn = qml_cn->classNode();
+ ClassNode* cn = qml_cn->classNode();
generateBrief(qml_cn, marker);
generateQmlInherits(qml_cn, marker);
generateQmlInheritedBy(qml_cn, marker);
if (node && !node->doc().location().isEmpty())
out() << "<!-- " << node->doc().location().fileName() << " -->\n";
- QString shortVersion = myTree->version();
+ QString shortVersion = tree_->version();
if (shortVersion.count(QChar('.')) == 2)
shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
if (!project.isEmpty())
generateMacRef(node, marker);
#endif
- out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+ out() << QString(postHeader).replace("\\" + COMMAND_VERSION, tree_->version());
generateBreadCrumbs(title,node,marker);
- out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
+ out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, tree_->version());
navigationLinks.clear();
if (node && !node->links().empty())
out() << "<p class=\"naviNextPrevious footerNavi\">\n" << navigationLinks << "</p>\n";
- out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version())
- << QString(address).replace("\\" + COMMAND_VERSION, myTree->version());
+ out() << QString(footer).replace("\\" + COMMAND_VERSION, tree_->version())
+ << QString(address).replace("\\" + COMMAND_VERSION, tree_->version());
out() << "</body>\n";
out() << "</html>\n";
QMap<QString, FakeNode *> uncategorizedNodeMap;
QRegExp singleDigit("\\b([0-9])\\b");
- const NodeList children = myTree->root()->childNodes();
+ const NodeList children = tree_->root()->childNodes();
foreach (Node *child, children) {
if (child->type() == Node::Fake && child != relative) {
FakeNode *fakeNode = static_cast<FakeNode *>(child);
else if (!isGroupPage) {
// If we encounter a page that belongs to a group then
// we add that page to the list for that group.
- const FakeNode *groupNode = static_cast<const FakeNode *>(myTree->root()->findNode(group, Node::Fake));
- if (groupNode)
- fakeNodeMap[groupNode].insert(sortKey, fakeNode);
- //else
- // uncategorizedNodeMap.insert(sortKey, fakeNode);
- }// else
- // uncategorizedNodeMap.insert(sortKey, fakeNode);
- }// else
- // uncategorizedNodeMap.insert(sortKey, fakeNode);
+ const FakeNode* gn = tree_->findGroupNode(QStringList(group));
+ if (gn)
+ fakeNodeMap[gn].insert(sortKey, fakeNode);
+ }
+ }
}
}
if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
const Node* n = marker->resolveTarget(par1.toString(),
- myTree,
+ tree_,
relative);
QString link = linkForNode(n, relative);
addLink(link, arg, &html);
bool handled = false;
if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self);
+ const Node* n = marker->resolveTarget(arg.toString(), tree_, relative, self);
html += QLatin1String("<span class=\"type\">");
if (n && n->subType() == Node::QmlBasicType) {
if (relative && relative->subType() == Node::QmlClass)
}
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = marker->resolveTarget(arg.toString(), myTree, relative);
+ const Node* n = marker->resolveTarget(arg.toString(), tree_, relative);
addLink(linkForNode(n,relative), arg, &html);
handled = true;
}
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
par1 = QStringRef();
- const Node* n = marker->resolveTarget(arg.toString(), myTree, relative);
+ const Node* n = marker->resolveTarget(arg.toString(), tree_, relative);
addLink(linkForNode(n,relative), arg, &html);
handled = true;
}
case Node::Variable:
ref = node->name() + "-var";
break;
- case Node::Target:
- return protectEnc(node->name());
}
return registerRef(ref);
}
node = relative;
}
else if (target.endsWith(".html")) {
- node = myTree->root()->findNode(target, Node::Fake);
+ node = tree_->root()->findChildNodeByNameAndType(target, Node::Fake);
}
else if (marker) {
- node = marker->resolveTarget(target, myTree, relative);
+ node = marker->resolveTarget(target, tree_, relative);
if (!node) {
- node = myTree->findFakeNodeByTitle(target, relative);
+ node = tree_->findFakeNodeByTitle(target, relative);
}
if (!node && atom) {
- node = myTree->findUnambiguousTarget(target, *const_cast<Atom**>(&atom), relative);
+ node = tree_->findUnambiguousTarget(target, *const_cast<Atom**>(&atom), relative);
}
}
*node = relative;
}
else if (first.endsWith(".html")) {
- *node = myTree->root()->findNode(first, Node::Fake);
+ /*
+ This is not a recursive search. That's ok in
+ this case, because we are searching for a page
+ node, which must be a direct child of the tree
+ root.
+ */
+ *node = tree_->root()->findChildNodeByNameAndType(first, Node::Fake);
}
else {
- *node = marker->resolveTarget(first, myTree, relative);
+ *node = marker->resolveTarget(first, tree_, relative);
if (!*node) {
- *node = myTree->findFakeNodeByTitle(first, relative);
+ *node = tree_->findFakeNodeByTitle(first, relative);
}
if (!*node) {
- *node = myTree->findUnambiguousTarget(first, targetAtom, relative);
+ *node = tree_->findUnambiguousTarget(first, targetAtom, relative);
}
}
if (*node) {
target.
*/
while (!path.isEmpty()) {
- targetAtom = myTree->findTarget(path.first(), *node);
+ targetAtom = tree_->findTarget(path.first(), *node);
if (targetAtom == 0)
break;
path.removeFirst();
return link;
}
-/*!
- This function can be called if getLink() returns an empty
- string. It tests the \a atom string to see if it is a link
- of the form <element> :: <name>, where <element> is a QML
- element or component without a module qualifier. If so, it
- constructs a link to the <name> clause on the disambiguation
- page for <element> and returns that link string. It also
- adds the <name> as a target in the NameCollisionNode for
- <element>. These clauses are then constructed when the
- disambiguation page is actually generated.
- */
-QString HtmlGenerator::getDisambiguationLink(const Atom *atom, CodeMarker *)
-{
- QString link;
- if (!atom->string().contains("::"))
- return link;
- QStringList path = atom->string().split("::");
- NameCollisionNode* ncn = myTree->findCollisionNode(path[0]);
- if (ncn) {
- QString label;
- if (atom->next() && atom->next()->next()) {
- if (atom->next()->type() == Atom::FormattingLeft &&
- atom->next()->next()->type() == Atom::String)
- label = atom->next()->next()->string();
- }
- ncn->addLinkTarget(path[1],label);
- link = fileName(ncn);
- link += QLatin1Char('#');
- link += Doc::canonicalTitle(path[1]);
- }
- return link;
-}
-
void HtmlGenerator::generateIndex(const QString &fileBase,
const QString &url,
const QString &title)
{
- myTree->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index", url, title);
+ tree_->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index", url, title);
}
void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
<< "We strongly advise against "
<< "using it in new code. See ";
- const FakeNode *fakeNode = myTree->findFakeNodeByTitle("Porting To Qt 4");
+ const FakeNode *fakeNode = tree_->findFakeNodeByTitle("Porting To Qt 4");
Atom *targetAtom = 0;
if (fakeNode && node->type() == Node::Class) {
QString oldName(node->name());
oldName.remove(QLatin1Char('3'));
- targetAtom = myTree->findTarget(oldName,
+ targetAtom = tree_->findTarget(oldName,
fakeNode);
}
Outputs the html detailed documentation for a section
on a QML element reference page.
*/
-void HtmlGenerator::generateDetailedQmlMember(const Node *node,
+void HtmlGenerator::generateDetailedQmlMember(Node *node,
const InnerNode *relative,
CodeMarker *marker)
{
- const QmlPropertyNode* qpn = 0;
+ QmlPropertyNode* qpn = 0;
#ifdef GENERATE_MAC_REFS
generateMacRef(node, marker);
#endif
out() << "<table class=\"qmlname\">";
while (p != qpgn->childNodes().end()) {
if ((*p)->type() == Node::QmlProperty) {
- qpn = static_cast<const QmlPropertyNode*>(*p);
+ qpn = static_cast<QmlPropertyNode*>(*p);
out() << "<tr valign=\"top\" class=\"odd\">";
out() << "<td class=\"tblQmlPropNode\"><p>";
out() << "<a name=\"" + refForNode(qpn) + "\"></a>";
int ro = qpn->getReadOnly();
if (ro < 0) {
- if (!qpn->isWritable(myTree)) {
+ if (!qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
}
out() << "</div>";
}
else if (node->type() == Node::QmlProperty) {
- qpn = static_cast<const QmlPropertyNode*>(node);
+ qpn = static_cast<QmlPropertyNode*>(node);
/*
If the QML property node has a single subproperty,
override, replace qpn with that override node and
if (qpn->qmlPropNodes().size() == 1) {
Node* n = qpn->qmlPropNodes().at(0);
if (n->type() == Node::QmlProperty)
- qpn = static_cast<const QmlPropertyNode*>(n);
+ qpn = static_cast<QmlPropertyNode*>(n);
}
/*
Now qpn either has no overrides, or it has more
int ro = qpn->getReadOnly();
if (ro < 0) {
const ClassNode* cn = qpn->declarativeCppNode();
- if (cn && !qpn->isWritable(myTree)) {
+ if (cn && !qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
}
int ro = qpn->getReadOnly();
if (ro < 0) {
- if (!qpn->isWritable(myTree)) {
+ if (!qpn->isWritable(tree_)) {
out() << "<span class=\"qmlreadonly\">read-only</span>";
}
}
If there is no class node, or if the class node status
is set to Node::Internal, do nothing.
*/
-void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker)
+void HtmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker)
{
- const ClassNode* cn = qcn->classNode();
+ ClassNode* cn = qcn->classNode();
if (cn && (cn->status() != Node::Internal)) {
Text text;
text << Atom::ParaLeft;
If there is no QML element, or if the class node status
is set to Node::Internal, do nothing.
*/
-void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker)
+void HtmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker)
{
if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) {
const QmlClassNode* qcn = cn->qmlElement();
case Node::Variable:
anchorRef = QLatin1Char('#') + node->name() + "-var";
break;
- case Node::Target:
- anchorRef = QLatin1Char('#') + Doc::canonicalTitle(node->name());
- break;
case Node::Fake:
{
/*
if (!related)
child->location().warning(tr("Global variable, %1, %2").arg(child->name()).arg(message));
break;
- case Node::Target:
- break;
case Node::QmlProperty:
if (!related)
child->location().warning(tr("Global QML property, %1, %2").arg(child->name()).arg(message));
xmlWriter().writeStartElement("topicref");
xmlWriter().writeAttribute("navtitle",t->navtitle());
if (t->href().isEmpty()) {
- const FakeNode* fn = myTree->findFakeNodeByTitle(t->navtitle());
+ const FakeNode* fn = tree_->findFakeNodeByTitle(t->navtitle());
if (fn)
xmlWriter().writeAttribute("href",fileName(fn));
}
virtual void initializeGenerator(const Config& config);
virtual void terminateGenerator();
virtual QString format();
- virtual void generateTree(const Tree *tree);
- virtual void generateDisambiguationPages();
+ virtual void generateTree(Tree *tree);
+ void generateCollisionPages();
void generateManifestFiles();
QString protectEnc(const QString &string);
virtual int generateAtom(const Atom *atom,
const Node *relative,
CodeMarker *marker);
- virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
- virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
+ virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
+ virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker);
virtual QString fileExtension(const Node *node) const;
virtual QString refForNode(const Node *node);
virtual QString linkForNode(const Node *node, const Node *relative);
const Node *relative,
CodeMarker *marker,
bool summary);
- void generateDetailedQmlMember(const Node *node,
+ void generateDetailedQmlMember(Node *node,
const InnerNode *relative,
CodeMarker *marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
- void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
+ void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker);
+ void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker);
void generateSection(const NodeList& nl,
const Node *relative,
const Node *relative,
CodeMarker *marker,
const Node** node);
- QString getDisambiguationLink(const Atom* atom, CodeMarker* marker);
virtual void generateIndex(const QString &fileBase,
const QString &url,
const QString &title);
QString manifestDir;
QStringList stylesheets;
QStringList customHeadElements;
- const Tree *myTree;
bool obsoleteLinks;
QMap<QString, NodeMap > moduleClassMap;
QMap<QString, NodeMap > moduleNamespaceMap;
return "property";
case Variable:
return "variable";
- case Target:
- return "target";
case QmlProperty:
return "QML property";
case QmlSignal:
If it is a child of a QML class node, return a pointer to
the QML class node. Otherwise, return 0;
*/
-const QmlClassNode* Node::qmlClassNode() const
+QmlClassNode* Node::qmlClassNode()
{
if (isQmlNode()) {
- const Node* n = this;
+ Node* n = this;
while (n && n->subType() != Node::QmlClass)
n = n->parent();
if (n && n->subType() == Node::QmlClass)
- return static_cast<const QmlClassNode*>(n);
+ return static_cast<QmlClassNode*>(n);
}
return 0;
}
class node is a component. It will be non-null if
the QML class node is a QML element.
*/
-const ClassNode* Node::declarativeCppNode() const
+ClassNode* Node::declarativeCppNode()
{
- const QmlClassNode* qcn = qmlClassNode();
+ QmlClassNode* qcn = qmlClassNode();
if (qcn)
return qcn->classNode();
return 0;
}
/*!
+ Returns true if the node's status is Internal, or if its
+ parent is a class with internal status.
+ */
+bool Node::isInternal() const
+{
+ if (status() == Internal)
+ return true;
+ if (parent() && parent()->status() == Internal)
+ return true;
+ if (relates() && relates()->status() == Internal)
+ return true;
+ return false;
+}
+
+/*!
\class InnerNode
*/
sure to also look in the children of its property
group nodes. Return the matching node or 0.
*/
-Node *InnerNode::findNode(const QString& name)
+Node *InnerNode::findChildNodeByName(const QString& name)
{
Node *node = childMap.value(name);
if (node && node->subType() != QmlPropertyGroup)
for (int i=0; i<children.size(); ++i) {
Node* n = children.at(i);
if (n->subType() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(n)->findNode(name);
+ node = static_cast<InnerNode*>(n)->findChildNodeByName(name);
if (node)
return node;
}
for (int i=0; i<children.size(); ++i) {
node = children.at(i);
if (node->subType() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findNode(name);
+ node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node) {
n.append(node);
return;
if (node->subType() != QmlPropertyGroup)
n.append(node);
else {
- node = static_cast<InnerNode*>(node)->findNode(name);
+ node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node)
n.append(node);
}
/*!
Find the node in this node's children that has the given \a name. If
this node is a QML class node, be sure to also look in the children
- of its property group nodes. Return the matching node or 0.
+ of its property group nodes. Return the matching node or 0. This is
+ not a recearsive search.
If \a qml is true, only match a node for which node->isQmlNode()
returns true. If \a qml is false, only match a node for which
node->isQmlNode() returns false.
*/
-Node* InnerNode::findNode(const QString& name, bool qml)
+Node* InnerNode::findChildNodeByName(const QString& name, bool qml)
{
QList<Node*> nodes = childMap.values(name);
if (!nodes.isEmpty()) {
for (int i=0; i<children.size(); ++i) {
Node* node = children.at(i);
if (node->subType() == QmlPropertyGroup) {
- node = static_cast<InnerNode*>(node)->findNode(name);
+ node = static_cast<InnerNode*>(node)->findChildNodeByName(name);
if (node)
return node;
}
}
/*!
- Same as the other findNode(), but if the node with the
- specified \a name is not of the specified \a type, return
- 0.
+ This function is like findChildNodeByName(), but if a node
+ with the specified \a name is found but it is not of the
+ specified \a type, 0 is returned.
+
+ This function is not recursive and therefore can't handle
+ collisions. If it finds a collision node named \a name, it
+ will return that node. But it might not find the collision
+ node because it looks up \a name in the child map, not the
+ list.
*/
-Node *InnerNode::findNode(const QString& name, Type type)
+Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type)
{
- if (type == Function) {
+ if (type == Function)
return primaryFunctionMap.value(name);
- }
else {
Node *node = childMap.value(name);
- if (node && node->type() == type) {
+ if (node && node->type() == type)
return node;
- }
- else {
- return 0;
- }
}
+ return 0;
}
/*!
- Find the function node in this node for the function named \a name.
+ Find a function node that is a child of this nose, such
+ that the function node has the specified \a name.
*/
FunctionNode *InnerNode::findFunctionNode(const QString& name)
{
}
/*!
- Find the function node in this node that has the same name as \a clone.
+ Find the function node that is a child of this node, such
+ that the function has the same name and signature as the
+ \a clone node.
*/
FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone)
{
- QMap<QString, Node *>::ConstIterator c =
- primaryFunctionMap.find(clone->name());
+ QMap<QString,Node*>::ConstIterator c = primaryFunctionMap.find(clone->name());
if (c != primaryFunctionMap.end()) {
if (isSameSignature(clone, (FunctionNode *) *c)) {
return (FunctionNode *) *c;
/*!
*/
-const Node *InnerNode::findNode(const QString& name) const
+const Node *InnerNode::findChildNodeByName(const QString& name) const
{
InnerNode *that = (InnerNode *) this;
- return that->findNode(name);
+ return that->findChildNodeByName(name);
}
/*!
returns true. If \a qml is false, only match a node for which
node->isQmlNode() returns false.
*/
-const Node* InnerNode::findNode(const QString& name, bool qml) const
+const Node* InnerNode::findChildNodeByName(const QString& name, bool qml) const
{
InnerNode*that = (InnerNode*) this;
- return that->findNode(name, qml);
+ return that->findChildNodeByName(name, qml);
}
/*!
+ Searches this node's children for a child named \a name
+ with the specified node \a type.
*/
-const Node *InnerNode::findNode(const QString& name, Type type) const
+const Node* InnerNode::findChildNodeByNameAndType(const QString& name, Type type) const
{
InnerNode *that = (InnerNode *) this;
- return that->findNode(name, type);
+ return that->findChildNodeByNameAndType(name, type);
}
/*!
- Find the function node in this node that has the given \a name.
+ Find a function node that is a child of this nose, such
+ that the function node has the specified \a name. This
+ function calls the non-const version of itself.
*/
const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
{
}
/*!
- Find the function node in this node that has the same name as \a clone.
+ Find the function node that is a child of this node, such
+ that the function has the same name and signature as the
+ \a clone node. This function calls the non-const version.
*/
const FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const
{
\class LeafNode
*/
-/*!
+/*! \fn bool LeafNode::isInnerNode() const
Returns false because this is a LeafNode.
*/
-bool LeafNode::isInnerNode() const
-{
- return false;
-}
/*!
Constructs a leaf node named \a name of the specified
Search the child list to find the property node with the
specified \a name.
*/
-const PropertyNode *ClassNode::findPropertyNode(const QString &name) const
+PropertyNode* ClassNode::findPropertyNode(const QString& name)
{
- const Node *n = findNode(name, Node::Property);
+ Node* n = findChildNodeByNameAndType(name, Node::Property);
if (n)
- return static_cast<const PropertyNode*>(n);
+ return static_cast<PropertyNode*>(n);
- const PropertyNode *pn = 0;
+ PropertyNode* pn = 0;
const QList<RelatedClass> &bases = baseClasses();
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- const ClassNode *cn = bases[i].node;
+ ClassNode* cn = bases[i].node;
pn = cn->findPropertyNode(name);
if (pn)
break;
const QList<RelatedClass>& ignoredBases = ignoredBaseClasses();
if (!ignoredBases.isEmpty()) {
for (int i = 0; i < ignoredBases.size(); ++i) {
- const ClassNode *cn = ignoredBases[i].node;
+ ClassNode* cn = ignoredBases[i].node;
pn = cn->findPropertyNode(name);
if (pn)
break;
finds one, it returns the pointer to that QML element. If
it doesn't find one, it returns null.
*/
-const QmlClassNode* ClassNode::findQmlBaseNode() const
+QmlClassNode* ClassNode::findQmlBaseNode()
{
- const QmlClassNode* result = 0;
+ QmlClassNode* result = 0;
const QList<RelatedClass>& bases = baseClasses();
if (!bases.isEmpty()) {
for (int i = 0; i < bases.size(); ++i) {
- const ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node;
if (cn && cn->qmlElement()) {
return cn->qmlElement();
}
}
for (int i = 0; i < bases.size(); ++i) {
- const ClassNode* cn = bases[i].node;
+ ClassNode* cn = bases[i].node;
if (cn) {
result = cn->findQmlBaseNode();
if (result != 0) {
else
return title();
}
- else if ((nodeSubtype_ == HeaderFile) || (nodeSubtype_ == Collision)) {
+ else if (nodeSubtype_ == HeaderFile) {
if (title().isEmpty())
return name();
else
return name() + " - " + title();
}
+ else if (nodeSubtype_ == Collision) {
+ return title();
+ }
else {
return title();
}
}
/*!
- Returns true if the node's status is Internal, or if its
- parent is a class with internal status.
- */
-bool FunctionNode::isInternal() const
-{
- if (status() == Internal)
- return true;
- if (parent() && parent()->status() == Internal)
- return true;
- if (relates() && relates()->status() == Internal)
- return true;
- return false;
-}
-
-/*!
Print some debugging stuff.
*/
void FunctionNode::debug() const
}
}
-/*!
- \class TargetNode
- */
-
-/*!
- */
-TargetNode::TargetNode(InnerNode *parent, const QString& name)
- : LeafNode(Target, parent, name)
-{
-}
-
-/*!
- Returns false because this is a TargetNode.
- */
-bool TargetNode::isInnerNode() const
-{
- return false;
-}
-
bool QmlClassNode::qmlOnly = false;
QMultiMap<QString,Node*> QmlClassNode::inheritedBy;
QMap<QString, QmlClassNode*> QmlClassNode::moduleMap;
*/
QmlClassNode::QmlClassNode(InnerNode *parent,
const QString& name,
- const ClassNode* cn)
+ ClassNode* cn)
: FakeNode(parent, name, QmlClass, Node::ApiPage),
abstract(false),
cnode_(cn),
to output the line in the documentation that specifies the
QML element that a QML element inherits.
*/
-void QmlClassNode::resolveInheritance(const Tree* tree)
+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("::");
- const Node* n = tree->findNode(strList,Node::Fake);
- if (n && (n->subType() == Node::QmlClass || n->subType() == Node::Collision)) {
- base_ = static_cast<const FakeNode*>(n);
+ Node* n = tree->findQmlClassNode(strList);
+ if (n) {
+ base_ = static_cast<FakeNode*>(n);
if (base_ && base_->subType() == Node::QmlClass) {
return;
}
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<const FakeNode*>(children.at(j));
+ base_ = static_cast<FakeNode*>(children.at(j));
return;
}
}
QString qmid = qmlModuleIdentifier();
for (int k=0; k<children.size(); ++k) {
if (qmid == children.at(k)->qmlModuleIdentifier()) {
- base_ = static_cast<const QmlClassNode*>(children.at(k));
+ base_ = static_cast<QmlClassNode*>(children.at(k));
return;
}
}
return;
}
if (cnode_) {
- const QmlClassNode* qcn = cnode_->findQmlBaseNode();
+ QmlClassNode* qcn = cnode_->findQmlBaseNode();
if (qcn != 0)
base_ = qcn;
}
doesn't work for qmlproperty bool PropertyChanges::explicit,
because the tokenizer gets confused on "explicit".
*/
-bool QmlPropertyNode::isWritable(const Tree* tree) const
+bool QmlPropertyNode::isWritable(Tree* tree)
{
if (wri != Trool_Default)
return fromTrool(wri, false);
- const PropertyNode *pn = correspondingProperty(tree);
+ PropertyNode* pn = correspondingProperty(tree);
if (pn)
return pn->isWritable();
else {
}
}
-const PropertyNode *QmlPropertyNode::correspondingProperty(const Tree *tree) const
+PropertyNode* QmlPropertyNode::correspondingProperty(Tree *tree)
{
- const PropertyNode *pn;
+ PropertyNode* pn;
Node* n = parent();
while (n && n->subType() != Node::QmlClass)
n = n->parent();
if (n) {
- const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
- const ClassNode* cn = qcn->classNode();
+ QmlClassNode* qcn = static_cast<QmlClassNode*>(n);
+ ClassNode* cn = qcn->classNode();
if (cn) {
QStringList dotSplit = name().split(QChar('.'));
pn = cn->findPropertyNode(dotSplit[0]);
// the property group, <group>.<property>.
QStringList path(extractClassName(pn->qualifiedDataType()));
- const Node* nn = tree->findNode(path,Class);
+ Node* nn = tree->findClassNode(path);
if (nn) {
- const ClassNode* cn = static_cast<const ClassNode*>(nn);
- const PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
+ ClassNode* cn = static_cast<ClassNode*>(nn);
+ PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
if (pn2)
return pn2; // Return the property for the QML property.
else
NameCollisionNode::NameCollisionNode(InnerNode* child)
: FakeNode(child->parent(), child->name(), Collision, Node::NoPageType)
{
- setTitle("Name Collisions For: " + child->name());
+ setTitle("Name Collision: " + child->name());
addCollision(child);
current = 0;
}
Find any of this collision node's children that has type \a t
and subtype \a st and return a pointer to it.
*/
-const InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st) const
+InnerNode* NameCollisionNode::findAny(Node::Type t, Node::SubType st)
{
if (current) {
if (current->type() == t && current->subType() == st)
NodeList::ConstIterator i = cn.begin();
while (i != cn.end()) {
if ((*i)->type() == t && (*i)->subType() == st)
- return static_cast<const InnerNode*>(*i);
+ return static_cast<InnerNode*>(*i);
++i;
}
return 0;
case Node::Variable:
str = "var-" + name();
break;
- case Node::Target:
- str = name();
- break;
default:
qDebug() << "ERROR: A case was not handled in Node::idForNode():"
<< "type():" << type() << "subType():" << subType();
Function,
Property,
Variable,
- Target,
QmlProperty,
QmlSignal,
QmlSignalHandler,
virtual void setOutputFileName(const QString& ) { }
virtual bool isInnerNode() const = 0;
+ virtual bool isLeaf() const { return false; }
virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; }
virtual bool isQmlNode() const { return false; }
- virtual bool isInternal() 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 void setAbstract(bool ) { }
virtual QString title() const { return QString(); }
+ bool isInternal() const;
bool isIndexNode() const { return indexNodeFlag_; }
Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; }
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;
virtual QString qmlModuleVersion() const { return qmlModuleVersion_; }
virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersion_; }
virtual void setQmlModuleName(const QString& );
- virtual const ClassNode* classNode() const { return 0; }
+ virtual ClassNode* classNode() { return 0; }
virtual void clearCurrentChild() { }
virtual const ImportList* importList() const { return 0; }
virtual void setImportList(const ImportList& ) { }
virtual const Node* applyModuleIdentifier(const Node* ) const { return 0; }
- const QmlClassNode* qmlClassNode() const;
- const ClassNode* declarativeCppNode() const;
+ QmlClassNode* qmlClassNode();
+ ClassNode* declarativeCppNode();
const QString& outputSubdirectory() const { return outSubDir_; }
QString fullDocumentName() const;
static QString cleanId(QString str);
public:
virtual ~InnerNode();
- Node* findNode(const QString& name);
- Node* findNode(const QString& name, bool qml);
- Node* findNode(const QString& name, Type type);
+ Node* findChildNodeByName(const QString& name);
+ Node* findChildNodeByName(const QString& name, bool qml);
+ Node* findChildNodeByNameAndType(const QString& name, Type type);
void findNodes(const QString& name, QList<Node*>& n);
FunctionNode* findFunctionNode(const QString& name);
FunctionNode* findFunctionNode(const FunctionNode* clone);
void removeFromRelated();
virtual bool isInnerNode() const { return true; }
- const Node* findNode(const QString& name) const;
- const Node* findNode(const QString& name, bool qml) const;
- const Node* findNode(const QString& name, Type type) const;
+ virtual bool isLeaf() const { return false; }
+ const Node* findChildNodeByName(const QString& name) const;
+ const Node* findChildNodeByName(const QString& name, bool qml) const;
+ const Node* findChildNodeByNameAndType(const QString& name, Type type) const;
const FunctionNode* findFunctionNode(const QString& name) const;
const FunctionNode* findFunctionNode(const FunctionNode* clone) const;
const EnumNode* findEnumNodeForValue(const QString &enumValue) const;
LeafNode();
virtual ~LeafNode() { }
- virtual bool isInnerNode() const;
+ virtual bool isInnerNode() const { return false; }
+ virtual bool isLeaf() const { return true; }
protected:
LeafNode(Type type, InnerNode* parent, const QString& name);
QString serviceName() const { return sname; }
void setServiceName(const QString& value) { sname = value; }
- const QmlClassNode* qmlElement() const { return qmlelement; }
+ QmlClassNode* qmlElement() { return qmlelement; }
void setQmlElement(QmlClassNode* qcn) { qmlelement = qcn; }
virtual bool isAbstract() const { return abstract; }
virtual void setAbstract(bool b) { abstract = b; }
- const PropertyNode* findPropertyNode(const QString& name) const;
- const QmlClassNode* findQmlBaseNode() const;
+ PropertyNode* findPropertyNode(const QString& name);
+ QmlClassNode* findQmlBaseNode();
private:
QList<RelatedClass> bases;
void setTitle(const QString &title) { title_ = title; }
void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
- void addGroupMember(Node* node) { nodeList.append(node); }
- void addQmlModuleMember(Node* node) { nodeList.append(node); }
+ 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;
const NodeList& qmlModuleMembers() const { return nodeList; }
virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { }
+ virtual bool isQmlPropertyGroup() const { return (nodeSubtype_ == QmlPropertyGroup); }
protected:
SubType nodeSubtype_;
virtual void setCurrentChild(InnerNode* child) { current = child; }
virtual void clearCurrentChild() { current = 0; }
virtual bool isQmlNode() const;
+ virtual bool isCollisionNode() const { return true; }
virtual const Node* applyModuleIdentifier(const Node* origin) const;
- const InnerNode* findAny(Node::Type t, Node::SubType st) const;
+ InnerNode* findAny(Node::Type t, Node::SubType st);
void addCollision(InnerNode* child);
const QMap<QString,QString>& linkTargets() const { return targets; }
void addLinkTarget(const QString& t, const QString& v) { targets.insert(t,v); }
public:
QmlClassNode(InnerNode* parent,
const QString& name,
- const ClassNode* cn);
+ ClassNode* cn);
virtual ~QmlClassNode();
virtual bool isQmlNode() const { return true; }
virtual bool isQtQuickNode() const { return (qmlModuleName() == QLatin1String("QtQuick")); }
- virtual const ClassNode* classNode() const { return cnode_; }
+ virtual ClassNode* classNode() { return cnode_; }
virtual QString fileBase() const;
virtual void setCurrentChild();
virtual void clearCurrentChild();
virtual bool isAbstract() const { return abstract; }
virtual void setAbstract(bool b) { abstract = b; }
const FakeNode* qmlBase() const { return base_; }
- void resolveInheritance(const Tree* tree);
+ void resolveInheritance(Tree* tree);
static void addInheritedBy(const QString& base, Node* sub);
static void subclasses(const QString& base, NodeList& subs);
static void terminate();
private:
bool abstract;
- const ClassNode* cnode_;
- const FakeNode* base_;
+ ClassNode* cnode_;
+ FakeNode* base_;
ImportList importList_;
};
bool isDefault() const { return isdefault_; }
bool isStored() const { return fromTrool(sto,true); }
bool isDesignable() const { return fromTrool(des,false); }
- bool isWritable(const Tree* tree) const;
+ bool isWritable(Tree* tree);
bool isAttached() const { return attached_; }
bool isReadOnly() const { return (readOnly_ > 0); }
virtual bool isQmlNode() const { return true; }
virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); }
virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); }
- const PropertyNode *correspondingProperty(const Tree *tree) const;
+ PropertyNode* correspondingProperty(Tree* tree);
const QString& element() const { return static_cast<QmlPropGroupNode*>(parent())->element(); }
void appendQmlPropNode(QmlPropertyNode* p) { qmlPropNodes_.append(p); }
QString signature(bool values = false) const;
const QString& element() const { return parent()->name(); }
bool isAttached() const { return attached_; }
- virtual bool isInternal() const;
virtual bool isQmlNode() const {
return ((type() == QmlSignal) ||
(type() == QmlMethod) ||
// nothing.
}
-class TargetNode : public LeafNode
-{
-public:
- TargetNode(InnerNode* parent, const QString& name);
- virtual ~TargetNode() { }
-
- virtual bool isInnerNode() const;
-};
-
class DitaMapNode : public FakeNode
{
public:
delete priv;
}
-/*!
- This function simply calls the const version of itself and
- returns the result.
- */
-Node* Tree::findNode(const QStringList& path, Node* relative, int findFlags, const Node* self)
-{
- return const_cast<Node*>(const_cast<const Tree*>(this)->findNode(path,
- relative,
- findFlags,
- self));
-}
-
+// 1 calls 2
/*!
Searches the tree for a node that matches the \a path. The
search begins at \a start but can move up the parent chain
return n;
}
+// 2 is private; it is only called by 1.
/*!
- This code in this function was extracted from the other
- version of findNode() that has the same signature without
- the last bool parameter \a qml. This function is called
- only by that other findNode(). It can be called a second
- time if the first call returns null. If \a qml is false,
- the search will only match a node that is not a QML node.
- If \a qml is true, the search will only match a node that
- is a QML node.
- */
+ This overload function was extracted from the one above that has the
+ same signature without the last bool parameter, \a qml. This version
+ is called only by that other one. It is therefore private. It can
+ be called a second time by that other version, if the first call
+ returns null. If \a qml is false, the search will only match a node
+ that is not a QML node. If \a qml is true, the search will only
+ match a node that is a QML node.
+*/
const Node* Tree::findNode(const QStringList& path,
const Node* start,
int findFlags,
if (node == 0 || !node->isInnerNode())
break;
- const Node* next = static_cast<const InnerNode*>(node)->findNode(path.at(i), qml);
+ const Node* next = static_cast<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
if (!next && !qml && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
foreach (const Node* baseClass, baseClasses) {
- next = static_cast<const InnerNode*>(baseClass)->findNode(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
- next = static_cast<const InnerNode*>(baseClass)
- ->findEnumNodeForValue(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findEnumNodeForValue(path.at(i));
if (next)
break;
}
}
/*!
- Find the node with the specified \a path name of the
- specified \a type.
- */
-Node* Tree::findNode(const QStringList& path,
- Node::Type type,
- Node* relative,
- int findFlags)
-{
- return const_cast<Node*>(const_cast<const Tree*>(this)->findNode(path,
- type,
- relative,
- findFlags));
-}
-
-/*!
- This function just calls the const version of itself and returns
- a pointer to the QML class node, or null.
- */
-QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& element)
-{
- return const_cast<QmlClassNode*>(const_cast<const Tree*>(this)->findQmlClassNode(module, element));
-}
-
-/*!
- Find the node with the specified \a path name of the
- specified \a type.
- */
-const Node* Tree::findNode(const QStringList& path,
- Node::Type type,
- const Node* relative,
- int findFlags) const
-{
- const Node* node = findNode(path, relative, findFlags);
- if (node != 0 && node->type() == type)
- return node;
- return 0;
-}
-
-/*!
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 FakeNode that has
child is a QML class. If the collision node does not have a child
that is a QML class node, return 0.
*/
-const QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name) const
+QmlClassNode* Tree::findQmlClassNode(const QString& module, const QString& name)
{
if (module.isEmpty()) {
- const Node* n = findNode(QStringList(name), Node::Fake);
+ Node* n = findQmlClassNode(QStringList(name));
if (n) {
if (n->subType() == Node::QmlClass)
- return static_cast<const QmlClassNode*>(n);
+ return static_cast<QmlClassNode*>(n);
else if (n->subType() == Node::Collision) {
- const NameCollisionNode* ncn;
- ncn = static_cast<const NameCollisionNode*>(n);
- return static_cast<const QmlClassNode*>(ncn->findAny(Node::Fake,Node::QmlClass));
+ NameCollisionNode* ncn;
+ ncn = static_cast<NameCollisionNode*>(n);
+ return static_cast<QmlClassNode*>(ncn->findAny(Node::Fake,Node::QmlClass));
}
}
return 0;
if (i == path.size() - 1)
next = ((InnerNode*) node)->findFunctionNode(path.at(i));
else
- next = ((InnerNode*) node)->findNode(path.at(i));
+ next = ((InnerNode*) node)->findChildNodeByName(path.at(i));
- if (!next && node->type() == Node::Class &&
- (findFlags & SearchBaseClasses)) {
+ if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
NodeList baseClasses = allBaseClasses(static_cast<const ClassNode*>(node));
foreach (const Node* baseClass, baseClasses) {
if (i == path.size() - 1)
next = static_cast<const InnerNode*>(baseClass)->findFunctionNode(path.at(i));
else
- next = static_cast<const InnerNode*>(baseClass)->findNode(path.at(i));
+ next = static_cast<const InnerNode*>(baseClass)->findChildNodeByName(path.at(i));
if (next)
break;
return ((InnerNode*)parent)->findFunctionNode(clone);
}
}
+//findNode(parameter.leftType().split("::"), 0, SearchBaseClasses|NonFunction);
static const int NumSuffixes = 3;
static const char* const suffixes[NumSuffixes] = { "", "s", "es" };
QList<InheritanceBound> bounds = priv->unresolvedInheritanceMap[classe];
QList<InheritanceBound>::ConstIterator b = bounds.begin();
while (b != bounds.end()) {
- ClassNode* baseClass = (ClassNode*)findNode((*b).basePath,
- Node::Class);
- if (!baseClass && (*b).parent) {
- baseClass = (ClassNode*)findNode((*b).basePath,
- Node::Class,
- (*b).parent);
+ Node* n = findClassNode((*b).basePath);
+ if (!n && (*b).parent) {
+ n = findClassNode((*b).basePath, (*b).parent);
}
- if (baseClass) {
- classe->addBaseClass((*b).access,
- baseClass,
- (*b).dataTypeWithTemplateArgs);
+ if (n) {
+ classe->addBaseClass((*b).access, static_cast<ClassNode*>(n), (*b).dataTypeWithTemplateArgs);
}
++b;
}
if (i.value()->access() == Node::Private)
continue;
- FakeNode* fake =
- static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake));
- if (fake && fake->subType() == Node::Group) {
- fake->addGroupMember(i.value());
- }
+ Node* n = findGroupNode(QStringList(i.key()));
+ if (n)
+ n->addGroupMember(i.value());
}
}
{
NodeMultiMap::const_iterator i;
for (i = priv->qmlModuleMap.constBegin(); i != priv->qmlModuleMap.constEnd(); ++i) {
- FakeNode* fake =
- static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake));
- if (fake && fake->subType() == Node::QmlModule) {
- fake->addQmlModuleMember(i.value());
- }
+ Node* n = findQmlModuleNode(QStringList(i.key()));
+ if (n)
+ n->addQmlModuleMember(i.value());
}
}
/*!
*/
-void Tree::fixPropertyUsingBaseClasses(ClassNode* classe,
- PropertyNode* property)
+void Tree::fixPropertyUsingBaseClasses(ClassNode* classe, PropertyNode* property)
{
QList<RelatedClass>::const_iterator r = classe->baseClasses().begin();
while (r != classe->baseClasses().end()) {
- PropertyNode* baseProperty =
- static_cast<PropertyNode*>(r->node->findNode(property->name(),
- Node::Property));
- if (baseProperty) {
+ Node* n = r->node->findChildNodeByNameAndType(property->name(), Node::Property);
+ if (n) {
+ PropertyNode* baseProperty = static_cast<PropertyNode*>(n);
fixPropertyUsingBaseClasses(r->node, baseProperty);
property->setOverriddenFrom(baseProperty);
}
foreach (pair, priv->basesList) {
foreach (const QString& base, pair.second.split(QLatin1Char(','))) {
- Node* baseClass = root()->findNode(base, Node::Class);
- if (baseClass) {
- pair.first->addBaseClass(Node::Public,
- static_cast<ClassNode*>(baseClass));
+ Node* n = root()->findChildNodeByNameAndType(base, Node::Class);
+ if (n) {
+ pair.first->addBaseClass(Node::Public, static_cast<ClassNode*>(n));
}
}
}
QPair<FunctionNode*,QString> relatedPair;
foreach (relatedPair, priv->relatedList) {
- Node* classNode = root()->findNode(relatedPair.second, Node::Class);
- if (classNode)
- relatedPair.first->setRelates(static_cast<ClassNode*>(classNode));
+ Node* n = root()->findChildNodeByNameAndType(relatedPair.second, Node::Class);
+ if (n)
+ relatedPair.first->setRelates(static_cast<ClassNode*>(n));
}
}
false.
*/
bool Tree::generateIndexSection(QXmlStreamWriter& writer,
- const Node* node,
- bool generateInternalNodes) const
+ Node* node,
+ bool generateInternalNodes)
{
if (!node->url().isEmpty())
return false;
case Node::Variable:
nodeName = "variable";
break;
- case Node::Target:
- nodeName = "target";
- break;
case Node::QmlProperty:
nodeName = "qmlproperty";
break;
case Node::QmlProperty:
{
- const QmlPropertyNode* qpn = static_cast<const QmlPropertyNode*>(node);
+ 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");
foreach (const Parameter& parameter, functionNode->parameters()) {
QString leftType = parameter.leftType();
- const Node* leftNode =
- const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
- Node::Typedef, 0, SearchBaseClasses|NonFunction);
- if (!leftNode) {
- leftNode = const_cast<Tree*>(this)->findNode(
- parameter.leftType().split("::"), Node::Typedef,
+ const Node* leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
+ 0, SearchBaseClasses|NonFunction);
+ if (!leftNode || leftNode->type() != Node::Typedef) {
+ leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
node->parent(), SearchBaseClasses|NonFunction);
}
- if (leftNode) {
+ if (leftNode && leftNode->type() == Node::Typedef) {
if (leftNode->type() == Node::Typedef) {
const TypedefNode* typedefNode =
static_cast<const TypedefNode*>(leftNode);
if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" +
- typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
+ leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() + QLatin1Char('>');
}
}
else
they will be omitted.
*/
void Tree::generateIndexSections(QXmlStreamWriter& writer,
- const Node* node,
- bool generateInternalNodes) const
+ Node* node,
+ bool generateInternalNodes)
{
if (generateIndexSection(writer, node, generateInternalNodes)) {
NodeList cnodes = inner->childNodes();
qSort(cnodes.begin(), cnodes.end(), compareNodes);
- foreach (const Node* child, cnodes) {
+ foreach (Node* child, cnodes) {
/*
Don't generate anything for a QML property group node.
It is just a place holder for a collection of QML property
*/
if (child->subType() == Node::QmlPropertyGroup) {
const InnerNode* pgn = static_cast<const InnerNode*>(child);
- foreach (const Node* c, pgn->childNodes()) {
+ foreach (Node* c, pgn->childNodes()) {
generateIndexSections(writer, c, generateInternalNodes);
}
}
void Tree::generateIndex(const QString& fileName,
const QString& url,
const QString& title,
- bool generateInternalNodes) const
+ bool generateInternalNodes)
{
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text))
specified, returning true if an element was written; otherwise returns
false.
*/
-void Tree::generateTagFileCompounds(QXmlStreamWriter& writer,
- const InnerNode* inner) const
+void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, const InnerNode* inner)
{
foreach (const Node* node, inner->childNodes()) {
case Node::Property:
case Node::Function:
case Node::Variable:
- case Node::Target:
default:
continue;
}
/*!
*/
-void Tree::generateTagFileMembers(QXmlStreamWriter& writer,
- const InnerNode* inner) const
+void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inner)
{
foreach (const Node* node, inner->childNodes()) {
nodeName = "class";
break;
case Node::Variable:
- case Node::Target:
default:
continue;
}
foreach (const Parameter& parameter, functionNode->parameters()) {
QString leftType = parameter.leftType();
const Node* leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
- Node::Typedef, 0, SearchBaseClasses|NonFunction);
- if (!leftNode) {
- leftNode = const_cast<Tree*>(this)->findNode(
- parameter.leftType().split("::"), Node::Typedef,
- node->parent(), SearchBaseClasses|NonFunction);
+ 0, SearchBaseClasses|NonFunction);
+ if (!leftNode || leftNode->type() != Node::Typedef) {
+ leftNode = const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
+ node->parent(), SearchBaseClasses|NonFunction);
}
- if (leftNode) {
+ if (leftNode && leftNode->type() == Node::Typedef) {
const TypedefNode* typedefNode = static_cast<const TypedefNode*>(leftNode);
if (typedefNode->associatedEnum()) {
- leftType = "QFlags<" +
- typedefNode->associatedEnum()->fullDocumentName() +
- QLatin1Char('>');
+ leftType = "QFlags<" + typedefNode->associatedEnum()->fullDocumentName() + QLatin1Char('>');
}
}
signatureList.append(leftType + QLatin1Char(' ') + parameter.name());
break;
case Node::Variable:
- case Node::Target:
default:
break;
}
}
/*!
+ Writes a tag file named \a fileName.
*/
-void Tree::generateTagFile(const QString& fileName) const
+void Tree::generateTagFile(const QString& fileName)
{
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text))
fakeNode->setDoc(doc);
}
+/*!
+ Find the node with the specified \a path name that is of
+ the specified \a type and \a subtype. Begin the search at
+ the \a start node. If the \a start node is 0, begin the
+ search at the tree root. \a subtype is not used unless
+ \a type is \c{Fake}.
+ */
+Node* Tree::findNodeByNameAndType(const QStringList& path,
+ Node::Type type,
+ Node::SubType subtype,
+ Node* start,
+ bool acceptCollision)
+{
+ if (!start)
+ start = const_cast<NamespaceNode*>(root());
+ Node* result = findNodeRecursive(path, 0, start, type, subtype, acceptCollision);
+ return result;
+}
+
+#if 0
+ if (result)
+ qDebug() << "FOUND:" << path << Node::nodeTypeString(type)
+ << Node::nodeSubtypeString(subtype);
+ else
+ qDebug() << "NOT FOUND:" << path << Node::nodeTypeString(type)
+ << Node::nodeSubtypeString(subtype);
+#endif
+
+/*!
+ Recursive search for a node identified by \a path. Each
+ path element is a name. \a pathIndex specifies the index
+ of the name in \a path to try to match. \a start is the
+ node whose children shoulod be searched for one that has
+ that name. Each time a match is found, increment the
+ \a pathIndex and call this function recursively.
+
+ If the end of the path is reached (i.e. if a matching
+ node is found for each name in the \a path), the \a type
+ must match the type of the last matching node, and if the
+ type is \e{Fake}, the \a subtype must match as well.
+
+ If the algorithm is successful, the pointer to the final
+ node is returned. Otherwise 0 is returned.
+ */
+Node* Tree::findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ Node::Type type,
+ Node::SubType subtype,
+ bool acceptCollision)
+{
+ if (!start || path.isEmpty())
+ return 0; // no place to start, or nothing to search for.
+ if (start->isLeaf()) {
+ if (pathIndex >= path.size())
+ return start; // found a match.
+ return 0; // premature leaf
+ }
+ if (pathIndex >= path.size())
+ return 0; // end of search path.
+
+ InnerNode* current = static_cast<InnerNode*>(start);
+ const NodeList& children = current->childNodes();
+ const QString& name = path.at(pathIndex);
+ for (int i=0; i<children.size(); ++i) {
+ Node* n = children.at(i);
+ if (!n)
+ continue;
+ if (n->isQmlPropertyGroup()) {
+ if (type == Node::QmlProperty) {
+ n = findNodeRecursive(path, pathIndex, n, type, subtype);
+ if (n)
+ return n;
+ }
+ }
+ else if (n->name() == name) {
+ if (pathIndex+1 >= path.size()) {
+ if (n->type() == type) {
+ if (type == Node::Fake) {
+ if (n->subType() == subtype)
+ return n;
+ else if (n->subType() == Node::Collision && acceptCollision)
+ return n;
+ else if (subtype == Node::NoSubType)
+ return n; // don't care what subtype is.
+ return 0;
+ }
+ else
+ return n;
+ }
+ else if (n->isCollisionNode()) {
+ if (acceptCollision)
+ return n;
+ return n = findNodeRecursive(path, pathIndex, n, type, subtype);
+ if (n)
+ return n;
+ }
+ else
+ return 0;
+ }
+ else { // Not at the end of the path.
+ n = findNodeRecursive(path, pathIndex+1, n, type, subtype);
+ if (n)
+ return n;
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ Find the Enum 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 an Enum type node named \a path is
+ acceptible. If one is not found, 0 is returned.
+ */
+EnumNode* Tree::findEnumNode(const QStringList& path, Node* start)
+{
+ return static_cast<EnumNode*>(findNodeRecursive(path, 0, start, Node::Enum, Node::NoSubType));
+}
+
+/*!
+ Find the C++ 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 C++ class node named \a path is
+ acceptible. If one is not found, 0 is returned.
+ */
+ClassNode* Tree::findClassNode(const QStringList& path, Node* start)
+{
+ return static_cast<ClassNode*>(findNodeRecursive(path, 0, start, Node::Class, Node::NoSubType));
+}
+
+/*!
+ 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.
+ */
+QmlClassNode* Tree::findQmlClassNode(const QStringList& path, Node* start)
+{
+ /*
+ 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 yes, that reference identifies a
+ QML class node.
+ */
+ if (path.size() >= 2) {
+ QmlClassNode* qcn = QmlClassNode::moduleMap.value(path[0]+ "::" +path[1]);
+ if (qcn)
+ return qcn;
+ }
+
+ return static_cast<QmlClassNode*>(findNodeRecursive(path, 0, start, Node::Fake, 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)
+{
+ return static_cast<NamespaceNode*>(findNodeRecursive(path, 0, start, Node::Namespace, Node::NoSubType));
+}
+
+/*!
+ Find the Group 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 Group node named \a path is
+ acceptible. If one is not found, 0 is returned.
+ */
+FakeNode* Tree::findGroupNode(const QStringList& path, Node* start)
+{
+ return static_cast<FakeNode*>(findNodeRecursive(path, 0, start, Node::Fake, Node::Group));
+}
+
+/*!
+ Find the Qml module 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 module node named \a path is
+ acceptible. If one is not found, 0 is returned.
+ */
+FakeNode* Tree::findQmlModuleNode(const QStringList& path, Node* start)
+{
+ return static_cast<FakeNode*>(findNodeRecursive(path, 0, start, Node::Fake, Node::QmlModule));
+}
+
QT_END_NAMESPACE
+
+#if 0
+const Node* Tree::findNodeXXX(const QStringList& path, bool qml) const
+{
+ const Node* current = root();
+ do {
+ const Node* node = current;
+ int i;
+ int start_idx = 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 yes, that reference identifies a
+ QML class node.
+ */
+ if (qml && path.size() >= 2) {
+ QmlClassNode* qcn = QmlClassNode::moduleMap.value(path[0]+ "::" +path[1]);
+ if (qcn) {
+ node = qcn;
+ if (path.size() == 2)
+ return node;
+ start_idx = 2;
+ }
+ }
+
+ for (i = start_idx; i < path.size(); ++i) {
+ if (node == 0 || !node->isInnerNode())
+ break;
+
+ const Node* next = static_cast<const InnerNode*>(node)->findChildNodeByName(path.at(i), qml);
+ node = next;
+ }
+ if (node && i == path.size()) {
+ if (node->subType() != Node::QmlPropertyGroup) {
+ if (node->subType() == Node::Collision) {
+ node = node->applyModuleIdentifier(start);
+ }
+ return node;
+ }
+ }
+ current = current->parent();
+ } while (current);
+
+ return 0;
+}
+#endif
Tree();
~Tree();
- Node* findNode(const QStringList &path,
- Node* relative=0,
- int findFlags=0,
- const Node* self=0);
- Node* findNode(const QStringList &path,
- Node::Type type,
- Node* relative = 0,
- int findFlags = 0);
+ 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);
+ FakeNode* findGroupNode(const QStringList& path, Node* start = 0);
+ FakeNode* findQmlModuleNode(const QStringList& path, Node* start = 0);
+
+ Node* findNodeByNameAndType(const QStringList& path,
+ Node::Type type,
+ Node::SubType subtype,
+ Node* start,
+ bool acceptCollision = false);
+
+ Node* findNodeRecursive(const QStringList& path,
+ int pathIndex,
+ Node* start,
+ Node::Type type,
+ Node::SubType subtype,
+ bool acceptCollision = false);
+
+ const Node* findNode(const QStringList &path,
+ const Node* relative = 0,
+ 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;
void fixInheritance(NamespaceNode *rootNode = 0);
void setVersion(const QString &version) { vers = version; }
NamespaceNode *root() { return &roo; }
-
QString version() const { return vers; }
- const Node* findNode(const QStringList &path,
- const Node* relative = 0,
- int findFlags = 0,
- const Node* self=0) const;
- const Node* findNode(const QStringList &path,
- Node::Type type, const
- Node* relative = 0,
- int findFlags = 0) const;
- const QmlClassNode* findQmlClassNode(const QString& module, const QString& element) const;
+
const FunctionNode *findFunctionNode(const QStringList &path,
const Node *relative = 0,
int findFlags = 0) const;
Atom *findTarget(const QString &target, const Node *node) const;
const NamespaceNode *root() const { return &roo; }
void readIndexes(const QStringList &indexFiles);
- bool generateIndexSection(QXmlStreamWriter &writer, const Node *node,
- bool generateInternalNodes = false) const;
- void generateIndexSections(QXmlStreamWriter &writer, const Node *node,
- bool generateInternalNodes = false) const;
+ bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
+ void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndex(const QString &fileName,
const QString &url,
const QString &title,
- bool generateInternalNodes = false) const;
+ bool generateInternalNodes = false);
void generateTagFileCompounds(QXmlStreamWriter &writer,
- const InnerNode *inner) const;
+ const InnerNode *inner);
void generateTagFileMembers(QXmlStreamWriter &writer,
- const InnerNode *inner) const;
- void generateTagFile(const QString &fileName) const;
+ const InnerNode *inner);
+ void generateTagFile(const QString &fileName);
void addExternalLink(const QString &url, const Node *relative);
QString fullDocumentLocation(const Node *node) const;
void resolveQmlInheritance();