aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/qtdocparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/ApiExtractor/qtdocparser.cpp')
-rw-r--r--sources/shiboken6/ApiExtractor/qtdocparser.cpp197
1 files changed, 135 insertions, 62 deletions
diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.cpp b/sources/shiboken6/ApiExtractor/qtdocparser.cpp
index b20a53632..5bd99bbd8 100644
--- a/sources/shiboken6/ApiExtractor/qtdocparser.cpp
+++ b/sources/shiboken6/ApiExtractor/qtdocparser.cpp
@@ -3,10 +3,11 @@
#include "qtdocparser.h"
#include "classdocumentation.h"
+#include "abstractmetaargument.h"
#include "abstractmetaenum.h"
-#include "abstractmetafield.h"
#include "abstractmetafunction.h"
#include "abstractmetalang.h"
+#include "abstractmetatype.h"
#include "documentation.h"
#include "modifications.h"
#include "messages.h"
@@ -14,6 +15,8 @@
#include "reporthandler.h"
#include "flagstypeentry.h"
#include "complextypeentry.h"
+#include "functiontypeentry.h"
+#include "enumtypeentry.h"
#include "qtcompat.h"
@@ -25,8 +28,9 @@ using namespace Qt::StringLiterals;
enum { debugFunctionSearch = 0 };
-static inline QString briefStartElement() { return QStringLiteral("<brief>"); }
-static inline QString briefEndElement() { return QStringLiteral("</brief>"); }
+constexpr auto briefStartElement = "<brief>"_L1;
+constexpr auto briefEndElement = "</brief>"_L1;
+constexpr auto webxmlSuffix = ".webxml"_L1;
Documentation QtDocParser::retrieveModuleDocumentation()
{
@@ -56,7 +60,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str,
case AbstractMetaType::FlagsPattern: {
// Modify qualified name "QFlags<Qt::AlignmentFlag>" with name "Alignment"
// to "Qt::Alignment" as seen by qdoc.
- const auto *flagsEntry = static_cast<const FlagsTypeEntry *>(metaType.typeEntry());
+ const auto flagsEntry = std::static_pointer_cast<const FlagsTypeEntry>(metaType.typeEntry());
QString name = flagsEntry->qualifiedCppName();
if (name.endsWith(u'>') && name.startsWith(u"QFlags<")) {
const int lastColon = name.lastIndexOf(u':');
@@ -73,7 +77,7 @@ static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str,
case AbstractMetaType::ContainerPattern: { // QVector<int>
str << metaType.typeEntry()->qualifiedCppName() << '<';
const auto instantiations = metaType.instantiations();
- for (int i = 0, size = instantiations.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = instantiations.size(); i < size; ++i) {
if (i)
str << ", ";
const auto &instantiation = instantiations.at(i);
@@ -99,51 +103,34 @@ static QString formatFunctionArgTypeQuery(const AbstractMetaType &metaType)
return result;
}
-QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
- const ClassDocumentation &classDocumentation,
- const AbstractMetaClass* metaClass,
- const AbstractMetaFunctionCPtr &func,
- const DocModificationList &signedModifs,
- QString *errorMessage)
+QString QtDocParser::functionDocumentation(const QString &sourceFileName,
+ const ClassDocumentation &classDocumentation,
+ const AbstractMetaClassCPtr &metaClass,
+ const AbstractMetaFunctionCPtr &func,
+ QString *errorMessage)
{
errorMessage->clear();
- DocModificationList funcModifs;
- for (const DocModification &funcModif : signedModifs) {
- if (funcModif.signature() == func->minimalSignature())
- funcModifs.append(funcModif);
- }
-
const QString docString =
queryFunctionDocumentation(sourceFileName, classDocumentation, metaClass,
func, errorMessage);
+ const auto funcModifs = DocParser::getXpathDocModifications(func, metaClass);
return docString.isEmpty() || funcModifs.isEmpty()
? docString : applyDocModifications(funcModifs, docString);
}
QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
const ClassDocumentation &classDocumentation,
- const AbstractMetaClass* metaClass,
+ const AbstractMetaClassCPtr &metaClass,
const AbstractMetaFunctionCPtr &func,
QString *errorMessage)
{
- // Properties
- if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) {
- const QPropertySpec &prop = metaClass->propertySpecs().at(func->propertySpecIndex());
- const auto index = classDocumentation.indexOfProperty(prop.name());
- if (index == -1) {
- *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data());
- return {};
- }
- return classDocumentation.properties.at(index).description;
- }
-
// Search candidates by name and const-ness
FunctionDocumentationList candidates =
classDocumentation.findFunctionCandidates(func->name(), func->isConstant());
if (candidates.isEmpty()) {
- *errorMessage = msgCannotFindDocumentation(sourceFileName, func.data())
+ *errorMessage = msgCannotFindDocumentation(sourceFileName, func.get())
+ u" (no matches)"_s;
return {};
}
@@ -188,13 +175,13 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
candidates.erase(pend, candidates.end());
if (candidates.size() == 1) {
const auto &match = candidates.constFirst();
- QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.data())
+ QTextStream(errorMessage) << msgFallbackForDocumentation(sourceFileName, func.get())
<< "\n Falling back to \"" << match.signature
<< "\" obtained by matching the argument count only.";
return candidates.constFirst().description;
}
- QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.data())
+ QTextStream(errorMessage) << msgCannotFindDocumentation(sourceFileName, func.get())
<< " (" << candidates.size() << " candidates matching the argument count)";
return {};
}
@@ -203,29 +190,100 @@ QString QtDocParser::queryFunctionDocumentation(const QString &sourceFileName,
// from the source.
static QString extractBrief(QString *value)
{
- const auto briefStart = value->indexOf(briefStartElement());
+ const auto briefStart = value->indexOf(briefStartElement);
if (briefStart < 0)
return {};
- const auto briefEnd = value->indexOf(briefEndElement(),
- briefStart + briefStartElement().size());
+ const auto briefEnd = value->indexOf(briefEndElement,
+ briefStart + briefStartElement.size());
if (briefEnd < briefStart)
return {};
- const auto briefLength = briefEnd + briefEndElement().size() - briefStart;
+ const auto briefLength = briefEnd + briefEndElement.size() - briefStart;
QString briefValue = value->mid(briefStart, briefLength);
- briefValue.insert(briefValue.size() - briefEndElement().size(),
+ briefValue.insert(briefValue.size() - briefEndElement.size(),
u"<rst> More_...</rst>"_s);
value->remove(briefStart, briefLength);
return briefValue;
}
-void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
+// Find the webxml file for global functions/enums
+// by the doc-file typesystem attribute or via include file.
+static QString findGlobalWebXmLFile(const QString &documentationDataDirectory,
+ const QString &docFile,
+ const Include &include)
+{
+ QString result;
+ if (!docFile.isEmpty()) {
+ result = documentationDataDirectory + u'/' + docFile;
+ if (!result.endsWith(webxmlSuffix))
+ result += webxmlSuffix;
+ return QFileInfo::exists(result) ? result : QString{};
+ }
+ if (include.name().isEmpty())
+ return {};
+ // qdoc "\headerfile <QtLogging>" directive produces "qtlogging.webxml"
+ result = documentationDataDirectory + u'/' +
+ QFileInfo(include.name()).baseName() + webxmlSuffix;
+ if (QFileInfo::exists(result))
+ return result;
+ // qdoc "\headerfile <qdrawutil.h>" produces "qdrawutil-h.webxml"
+ result.insert(result.size() - webxmlSuffix.size(), "-h"_L1);
+ return QFileInfo::exists(result) ? result : QString{};
+}
+
+void QtDocParser::fillGlobalFunctionDocumentation(const AbstractMetaFunctionPtr &f)
+{
+ auto te = f->typeEntry();
+ if (te == nullptr)
+ return;
+
+ const QString sourceFileName =
+ findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include());
+ if (sourceFileName.isEmpty())
+ return;
+
+ QString errorMessage;
+ auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage);
+ if (!classDocumentationO.has_value()) {
+ qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ return;
+ }
+ const QString detailed =
+ functionDocumentation(sourceFileName, classDocumentationO.value(),
+ {}, f, &errorMessage);
+ if (!errorMessage.isEmpty())
+ qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ const Documentation documentation(detailed, {});
+ f->setDocumentation(documentation);
+}
+
+void QtDocParser::fillGlobalEnumDocumentation(AbstractMetaEnum &e)
+{
+ auto te = e.typeEntry();
+ const QString sourceFileName =
+ findGlobalWebXmLFile(documentationDataDirectory(), te->docFile(), te->include());
+ if (sourceFileName.isEmpty())
+ return;
+
+ QString errorMessage;
+ auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage);
+ if (!classDocumentationO.has_value()) {
+ qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ return;
+ }
+ if (!extractEnumDocumentation(classDocumentationO.value(), e)) {
+ qCWarning(lcShibokenDoc, "%s",
+ qPrintable(msgCannotFindDocumentation(sourceFileName, {}, e, {})));
+ }
+}
+
+void QtDocParser::fillDocumentation(const AbstractMetaClassPtr &metaClass)
{
if (!metaClass)
return;
- const AbstractMetaClass* context = metaClass->enclosingClass();
- while(context) {
- if (context->enclosingClass() == nullptr)
+ auto context = metaClass->enclosingClass();
+ while (context) {
+ if (!context->enclosingClass())
break;
context = context->enclosingClass();
}
@@ -234,9 +292,9 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
+ metaClass->qualifiedCppName().toLower();
sourceFileRoot.replace(u"::"_s, u"-"_s);
- QFileInfo sourceFile(sourceFileRoot + QStringLiteral(".webxml"));
+ QFileInfo sourceFile(sourceFileRoot + webxmlSuffix);
if (!sourceFile.exists())
- sourceFile.setFile(sourceFileRoot + QStringLiteral(".xml"));
+ sourceFile.setFile(sourceFileRoot + ".xml"_L1);
if (!sourceFile.exists()) {
qCWarning(lcShibokenDoc).noquote().nospace()
<< "Can't find qdoc file for class " << metaClass->name() << ", tried: "
@@ -247,22 +305,20 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
const QString sourceFileName = sourceFile.absoluteFilePath();
QString errorMessage;
- ClassDocumentation classDocumentation = parseWebXml(sourceFileName, &errorMessage);
- if (!classDocumentation) {
+ const auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage);
+ if (!classDocumentationO.has_value()) {
qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
return;
}
- DocModificationList signedModifs, classModifs;
- const DocModificationList &mods = metaClass->typeEntry()->docModifications();
- for (const DocModification &docModif : mods) {
- if (docModif.signature().isEmpty())
- classModifs.append(docModif);
- else
- signedModifs.append(docModif);
+ const auto &classDocumentation = classDocumentationO.value();
+ for (const auto &p : classDocumentation.properties) {
+ Documentation doc(p.description, p.brief);
+ metaClass->setPropertyDocumentation(p.name, doc);
}
- QString docString = applyDocModifications(mods, classDocumentation.description);
+ QString docString = applyDocModifications(DocParser::getXpathDocModifications(metaClass),
+ classDocumentation.description);
if (docString.isEmpty()) {
QString className = metaClass->name();
@@ -281,12 +337,12 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
const auto &funcs = DocParser::documentableFunctions(metaClass);
for (const auto &func : funcs) {
const QString detailed =
- queryFunctionDocumentation(sourceFileName, classDocumentation,
- metaClass, func, signedModifs, &errorMessage);
+ functionDocumentation(sourceFileName, classDocumentation,
+ metaClass, func, &errorMessage);
if (!errorMessage.isEmpty())
qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
const Documentation documentation(detailed, {});
- qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(documentation);
+ std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(documentation);
}
#if 0
// Fields
@@ -302,18 +358,35 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
#endif
// Enums
for (AbstractMetaEnum &meta_enum : metaClass->enums()) {
- Documentation enumDoc;
- const auto index = classDocumentation.indexOfEnum(meta_enum.name());
- if (index != -1) {
- enumDoc.setValue(classDocumentation.enums.at(index).description);
- meta_enum.setDocumentation(enumDoc);
- } else {
+ if (!extractEnumDocumentation(classDocumentation, meta_enum)) {
qCWarning(lcShibokenDoc, "%s",
qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, {})));
}
}
}
+bool QtDocParser::extractEnumDocumentation(const ClassDocumentation &classDocumentation,
+ AbstractMetaEnum &meta_enum)
+{
+ Documentation enumDoc;
+ const auto index = classDocumentation.indexOfEnum(meta_enum.name());
+ if (index == -1)
+ return false;
+ QString doc = classDocumentation.enums.at(index).description;
+ const auto firstPara = doc.indexOf(u"<para>");
+ if (firstPara != -1) {
+ const QString baseClass = QtDocParser::enumBaseClass(meta_enum);
+ if (baseClass != "Enum"_L1) {
+ const QString note = "(inherits <teletype>enum."_L1 + baseClass
+ + "</teletype>) "_L1;
+ doc.insert(firstPara + 6, note);
+ }
+ }
+ enumDoc.setValue(doc);
+ meta_enum.setDocumentation(enumDoc);
+ return true;
+}
+
static QString qmlReferenceLink(const QFileInfo &qmlModuleFi)
{
QString result;