diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-11-25 10:10:30 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-11-26 06:20:37 +0000 |
| commit | 0f247c44a76f26587a5ea0ac9414e054da1f35e1 (patch) | |
| tree | 22601446acf2c28fb5f5e3f38b5d40d9512cc220 | |
| parent | 44b03e3ded688aabe8352e8bda66df8677acc8a4 (diff) | |
shiboken6: Port QtDocGenerator to the new text stream
Finally remove the old indentor.
Change-Id: I25150f61f914c1a6adc13341057a94c8bd281296
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
| -rw-r--r-- | sources/shiboken6/generator/indentor.h | 99 | ||||
| -rw-r--r-- | sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp | 140 | ||||
| -rw-r--r-- | sources/shiboken6/generator/qtdoc/qtdocgenerator.h | 22 | ||||
| -rw-r--r-- | sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp | 162 | ||||
| -rw-r--r-- | sources/shiboken6/generator/qtdoc/qtxmltosphinx.h | 11 | ||||
| -rw-r--r-- | sources/shiboken6/generator/qtdoc/rstformat.h | 16 |
6 files changed, 156 insertions, 294 deletions
diff --git a/sources/shiboken6/generator/indentor.h b/sources/shiboken6/generator/indentor.h deleted file mode 100644 index 4516cbbab..000000000 --- a/sources/shiboken6/generator/indentor.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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 INDENTOR_H -#define INDENTOR_H - -#include <QtCore/QTextStream> - -/** -* Utility class to store the indentation level, use it in a QTextStream. -*/ - -template <int tabWidth> -class IndentorBase -{ -public: - int total() const { return tabWidth * indent; } - - int indent = 0; -}; - -using Indentor = IndentorBase<4>; -using Indentor1 = IndentorBase<1>; - -/** -* Class that use the RAII idiom to set and unset the indentation level. -*/ - -template <int tabWidth> -class IndentationBase -{ -public: - using Indentor = IndentorBase<tabWidth>; - - IndentationBase(Indentor &indentor, int count = 1) : m_count(count), indentor(indentor) - { - indentor.indent += m_count; - } - - ~IndentationBase() - { - indentor.indent -= m_count; - } - -private: - const int m_count; - Indentor &indentor; -}; - -using Indentation4 = IndentationBase<4>; - -template <int tabWidth> -inline QTextStream &operator <<(QTextStream &s, const IndentorBase<tabWidth> &indentor) -{ - for (int i = 0, total = indentor.total(); i < total; ++i) - s << ' '; - return s; -} - -template <int tabWidth> -const char *indent(IndentorBase<tabWidth> &indentor) -{ - ++indentor.indent; - return ""; -} - -template <int tabWidth> -const char *outdent(IndentorBase<tabWidth> &indentor) -{ - --indentor.indent; - return ""; -} - -#endif // GENERATOR_H diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp index a84426ccf..9a53bd97a 100644 --- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.cpp @@ -28,7 +28,6 @@ #include "qtdocgenerator.h" #include "qtxmltosphinx.h" -#include "indentor.h" #include "rstformat.h" #include "ctypenames.h" #include <abstractmetaenum.h> @@ -40,6 +39,7 @@ #include <modifications.h> #include <propertyspec.h> #include <reporthandler.h> +#include <textstream.h> #include <typesystem.h> #include <qtdocparser.h> #include <doxygenparser.h> @@ -51,8 +51,6 @@ #include <algorithm> #include <limits> -static Indentor INDENT; - static inline QString additionalDocumentationOption() { return QStringLiteral("additional-documentation"); } static inline QString briefStartElement() { return QStringLiteral("<brief>"); } @@ -179,7 +177,7 @@ QString QtDocGenerator::fileNameForContext(const GeneratorContext &context) cons return fileNameBase + fileNameSuffix(); } -void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc, +void QtDocGenerator::writeFormattedText(TextStream &s, const Documentation &doc, const AbstractMetaClass *metaClass, Documentation::Type docType) const { @@ -189,7 +187,7 @@ void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc metaClassName = metaClass->fullName(); if (doc.format() == Documentation::Native) { - QtXmlToSphinx x(this, INDENT, doc.value(docType), metaClassName); + QtXmlToSphinx x(this, doc.value(docType), metaClassName); s << x; } else { const QString &value = doc.value(docType); @@ -205,17 +203,16 @@ void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc if (typesystemIndentation == std::numeric_limits<int>::max()) typesystemIndentation = 0; for (const auto &line : lines) { - s << INDENT - << (typesystemIndentation > 0 && typesystemIndentation < line.size() + s << (typesystemIndentation > 0 && typesystemIndentation < line.size() ? line.right(line.size() - typesystemIndentation) : line) - << Qt::endl; + << '\n'; } } - s << Qt::endl; + s << '\n'; } -static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) +static void writeInheritedByList(TextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) { AbstractMetaClassList res; for (AbstractMetaClass *c : allClasses) { @@ -230,7 +227,7 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl QStringList classes; for (AbstractMetaClass *c : qAsConst(res)) classes << QLatin1String(":ref:`") + c->name() + QLatin1Char('`'); - s << classes.join(QLatin1String(", ")) << Qt::endl << Qt::endl; + s << classes.join(QLatin1String(", ")) << "\n\n"; } // Extract the <brief> section from a WebXML (class) documentation and remove it @@ -257,9 +254,8 @@ static bool extractBrief(Documentation *sourceDoc, Documentation *brief) return true; } -void QtDocGenerator::generateClass(TextStream &ts, const GeneratorContext &classContext) +void QtDocGenerator::generateClass(TextStream &s, const GeneratorContext &classContext) { - QTextStream &s = ts.textStream(); const AbstractMetaClass *metaClass = classContext.metaClass(); qCDebug(lcShibokenDoc).noquote().nospace() << "Generating Documentation for " << metaClass->fullName(); @@ -272,16 +268,16 @@ void QtDocGenerator::generateClass(TextStream &ts, const GeneratorContext &class s << ".. _" << className << ":" << "\n\n"; s << ".. currentmodule:: " << metaClass->package() << "\n\n\n"; - s << className << Qt::endl; - s << Pad('*', className.count()) << Qt::endl << Qt::endl; + s << className << '\n'; + s << Pad('*', className.count()) << "\n\n"; auto documentation = metaClass->documentation(); Documentation brief; if (extractBrief(&documentation, &brief)) writeFormattedText(s, brief.value(), metaClass); - s << ".. inheritance-diagram:: " << metaClass->fullName() << Qt::endl - << " :parts: 2" << Qt::endl << Qt::endl; + s << ".. inheritance-diagram:: " << metaClass->fullName()<< '\n' + << " :parts: 2\n\n"; // TODO: This would be a parameter in the future... @@ -331,7 +327,7 @@ void QtDocGenerator::generateClass(TextStream &ts, const GeneratorContext &class writeInjectDocumentation(s, TypeSystem::DocModificationAppend, metaClass, nullptr); } -void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass) +void QtDocGenerator::writeFunctionList(TextStream& s, const AbstractMetaClass* cppClass) { QStringList functionList; QStringList virtualList; @@ -387,24 +383,23 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* } } -void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions) +void QtDocGenerator::writeFunctionBlock(TextStream& s, const QString& title, QStringList& functions) { if (!functions.isEmpty()) { - s << title << Qt::endl - << QString(title.size(), QLatin1Char('^')) << Qt::endl; + s << title << '\n' + << Pad('^', title.size()) << '\n'; std::sort(functions.begin(), functions.end()); s << ".. container:: function_list\n\n"; - Indentation4 indentation(INDENT); + Indentation indentation(s); for (const QString &func : qAsConst(functions)) - s << INDENT << '*' << ' ' << func << Qt::endl; - - s << Qt::endl << Qt::endl; + s << "* " << func << '\n'; + s << "\n\n"; } } -void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass) const +void QtDocGenerator::writeEnums(TextStream& s, const AbstractMetaClass* cppClass) const { static const QString section_title = QLatin1String(".. attribute:: "); @@ -418,7 +413,7 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas } -void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppClass) const +void QtDocGenerator::writeFields(TextStream& s, const AbstractMetaClass* cppClass) const { static const QString section_title = QLatin1String(".. attribute:: "); @@ -428,7 +423,7 @@ void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppCla } } -void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* cppClass) const +void QtDocGenerator::writeConstructors(TextStream& s, const AbstractMetaClass* cppClass) const { static const QString sectionTitle = QLatin1String(".. class:: "); @@ -441,25 +436,24 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* bool first = true; QHash<QString, AbstractMetaArgument> arg_map; - IndentorBase<1> indent1; - indent1.indent = INDENT.total(); if (lst.isEmpty()) { s << sectionTitle << cppClass->fullName(); } else { + QByteArray pad; for (AbstractMetaFunction *func : qAsConst(lst)) { - s << indent1; + s << pad; if (first) { first = false; s << sectionTitle; - indent1.indent += sectionTitle.size(); + pad = QByteArray(sectionTitle.size(), ' '); } s << functionSignature(cppClass, func) << "\n\n"; const auto version = versionOf(func->typeEntry()); if (!version.isNull()) - s << indent1 << rstVersionAdded(version); + s << pad << rstVersionAdded(version); if (func->attributes().testFlag(AbstractMetaAttributes::Deprecated)) - s << indent1 << rstDeprecationNote("constructor"); + s << pad << rstDeprecationNote("constructor"); const AbstractMetaArgumentList &arguments = func->arguments(); for (const AbstractMetaArgument &arg : arguments) { @@ -470,14 +464,15 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* } } - s << Qt::endl; + s << '\n'; for (auto it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { - Indentation4 indentation(INDENT, 2); + s.indent(2); writeParameterType(s, cppClass, it.value()); + s.outdent(2); } - s << Qt::endl; + s << '\n'; for (AbstractMetaFunction *func : qAsConst(lst)) writeFormattedText(s, func->documentation().value(), cppClass); @@ -531,12 +526,12 @@ QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* /* cppClass */ return ret; } -void QtDocGenerator::writeDocSnips(QTextStream &s, +void QtDocGenerator::writeDocSnips(TextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language) { - Indentation4 indentation(INDENT); + Indentation indentation(s); QStringList invalidStrings; const static QString startMarkup = QLatin1String("[sphinx-begin]"); const static QString endMarkup = QLatin1String("[sphinx-end]"); @@ -568,7 +563,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, if (row.trimmed().size() == 0) { if (currentRow == 0) continue; - s << Qt::endl; + s << '\n'; } if (currentRow == 0) { @@ -582,7 +577,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, break; } } - s << QStringView{row}.mid(offset) << Qt::endl; + s << QStringView{row}.mid(offset) << '\n'; currentRow++; } @@ -591,12 +586,12 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, } } -bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, +bool QtDocGenerator::writeInjectDocumentation(TextStream& s, TypeSystem::DocModificationMode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) { - Indentation4 indentation(INDENT); + Indentation indentation(s); bool didSomething = false; const DocModificationList &mods = cppClass->typeEntry()->docModifications(); @@ -622,7 +617,7 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, } } - s << Qt::endl; + s << '\n'; // TODO: Deprecate the use of doc string on glue code. // This is pre "add-function" and "inject-documentation" tags. @@ -707,17 +702,17 @@ QString QtDocGenerator::translateToPythonType(const AbstractMetaType &type, return strType; } -void QtDocGenerator::writeParameterType(QTextStream& s, const AbstractMetaClass* cppClass, +void QtDocGenerator::writeParameterType(TextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument &arg) const { - s << INDENT << ":param " << arg.name() << ": " - << translateToPythonType(arg.type(), cppClass) << Qt::endl; + s << ":param " << arg.name() << ": " + << translateToPythonType(arg.type(), cppClass) << '\n'; } -void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, +void QtDocGenerator::writeFunctionParametersType(TextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func) const { - s << Qt::endl; + s << '\n'; const AbstractMetaArgumentList &funcArgs = func->arguments(); for (const AbstractMetaArgument &arg : funcArgs) { @@ -742,27 +737,27 @@ void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractM if (retType.isEmpty()) retType = translateToPythonType(func->type(), cppClass); - s << INDENT << ":rtype: " << retType << Qt::endl; + s << ":rtype: " << retType << '\n'; } - s << Qt::endl; + s << '\n'; } -void QtDocGenerator::writeFunction(QTextStream& s, const AbstractMetaClass* cppClass, +void QtDocGenerator::writeFunction(TextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func, bool indexed) { s << functionSignature(cppClass, func); { - Indentation4 indentation(INDENT); + Indentation indentation(s); if (!indexed) - s << QLatin1Char('\n') << INDENT << QLatin1String(":noindex:"); + s << "\n:noindex:"; s << "\n\n"; writeFunctionParametersType(s, cppClass, func); const auto version = versionOf(func->typeEntry()); if (!version.isNull()) - s << INDENT << rstVersionAdded(version); + s << rstVersionAdded(version); if (func->attributes().testFlag(AbstractMetaAttributes::Deprecated)) - s << INDENT << rstDeprecationNote("function"); + s << rstDeprecationNote("function"); } writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func); if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) { @@ -772,7 +767,7 @@ void QtDocGenerator::writeFunction(QTextStream& s, const AbstractMetaClass* cppC writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func); } -static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 2) +static void writeFancyToc(TextStream& s, const QStringList& items, int cols = 2) { using TocMap = QMap<QChar, QStringList>; TocMap tocMap; @@ -796,14 +791,14 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 2 int itemsPerCol = (items.size() + tocMap.size()*2) / cols; QString currentColData; int i = 0; - QTextStream ss(¤tColData); + TextStream ss(¤tColData); QMutableMapIterator<QChar, QStringList> it(tocMap); while (it.hasNext()) { it.next(); std::sort(it.value().begin(), it.value().end()); if (i) - ss << Qt::endl; + ss << '\n'; ss << "**" << it.key() << "**\n\n"; i += 2; // a letter title is equivalent to two entries in space @@ -831,7 +826,7 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 2 table.appendRow(row); table.normalize(); s << ".. container:: pysidetoc\n\n"; - table.format(s, INDENT); + table.format(s); } bool QtDocGenerator::finishGeneration() @@ -851,16 +846,15 @@ void QtDocGenerator::writeModuleDocumentation() key.replace(QLatin1Char('.'), QLatin1Char('/')); QString outputDir = outputDirectory() + QLatin1Char('/') + key; FileOut output(outputDir + QLatin1String("/index.rst")); - QTextStream& s = output.stream.textStream(); - - s << ".. module:: " << it.key() << Qt::endl << Qt::endl; + TextStream& s = output.stream; const QString &title = it.key(); - s << title << Qt::endl; - s << Pad('*', title.length()) << Qt::endl << Qt::endl; + s << ".. module:: " << title << "\n\n" + << title << '\n' + << Pad('*', title.length()) << "\n\n"; /* Avoid showing "Detailed Description for *every* class in toc tree */ - Indentation4 indentation(INDENT); + Indentation indentation(s); // Store the it.key() in a QString so that it can be stripped off unwanted // information when neeeded. For example, the RST files in the extras directory // doesn't include the PySide# prefix in their names. @@ -892,12 +886,12 @@ void QtDocGenerator::writeModuleDocumentation() writeFancyToc(s, it.value()); - s << INDENT << ".. container:: hide\n\n" << indent(INDENT) - << INDENT << ".. toctree::\n" << indent(INDENT) - << INDENT << ":maxdepth: 1\n\n"; + s << ".. container:: hide\n\n" << indent + << ".. toctree::\n" << indent + << ":maxdepth: 1\n\n"; for (const QString &className : qAsConst(it.value())) - s << INDENT << className << Qt::endl; - s << "\n\n" << outdent(INDENT) << outdent(INDENT) + s << className << '\n'; + s << "\n\n" << outdent << outdent << "Detailed Description\n--------------------\n\n"; // module doc is always wrong and C++istic, so go straight to the extra directory! @@ -911,7 +905,7 @@ void QtDocGenerator::writeModuleDocumentation() if (moduleDoc.format() == Documentation::Native) { QString context = it.key(); QtXmlToSphinx::stripPythonQualifiers(&context); - QtXmlToSphinx x(this, INDENT, moduleDoc.value(), context); + QtXmlToSphinx x(this, moduleDoc.value(), context); s << x; } else { s << moduleDoc.value(); @@ -973,7 +967,7 @@ void QtDocGenerator::writeAdditionalDocumentation() const 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, INDENT, fi.absoluteFilePath(), + if (QtXmlToSphinx::convertToRst(this, fi.absoluteFilePath(), rstFile, context, &errorMessage)) { ++successCount; qCDebug(lcShibokenDoc).nospace().noquote() << __FUNCTION__ diff --git a/sources/shiboken6/generator/qtdoc/qtdocgenerator.h b/sources/shiboken6/generator/qtdoc/qtdocgenerator.h index 50b5575a6..356a0e210 100644 --- a/sources/shiboken6/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken6/generator/qtdoc/qtdocgenerator.h @@ -77,26 +77,26 @@ protected: bool finishGeneration() override; private: - void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass) const; + void writeEnums(TextStream& s, const AbstractMetaClass* cppClass) const; - void writeFields(QTextStream &s, const AbstractMetaClass *cppClass) const; + void writeFields(TextStream &s, const AbstractMetaClass *cppClass) const; static QString functionSignature(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunction(QTextStream& s, const AbstractMetaClass* cppClass, + void writeFunction(TextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func, bool indexed = true); - void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, + void writeFunctionParametersType(TextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func) const; - void writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass); - void writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions); - void writeParameterType(QTextStream &s, const AbstractMetaClass *cppClass, + void writeFunctionList(TextStream& s, const AbstractMetaClass* cppClass); + void writeFunctionBlock(TextStream& s, const QString& title, QStringList& functions); + void writeParameterType(TextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument &arg) const; - void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass) const; - void writeFormattedText(QTextStream &s, const Documentation &doc, + void writeConstructors(TextStream &s, const AbstractMetaClass *cppClass) const; + void writeFormattedText(TextStream &s, const Documentation &doc, const AbstractMetaClass *metaclass = nullptr, Documentation::Type docType = Documentation::Detailed) const; - bool writeInjectDocumentation(QTextStream& s, TypeSystem::DocModificationMode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); + bool writeInjectDocumentation(TextStream& s, TypeSystem::DocModificationMode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); + void writeDocSnips(TextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); void writeModuleDocumentation(); void writeAdditionalDocumentation() const; diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp index eff4b5121..427421a17 100644 --- a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp +++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.cpp @@ -28,7 +28,6 @@ #include "qtxmltosphinx.h" #include "fileout.h" -#include "indentor.h" #include "messages.h" #include "rstformat.h" #include "qtdocgenerator.h" @@ -49,33 +48,6 @@ static inline QString titleAttribute() { return QStringLiteral("title"); } static inline QString fullTitleAttribute() { return QStringLiteral("fulltitle"); } static inline QString briefAttribute() { return QStringLiteral("brief"); } -static QTextStream &formatCode(QTextStream &s, const QString &code, const Indentor &indentor) -{ - const auto lines= QStringView{code}.split(QLatin1Char('\n')); - for (const auto &line : lines) { - // Do not indent preprocessor lines - if (!line.isEmpty() && !line.startsWith(QLatin1Char('#'))) - s << indentor; - s << line << '\n'; - } - return s; -} - -// Return last character of a QString-buffered stream. -static QChar lastChar(const QTextStream &str) -{ - const QString *string = str.string(); - Q_ASSERT(string); - return string->isEmpty() ? QChar() : *(string->crbegin()); -} - -static QTextStream &ensureEndl(QTextStream &s) -{ - if (lastChar(s) != QLatin1Char('\n')) - s << '\n'; - return s; -} - struct QtXmlToSphinx::LinkContext { enum Type @@ -119,7 +91,7 @@ static const char *linkKeyWord(QtXmlToSphinx::LinkContext::Type type) return ""; } -QTextStream &operator<<(QTextStream &str, const QtXmlToSphinx::LinkContext &linkContext) +TextStream &operator<<(TextStream &str, const QtXmlToSphinx::LinkContext &linkContext) { // Temporarily turn off bold/italic since links do not work within if (linkContext.flags & QtXmlToSphinx::LinkContext::InsideBold) @@ -150,10 +122,11 @@ QTextStream &operator<<(QTextStream &str, const QtXmlToSphinx::LinkContext &link return str; } -QtXmlToSphinx::QtXmlToSphinx(const QtDocGenerator *generator, Indentor &indentor, +QtXmlToSphinx::QtXmlToSphinx(const QtDocGenerator *generator, const QString& doc, const QString& context) - : m_tableHasHeader(false), m_context(context), m_generator(generator), - INDENT(indentor), m_insideBold(false), m_insideItalic(false) + : m_output(static_cast<QString *>(nullptr)), + m_tableHasHeader(false), m_context(context), m_generator(generator), + m_insideBold(false), m_insideItalic(false) { m_handlerMap.insert(QLatin1String("heading"), &QtXmlToSphinx::handleHeadingTag); m_handlerMap.insert(QLatin1String("brief"), &QtXmlToSphinx::handleParaTag); @@ -305,7 +278,7 @@ QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) const QString QtXmlToSphinx::transform(const QString& doc) { Q_ASSERT(m_buffers.isEmpty()); - Indentation4 indentation(INDENT); + Indentation indentation(m_output); if (doc.trimmed().isEmpty()) return doc; @@ -320,7 +293,7 @@ QString QtXmlToSphinx::transform(const QString& doc) QTextStream(&message) << "XML Error " << reader.errorString() << " at " << reader.lineNumber() << ':' << reader.columnNumber() << '\n' << doc; - m_output << INDENT << message; + m_output << message; qCWarning(lcShibokenDoc).noquote().nospace() << message; break; } @@ -345,10 +318,10 @@ QString QtXmlToSphinx::transform(const QString& doc) if (!m_inlineImages.isEmpty()) { // Write out inline image definitions stored in handleInlineImageTag(). - m_output << '\n'; + m_output << '\n' << disableIndent; for (const InlineImage &img : qAsConst(m_inlineImages)) m_output << ".. |" << img.tag << "| image:: " << img.href << '\n'; - m_output << '\n'; + m_output << '\n' << enableIndent; m_inlineImages.clear(); } @@ -451,11 +424,12 @@ void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) else type = types[typeIdx]; } else if (token == QXmlStreamReader::EndElement) { - m_output << Pad(type, headingSize) << "\n\n"; + m_output << disableIndent << Pad(type, headingSize) << "\n\n" + << enableIndent; } else if (token == QXmlStreamReader::Characters) { - m_output << "\n\n"; + m_output << "\n\n" << disableIndent; headingSize = writeEscapedRstText(m_output, reader.text().trimmed()); - m_output << '\n'; + m_output << '\n' << enableIndent; } } @@ -471,16 +445,16 @@ void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) else if (result.startsWith(QLatin1String("**Note:**"))) result.replace(0, 9, QLatin1String(".. note:: ")); - m_output << INDENT << result << "\n\n"; + m_output << result << "\n\n"; } else if (token == QXmlStreamReader::Characters) { const auto text = reader.text(); - const QChar end = lastChar(m_output); - if (!text.isEmpty() && INDENT.indent == 0 && !end.isNull()) { + const QChar end = m_output.lastChar(); + if (!text.isEmpty() && m_output.indentation() == 0 && !end.isNull()) { QChar start = text[0]; if ((end == QLatin1Char('*') || end == QLatin1Char('`')) && start != QLatin1Char(' ') && !start.isPunct()) m_output << '\\'; } - m_output << INDENT << escape(text); + m_output << escape(text); } } @@ -548,7 +522,7 @@ void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) { switch (reader.tokenType()) { case QXmlStreamReader::StartElement: - m_output << INDENT << ".. seealso:: "; + m_output << ".. seealso:: "; break; case QXmlStreamReader::Characters: { // Direct embedded link: <see-also>rootIsDecorated()</see-also> @@ -584,7 +558,7 @@ static inline bool snippetComparison() } template <class Indent> // const char*/class Indentor -void formatSnippet(QTextStream &str, Indent indent, const QString &snippet) +void formatSnippet(TextStream &str, Indent indent, const QString &snippet) { const auto lines = QStringView{snippet}.split(QLatin1Char('\n')); for (const auto &line : lines) { @@ -597,17 +571,15 @@ void formatSnippet(QTextStream &str, Indent indent, const QString &snippet) static QString msgSnippetComparison(const QString &location, const QString &identifier, const QString &pythonCode, const QString &fallbackCode) { - QString result; - QTextStream str(&result); + StringStream str; + str.setTabWidth(2); str << "Python snippet " << location; if (!identifier.isEmpty()) str << " [" << identifier << ']'; - str << ":\n"; - formatSnippet(str, " ", pythonCode); - str << "Corresponding fallback snippet:\n"; - formatSnippet(str, " ", fallbackCode); - str << "-- end --\n"; - return result; + str << ":\n" << indent << pythonCode << ensureEndl << outdent + << "Corresponding fallback snippet:\n" + << indent << fallbackCode << ensureEndl << outdent << "-- end --\n"; + return str; } void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) @@ -646,14 +618,14 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) qCDebug(lcShibokenDoc, "%s", qPrintable(msgSnippetComparison(location, identifier, pythonCode, fallbackCode))); if (!consecutiveSnippet) - m_output << INDENT << "::\n\n"; + m_output << "::\n\n"; - Indentation4 indentation(INDENT); + Indentation indentation(m_output); const QString code = pythonCode.isEmpty() ? fallbackCode : pythonCode; if (code.isEmpty()) - m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>\n"; + m_output << "<Code snippet \"" << location << ':' << identifier << "\" not found>\n"; else - formatSnippet(m_output, INDENT, code); + m_output << code << ensureEndl; m_output << '\n'; } } @@ -667,18 +639,17 @@ void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) m_output.flush(); m_output.string()->chop(2); } else { - m_output << INDENT << "::\n\n"; + m_output << "::\n\n"; } - Indentation4 indentation(INDENT); + Indentation indentation(m_output); pushOutputBuffer(); - m_output << INDENT; int indent = reader.attributes().value(QLatin1String("indent")).toInt(); for (int i = 0; i < indent; ++i) m_output << ' '; } else if (token == QXmlStreamReader::Characters) { m_output << reader.text().toString(); } else if (token == QXmlStreamReader::EndElement) { - m_output << popOutputBuffer() << "\n\n\n"; + m_output << disableIndent << popOutputBuffer() << "\n\n\n" << enableIndent; } } @@ -693,7 +664,7 @@ void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader) m_currentTable.setHeaderEnabled(m_tableHasHeader); m_currentTable.normalize(); m_output << ensureEndl; - m_currentTable.format(m_output, INDENT); + m_currentTable.format(m_output); m_currentTable.clear(); } } @@ -767,21 +738,21 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) TableCell(QLatin1String("Description"))}); m_tableHasHeader = true; } - INDENT.indent--; + m_output.indent(); } else if (token == QXmlStreamReader::EndElement) { - INDENT.indent++; + m_output.outdent(); if (!m_currentTable.isEmpty()) { switch (listType) { case BulletList: case OrderedList: { m_output << '\n'; const char *separator = listType == BulletList ? "* " : "#. "; - const char *indent = listType == BulletList ? " " : " "; + const char *indentLine = listType == BulletList ? " " : " "; for (const TableCell &cell : m_currentTable.constFirst()) { const auto itemLines = QStringView{cell.data}.split(QLatin1Char('\n')); - m_output << INDENT << separator << itemLines.constFirst() << '\n'; + m_output << separator << itemLines.constFirst() << '\n'; for (int i = 1, max = itemLines.count(); i < max; ++i) - m_output << INDENT << indent << itemLines[i] << '\n'; + m_output << indentLine << itemLines[i] << '\n'; } m_output << '\n'; } @@ -790,7 +761,7 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) m_currentTable.setHeaderEnabled(m_tableHasHeader); m_currentTable.normalize(); m_output << ensureEndl; - m_currentTable.format(m_output, INDENT); + m_currentTable.format(m_output); break; } } @@ -989,7 +960,7 @@ void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) return; const QString href = reader.attributes().value(QLatin1String("href")).toString(); if (copyImage(href)) - m_output << INDENT << ".. image:: " << href << "\n\n"; + m_output << ".. image:: " << href << "\n\n"; } void QtXmlToSphinx::handleInlineImageTag(QXmlStreamReader& reader) @@ -1019,11 +990,10 @@ void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { QString format = reader.attributes().value(QLatin1String("format")).toString(); - m_output << INDENT << ".. raw:: " << format.toLower() << "\n\n"; + m_output << ".. raw:: " << format.toLower() << "\n\n"; } else if (token == QXmlStreamReader::Characters) { - const auto lst(reader.text().split(QLatin1Char('\n'))); - for (const auto &row : lst) - m_output << INDENT << INDENT << row << '\n'; + Indentation indent(m_output); + m_output << reader.text(); } else if (token == QXmlStreamReader::EndElement) { m_output << "\n\n"; } @@ -1033,15 +1003,12 @@ void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) { QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { - m_output << INDENT << "::\n\n"; - INDENT.indent++; + m_output << "::\n\n" << indent; } else if (token == QXmlStreamReader::Characters) { - const auto lst(reader.text().split(QLatin1Char('\n'))); - for (const auto &row : lst) - m_output << INDENT << INDENT << row << '\n'; + Indentation indent(m_output); + m_output << reader.text(); } else if (token == QXmlStreamReader::EndElement) { - m_output << "\n\n"; - INDENT.indent--; + m_output << outdent << "\n\n"; } } @@ -1071,6 +1038,8 @@ void QtXmlToSphinx::handlePageTag(QXmlStreamReader &reader) if (reader.tokenType() != QXmlStreamReader::StartElement) return; + m_output << disableIndent; + const auto title = reader.attributes().value(titleAttribute()); if (!title.isEmpty()) m_output << rstLabel(title.toString()); @@ -1080,7 +1049,8 @@ void QtXmlToSphinx::handlePageTag(QXmlStreamReader &reader) ? writeEscapedRstText(m_output, title) : writeEscapedRstText(m_output, fullTitle); - m_output << '\n' << Pad('*', size) << "\n\n"; + m_output << '\n' << Pad('*', size) << "\n\n" + << enableIndent; } void QtXmlToSphinx::handleTargetTag(QXmlStreamReader &reader) @@ -1089,7 +1059,7 @@ void QtXmlToSphinx::handleTargetTag(QXmlStreamReader &reader) return; const auto name = reader.attributes().value(nameAttribute()); if (!name.isEmpty()) - m_output << INDENT << rstLabel(name.toString()); + m_output << rstLabel(name.toString()); } void QtXmlToSphinx::handleIgnoredTag(QXmlStreamReader&) @@ -1115,7 +1085,7 @@ void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader) m_opened_anchor = anchor; if (!m_context.isEmpty()) anchor.prepend(m_context + QLatin1Char('_')); - m_output << INDENT << rstLabel(anchor); + m_output << rstLabel(anchor); } } else if (token == QXmlStreamReader::EndElement) { m_opened_anchor.clear(); @@ -1138,18 +1108,17 @@ void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) QString code = readFromLocation(location, QString(), &errorMessage); if (!errorMessage.isEmpty()) qCWarning(lcShibokenDoc, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); - m_output << INDENT << "::\n\n"; - Indentation4 indentation(INDENT); + m_output << "::\n\n"; + Indentation indentation(m_output); if (code.isEmpty()) - m_output << INDENT << "<Code snippet \"" << location << "\" not found>\n"; + m_output << "<Code snippet \"" << location << "\" not found>\n"; else - formatCode(m_output, code, INDENT); + m_output << code << ensureEndl; m_output << '\n'; } } bool QtXmlToSphinx::convertToRst(const QtDocGenerator *generator, - Indentor &indentor, const QString &sourceFileName, const QString &targetFileName, const QString &context, QString *errorMessage) @@ -1164,8 +1133,8 @@ bool QtXmlToSphinx::convertToRst(const QtDocGenerator *generator, sourceFile.close(); FileOut targetFile(targetFileName); - QtXmlToSphinx x(generator, indentor, doc, context); - targetFile.stream.textStream() << x; + QtXmlToSphinx x(generator, doc, context); + targetFile.stream << x; return targetFile.done(errorMessage) != FileOut::Failure; } @@ -1225,7 +1194,7 @@ void QtXmlToSphinx::Table::normalize() m_normalized = true; } -void QtXmlToSphinx::Table::format(QTextStream& s, const Indentor &INDENT) const +void QtXmlToSphinx::Table::format(TextStream& s) const { if (isEmpty()) return; @@ -1264,7 +1233,7 @@ void QtXmlToSphinx::Table::format(QTextStream& s, const Indentor &INDENT) const const QtXmlToSphinx::TableRow& row = m_rows.at(i); // print line - s << INDENT << '+'; + s << '+'; for (int col = 0; col < headerColumnCount; ++col) { char c; if (col >= row.length() || row[col].rowSpan == -1) @@ -1284,24 +1253,23 @@ void QtXmlToSphinx::Table::format(QTextStream& s, const Indentor &INDENT) const for (int maxJ = std::min(int(row.count()), headerColumnCount); j < maxJ; ++j) { // for each column const QtXmlToSphinx::TableCell& cell = row[j]; const auto rowLines = QStringView{cell.data}.split(QLatin1Char('\n')); // FIXME: Cache this!!! - if (!j) // First column, so we need print the identation - s << INDENT; if (!j || !cell.colSpan) s << '|'; else s << ' '; + const int width = colWidths.at(j); if (rowLine < rowLines.count()) - s << qSetFieldWidth(colWidths[j]) << Qt::left << rowLines.at(rowLine) << qSetFieldWidth(0); + s << AlignedField(rowLines.at(rowLine), width); else - s << Pad(' ', colWidths.at(j)); + s << Pad(' ', width); } for ( ; j < headerColumnCount; ++j) // pad s << '|' << Pad(' ', colWidths.at(j)); s << "|\n"; } } - s << INDENT << horizontalLine << "\n\n"; + s << horizontalLine << "\n\n"; } void QtXmlToSphinx::stripPythonQualifiers(QString *s) diff --git a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h index 636897fc4..7b6b7231d 100644 --- a/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h +++ b/sources/shiboken6/generator/qtdoc/qtxmltosphinx.h @@ -29,7 +29,7 @@ #ifndef QTXMLTOSPHINX_H #define QTXMLTOSPHINX_H -#include "indentor.h" +#include <textstream.h> #include <QtCore/QHash> #include <QtCore/QList> @@ -102,7 +102,7 @@ public: TableRow &first() { return m_rows.first(); } TableRow &last() { return m_rows.last(); } - void format(QTextStream& s, const Indentor &indent) const; + void format(TextStream& s) const; private: QList<TableRow> m_rows; @@ -111,13 +111,11 @@ public: }; explicit QtXmlToSphinx(const QtDocGenerator *generator, - Indentor &indentor, const QString& doc, const QString& context = QString()); ~QtXmlToSphinx(); static bool convertToRst(const QtDocGenerator *generator, - Indentor &indentor, const QString &sourceFileName, const QString &targetFileName, const QString &context = QString(), @@ -174,7 +172,7 @@ private: typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&); QHash<QString, TagHandler> m_handlerMap; QStack<TagHandler> m_handlers; - QTextStream m_output; + TextStream m_output; QString m_result; QStack<QString*> m_buffers; @@ -186,7 +184,6 @@ private: bool m_tableHasHeader; QString m_context; const QtDocGenerator* m_generator; - Indentor &INDENT; bool m_insideBold; bool m_insideItalic; QString m_lastTagName; @@ -203,7 +200,7 @@ private: bool copyImage(const QString &href) const; }; -inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx) +inline TextStream& operator<<(TextStream& s, const QtXmlToSphinx& xmlToSphinx) { return s << xmlToSphinx.result(); } diff --git a/sources/shiboken6/generator/qtdoc/rstformat.h b/sources/shiboken6/generator/qtdoc/rstformat.h index 628f33157..d14ecc55d 100644 --- a/sources/shiboken6/generator/qtdoc/rstformat.h +++ b/sources/shiboken6/generator/qtdoc/rstformat.h @@ -29,6 +29,8 @@ #ifndef RSTFORMAT_H #define RSTFORMAT_H +#include <textstream.h> + #include <QtCore/QByteArray> #include <QtCore/QString> #include <QtCore/QTextStream> @@ -41,7 +43,7 @@ struct rstVersionAdded const QVersionNumber m_version; }; -inline QTextStream &operator<<(QTextStream &s, const rstVersionAdded &v) +inline TextStream &operator<<(TextStream &s, const rstVersionAdded &v) { s << ".. versionadded:: "<< v.m_version.toString() << "\n\n"; return s; @@ -58,7 +60,7 @@ class Pad public: explicit Pad(char c, int count) : m_char(c), m_count(count) {} - void write(QTextStream &str) const + void write(TextStream &str) const { for (int i = 0; i < m_count; ++i) str << m_char; @@ -69,14 +71,14 @@ private: const int m_count; }; -inline QTextStream &operator<<(QTextStream &str, const Pad &pad) +inline TextStream &operator<<(TextStream &str, const Pad &pad) { pad.write(str); return str; } template <class String> -inline int writeEscapedRstText(QTextStream &str, const String &s) +inline int writeEscapedRstText(TextStream &str, const String &s) { int escaped = 0; for (const QChar &c : s) { @@ -99,13 +101,13 @@ class escape public: explicit escape(QStringView s) : m_string(s) {} - void write(QTextStream &str) const { writeEscapedRstText(str, m_string); } + void write(TextStream &str) const { writeEscapedRstText(str, m_string); } private: const QStringView m_string; }; -inline QTextStream &operator<<(QTextStream &str, const escape &e) +inline TextStream &operator<<(TextStream &str, const escape &e) { e.write(str); return str; @@ -131,7 +133,7 @@ class rstLabel public: explicit rstLabel(const QString &l) : m_label(l) {} - friend QTextStream &operator<<(QTextStream &str, const rstLabel &a) + friend TextStream &operator<<(TextStream &str, const rstLabel &a) { str << ".. _" << toRstLabel(a.m_label) << ":\n\n"; return str; |
