aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-12-11 16:16:02 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-12-15 16:21:32 +0000
commit29287d7db849688231a0fc9cc49afce4088cf3e2 (patch)
treefd06c6934b93a07972bd11937a2403c98dbd981c /sources
parent4df45fc227fdf07c965f26af086aa99a098e46b3 (diff)
Shiboken6: Decouple QtXmlToSphinx from the doc generator
To enable testing, decouple QtXmlToSphinx from the doc generator by introducing a parameter struct QtXmlToSphinxParameters and an interface QtXmlToSphinxDocGeneratorInterface. Move the messages back into qtxmltosphinx.cpp and move the helper function convertToRst to the doc generator since it uses FileOut. Change-Id: I176888dcbd65003856ea8797a5629949598801d5 Reviewed-by: Christian Tismer <tismer@stackless.com> (cherry picked from commit cddc4e975398c7c285b0dfada8a57fe997f05833) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp30
-rw-r--r--sources/shiboken6/ApiExtractor/messages.h7
-rw-r--r--sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp132
-rw-r--r--sources/shiboken6/generator/qtdoc/qtdocgenerator.h30
-rw-r--r--sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp218
-rw-r--r--sources/shiboken6/generator/qtdoc/qtxmltosphinx.h22
-rw-r--r--sources/shiboken6/generator/qtdoc/qtxmltosphinxinterface.h60
7 files changed, 289 insertions, 210 deletions
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index 5bdd58ae2..664db57eb 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -792,33 +792,3 @@ QString msgRegisterMetaTypeUnqualifiedName(const AbstractMetaClass *c,
<< "). This is currently fixed by a hack(ct) and needs improvement!";
return result;
}
-
-// qtdocgenerator.cpp
-
-QString msgTagWarning(const QXmlStreamReader &reader, const QString &context,
- const QString &tag, const QString &message)
-{
- QString result;
- QTextStream str(&result);
- str << "While handling <";
- const auto currentTag = reader.name();
- if (currentTag.isEmpty())
- str << tag;
- else
- str << currentTag;
- str << "> in " << context << ", line "<< reader.lineNumber()
- << ": " << message;
- return result;
-}
-
-QString msgFallbackWarning(const QXmlStreamReader &reader, const QString &context,
- const QString &tag, const QString &location,
- const QString &identifier, const QString &fallback)
-{
- QString message = QLatin1String("Falling back to \"")
- + QDir::toNativeSeparators(fallback) + QLatin1String("\" for \"")
- + location + QLatin1Char('"');
- if (!identifier.isEmpty())
- message += QLatin1String(" [") + identifier + QLatin1Char(']');
- return msgTagWarning(reader, context, tag, message);
-}
diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h
index 21b16a264..e3a89319f 100644
--- a/sources/shiboken6/ApiExtractor/messages.h
+++ b/sources/shiboken6/ApiExtractor/messages.h
@@ -231,11 +231,4 @@ QString msgUnknownTypeInArgumentTypeReplacement(const QString &typeReplaced,
QString msgRegisterMetaTypeUnqualifiedName(const AbstractMetaClass *c,
const char *file, int line);
-QString msgTagWarning(const QXmlStreamReader &reader, const QString &context,
- const QString &tag, const QString &message);
-
-QString msgFallbackWarning(const QXmlStreamReader &reader, const QString &context,
- const QString &tag, const QString &location,
- const QString &identifier, const QString &fallback);
-
#endif // MESSAGES_H
diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
index 06fc7aa42..07ec29f03 100644
--- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
+++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp
@@ -40,6 +40,7 @@
#include <propertyspec.h>
#include <reporthandler.h>
#include <textstream.h>
+#include <typedatabase.h>
#include <typesystem.h>
#include <qtdocparser.h>
#include <doxygenparser.h>
@@ -150,6 +151,8 @@ static QString getFuncName(const AbstractMetaFunctionCPtr& cppFunc)
QtDocGenerator::QtDocGenerator()
{
+ m_parameters.snippetComparison =
+ ReportHandler::debugLevel() >= ReportHandler::FullDebug;
}
QtDocGenerator::~QtDocGenerator() = default;
@@ -186,7 +189,7 @@ void QtDocGenerator::writeFormattedText(TextStream &s, const Documentation &doc,
metaClassName = metaClass->fullName();
if (doc.format() == Documentation::Native) {
- QtXmlToSphinx x(this, doc.value(docType), metaClassName);
+ QtXmlToSphinx x(this, m_parameters, doc.value(docType), metaClassName);
s << x;
} else {
const QString &value = doc.value(docType);
@@ -905,7 +908,7 @@ void QtDocGenerator::writeModuleDocumentation()
if (moduleDoc.format() == Documentation::Native) {
QString context = it.key();
QtXmlToSphinx::stripPythonQualifiers(&context);
- QtXmlToSphinx x(this, moduleDoc.value(), context);
+ QtXmlToSphinx x(this, m_parameters, moduleDoc.value(), context);
s << x;
} else {
s << moduleDoc.value();
@@ -962,13 +965,13 @@ void QtDocGenerator::writeAdditionalDocumentation() const
}
} else {
// Normal file entry
- QFileInfo fi(m_docDataDir + QLatin1Char('/') + line);
+ QFileInfo fi(m_parameters.docDataDir + QLatin1Char('/') + line);
if (fi.isFile()) {
const QString rstFileName = fi.baseName() + rstSuffix;
const QString rstFile = targetDir + QLatin1Char('/') + rstFileName;
const QString context = targetDir.mid(targetDir.lastIndexOf(QLatin1Char('/')) + 1);
- if (QtXmlToSphinx::convertToRst(this, fi.absoluteFilePath(),
- rstFile, context, &errorMessage)) {
+ if (convertToRst(fi.absoluteFilePath(),
+ rstFile, context, &errorMessage)) {
++successCount;
qCDebug(lcShibokenDoc).nospace().noquote() << __FUNCTION__
<< " converted " << fi.fileName()
@@ -978,7 +981,7 @@ void QtDocGenerator::writeAdditionalDocumentation() const
}
} else {
qCWarning(lcShibokenDoc, "%s",
- qPrintable(msgNonExistentAdditionalDocFile(m_docDataDir, line)));
+ qPrintable(msgNonExistentAdditionalDocFile(m_parameters.docDataDir, line)));
}
++count;
}
@@ -997,20 +1000,23 @@ void QtDocGenerator::writeAdditionalDocumentation() const
bool QtDocGenerator::doSetup()
{
- if (m_codeSnippetDirs.isEmpty())
- m_codeSnippetDirs = m_libSourceDir.split(QLatin1Char(PATH_SEP));
+ if (m_parameters.codeSnippetDirs.isEmpty()) {
+ m_parameters.codeSnippetDirs =
+ m_parameters.libSourceDir.split(QLatin1Char(PATH_SEP));
+ }
if (m_docParser.isNull())
m_docParser.reset(new QtDocParser);
- if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) {
+ if (m_parameters.libSourceDir.isEmpty()
+ || m_parameters.docDataDir.isEmpty()) {
qCWarning(lcShibokenDoc) << "Documentation data dir and/or Qt source dir not informed, "
"documentation will not be extracted from Qt sources.";
return false;
}
- m_docParser->setDocumentationDataDirectory(m_docDataDir);
- m_docParser->setLibrarySourceDirectory(m_libSourceDir);
+ m_docParser->setDocumentationDataDirectory(m_parameters.docDataDir);
+ m_docParser->setLibrarySourceDirectory(m_parameters.libSourceDir);
return true;
}
@@ -1037,15 +1043,15 @@ Generator::OptionDescriptions QtDocGenerator::options() const
bool QtDocGenerator::handleOption(const QString &key, const QString &value)
{
if (key == QLatin1String("library-source-dir")) {
- m_libSourceDir = value;
+ m_parameters.libSourceDir = value;
return true;
}
if (key == QLatin1String("documentation-data-dir")) {
- m_docDataDir = value;
+ m_parameters.docDataDir = value;
return true;
}
if (key == QLatin1String("documentation-code-snippets-dir")) {
- m_codeSnippetDirs = value.split(QLatin1Char(PATH_SEP));
+ m_parameters.codeSnippetDirs = value.split(QLatin1Char(PATH_SEP));
return true;
}
if (key == QLatin1String("documentation-extra-sections-dir")) {
@@ -1064,3 +1070,101 @@ bool QtDocGenerator::handleOption(const QString &key, const QString &value)
}
return false;
}
+
+bool QtDocGenerator::convertToRst(const QString &sourceFileName,
+ const QString &targetFileName,
+ const QString &context,
+ QString *errorMessage) const
+{
+ QFile sourceFile(sourceFileName);
+ if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ if (errorMessage)
+ *errorMessage = msgCannotOpenForReading(sourceFile);
+ return false;
+ }
+ const QString doc = QString::fromUtf8(sourceFile.readAll());
+ sourceFile.close();
+
+ FileOut targetFile(targetFileName);
+ QtXmlToSphinx x(this, m_parameters, doc, context);
+ targetFile.stream << x;
+ return targetFile.done(errorMessage) != FileOut::Failure;
+}
+
+// QtXmlToSphinxDocGeneratorInterface
+QString QtDocGenerator::expandFunction(const QString &function) const
+{
+ const int firstDot = function.indexOf(QLatin1Char('.'));
+ const AbstractMetaClass *metaClass = nullptr;
+ if (firstDot != -1) {
+ const auto className = QStringView{function}.left(firstDot);
+ for (const AbstractMetaClass *cls : classes()) {
+ if (cls->name() == className) {
+ metaClass = cls;
+ break;
+ }
+ }
+ }
+
+ return metaClass
+ ? metaClass->typeEntry()->qualifiedTargetLangName()
+ + function.right(function.size() - firstDot)
+ : function;
+}
+
+QString QtDocGenerator::expandClass(const QString &context,
+ const QString &name) const
+{
+ if (auto typeEntry = TypeDatabase::instance()->findType(name))
+ return typeEntry->qualifiedTargetLangName();
+ // fall back to the old heuristic if the type wasn't found.
+ QString result = name;
+ const auto rawlinklist = QStringView{name}.split(QLatin1Char('.'));
+ QStringList splittedContext = context.split(QLatin1Char('.'));
+ if (rawlinklist.size() == 1 || rawlinklist.constFirst() == splittedContext.constLast()) {
+ splittedContext.removeLast();
+ result.prepend(QLatin1Char('~') + splittedContext.join(QLatin1Char('.'))
+ + QLatin1Char('.'));
+ }
+ return result;
+}
+
+QString QtDocGenerator::resolveContextForMethod(const QString &context,
+ const QString &methodName) const
+{
+ const auto currentClass = QStringView{context}.split(QLatin1Char('.')).constLast();
+
+ const AbstractMetaClass *metaClass = nullptr;
+ for (const AbstractMetaClass *cls : classes()) {
+ if (cls->name() == currentClass) {
+ metaClass = cls;
+ break;
+ }
+ }
+
+ if (metaClass) {
+ AbstractMetaFunctionCList funcList;
+ const auto &methods = metaClass->queryFunctionsByName(methodName);
+ for (const auto &func : methods) {
+ if (methodName == func->name())
+ funcList.append(func);
+ }
+
+ const AbstractMetaClass *implementingClass = nullptr;
+ for (const auto &func : qAsConst(funcList)) {
+ implementingClass = func->implementingClass();
+ if (implementingClass->name() == currentClass)
+ break;
+ }
+
+ if (implementingClass)
+ return implementingClass->typeEntry()->qualifiedTargetLangName();
+ }
+
+ return QLatin1Char('~') + context;
+}
+
+const QLoggingCategory &QtDocGenerator::loggingCategory() const
+{
+ return lcShibokenDoc();
+}
diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.h b/sources/shiboken6/generator/qtdoc/qtdocgenerator.h
index 673dc9104..218625cef 100644
--- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.h
+++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.h
@@ -36,25 +36,19 @@
#include "documentation.h"
#include "typesystem_enums.h"
#include "typesystem_typedefs.h"
+#include "qtxmltosphinxinterface.h"
class DocParser;
/**
* The DocGenerator generates documentation from library being binded.
*/
-class QtDocGenerator : public Generator
+class QtDocGenerator : public Generator, public QtXmlToSphinxDocGeneratorInterface
{
public:
QtDocGenerator();
~QtDocGenerator();
- QString libSourceDir() const
- {
- return m_libSourceDir;
- }
-
- QString docDataDir() const { return m_docDataDir; }
-
bool doSetup() override;
const char* name() const override
@@ -65,10 +59,13 @@ public:
OptionDescriptions options() const override;
bool handleOption(const QString &key, const QString &value) override;
- QStringList codeSnippetDirs() const
- {
- return m_codeSnippetDirs;
- }
+ // QtXmlToSphinxDocGeneratorInterface
+ QString expandFunction(const QString &function) const override;
+ QString expandClass(const QString &context,
+ const QString &name) const override;
+ QString resolveContextForMethod(const QString &context,
+ const QString &methodName) const override;
+ const QLoggingCategory &loggingCategory() const override;
protected:
bool shouldGenerate(const AbstractMetaClass *) const override;
@@ -108,13 +105,16 @@ private:
const AbstractMetaFunctionCPtr &func);
QString translateToPythonType(const AbstractMetaType &type, const AbstractMetaClass *cppClass) const;
- QString m_docDataDir;
- QString m_libSourceDir;
- QStringList m_codeSnippetDirs;
+ bool convertToRst(const QString &sourceFileName,
+ const QString &targetFileName,
+ const QString &context = QString(),
+ QString *errorMessage = nullptr) const;
+
QString m_extraSectionDir;
QStringList m_functionList;
QMap<QString, QStringList> m_packages;
QScopedPointer<DocParser> m_docParser;
+ QtXmlToSphinxParameters m_parameters;
QString m_additionalDocumentationList;
};
diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp
index 12d13f6b7..66c267852 100644
--- a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp
+++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp
@@ -27,19 +27,13 @@
****************************************************************************/
#include "qtxmltosphinx.h"
-#include "fileout.h"
-#include "messages.h"
+#include "qtxmltosphinxinterface.h"
#include "rstformat.h"
-#include "qtdocgenerator.h"
-#include <abstractmetafunction.h>
-#include <abstractmetalang.h>
-#include <reporthandler.h>
-#include <typedatabase.h>
-#include <typesystem.h>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
+#include <QtCore/QLoggingCategory>
#include <QtCore/QRegularExpression>
#include <QtCore/QXmlStreamReader>
@@ -47,6 +41,34 @@ static inline QString nameAttribute() { return QStringLiteral("name"); }
static inline QString titleAttribute() { return QStringLiteral("title"); }
static inline QString fullTitleAttribute() { return QStringLiteral("fulltitle"); }
+QString msgTagWarning(const QXmlStreamReader &reader, const QString &context,
+ const QString &tag, const QString &message)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "While handling <";
+ const auto currentTag = reader.name();
+ if (currentTag.isEmpty())
+ str << tag;
+ else
+ str << currentTag;
+ str << "> in " << context << ", line "<< reader.lineNumber()
+ << ": " << message;
+ return result;
+}
+
+QString msgFallbackWarning(const QXmlStreamReader &reader, const QString &context,
+ const QString &tag, const QString &location,
+ const QString &identifier, const QString &fallback)
+{
+ QString message = QLatin1String("Falling back to \"")
+ + QDir::toNativeSeparators(fallback) + QLatin1String("\" for \"")
+ + location + QLatin1Char('"');
+ if (!identifier.isEmpty())
+ message += QLatin1String(" [") + identifier + QLatin1Char(']');
+ return msgTagWarning(reader, context, tag, message);
+}
+
struct QtXmlToSphinx::LinkContext
{
enum Type
@@ -211,10 +233,12 @@ static const WebXmlTagHash &webXmlTagHash()
return result;
}
-QtXmlToSphinx::QtXmlToSphinx(const QtDocGenerator *generator,
+QtXmlToSphinx::QtXmlToSphinx(const QtXmlToSphinxDocGeneratorInterface *docGenerator,
+ const QtXmlToSphinxParameters &parameters,
const QString& doc, const QString& context)
: m_output(static_cast<QString *>(nullptr)),
- m_tableHasHeader(false), m_context(context), m_generator(generator),
+ m_tableHasHeader(false), m_context(context),
+ m_generator(docGenerator), m_parameters(parameters),
m_insideBold(false), m_insideItalic(false)
{
m_result = transform(doc);
@@ -362,6 +386,16 @@ void QtXmlToSphinx::callHandler(WebXmlTag t, QXmlStreamReader &r)
}
}
+void QtXmlToSphinx::formatCurrentTable()
+{
+ if (m_currentTable.isEmpty())
+ return;
+ m_currentTable.setHeaderEnabled(m_tableHasHeader);
+ m_currentTable.normalize();
+ m_output << ensureEndl;
+ m_currentTable.format(m_output);
+}
+
void QtXmlToSphinx::pushOutputBuffer()
{
auto *buffer = new QString();
@@ -379,60 +413,6 @@ QString QtXmlToSphinx::popOutputBuffer()
return strcpy;
}
-QString QtXmlToSphinx::expandFunction(const QString& function) const
-{
- const int firstDot = function.indexOf(QLatin1Char('.'));
- const AbstractMetaClass *metaClass = nullptr;
- if (firstDot != -1) {
- const auto className = QStringView{function}.left(firstDot);
- for (const AbstractMetaClass *cls : m_generator->classes()) {
- if (cls->name() == className) {
- metaClass = cls;
- break;
- }
- }
- }
-
- return metaClass
- ? metaClass->typeEntry()->qualifiedTargetLangName()
- + function.right(function.size() - firstDot)
- : function;
-}
-
-QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) const
-{
- const auto currentClass = QStringView{m_context}.split(QLatin1Char('.')).constLast();
-
- const AbstractMetaClass *metaClass = nullptr;
- for (const AbstractMetaClass *cls : m_generator->classes()) {
- if (cls->name() == currentClass) {
- metaClass = cls;
- break;
- }
- }
-
- if (metaClass) {
- AbstractMetaFunctionCList funcList;
- const auto &methods = metaClass->queryFunctionsByName(methodName);
- for (const auto &func : methods) {
- if (methodName == func->name())
- funcList.append(func);
- }
-
- const AbstractMetaClass *implementingClass = nullptr;
- for (const auto &func : qAsConst(funcList)) {
- implementingClass = func->implementingClass();
- if (implementingClass->name() == currentClass)
- break;
- }
-
- if (implementingClass)
- return implementingClass->typeEntry()->qualifiedTargetLangName();
- }
-
- return QLatin1Char('~') + m_context;
-}
-
QString QtXmlToSphinx::transform(const QString& doc)
{
Q_ASSERT(m_buffers.isEmpty());
@@ -452,7 +432,7 @@ QString QtXmlToSphinx::transform(const QString& doc)
<< reader.errorString() << " at " << reader.lineNumber()
<< ':' << reader.columnNumber() << '\n' << doc;
m_output << message;
- qCWarning(lcShibokenDoc).noquote().nospace() << message;
+ warn(message);
break;
}
@@ -513,7 +493,8 @@ QString QtXmlToSphinx::readFromLocations(const QStringList &locations, const QSt
<< locations.join(QLatin1String("\", \""));
return QString(); // null
}
- qCDebug(lcShibokenDoc).noquote().nospace() << "snippet file " << path
+ qCDebug(m_generator->loggingCategory()).noquote().nospace()
+ << "snippet file " << path
<< " [" << identifier << ']' << " resolved to " << resolvedPath;
return readFromLocation(resolvedPath, identifier, errorMessage);
}
@@ -708,11 +689,6 @@ void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader)
static inline QString fallbackPathAttribute() { return QStringLiteral("path"); }
-static inline bool snippetComparison()
-{
- return ReportHandler::debugLevel() >= ReportHandler::FullDebug;
-}
-
template <class Indent> // const char*/class Indentor
void formatSnippet(TextStream &str, Indent indent, const QString &snippet)
{
@@ -752,26 +728,26 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader)
QString identifier = reader.attributes().value(QLatin1String("identifier")).toString();
QString errorMessage;
const QString pythonCode =
- readFromLocations(m_generator->codeSnippetDirs(), location, identifier, &errorMessage);
+ readFromLocations(m_parameters.codeSnippetDirs, location, identifier, &errorMessage);
if (!errorMessage.isEmpty())
- qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage)));
+ warn(msgTagWarning(reader, m_context, m_lastTagName, errorMessage));
// Fall back to C++ snippet when "path" attribute is present.
// Also read fallback snippet when comparison is desired.
QString fallbackCode;
- if ((pythonCode.isEmpty() || snippetComparison())
+ if ((pythonCode.isEmpty() || m_parameters.snippetComparison)
&& reader.attributes().hasAttribute(fallbackPathAttribute())) {
const QString fallback = reader.attributes().value(fallbackPathAttribute()).toString();
if (QFileInfo::exists(fallback)) {
if (pythonCode.isEmpty())
- qCWarning(lcShibokenDoc, "%s", qPrintable(msgFallbackWarning(reader, m_context, m_lastTagName, location, identifier, fallback)));
+ warn(msgFallbackWarning(reader, m_context, m_lastTagName, location, identifier, fallback));
fallbackCode = readFromLocation(fallback, identifier, &errorMessage);
if (!errorMessage.isEmpty())
- qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage)));
+ warn(msgTagWarning(reader, m_context, m_lastTagName, errorMessage));
}
}
- if (!pythonCode.isEmpty() && !fallbackCode.isEmpty() && snippetComparison())
- qCDebug(lcShibokenDoc, "%s", qPrintable(msgSnippetComparison(location, identifier, pythonCode, fallbackCode)));
+ if (!pythonCode.isEmpty() && !fallbackCode.isEmpty() && m_parameters.snippetComparison)
+ debug(msgSnippetComparison(location, identifier, pythonCode, fallbackCode));
if (!consecutiveSnippet)
m_output << "::\n\n";
@@ -817,10 +793,7 @@ void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader)
m_tableHasHeader = false;
} else if (token == QXmlStreamReader::EndElement) {
// write the table on m_output
- m_currentTable.setHeaderEnabled(m_tableHasHeader);
- m_currentTable.normalize();
- m_output << ensureEndl;
- m_currentTable.format(m_output);
+ formatCurrentTable();
m_currentTable.clear();
}
}
@@ -914,10 +887,7 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader)
}
break;
case EnumeratedList:
- m_currentTable.setHeaderEnabled(m_tableHasHeader);
- m_currentTable.normalize();
- m_output << ensureEndl;
- m_currentTable.format(m_output);
+ formatCurrentTable();
break;
}
}
@@ -965,32 +935,23 @@ QtXmlToSphinx::LinkContext *QtXmlToSphinx::handleLinkStart(const QString &type,
result->type = LinkContext::Method;
const auto rawlinklist = QStringView{result->linkRef}.split(QLatin1Char('.'));
if (rawlinklist.size() == 1 || rawlinklist.constFirst() == m_context) {
- QString context = resolveContextForMethod(rawlinklist.constLast().toString());
+ const auto lastRawLink = rawlinklist.constLast().toString();
+ QString context = m_generator->resolveContextForMethod(m_context, lastRawLink);
if (!result->linkRef.startsWith(context))
result->linkRef.prepend(context + QLatin1Char('.'));
} else {
- result->linkRef = expandFunction(result->linkRef);
+ result->linkRef = m_generator->expandFunction(result->linkRef);
}
} else if (type == functionLinkType() && m_context.isEmpty()) {
result->type = LinkContext::Function;
} else if (type == classLinkType()) {
result->type = LinkContext::Class;
- if (const TypeEntry *type = TypeDatabase::instance()->findType(result->linkRef)) {
- result->linkRef = type->qualifiedTargetLangName();
- } else { // fall back to the old heuristic if the type wasn't found.
- const auto rawlinklist = QStringView{result->linkRef}.split(QLatin1Char('.'));
- QStringList splittedContext = m_context.split(QLatin1Char('.'));
- if (rawlinklist.size() == 1 || rawlinklist.constFirst() == splittedContext.constLast()) {
- splittedContext.removeLast();
- result->linkRef.prepend(QLatin1Char('~') + splittedContext.join(QLatin1Char('.'))
- + QLatin1Char('.'));
- }
- }
+ result->linkRef = m_generator->expandClass(m_context, result->linkRef);
} else if (type == QLatin1String("enum")) {
result->type = LinkContext::Attribute;
} else if (type == QLatin1String("page")) {
// Module, external web page or reference
- if (result->linkRef == m_generator->moduleName())
+ if (result->linkRef == m_parameters.moduleName)
result->type = LinkContext::Module;
else if (result->linkRef.startsWith(QLatin1String("http")))
result->type = LinkContext::External;
@@ -1049,7 +1010,7 @@ void QtXmlToSphinx::handleLinkEnd(LinkContext *linkContext)
// by qdoc to a matching subdirectory under the "rst/PySide6/<module>" directory
static bool copyImage(const QString &href, const QString &docDataDir,
const QString &context, const QString &outputDir,
- QString *errorMessage)
+ const QLoggingCategory &lc, QString *errorMessage)
{
const QChar slash = QLatin1Char('/');
const int lastSlash = href.lastIndexOf(slash);
@@ -1092,7 +1053,7 @@ static bool copyImage(const QString &href, const QString &docDataDir,
<< source.errorString();
return false;
}
- qCDebug(lcShibokenDoc()).noquote().nospace() << __FUNCTION__ << " href=\""
+ qCDebug(lc).noquote().nospace() << __FUNCTION__ << " href=\""
<< href << "\", context=\"" << context << "\", docDataDir=\""
<< docDataDir << "\", outputDir=\"" << outputDir << "\", copied \""
<< source.fileName() << "\"->\"" << targetFileName << '"';
@@ -1103,10 +1064,12 @@ bool QtXmlToSphinx::copyImage(const QString &href) const
{
QString errorMessage;
const bool result =
- ::copyImage(href, m_generator->docDataDir(), m_context,
- m_generator->outputDirectory(), &errorMessage);
+ ::copyImage(href, m_parameters.docDataDir, m_context,
+ m_parameters.outputDirectory,
+ m_generator->loggingCategory(),
+ &errorMessage);
if (!result)
- qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage));
+ warn(errorMessage);
return result;
}
@@ -1171,8 +1134,10 @@ void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader)
void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader)
{
QXmlStreamReader::TokenType token = reader.tokenType();
- if (token == QXmlStreamReader::StartElement)
- qCDebug(lcShibokenDoc).noquote().nospace() << "Unknown QtDoc tag: \"" << reader.name().toString() << "\".";
+ if (token == QXmlStreamReader::StartElement) {
+ qCDebug(m_generator->loggingCategory()).noquote().nospace()
+ << "Unknown QtDoc tag: \"" << reader.name().toString() << "\".";
+ }
}
void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader)
@@ -1259,11 +1224,11 @@ void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader)
QXmlStreamReader::TokenType token = reader.tokenType();
if (token == QXmlStreamReader::Characters) {
QString location = reader.text().toString();
- location.prepend(m_generator->libSourceDir() + QLatin1Char('/'));
+ location.prepend(m_parameters.libSourceDir + QLatin1Char('/'));
QString errorMessage;
QString code = readFromLocation(location, QString(), &errorMessage);
if (!errorMessage.isEmpty())
- qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage)));
+ warn(msgTagWarning(reader, m_context, m_lastTagName, errorMessage));
m_output << "::\n\n";
Indentation indentation(m_output);
if (code.isEmpty())
@@ -1274,26 +1239,6 @@ void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader)
}
}
-bool QtXmlToSphinx::convertToRst(const QtDocGenerator *generator,
- const QString &sourceFileName,
- const QString &targetFileName,
- const QString &context, QString *errorMessage)
-{
- QFile sourceFile(sourceFileName);
- if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- if (errorMessage)
- *errorMessage = msgCannotOpenForReading(sourceFile);
- return false;
- }
- const QString doc = QString::fromUtf8(sourceFile.readAll());
- sourceFile.close();
-
- FileOut targetFile(targetFileName);
- QtXmlToSphinx x(generator, doc, context);
- targetFile.stream << x;
- return targetFile.done(errorMessage) != FileOut::Failure;
-}
-
void QtXmlToSphinx::Table::normalize()
{
if (m_normalized || isEmpty())
@@ -1355,10 +1300,7 @@ void QtXmlToSphinx::Table::format(TextStream& s) const
if (isEmpty())
return;
- if (!isNormalized()) {
- qCDebug(lcShibokenDoc) << "Attempt to print an unnormalized table!";
- return;
- }
+ Q_ASSERT(isNormalized());
// calc width and height of each column and row
const int headerColumnCount = m_rows.constFirst().count();
@@ -1434,3 +1376,13 @@ void QtXmlToSphinx::stripPythonQualifiers(QString *s)
if (lastSep != -1)
s->remove(0, lastSep + 1);
}
+
+void QtXmlToSphinx::warn(const QString &message) const
+{
+ qCWarning(m_generator->loggingCategory(), "%s", qPrintable(message));
+}
+
+void QtXmlToSphinx::debug(const QString &message) const
+{
+ qCDebug(m_generator->loggingCategory(), "%s", qPrintable(message));
+}
diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h
index feaff1563..6fb626e2b 100644
--- a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h
+++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h
@@ -40,7 +40,9 @@
QT_BEGIN_NAMESPACE
class QXmlStreamReader;
QT_END_NAMESPACE
-class QtDocGenerator;
+
+class QtXmlToSphinxDocGeneratorInterface;
+struct QtXmlToSphinxParameters;
enum class WebXmlTag;
@@ -112,17 +114,12 @@ public:
bool m_normalized = false;
};
- explicit QtXmlToSphinx(const QtDocGenerator *generator,
+ explicit QtXmlToSphinx(const QtXmlToSphinxDocGeneratorInterface *docGenerator,
+ const QtXmlToSphinxParameters &parameters,
const QString& doc,
const QString& context = QString());
~QtXmlToSphinx();
- static bool convertToRst(const QtDocGenerator *generator,
- const QString &sourceFileName,
- const QString &targetFileName,
- const QString &context = QString(),
- QString *errorMessage = nullptr);
-
QString result() const
{
return m_result;
@@ -131,8 +128,6 @@ public:
static void stripPythonQualifiers(QString *s);
private:
- QString resolveContextForMethod(const QString& methodName) const;
- QString expandFunction(const QString& function) const;
QString transform(const QString& doc);
void handleHeadingTag(QXmlStreamReader& reader);
@@ -171,6 +166,9 @@ private:
void handleLinkText(LinkContext *linkContext, const QString &linktext) const;
void handleLinkEnd(LinkContext *linkContext);
+ void warn(const QString &message) const;
+ void debug(const QString &message) const;
+
QStack<WebXmlTag> m_tagStack;
TextStream m_output;
QString m_result;
@@ -182,7 +180,8 @@ private:
QScopedPointer<LinkContext> m_seeAlsoContext; // for <see-also>foo()</see-also>
bool m_tableHasHeader;
QString m_context;
- const QtDocGenerator* m_generator;
+ const QtXmlToSphinxDocGeneratorInterface *m_generator;
+ const QtXmlToSphinxParameters &m_parameters;
bool m_insideBold;
bool m_insideItalic;
QString m_lastTagName;
@@ -198,6 +197,7 @@ private:
void writeTable(Table& table);
bool copyImage(const QString &href) const;
void callHandler(WebXmlTag t, QXmlStreamReader &);
+ void formatCurrentTable();
};
inline TextStream& operator<<(TextStream& s, const QtXmlToSphinx& xmlToSphinx)
diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinxinterface.h b/sources/shiboken6/generator/qtdoc/qtxmltosphinxinterface.h
new file mode 100644
index 000000000..c4bdedd21
--- /dev/null
+++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinxinterface.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTXMLTOSPHINXINTERFACE_H
+#define QTXMLTOSPHINXINTERFACE_H
+
+#include <QtCore/QStringList>
+
+QT_FORWARD_DECLARE_CLASS(QLoggingCategory)
+
+struct QtXmlToSphinxParameters
+{
+ QString moduleName;
+ QString docDataDir;
+ QString outputDirectory;
+ QString libSourceDir;
+ QStringList codeSnippetDirs;
+ bool snippetComparison = false;
+};
+
+class QtXmlToSphinxDocGeneratorInterface
+{
+public:
+ virtual QString expandFunction(const QString &function) const = 0;
+ virtual QString expandClass(const QString &context,
+ const QString &name) const = 0;
+ virtual QString resolveContextForMethod(const QString &context,
+ const QString &methodName) const = 0;
+
+ virtual const QLoggingCategory &loggingCategory() const = 0;
+
+ virtual ~QtXmlToSphinxDocGeneratorInterface() = default;
+};
+
+#endif // QTXMLTOSPHINXINTERFACE_H