diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/qtdocparser.cpp')
-rw-r--r-- | sources/shiboken6/ApiExtractor/qtdocparser.cpp | 476 |
1 files changed, 277 insertions, 199 deletions
diff --git a/sources/shiboken6/ApiExtractor/qtdocparser.cpp b/sources/shiboken6/ApiExtractor/qtdocparser.cpp index 3b5837c95..5bd99bbd8 100644 --- a/sources/shiboken6/ApiExtractor/qtdocparser.cpp +++ b/sources/shiboken6/ApiExtractor/qtdocparser.cpp @@ -1,69 +1,69 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #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" #include "propertyspec.h" #include "reporthandler.h" -#include "typesystem.h" -#include "xmlutils.h" +#include "flagstypeentry.h" +#include "complextypeentry.h" +#include "functiontypeentry.h" +#include "enumtypeentry.h" + +#include "qtcompat.h" #include <QtCore/QDir> #include <QtCore/QFile> -#include <QtCore/QTextStream> -#include <QtCore/QXmlStreamAttributes> -#include <QtCore/QXmlStreamReader> -#include <QUrl> +#include <QtCore/QUrl> + +using namespace Qt::StringLiterals; + +enum { debugFunctionSearch = 0 }; + +constexpr auto briefStartElement = "<brief>"_L1; +constexpr auto briefEndElement = "</brief>"_L1; +constexpr auto webxmlSuffix = ".webxml"_L1; Documentation QtDocParser::retrieveModuleDocumentation() { return retrieveModuleDocumentation(packageName()); } -static void formatFunctionArgTypeQuery(QTextStream &str, const AbstractMetaArgument &arg) +static void formatPreQualifications(QTextStream &str, const AbstractMetaType &type) { - const AbstractMetaType &metaType = arg.type(); - if (metaType.isConstant()) + if (type.isConstant()) str << "const " ; +} + +static void formatPostQualifications(QTextStream &str, const AbstractMetaType &type) +{ + if (type.referenceType() == LValueReference) + str << " &"; + else if (type.referenceType() == RValueReference) + str << " &&"; + else if (type.indirections()) + str << ' ' << QByteArray(type.indirections(), '*'); +} + +static void formatFunctionUnqualifiedArgTypeQuery(QTextStream &str, + const AbstractMetaType &metaType) +{ switch (metaType.typeUsagePattern()) { 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(QLatin1Char('>')) && name.startsWith(QLatin1String("QFlags<"))) { - const int lastColon = name.lastIndexOf(QLatin1Char(':')); + if (name.endsWith(u'>') && name.startsWith(u"QFlags<")) { + const int lastColon = name.lastIndexOf(u':'); if (lastColon != -1) { name.replace(lastColon + 1, name.size() - lastColon - 1, metaType.name()); name.remove(0, 7); @@ -77,10 +77,13 @@ static void formatFunctionArgTypeQuery(QTextStream &str, const AbstractMetaArgum 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 << ", "; - str << instantiations.at(i).typeEntry()->qualifiedCppName(); + const auto &instantiation = instantiations.at(i); + formatPreQualifications(str, instantiation); + str << instantiation.typeEntry()->qualifiedCppName(); + formatPostQualifications(str, instantiation); } str << '>'; } @@ -89,151 +92,209 @@ static void formatFunctionArgTypeQuery(QTextStream &str, const AbstractMetaArgum str << metaType.typeEntry()->qualifiedCppName(); break; } - - if (metaType.referenceType() == LValueReference) - str << " &"; - else if (metaType.referenceType() == RValueReference) - str << " &&"; - else if (metaType.indirections()) - str << ' ' << QByteArray(metaType.indirections(), '*'); } -enum FunctionMatchFlags -{ - MatchArgumentCount = 0x1, - MatchArgumentType = 0x2, - DescriptionOnly = 0x4 -}; - -static QString functionXQuery(const QString &classQuery, - const AbstractMetaFunctionCPtr &func, - unsigned matchFlags = MatchArgumentCount | MatchArgumentType - | DescriptionOnly) +static QString formatFunctionArgTypeQuery(const AbstractMetaType &metaType) { QString result; - QTextStream str(&result); - const AbstractMetaArgumentList &arguments = func->arguments(); - str << classQuery << "/function[@name=\"" << func->originalName() - << "\" and @const=\"" << (func->isConstant() ? "true" : "false") << '"'; - if (matchFlags & MatchArgumentCount) - str << " and count(parameter)=" << arguments.size(); - str << ']'; - if (!arguments.isEmpty() && (matchFlags & MatchArgumentType)) { - for (int i = 0, size = arguments.size(); i < size; ++i) { - str << "/parameter[" << (i + 1) << "][@type=\""; - // Fixme: Use arguments.at(i)->type()->originalTypeDescription() - // instead to get unresolved typedefs? - formatFunctionArgTypeQuery(str, arguments.at(i)); - str << "\"]/.."; - } - } - if (matchFlags & DescriptionOnly) - str << "/description"; + QTextStream str(&result);formatPreQualifications(str, metaType); + formatFunctionUnqualifiedArgTypeQuery(str, metaType); + formatPostQualifications(str, metaType); return result; } -static QStringList signaturesFromWebXml(QString w) +QString QtDocParser::functionDocumentation(const QString &sourceFileName, + const ClassDocumentation &classDocumentation, + const AbstractMetaClassCPtr &metaClass, + const AbstractMetaFunctionCPtr &func, + QString *errorMessage) { - QStringList result; - if (w.isEmpty()) - return result; - w.prepend(QLatin1String("<root>")); // Fake root element - w.append(QLatin1String("</root>")); - QXmlStreamReader reader(w); - while (!reader.atEnd()) { - if (reader.readNext() == QXmlStreamReader::StartElement - && reader.name() == QLatin1String("function")) { - result.append(reader.attributes().value(QStringLiteral("signature")).toString()); - } - } - return result; -} + errorMessage->clear(); -static QString msgArgumentCountMatch(const AbstractMetaFunction *func, - const QStringList &matches) -{ - QString result; - QTextStream str(&result); - str << "\n Note: Querying for the argument count==" - << func->arguments().size() << " only yields " << matches.size() - << " matches"; - if (!matches.isEmpty()) - str << ": \"" << matches.join(QLatin1String("\", \"")) << '"'; - return result; + 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 AbstractMetaClass* metaClass, - const QString &classQuery, + const ClassDocumentation &classDocumentation, + const AbstractMetaClassCPtr &metaClass, const AbstractMetaFunctionCPtr &func, - const DocModificationList &signedModifs, - const XQueryPtr &xquery, QString *errorMessage) { - DocModificationList funcModifs; - for (const DocModification &funcModif : signedModifs) { - if (funcModif.signature() == func->minimalSignature()) - funcModifs.append(funcModif); + // Search candidates by name and const-ness + FunctionDocumentationList candidates = + classDocumentation.findFunctionCandidates(func->name(), func->isConstant()); + if (candidates.isEmpty()) { + *errorMessage = msgCannotFindDocumentation(sourceFileName, func.get()) + + u" (no matches)"_s; + return {}; } - // Properties - if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) { - const auto prop = metaClass->propertySpecs().at(func->propertySpecIndex()); - const QString propertyQuery = classQuery + QLatin1String("/property[@name=\"") - + prop.name() + QLatin1String("\"]/description"); - const QString properyDocumentation = getDocumentation(xquery, propertyQuery, funcModifs); - if (properyDocumentation.isEmpty()) { - *errorMessage = - msgCannotFindDocumentation(sourceFileName, metaClass, func.data(), - propertyQuery); + // Try an exact query + FunctionDocumentationQuery fq; + fq.name = func->name(); + fq.constant = func->isConstant(); + for (const auto &arg : func->arguments()) + fq.parameters.append(formatFunctionArgTypeQuery(arg.type())); + + const auto funcFlags = func->flags(); + // Re-add arguments removed by the metabuilder to binary operator functions + if (funcFlags.testFlag(AbstractMetaFunction::Flag::OperatorLeadingClassArgumentRemoved) + || funcFlags.testFlag(AbstractMetaFunction::Flag::OperatorTrailingClassArgumentRemoved)) { + QString classType = metaClass->qualifiedCppName(); + if (!funcFlags.testFlag(AbstractMetaFunction::Flag::OperatorClassArgumentByValue)) { + classType.prepend(u"const "_s); + classType.append(u" &"_s); } - return properyDocumentation; + if (funcFlags.testFlag(AbstractMetaFunction::Flag::OperatorLeadingClassArgumentRemoved)) + fq.parameters.prepend(classType); + else + fq.parameters.append(classType); } - // Query with full match of argument types - const QString fullQuery = functionXQuery(classQuery, func); - const QString result = getDocumentation(xquery, fullQuery, funcModifs); - if (!result.isEmpty()) - return result; - *errorMessage = msgCannotFindDocumentation(sourceFileName, metaClass, func.data(), fullQuery); - if (func->arguments().isEmpty()) // No arguments, can't be helped + const qsizetype index = ClassDocumentation::indexOfFunction(candidates, fq); + + if (debugFunctionSearch) { + qDebug() << __FUNCTION__ << metaClass->name() << fq << funcFlags << "returns" + << index << "\n " << candidates.value(index) << "\n " << candidates; + } + + if (index != -1) + return candidates.at(index).description; + + // Fallback: Try matching by argument count + const auto parameterCount = func->arguments().size(); + auto pend = std::remove_if(candidates.begin(), candidates.end(), + [parameterCount](const FunctionDocumentation &fd) { + return fd.parameters.size() != parameterCount; }); + candidates.erase(pend, candidates.end()); + if (candidates.size() == 1) { + const auto &match = candidates.constFirst(); + 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.get()) + << " (" << candidates.size() << " candidates matching the argument count)"; + return {}; +} + +// Extract the <brief> section from a WebXML (class) documentation and remove it +// from the source. +static QString extractBrief(QString *value) +{ + const auto briefStart = value->indexOf(briefStartElement); + if (briefStart < 0) + return {}; + const auto briefEnd = value->indexOf(briefEndElement, + briefStart + briefStartElement.size()); + if (briefEnd < briefStart) + return {}; + const auto briefLength = briefEnd + briefEndElement.size() - briefStart; + QString briefValue = value->mid(briefStart, briefLength); + briefValue.insert(briefValue.size() - briefEndElement.size(), + u"<rst> More_...</rst>"_s); + value->remove(briefStart, briefLength); + return briefValue; +} + +// 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; - // Test whether some mismatch in argument types occurred by checking for - // the argument count only. Include the outer <function> element. - QString countOnlyQuery = functionXQuery(classQuery, func, MatchArgumentCount); - QStringList signatures = - signaturesFromWebXml(getDocumentation(xquery, countOnlyQuery, funcModifs)); - if (signatures.size() == 1) { - // One match was found. Repeat the query restricted to the <description> - // element and use the result with a warning. - countOnlyQuery = functionXQuery(classQuery, func, MatchArgumentCount | DescriptionOnly); - errorMessage->append(QLatin1String("\n Falling back to \"") + signatures.constFirst() - + QLatin1String("\" obtained by matching the argument count only.")); - return getDocumentation(xquery, countOnlyQuery, funcModifs); + // 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; } - *errorMessage += msgArgumentCountMatch(func.data(), signatures); - return result; + 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::fillDocumentation(AbstractMetaClass* metaClass) +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(); } - QString sourceFileRoot = documentationDataDirectory() + QLatin1Char('/') + QString sourceFileRoot = documentationDataDirectory() + u'/' + metaClass->qualifiedCppName().toLower(); - sourceFileRoot.replace(QLatin1String("::"), QLatin1String("-")); + 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: " @@ -243,43 +304,45 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) const QString sourceFileName = sourceFile.absoluteFilePath(); QString errorMessage; - XQueryPtr xquery = XQuery::create(sourceFileName, &errorMessage); - if (xquery.isNull()) { + + const auto classDocumentationO = parseWebXml(sourceFileName, &errorMessage); + if (!classDocumentationO.has_value()) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return; } - QString className = metaClass->name(); + const auto &classDocumentation = classDocumentationO.value(); + for (const auto &p : classDocumentation.properties) { + Documentation doc(p.description, p.brief); + metaClass->setPropertyDocumentation(p.name, doc); + } - // Class/Namespace documentation - const QString classQuery = QLatin1String("/WebXML/document/") - + (metaClass->isNamespace() ? QLatin1String("namespace") : QLatin1String("class")) - + QLatin1String("[@name=\"") + className + QLatin1String("\"]"); - QString query = classQuery + QLatin1String("/description"); + QString docString = applyDocModifications(DocParser::getXpathDocModifications(metaClass), + classDocumentation.description); - 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); + if (docString.isEmpty()) { + QString className = metaClass->name(); + qCWarning(lcShibokenDoc, "%s", + qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, {}))); } + const QString brief = extractBrief(&docString); - Documentation doc(getDocumentation(xquery, query, classModifs)); - if (doc.isEmpty()) - qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, query))); + Documentation doc; + if (!brief.isEmpty()) + doc.setValue(brief, Documentation::Brief); + doc.setValue(docString); metaClass->setDocumentation(doc); //Functions Documentation const auto &funcs = DocParser::documentableFunctions(metaClass); for (const auto &func : funcs) { - const QString documentation = - queryFunctionDocumentation(sourceFileName, metaClass, classQuery, - func, signedModifs, xquery, &errorMessage); + const QString detailed = + functionDocumentation(sourceFileName, classDocumentation, + metaClass, func, &errorMessage); if (!errorMessage.isEmpty()) qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); - qSharedPointerConstCast<AbstractMetaFunction>(func)->setDocumentation(Documentation(documentation)); + const Documentation documentation(detailed, {}); + std::const_pointer_cast<AbstractMetaFunction>(func)->setDocumentation(documentation); } #if 0 // Fields @@ -295,24 +358,41 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) #endif // Enums for (AbstractMetaEnum &meta_enum : metaClass->enums()) { - query.clear(); - QTextStream(&query) << classQuery << "/enum[@name=\"" - << meta_enum.name() << "\"]/description"; - doc.setValue(getDocumentation(xquery, query, DocModificationList())); - if (doc.isEmpty()) { + if (!extractEnumDocumentation(classDocumentation, meta_enum)) { qCWarning(lcShibokenDoc, "%s", - qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, query))); + 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); } - meta_enum.setDocumentation(doc); } + enumDoc.setValue(doc); + meta_enum.setDocumentation(enumDoc); + return true; } static QString qmlReferenceLink(const QFileInfo &qmlModuleFi) { QString result; QTextStream(&result) << "<para>The module also provides <link" - << " type=\"page\"" - << " page=\"http://doc.qt.io/qt-5/" << qmlModuleFi.baseName() << ".html\"" + << R"( type="page" page="https://doc.qt.io/qt-)" << QT_VERSION_MAJOR + << '/' << qmlModuleFi.baseName() << R"(.html")" << ">QML types</link>.</para>"; return result; } @@ -322,13 +402,13 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) // TODO: This method of acquiring the module name supposes that the target language uses // dots as module separators in package names. Improve this. QString moduleName = name; - moduleName.remove(0, name.lastIndexOf(QLatin1Char('.')) + 1); - const QString prefix = documentationDataDirectory() + QLatin1Char('/') + moduleName.remove(0, name.lastIndexOf(u'.') + 1); + if (moduleName == u"QtQuickControls2") + moduleName.chop(1); + const QString prefix = documentationDataDirectory() + u'/' + moduleName.toLower(); - QString sourceFile = prefix + QLatin1String(".xml"); - if (!QFile::exists(sourceFile)) - sourceFile = prefix + QLatin1String("-module.webxml"); + const QString sourceFile = prefix + u"-index.webxml"_s; if (!QFile::exists(sourceFile)) { qCWarning(lcShibokenDoc).noquote().nospace() << "Can't find qdoc file for module " << name << ", tried: " @@ -337,29 +417,27 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) } QString errorMessage; - XQueryPtr xquery = XQuery::create(sourceFile, &errorMessage); - if (xquery.isNull()) { + QString docString = webXmlModuleDescription(sourceFile, &errorMessage); + if (!errorMessage.isEmpty()) { qCWarning(lcShibokenDoc, "%s", qPrintable(errorMessage)); return {}; } - // Module documentation - QString query = QLatin1String("/WebXML/document/module[@name=\"") - + moduleName + QLatin1String("\"]/description"); - Documentation doc = getDocumentation(xquery, query, DocModificationList()); + Documentation doc(docString, {}); if (doc.isEmpty()) { - qCWarning(lcShibokenDoc, "%s", qPrintable(msgCannotFindDocumentation(sourceFile, "module", name, query))); + qCWarning(lcShibokenDoc, "%s", + qPrintable(msgCannotFindDocumentation(sourceFile, "module", name))); return doc; } // If a QML module info file exists, insert a link to the Qt docs. - const QFileInfo qmlModuleFi(prefix + QLatin1String("-qmlmodule.webxml")); + const QFileInfo qmlModuleFi(prefix + u"-qmlmodule.webxml"_s); if (qmlModuleFi.isFile()) { - QString docString = doc.value(); - const int pos = docString.lastIndexOf(QLatin1String("</description>")); + QString docString = doc.detailed(); + const int pos = docString.lastIndexOf(u"</description>"); if (pos != -1) { docString.insert(pos, qmlReferenceLink(qmlModuleFi)); - doc.setValue(docString); + doc.setDetailed(docString); } } |