summaryrefslogtreecommitdiffstats
path: root/src/qdoc/generator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qdoc/generator.cpp')
-rw-r--r--src/qdoc/generator.cpp196
1 files changed, 124 insertions, 72 deletions
diff --git a/src/qdoc/generator.cpp b/src/qdoc/generator.cpp
index 46d3ad453..bdeeec2be 100644
--- a/src/qdoc/generator.cpp
+++ b/src/qdoc/generator.cpp
@@ -75,11 +75,8 @@ QStringList Generator::styleFiles;
bool Generator::noLinkErrors_ = false;
bool Generator::autolinkErrors_ = false;
bool Generator::redirectDocumentationToDevNull_ = false;
-Generator::QDocPass Generator::qdocPass_ = Generator::Neither;
bool Generator::qdocSingleExec_ = false;
-bool Generator::qdocWriteQaPages_ = false;
bool Generator::useOutputSubdirs_ = true;
-bool Generator::useTimestamps_ = false;
QmlTypeNode *Generator::qmlTypeContext_ = nullptr;
static QRegExp tag("</?@[^>]*>");
@@ -393,9 +390,10 @@ QString Generator::fileBase(const Node *node) const
to the file name. The suffix, if one exists, is appended to the
module name.
*/
- if (!node->logicalModuleName().isEmpty()) {
+ if (!node->logicalModuleName().isEmpty()
+ && (!node->logicalModule()->isInternal() || showInternal_))
base.prepend(node->logicalModuleName() + outputSuffix(node) + QLatin1Char('-'));
- }
+
base.prepend(outputPrefix(node));
} else if (node->isProxyNode()) {
base = node->name();
@@ -761,55 +759,55 @@ const Atom *Generator::generateAtomList(const Atom *atom, const Node *relative,
*/
void Generator::generateBody(const Node *node, CodeMarker *marker)
{
+ const FunctionNode *fn = node->isFunction() ? static_cast<const FunctionNode *>(node) : nullptr;
if (!node->hasDoc() && !node->hasSharedDoc()) {
/*
Test for special function, like a destructor or copy constructor,
that has no documentation.
*/
- if (node->isFunction()) {
- const FunctionNode *func = static_cast<const FunctionNode *>(node);
- if (func->isDtor()) {
+ if (fn) {
+ if (fn->isDtor()) {
Text text;
text << "Destroys the instance of ";
- text << func->parent()->name() << ".";
- if (func->isVirtual())
+ text << fn->parent()->name() << ".";
+ if (fn->isVirtual())
text << " The destructor is virtual.";
out() << "<p>";
generateText(text, node, marker);
out() << "</p>";
- } else if (func->isCtor()) {
+ } else if (fn->isCtor()) {
Text text;
text << "Default constructs an instance of ";
- text << func->parent()->name() << ".";
+ text << fn->parent()->name() << ".";
out() << "<p>";
generateText(text, node, marker);
out() << "</p>";
- } else if (func->isCCtor()) {
+ } else if (fn->isCCtor()) {
Text text;
text << "Copy constructor.";
out() << "<p>";
generateText(text, node, marker);
out() << "</p>";
- } else if (func->isMCtor()) {
+ } else if (fn->isMCtor()) {
Text text;
text << "Move-copy constructor.";
out() << "<p>";
generateText(text, node, marker);
out() << "</p>";
- } else if (func->isCAssign()) {
+ } else if (fn->isCAssign()) {
Text text;
text << "Copy-assignment operator.";
out() << "<p>";
generateText(text, node, marker);
out() << "</p>";
- } else if (func->isMAssign()) {
+ } else if (fn->isMAssign()) {
Text text;
text << "Move-assignment operator.";
out() << "<p>";
generateText(text, node, marker);
out() << "</p>";
} else if (!node->isWrapper() && !node->isMarkedReimp()) {
- if (!func->isIgnored()) // undocumented functions added by Q_OBJECT
+ if (!fn->isIgnored()) // undocumented functions added by Q_OBJECT
node->location().warning(
tr("No documentation for '%1'").arg(node->plainSignature()));
}
@@ -820,8 +818,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
tr("No documentation for '%1'").arg(node->plainSignature()));
}
} else if (!node->isSharingComment()) {
- if (node->isFunction()) {
- const FunctionNode *fn = static_cast<const FunctionNode *>(node);
+ if (fn) {
if (!fn->overridesThis().isEmpty())
generateReimplementsClause(fn, marker);
}
@@ -831,6 +828,18 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
return;
}
+ if (fn) {
+ if (fn->isQmlSignal())
+ generateAddendum(node, QmlSignalHandler, marker);
+ if (fn->isPrivateSignal())
+ generateAddendum(node, PrivateSignal, marker);
+ if (fn->isInvokable())
+ generateAddendum(node, Invokable, marker);
+ if (fn->hasAssociatedProperties())
+ generateAddendum(node, AssociatedProperties, marker);
+ }
+
+ // Generate warnings
if (node->isEnumType()) {
const EnumNode *enume = static_cast<const EnumNode *>(node);
@@ -862,8 +871,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
}
}
- } else if (node->isFunction()) {
- const FunctionNode *fn = static_cast<const FunctionNode *>(node);
+ } else if (fn) {
const QSet<QString> declaredNames = fn->parameters().getNames();
const QSet<QString> documentedNames = fn->doc().parameterNames();
if (declaredNames != documentedNames) {
@@ -920,7 +928,7 @@ void Generator::generateRequiredLinks(const Node *node, CodeMarker *marker)
return;
const ExampleNode *en = static_cast<const ExampleNode *>(node);
- QString exampleUrl = config()->getString(CONFIG_URL + Config::dot + CONFIG_EXAMPLES);
+ QString exampleUrl = Config::instance().getString(CONFIG_URL + Config::dot + CONFIG_EXAMPLES);
if (exampleUrl.isEmpty()) {
if (!en->noAutoList()) {
@@ -962,7 +970,7 @@ void Generator::generateLinkToExample(const ExampleNode *en, CodeMarker *marker,
// Construct a path to the example; <install path>/<example name>
QString pathRoot = en->doc().metaTagMap().value(QLatin1String("installpath"));
if (pathRoot.isEmpty())
- pathRoot = config()->getString(CONFIG_EXAMPLESINSTALLPATH);
+ pathRoot = Config::instance().getString(CONFIG_EXAMPLESINSTALLPATH);
QStringList path = QStringList() << pathRoot << en->name();
path.removeAll({});
@@ -1261,8 +1269,12 @@ void Generator::generateReimplementsClause(const FunctionNode *fn, CodeMarker *m
appendFullName(text, overrides->parent(), fullName, overrides);
text << "." << Atom::ParaRight;
generateText(text, fn, marker);
- return;
+ } else {
+ fn->doc().location().warning(
+ tr("Illegal \\reimp; no documented virtual function for %1")
+ .arg(overrides->plainSignature()));
}
+ return;
}
const PropertyNode *sameName = cn->findOverriddenProperty(fn);
if (sameName && sameName->hasDoc()) {
@@ -1272,10 +1284,6 @@ void Generator::generateReimplementsClause(const FunctionNode *fn, CodeMarker *m
appendFullName(text, sameName->parent(), fullName, sameName);
text << "." << Atom::ParaRight;
generateText(text, fn, marker);
- } else {
- fn->doc().location().warning(
- tr("Illegal \\reimp; no documented virtual function for %1")
- .arg(fn->plainSignature()));
}
}
}
@@ -1346,33 +1354,76 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
}
/*!
- Generates a bold line that explains that this is a private signal,
- only made public to let users pass it to connect().
- */
-void Generator::generatePrivateSignalNote(const Node *node, CodeMarker *marker)
+ Generates an addendum note of type \a type for \a node, using \a marker
+ as the code marker.
+*/
+void Generator::generateAddendum(const Node *node, Addendum type, CodeMarker *marker)
{
+ Q_ASSERT(node && !node->name().isEmpty());
Text text;
text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
- << "Note: " << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
- << "This is a private signal. It can be used in signal connections but cannot be emitted "
- "by the user."
- << Atom::ParaRight;
- generateText(text, node, marker);
-}
+ << "Note: " << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD);
+
+ switch (type) {
+ case Invokable:
+ text << "This function can be invoked via the meta-object system and from QML. See "
+ << Atom(Atom::Link, "Q_INVOKABLE")
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << "Q_INVOKABLE"
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << ".";
+ break;
+ case PrivateSignal:
+ text << "This is a private signal. It can be used in signal connections "
+ "but cannot be emitted by the user.";
+ break;
+ case QmlSignalHandler:
+ {
+ QString handler(node->name());
+ handler[0] = handler[0].toTitleCase();
+ handler.prepend(QLatin1String("on"));
+ text << "The corresponding handler is "
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_TELETYPE) << handler
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_TELETYPE) << ".";
+ break;
+ }
+ case AssociatedProperties:
+ {
+ if (!node->isFunction())
+ return;
+ const FunctionNode *fn = static_cast<const FunctionNode *>(node);
+ NodeList nodes = fn->associatedProperties();
+ if (nodes.isEmpty())
+ return;
+ std::sort(nodes.begin(), nodes.end(), Node::nodeNameLessThan);
+ for (const auto *n : qAsConst(nodes)) {
+ QString msg;
+ const PropertyNode *pn = static_cast<const PropertyNode *>(n);
+ switch (pn->role(fn)) {
+ case PropertyNode::Getter:
+ msg = QStringLiteral("Getter function");
+ break;
+ case PropertyNode::Setter:
+ msg = QStringLiteral("Setter function");
+ break;
+ case PropertyNode::Resetter:
+ msg = QStringLiteral("Resetter function");
+ break;
+ case PropertyNode::Notifier:
+ msg = QStringLiteral("Notifier signal");
+ break;
+ default:
+ continue;
+ }
+ text << msg << " for property " << Atom(Atom::Link, pn->name())
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << pn->name()
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << ". ";
+ }
+ break;
+ }
+ default:
+ return;
+ }
-/*!
- Generates a bold line that says:
- "This function can be invoked via the meta-object system and from QML. See Q_INVOKABLE."
- */
-void Generator::generateInvokableNote(const Node *node, CodeMarker *marker)
-{
- Text text;
- text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
- << "Note: " << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
- << "This function can be invoked via the meta-object system and from QML. See "
- << Atom(Atom::Link, "Q_INVOKABLE") << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << "Q_INVOKABLE" << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << "."
- << Atom::ParaRight;
+ text << Atom::ParaRight;
generateText(text, node, marker);
}
@@ -1562,11 +1613,7 @@ QString Generator::getOverloadedSignalCode(const Node *node)
}
/*!
- If the node is an overloaded signal, and a node with an example on how to connect to it
-
- Someone didn't finish writing this comment, and I don't know what this
- function is supposed to do, so I have not tried to complete the comment
- yet.
+ If the node is an overloaded signal, add a node with an example on how to connect to it
*/
void Generator::generateOverloadedSignal(const Node *node, CodeMarker *marker)
{
@@ -1690,8 +1737,9 @@ QString Generator::indent(int level, const QString &markedCode)
return t;
}
-void Generator::initialize(const Config &config)
+void Generator::initialize()
{
+ Config &config = Config::instance();
outputFormats = config.getOutputFormats();
redirectDocumentationToDevNull_ = config.getBool(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL);
@@ -1711,7 +1759,7 @@ void Generator::initialize(const Config &config)
for (auto &g : generators) {
if (outputFormats.contains(g->format())) {
currentGenerator_ = g;
- g->initializeGenerator(config);
+ g->initializeGenerator();
}
}
@@ -1770,9 +1818,9 @@ void Generator::initialize(const Config &config)
Creates template-specific subdirs (e.g. /styles and /scripts for HTML)
and copies the files to them.
*/
-void Generator::copyTemplateFiles(const Config &config, const QString &configVar,
- const QString &subDir)
+void Generator::copyTemplateFiles(const QString &configVar, const QString &subDir)
{
+ Config &config = Config::instance();
QStringList files = config.getCanonicalPathList(configVar, true);
if (!files.isEmpty()) {
QDir dirInfo;
@@ -1790,12 +1838,13 @@ void Generator::copyTemplateFiles(const Config &config, const QString &configVar
}
/*!
- Reads format-specific variables from \a config, sets output
+ Reads format-specific variables from config, sets output
(sub)directories, creates them on the filesystem and copies the
template-specific files.
*/
-void Generator::initializeFormat(const Config &config)
+void Generator::initializeFormat()
{
+ Config &config = Config::instance();
outFileNames_.clear();
useOutputSubdirs_ = true;
if (config.getBool(format() + Config::dot + "nosubdirs"))
@@ -1814,7 +1863,7 @@ void Generator::initializeFormat(const Config &config)
QDir dirInfo;
if (dirInfo.exists(outDir_)) {
- if (!generating() && Generator::useOutputSubdirs()) {
+ if (!config.generating() && Generator::useOutputSubdirs()) {
if (!Config::removeDirContents(outDir_))
config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_));
}
@@ -1823,16 +1872,16 @@ void Generator::initializeFormat(const Config &config)
}
// Output directory exists, which is enough for prepare phase.
- if (preparing())
+ if (config.preparing())
return;
if (!dirInfo.exists(outDir_ + "/images") && !dirInfo.mkdir(outDir_ + "/images"))
config.lastLocation().fatal(
tr("Cannot create images directory '%1'").arg(outDir_ + "/images"));
- copyTemplateFiles(config, format() + Config::dot + CONFIG_STYLESHEETS, "style");
- copyTemplateFiles(config, format() + Config::dot + CONFIG_SCRIPTS, "scripts");
- copyTemplateFiles(config, format() + Config::dot + CONFIG_EXTRAIMAGES, "images");
+ copyTemplateFiles(format() + Config::dot + CONFIG_STYLESHEETS, "style");
+ copyTemplateFiles(format() + Config::dot + CONFIG_SCRIPTS, "scripts");
+ copyTemplateFiles(format() + Config::dot + CONFIG_EXTRAIMAGES, "images");
// Use a format-specific .quotinginformation if defined, otherwise a global value
if (config.subVars(format()).contains(CONFIG_QUOTINGINFORMATION))
@@ -1856,11 +1905,10 @@ void Generator::augmentImageDirs(QSet<QString> &moreImageDirs)
/*!
Sets the generator's pointer to the Config instance.
*/
-void Generator::initializeGenerator(const Config &config)
+void Generator::initializeGenerator()
{
- config_ = &config;
- showInternal_ = config.getBool(CONFIG_SHOWINTERNAL);
- singleExec_ = config.getBool(CONFIG_SINGLEEXEC);
+ showInternal_ = Config::instance().getBool(CONFIG_SHOWINTERNAL);
+ singleExec_ = Config::instance().getBool(CONFIG_SINGLEEXEC);
}
bool Generator::matchAhead(const Atom *atom, Atom::AtomType expectedAtomType)
@@ -2138,8 +2186,8 @@ QString Generator::typeString(const Node *node)
case Node::Union:
return "union";
case Node::QmlType:
- return "type";
case Node::QmlBasicType:
+ case Node::JsBasicType:
return "type";
case Node::Page:
return "documentation";
@@ -2171,6 +2219,10 @@ QString Generator::typeString(const Node *node)
case Node::JsModule:
case Node::QmlModule:
return "module";
+ case Node::SharedComment: {
+ const auto &collective = static_cast<const SharedCommentNode *>(node)->collective();
+ return collective.first()->nodeTypeString();
+ }
default:
return "documentation";
}