diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/classdocumentation.cpp')
| -rw-r--r-- | sources/shiboken6/ApiExtractor/classdocumentation.cpp | 425 |
1 files changed, 0 insertions, 425 deletions
diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.cpp b/sources/shiboken6/ApiExtractor/classdocumentation.cpp deleted file mode 100644 index 6f7159845..000000000 --- a/sources/shiboken6/ApiExtractor/classdocumentation.cpp +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "classdocumentation.h" -#include "messages.h" -#include "debughelpers_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qbuffer.h> -#include <QtCore/qfile.h> -#include <QtCore/qxmlstream.h> - -#include <algorithm> - -using namespace Qt::StringLiterals; - -// Sort functions by name and argument count -static bool functionDocumentationLessThan(const FunctionDocumentation &f1, - const FunctionDocumentation &f2) -{ - const int nc = f1.name.compare(f2.name); - if (nc != 0) - return nc < 0; - return f1.parameters.size() < f2.parameters.size(); -} - -static void sortDocumentation(ClassDocumentation *cd) -{ - std::stable_sort(cd->enums.begin(), cd->enums.end(), - [] (const EnumDocumentation &e1, const EnumDocumentation &e2) { - return e1.name < e2.name; }); - std::stable_sort(cd->properties.begin(), cd->properties.end(), - [] (const PropertyDocumentation &p1, const PropertyDocumentation &p2) { - return p1.name < p2.name; }); - std::stable_sort(cd->functions.begin(), cd->functions.end(), - functionDocumentationLessThan); -} - -qsizetype ClassDocumentation::indexOfEnum(const QString &name) const -{ - for (qsizetype i = 0, size = enums.size(); i < size; ++i) { - if (enums.at(i).name == name) - return i; - } - return -1; -} - -FunctionDocumentationList ClassDocumentation::findFunctionCandidates(const QString &name, - bool constant) const -{ - FunctionDocumentationList result; - std::copy_if(functions.cbegin(), functions.cend(), - std::back_inserter(result), - [name, constant](const FunctionDocumentation &fd) { - return fd.constant == constant && fd.name == name; - }); - return result; -} - -static bool matches(const FunctionDocumentation &fd, const FunctionDocumentationQuery &q) -{ - return fd.name == q.name && fd.constant == q.constant && fd.parameters == q.parameters; -} - -qsizetype ClassDocumentation::indexOfFunction(const FunctionDocumentationList &fl, - const FunctionDocumentationQuery &q) -{ - for (qsizetype i = 0, size = fl.size(); i < size; ++i) { - if (matches(fl.at(i), q)) - return i; - } - return -1; -} - -qsizetype ClassDocumentation::indexOfProperty(const QString &name) const -{ - for (qsizetype i = 0, size = properties.size(); i < size; ++i) { - if (properties.at(i).name == name) - return i; - } - return -1; -} - -enum class WebXmlCodeTag : std::uint8_t -{ - Class, Description, Enum, Function, Header, Parameter, Property, Typedef, Other -}; - -static WebXmlCodeTag tag(QStringView name) -{ - if (name == "class"_L1 || name == "struct"_L1 || name == "namespace"_L1) - return WebXmlCodeTag::Class; - if (name == u"enum") - return WebXmlCodeTag::Enum; - if (name == u"function") - return WebXmlCodeTag::Function; - if (name == u"description") - return WebXmlCodeTag::Description; - if (name == u"header") - return WebXmlCodeTag::Header; - if (name == u"parameter") - return WebXmlCodeTag::Parameter; - if (name == u"property") - return WebXmlCodeTag::Property; - if (name == u"typedef") - return WebXmlCodeTag::Typedef; - return WebXmlCodeTag::Other; -} - -static void parseWebXmlElement(WebXmlCodeTag tag, const QXmlStreamAttributes &attributes, - ClassDocumentation *cd) -{ - switch (tag) { - case WebXmlCodeTag::Class: - cd->name = attributes.value(u"name"_s).toString(); - cd->type = ClassDocumentation::Class; - break; - case WebXmlCodeTag::Header: - cd->name = attributes.value(u"name"_s).toString(); - cd->type = ClassDocumentation::Header; - break; - case WebXmlCodeTag::Enum: { - EnumDocumentation ed; - ed.name = attributes.value(u"name"_s).toString(); - cd->enums.append(ed); - } - break; - case WebXmlCodeTag::Function: { - FunctionDocumentation fd; - fd.name = attributes.value(u"name"_s).toString(); - fd.signature = attributes.value(u"signature"_s).toString(); - fd.returnType = attributes.value(u"type"_s).toString(); - fd.constant = attributes.value(u"const"_s) == u"true"; - cd->functions.append(fd); - } - break; - case WebXmlCodeTag::Parameter: - Q_ASSERT(!cd->functions.isEmpty()); { - FunctionDocumentation &last = cd->functions.last(); - last.parameters.append(attributes.value(u"type"_s).toString()); - last.parameterNames.append(attributes.value(u"name"_s).toString()); - } - break; - case WebXmlCodeTag::Property: { - PropertyDocumentation pd; - pd.name = attributes.value(u"name"_s).toString(); - pd.brief = attributes.value(u"brief"_s).toString(); - cd->properties.append(pd); - } - break; - default: - break; - } -} - -// Retrieve the contents of <description> -static QString extractWebXmlDescription(QXmlStreamReader &reader) -{ - QBuffer buffer; - buffer.open(QIODeviceBase::WriteOnly); - QXmlStreamWriter writer(&buffer); - - do { - switch (reader.tokenType()) { - case QXmlStreamReader::StartElement: - writer.writeStartElement(reader.name().toString()); - writer.writeAttributes(reader.attributes()); - break; - case QXmlStreamReader::Characters: - writer.writeCharacters(reader.text().toString()); - break; - case QXmlStreamReader::EndElement: - writer.writeEndElement(); - if (reader.name() == u"description") { - buffer.close(); - return QString::fromUtf8(buffer.buffer()).trimmed(); - } - break; - default: - break; - } - reader.readNext(); - } while (!reader.atEnd()); - - return {}; -} - -static QString msgXmlError(const QString &fileName, const QXmlStreamReader &reader) -{ - QString result; - QTextStream(&result) << fileName << ':' << reader.lineNumber() << ':' - << reader.columnNumber() << ':' << reader.errorString(); - return result; -} - -static bool parseWebXmlHelper(QFile *file, ClassDocumentation *result, QString *errorMessage) -{ - WebXmlCodeTag lastTag = WebXmlCodeTag::Other; - QXmlStreamReader reader(file); - while (!reader.atEnd()) { - switch (reader.readNext()) { - case QXmlStreamReader::StartElement: { - const auto currentTag = tag(reader.name()); - parseWebXmlElement(currentTag, reader.attributes(), result); - switch (currentTag) { // Store relevant tags in lastTag - case WebXmlCodeTag::Class: - case WebXmlCodeTag::Function: - case WebXmlCodeTag::Enum: - case WebXmlCodeTag::Header: - case WebXmlCodeTag::Property: - case WebXmlCodeTag::Typedef: - lastTag = currentTag; - break; - case WebXmlCodeTag::Description: { // Append the description to the element - QString *target = nullptr; - switch (lastTag) { - case WebXmlCodeTag::Class: - target = &result->description; - break; - case WebXmlCodeTag::Function: - target = &result->functions.last().description; - break; - case WebXmlCodeTag::Enum: - target = &result->enums.last().description; - break; - case WebXmlCodeTag::Property: - target = &result->properties.last().description; - default: - break; - } - if (target != nullptr && target->isEmpty()) - *target = extractWebXmlDescription(reader); - } - break; - default: - break; - } - } - default: - break; - } - } - - if (reader.error() != QXmlStreamReader::NoError) { - *errorMessage= msgXmlError(file->fileName(), reader); - return false; - } - - return result; -} - -std::optional<ClassDocumentation> parseWebXml(const QStringList &fileNames, QString *errorMessage) -{ - ClassDocumentation result; - for (const auto &fileName : fileNames) { - QFile file(fileName); - if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) { - *errorMessage = msgCannotOpenForReading(file); - return std::nullopt; - } - if (!parseWebXmlHelper(&file, &result, errorMessage)) - return std::nullopt; - } - - sortDocumentation(&result); - return result; -} - -// Helpers to remove some sections with information on how to build -// and link and the C++ reference from the WebXML module description -static void removeElement(QByteArrayView begin, QByteArrayView end, - QByteArray *data) -{ - auto startPos = data->indexOf(begin); - if (startPos != -1) { - auto endPos = data->indexOf(end, startPos + begin.size()); - if (endPos != -1) - data->remove(startPos, endPos + end.size() - startPos); - } -} - -static void removeSection(const QByteArray &id, - QByteArray *data) -{ - QByteArray contentBegin = "<contents name=\"" + id + '"'; - removeElement(contentBegin, "/>"_ba, data); - QByteArray sectionBegin = "<section id=\""_ba + id + "\">"_ba; - removeElement(sectionBegin, "</section>"_ba, data); -} - -QString webXmlModuleDescription(const QString &fileName, QString *errorMessage) -{ - QFile file(fileName); - if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) { - *errorMessage = msgCannotOpenForReading(file); - return {}; - } - - QByteArray text = file.readAll(); - file.close(); - static const QByteArrayList cppSectionIds{ - "api-reference"_ba, "building-with-cmake"_ba, "building-with-qmake"_ba, - "c-api"_ba, "c-classes"_ba, "examples"_ba, "qml-api"_ba, "reference"_ba, - "reference-and-examples"_ba, "using-the-module"_ba - }; - for (const auto &cppSectionId : cppSectionIds) - removeSection(cppSectionId, &text); - - QBuffer buffer(&text); - buffer.open(QIODevice::ReadOnly); - - QString result; - QXmlStreamReader reader(&buffer); - while (!reader.atEnd()) { - switch (reader.readNext()) { - case QXmlStreamReader::StartElement: - if (reader.name() == u"description") - result = extractWebXmlDescription(reader); - break; - default: - break; - } - } - - if (reader.error() != QXmlStreamReader::NoError) { - *errorMessage= msgXmlError(fileName, reader); - return {}; - } - - return result; -} - -static void formatDescription(QDebug &debug, const QString &desc) -{ - debug << "description="; - if (desc.isEmpty()) { - debug << "<empty>"; - return; - } - if (debug.verbosity() < 3) - debug << desc.size() << " chars"; - else - debug << '"' << desc << '"'; -} - -QDebug operator<<(QDebug debug, const EnumDocumentation &e) -{ - QDebugStateSaver saver(debug); - debug.noquote(); - debug.nospace(); - debug << "Enum("; - if (e.name.isEmpty()) { - debug << "invalid"; - } else { - debug << e.name << ", "; - formatDescription(debug, e.description); - } - debug << ')'; - return debug; -} - -QDebug operator<<(QDebug debug, const PropertyDocumentation &p) -{ - QDebugStateSaver saver(debug); - debug.noquote(); - debug.nospace(); - debug << "Property("; - if (p.name.isEmpty()) { - debug << "invalid"; - } else { - debug << p.name << ", "; - formatDescription(debug, p.description); - } - debug << ')'; - return debug; -} - -QDebug operator<<(QDebug debug, const FunctionDocumentation &f) -{ - QDebugStateSaver saver(debug); - debug.noquote(); - debug.nospace(); - debug << "Function("; - if (f.name.isEmpty()) { - debug << "invalid"; - } else { - debug << f.name; - if (!f.returnType.isEmpty()) - debug << ", returns " << f.returnType; - if (f.constant) - debug << ", const"; - formatList(debug, ", parameters", f.parameters, ", "); - debug << ", signature=\"" << f.signature << "\", "; - formatDescription(debug, f.description); - } - debug << ')'; - return debug; -} - -QDebug operator<<(QDebug debug, const FunctionDocumentationQuery &q) -{ - QDebugStateSaver saver(debug); - debug.noquote(); - debug.nospace(); - debug << "FunctionQuery(" << q.name; - if (q.constant) - debug << ", const"; - formatList(debug, ", parameters", q.parameters); - debug << ')'; - return debug; -} - -QDebug operator<<(QDebug debug, const ClassDocumentation &c) -{ - QDebugStateSaver saver(debug); - debug.noquote(); - debug.nospace(); - debug << "Class(" << c.name << ", "; - formatDescription(debug, c.description); - formatList(debug, ", enums", c.enums); - formatList(debug, ", properties", c.properties); - formatList(debug, ", functions", c.functions); - debug << ')'; - return debug; -} |
