diff options
Diffstat (limited to 'sources')
18 files changed, 430 insertions, 70 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt index f8e504583..28644fe49 100644 --- a/sources/shiboken2/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt @@ -13,6 +13,7 @@ fileout.cpp graph.cpp messages.cpp reporthandler.cpp +sourcelocation.cpp typeparser.cpp typesystem.cpp typesystemparser.cpp diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index d4268941f..093b2fb68 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -212,9 +212,8 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() if (!found) { qCWarning(lcShiboken).noquote().nospace() - << msgNoFunctionForModification(signature, + << msgNoFunctionForModification(clazz, signature, modification.originalSignature(), - clazz->qualifiedCppName(), possibleSignatures, functions); } } @@ -553,9 +552,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) && !entry->isCustom() && (entry->generateCode() & TypeEntry::GenerateTargetLang) && !AbstractMetaClass::findClass(m_metaClasses, entry)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") - .arg(entry->qualifiedCppName()); + qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry))); } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { auto fte = static_cast<const FunctionTypeEntry *>(entry); const QStringList &signatures = fte->signatures(); @@ -568,13 +565,13 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) } } if (!ok) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") - .arg(signature); + qCWarning(lcShiboken, "%s", + qPrintable(msgGlobalFunctionNotDefined(fte, signature))); } } } else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) { - const QString name = static_cast<const EnumTypeEntry *>(entry)->targetLangQualifier(); + auto enumEntry = static_cast<const EnumTypeEntry *>(entry); + const QString name = enumEntry->targetLangQualifier(); AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name); const bool enumFound = cls @@ -583,9 +580,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!enumFound) { entry->setCodeGeneration(TypeEntry::GenerateNothing); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum '%1' is specified in typesystem, but not declared") - .arg(entry->qualifiedCppName()); + qCWarning(lcShiboken, "%s", + qPrintable(msgEnumNotDefined(enumEntry))); } } @@ -744,8 +740,8 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName()); if (!type) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName); + qCWarning(lcShiboken, "%s", + qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName))); return nullptr; } @@ -1035,6 +1031,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem } auto *metaClass = new AbstractMetaClass; + metaClass->setSourceLocation(classItem->sourceLocation()); metaClass->setTypeEntry(type); if (classItem->isFinal()) @@ -1188,9 +1185,8 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel if (!metaType) { const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'") - .arg(cls->name(), fieldName, type); + qCWarning(lcShiboken, "%s", + qPrintable(msgSkippingField(field, cls->name(), type))); } delete metaField; return nullptr; @@ -1454,9 +1450,8 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) for (const auto &baseClassName : baseClasses) { if (!types->isClassRejected(baseClassName)) { if (!types->findType(baseClassName)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class '%1' inherits from unknown base class '%2'") - .arg(metaClass->name(), baseClassName); + qCWarning(lcShiboken, "%s", + qPrintable(msgUnknownBase(metaClass, baseClassName))); return false; } auto baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClassName); @@ -1769,6 +1764,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } auto *metaFunction = new AbstractMetaFunction; + metaFunction->setSourceLocation(functionItem->sourceLocation()); if (deprecated) *metaFunction += AbstractMetaAttributes::Deprecated; @@ -1871,12 +1867,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio if (!currentClass || (currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { - qCWarning(lcShiboken).noquote().nospace() - << "Stripping argument #" << (i + 1) << " of " - << originalQualifiedSignatureWithReturn - << " due to unmatched type \"" << arg->type().toString() - << "\" with default expression \"" - << arg->defaultValueExpression() << "\"."; + qCWarning(lcShiboken, "%s", + qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg))); } break; } @@ -1940,8 +1932,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio fixArgumentNames(metaFunction, functionMods); QString errorMessage; if (!applyArrayArgumentModifications(functionMods, metaFunction, &errorMessage)) { - qCWarning(lcShiboken, "While traversing %s: %s", - qPrintable(className), qPrintable(errorMessage)); + qCWarning(lcShiboken, "%s", + qPrintable(msgArrayModificationFailed(functionItem, className, errorMessage))); } } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 390143cda..e9a2c2b57 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -783,6 +783,16 @@ bool AbstractMetaFunction::autoDetectAllowThread() const return !maybeGetter; } +SourceLocation AbstractMetaFunction::sourceLocation() const +{ + return m_sourceLocation; +} + +void AbstractMetaFunction::setSourceLocation(const SourceLocation &sourceLocation) +{ + m_sourceLocation = sourceLocation; +} + static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass) { return klass->typeEntry()->allowThread(); @@ -2636,6 +2646,16 @@ void AbstractMetaClass::formatMembers(QDebug &d) const } } +SourceLocation AbstractMetaClass::sourceLocation() const +{ + return m_sourceLocation; +} + +void AbstractMetaClass::setSourceLocation(const SourceLocation &sourceLocation) +{ + m_sourceLocation = sourceLocation; +} + QDebug operator<<(QDebug d, const AbstractMetaClass *ac) { QDebugStateSaver saver(d); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 00f137100..830631e68 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -30,6 +30,7 @@ #define ABSTRACTMETALANG_H #include "abstractmetalang_typedefs.h" +#include "sourcelocation.h" #include "typesystem_enums.h" #include "typesystem_typedefs.h" @@ -1093,6 +1094,9 @@ public: void formatDebugVerbose(QDebug &d) const; #endif + SourceLocation sourceLocation() const; + void setSourceLocation(const SourceLocation &sourceLocation); + private: bool autoDetectAllowThread() const; @@ -1111,6 +1115,7 @@ private: QPropertySpec *m_propertySpec = nullptr; AbstractMetaArgumentList m_arguments; AddedFunctionPtr m_addedFunction; + SourceLocation m_sourceLocation; uint m_constant : 1; uint m_reverse : 1; uint m_explicit : 1; @@ -1682,6 +1687,9 @@ public: static AbstractMetaEnum *findEnum(const AbstractMetaClassList &classes, const EnumTypeEntry *entry); + SourceLocation sourceLocation() const; + void setSourceLocation(const SourceLocation &sourceLocation); + private: #ifndef QT_NO_DEBUG_STREAM void format(QDebug &d) const; @@ -1719,6 +1727,7 @@ private: QStringList m_baseClassNames; // Base class names from C++, including rejected QVector<TypeEntry *> m_templateArgs; ComplexTypeEntry *m_typeEntry = nullptr; + SourceLocation m_sourceLocation; // FunctionModelItem m_qDebugStreamFunction; bool m_stream = false; diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index 0e905c9a0..930cd2c70 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -28,6 +28,7 @@ #include "messages.h" #include "abstractmetalang.h" +#include "sourcelocation.h" #include "typedatabase.h" #include "typesystem.h" #include <codemodel.h> @@ -43,19 +44,20 @@ static inline QString colonColon() { return QStringLiteral("::"); } // abstractmetabuilder.cpp -QString msgNoFunctionForModification(const QString &signature, +QString msgNoFunctionForModification(const AbstractMetaClass *klass, + const QString &signature, const QString &originalSignature, - const QString &className, const QStringList &possibleSignatures, const AbstractMetaFunctionList &allFunctions) { QString result; QTextStream str(&result); - str << "signature '" << signature << '\''; + str << klass->typeEntry()->sourceLocation() << "signature '" + << signature << '\''; if (!originalSignature.isEmpty() && originalSignature != signature) str << " (specified as '" << originalSignature << "')"; str << " for function modification in '" - << className << "' not found."; + << klass->qualifiedCppName() << "' not found."; if (!possibleSignatures.isEmpty()) { str << "\n Possible candidates:\n"; for (const auto &s : possibleSignatures) @@ -135,6 +137,7 @@ QString msgNoEnumTypeEntry(const EnumModelItem &enumItem, { QString result; QTextStream str(&result); + str << enumItem->sourceLocation(); msgFormatEnumType(str, enumItem, className); str << " does not have a type entry"; return result; @@ -148,11 +151,22 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, QDebug debug(&result); // Use the debug operator for TypeEntry::Type debug.noquote(); debug.nospace(); + debug << enumItem->sourceLocation().toString(); msgFormatEnumType(debug, enumItem, className); debug << " is not an enum (type: " << t->type() << ')'; return result; } +QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, + const QString &fullName) +{ + QString result; + QTextStream str(&result); + str << item->sourceLocation() << "namespace '" << fullName + << "' does not have a type entry"; + return result; +} + QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te) { QString result = QLatin1String("Ambiguous types of varying types found for \"") + qualifiedName @@ -195,7 +209,7 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem, { QString result; QTextStream str(&result); - str << "skipping "; + str << functionItem->sourceLocation() << "skipping "; if (functionItem->isAbstract()) str << "abstract "; str << "function '" << signature << "', " << why; @@ -206,6 +220,80 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem, return result; } +QString msgSkippingField(const VariableModelItem &field, const QString &className, + const QString &type) +{ + QString result; + QTextStream str(&result); + str << field->sourceLocation() << "skipping field '" << className + << "::" << field->name() << "' with unmatched type '" << type << '\''; + return result; +} + +static const char msgCompilationError[] = + "This could potentially lead to compilation errors."; + +QString msgTypeNotDefined(const TypeEntry *entry) +{ + QString result; + QTextStream str(&result); + str << entry->sourceLocation() << "type '" <<entry->qualifiedCppName() + << "' is specified in typesystem, but not defined. " << msgCompilationError; + return result; +} + +QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte, + const QString &signature) +{ + QString result; + QTextStream str(&result); + str << fte->sourceLocation() << "Global function '" << signature + << "' is specified in typesystem, but not defined. " << msgCompilationError; + return result; +} + +QString msgStrippingArgument(const FunctionModelItem &f, int i, + const QString &originalSignature, + const ArgumentModelItem &arg) +{ + QString result; + QTextStream str(&result); + str << f->sourceLocation() << "Stripping argument #" << (i + 1) << " of " + << originalSignature << " due to unmatched type \"" + << arg->type().toString() << "\" with default expression \"" + << arg->defaultValueExpression() << "\"."; + return result; +} + +QString msgEnumNotDefined(const EnumTypeEntry *t) +{ + QString result; + QTextStream str(&result); + str << t->sourceLocation() << "enum '" << t->qualifiedCppName() + << "' is specified in typesystem, but not declared."; + return result; +} + +QString msgUnknownBase(const AbstractMetaClass *metaClass, const QString &baseClassName) +{ + QString result; + QTextStream str(&result); + str << metaClass->sourceLocation() << "class '" << metaClass->name() + << "' inherits from unknown base class '" << baseClassName << "'"; + return result; +} + +QString msgArrayModificationFailed(const FunctionModelItem &functionItem, + const QString &className, + const QString &errorMessage) +{ + QString result; + QTextStream str(&result); + str << functionItem->sourceLocation() << "While traversing " << className + << ": " << errorMessage; + return result; +} + QString msgCannotResolveEntity(const QString &name, const QString &reason) { return QLatin1String("Cannot resolve entity \"") + name diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index 3934c35b3..72484050a 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -37,6 +37,8 @@ #include <QtCore/QString> #include <QtCore/QVector> +class EnumTypeEntry; +class FunctionTypeEntry; class TypeEntry; class TypeInfo; struct TypeRejection; @@ -52,9 +54,9 @@ QString msgAddedFunctionInvalidArgType(const QString &addedFuncName, QString msgAddedFunctionInvalidReturnType(const QString &addedFuncName, const QString &typeName, const QString &why); -QString msgNoFunctionForModification(const QString &signature, +QString msgNoFunctionForModification(const AbstractMetaClass *klass, + const QString &signature, const QString &originalSignature, - const QString &className, const QStringList &possibleSignatures, const AbstractMetaFunctionList &allFunctions); @@ -66,6 +68,9 @@ QString msgNoEnumTypeConflict(const EnumModelItem &enumItem, const QString &className, const TypeEntry *t); +QString msgNamespaceNoTypeEntry(const NamespaceModelItem &item, + const QString &fullName); + QString msgAmbiguousVaryingTypesFound(const QString &qualifiedName, const TypeEntries &te); QString msgAmbiguousTypesFound(const QString &qualifiedName, const TypeEntries &te); @@ -78,6 +83,27 @@ QString msgUnmatchedReturnType(const FunctionModelItem &functionItem, QString msgSkippingFunction(const FunctionModelItem &functionItem, const QString &signature, const QString &why); +QString msgSkippingField(const VariableModelItem &field, const QString &className, + const QString &type); + +QString msgTypeNotDefined(const TypeEntry *entry); + +QString msgGlobalFunctionNotDefined(const FunctionTypeEntry *fte, + const QString &signature); + +QString msgStrippingArgument(const FunctionModelItem &f, int i, + const QString &originalSignature, + const ArgumentModelItem &arg); + +QString msgEnumNotDefined(const EnumTypeEntry *t); + +QString msgUnknownBase(const AbstractMetaClass *metaClass, + const QString &baseClassName); + +QString msgArrayModificationFailed(const FunctionModelItem &functionItem, + const QString &className, + const QString &errorMessage); + QString msgCannotResolveEntity(const QString &name, const QString &reason); QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index e381ba083..e5a6e074c 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -30,6 +30,7 @@ #include "codemodel.h" +#include <sourcelocation.h> #include <clangparser/clangutils.h> #include <algorithm> @@ -608,6 +609,11 @@ void _CodeModelItem::setEndPosition(int line, int column) m_endColumn = column; } +SourceLocation _CodeModelItem::sourceLocation() const +{ + return SourceLocation(m_fileName, m_startLine); +} + #ifndef QT_NO_DEBUG_STREAM template <class It> static void formatPtrSequence(QDebug &d, It i1, It i2, const char *separator=", ") diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 5bbd9ed3e..ea9cdc30d 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -47,6 +47,8 @@ QT_FORWARD_DECLARE_CLASS(QDebug) #define DECLARE_MODEL_NODE(k) \ enum { __node_kind = Kind_##k }; +class SourceLocation; + class CodeModel { public: @@ -296,6 +298,8 @@ public: void getEndPosition(int *line, int *column); void setEndPosition(int line, int column); + SourceLocation sourceLocation() const; + inline CodeModel *model() const { return m_model; } #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp index a489f7548..2c6ab444b 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp @@ -122,13 +122,19 @@ void ReportHandler::setPrefix(const QString &p) void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &text) { + // Check for file location separator added by SourceLocation + int fileLocationPos = text.indexOf(QLatin1String(":\t")); if (type == QtWarningMsg) { if (m_silent || m_reportedWarnings.contains(text)) return; - const TypeDatabase *db = TypeDatabase::instance(); - if (db && db->isSuppressedWarning(text)) { - ++m_suppressedCount; - return; + if (auto db = TypeDatabase::instance()) { + const bool suppressed = fileLocationPos >= 0 + ? db->isSuppressedWarning(text.midRef(fileLocationPos + 2)) + : db->isSuppressedWarning(text); + if (suppressed) { + ++m_suppressedCount; + return; + } } ++m_warningCount; ++m_step_warning; @@ -137,7 +143,11 @@ void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &cont QString message = m_prefix; if (!message.isEmpty()) message.append(QLatin1Char(' ')); + const int prefixLength = message.size(); message.append(text); + // Replace file location tab by space + if (fileLocationPos >= 0) + message[prefixLength + fileLocationPos + 1] = QLatin1Char(' '); fprintf(stderr, "%s\n", qPrintable(qFormatLogMessage(type, context, message))); } diff --git a/sources/shiboken2/ApiExtractor/sourcelocation.cpp b/sources/shiboken2/ApiExtractor/sourcelocation.cpp new file mode 100644 index 000000000..1ba66e05b --- /dev/null +++ b/sources/shiboken2/ApiExtractor/sourcelocation.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "sourcelocation.h" +#include <QtCore/QDir> +#include <QtCore/QDebug> + +SourceLocation::SourceLocation() = default; + +SourceLocation::SourceLocation(const QString &file, int l) + : m_fileName(file), m_lineNumber(l) +{ +} + +bool SourceLocation::isValid() const +{ + return m_lineNumber >= 0 && !m_fileName.isEmpty(); +} + +QString SourceLocation::fileName() const +{ + return m_fileName; +} + +void SourceLocation::setFileName(const QString &fileName) +{ + m_fileName = fileName; +} + +int SourceLocation::lineNumber() const +{ + return m_lineNumber; +} + +void SourceLocation::setLineNumber(int lineNumber) +{ + m_lineNumber = lineNumber; +} + +QString SourceLocation::toString() const +{ + QString result; + QTextStream s(&result); + format(s); + return result; +} + +template<class Stream> +void SourceLocation::format(Stream &s) const +{ + if (isValid()) + s << QDir::toNativeSeparators(m_fileName) << ':' << m_lineNumber << ':'; + else + s << "<unknown>"; +} + +QTextStream &operator<<(QTextStream &s, const SourceLocation &l) +{ + if (l.isValid()) { + l.format(s); + s << '\t'; // ":\t" is used by ReportHandler for filtering suppressions + } + return s; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const SourceLocation &l) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + l.format(d); + return d; +} +#endif diff --git a/sources/shiboken2/ApiExtractor/sourcelocation.h b/sources/shiboken2/ApiExtractor/sourcelocation.h new file mode 100644 index 000000000..630a841d8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/sourcelocation.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 SOURCE_LOCATION_H +#define SOURCE_LOCATION_H + +#include <QString> + +QT_FORWARD_DECLARE_CLASS(QDebug) +QT_FORWARD_DECLARE_CLASS(QTextStream) + +class SourceLocation +{ +public: + explicit SourceLocation(const QString &file, int l); + SourceLocation(); + + bool isValid() const; + + QString fileName() const; + void setFileName(const QString &fileName); + + int lineNumber() const; + void setLineNumber(int lineNumber); + + QString toString() const; + + template<class Stream> + void format(Stream &s) const; + +private: + QString m_fileName; + int m_lineNumber = 0; +}; + +QTextStream &operator<<(QTextStream &s, const SourceLocation &l); + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const SourceLocation &l); +#endif + +#endif // SOURCE_LOCATION_H diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 4a29a25c9..0cfde1c66 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -568,17 +568,25 @@ bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMe return true; } -bool TypeDatabase::isSuppressedWarning(const QString& s) const +template <class String> // QString, QStringRef +bool TypeDatabase::isSuppressedWarningHelper(const String &s) const { if (!m_suppressWarnings) return false; + return std::any_of(m_suppressedWarnings.cbegin(), m_suppressedWarnings.end(), + [&s] (const QRegularExpression &e) { + return e.match(s).hasMatch(); + }); +} - for (const QRegularExpression &warning : m_suppressedWarnings) { - if (warning.match(s).hasMatch()) - return true; - } +bool TypeDatabase::isSuppressedWarning(const QString &s) const +{ + return isSuppressedWarningHelper(s); +} - return false; +bool TypeDatabase::isSuppressedWarning(const QStringRef &s) const +{ + return isSuppressedWarningHelper(s); } QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index 7651d6b7b..7981febf3 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -163,6 +163,7 @@ public: bool addSuppressedWarning(const QString &warning, QString *errorMessage); bool isSuppressedWarning(const QString &s) const; + bool isSuppressedWarning(const QStringRef &s) const; static QString globalNamespaceClassName(const TypeEntry *te); @@ -192,6 +193,8 @@ private: template <class Predicate> TypeEntries findTypesHelper(const QString &name, Predicate pred) const; TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); + template <class String> + bool isSuppressedWarningHelper(const String &s) const; bool m_suppressWarnings = true; TypeEntryMultiMap m_entries; // Contains duplicate entries (cf addInlineNamespaceLookups). diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 729e6b32b..5634aa515 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -811,6 +811,16 @@ QString TypeEntry::buildTargetLangName() const return result; } +SourceLocation TypeEntry::sourceLocation() const +{ + return m_sourceLocation; +} + +void TypeEntry::setSourceLocation(const SourceLocation &sourceLocation) +{ + m_sourceLocation = sourceLocation; +} + QString TypeEntry::targetLangEntryName() const { if (m_cachedTargetLangEntryName.isEmpty()) { diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index c6995b64d..9d97f5c93 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -32,6 +32,7 @@ #include "typesystem_enums.h" #include "typesystem_typedefs.h" #include "include.h" +#include "sourcelocation.h" #include <QtCore/QHash> #include <QtCore/qobjectdefs.h> @@ -848,6 +849,9 @@ public: void useAsTypedef(const TypeEntry *source); + SourceLocation sourceLocation() const; + void setSourceLocation(const SourceLocation &sourceLocation); + #ifndef QT_NO_DEBUG_STREAM virtual void formatDebug(QDebug &d) const; #endif @@ -874,6 +878,7 @@ private: QString m_conversionRule; QVersionNumber m_version; CustomConversion *m_customConversion = nullptr; + SourceLocation m_sourceLocation; // XML file uint m_codeGeneration = GenerateAll; int m_revision = 0; int m_sbkIndex = 0; diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 0c4d43e76..ff8f1d59d 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -519,14 +519,14 @@ static QString msgReaderMessage(const QXmlStreamReader &reader, { QString message; QTextStream str(&message); - str << type << ": "; const QString fileName = readerFileName(reader); if (fileName.isEmpty()) str << "<stdin>:"; else str << QDir::toNativeSeparators(fileName) << ':'; + // Use a tab separator like SourceLocation for suppression detection str << reader.lineNumber() << ':' << reader.columnNumber() - << ": " << what; + << ":\t" << type << ": " << what; return message; } @@ -631,6 +631,7 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) { m_error.clear(); m_currentPath.clear(); + m_currentFile.clear(); m_smartPointerInstantiations.clear(); const bool result = parseXml(reader) && setupSmartPointerInstantiations(); m_smartPointerInstantiations.clear(); @@ -640,8 +641,11 @@ bool TypeSystemParser::parse(QXmlStreamReader &reader) bool TypeSystemParser::parseXml(QXmlStreamReader &reader) { const QString fileName = readerFileName(reader); - if (!fileName.isEmpty()) - m_currentPath = QFileInfo(fileName).absolutePath(); + if (!fileName.isEmpty()) { + QFileInfo fi(fileName); + m_currentPath = fi.absolutePath(); + m_currentFile = fi.absoluteFilePath(); + } m_entityResolver.reset(new TypeSystemEntityResolver(m_currentPath)); reader.setEntityResolver(m_entityResolver.data()); @@ -1109,8 +1113,11 @@ bool TypeSystemParser::checkRootElement() return ok; } -void TypeSystemParser::applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const +void TypeSystemParser::applyCommonAttributes(const QXmlStreamReader &reader, TypeEntry *type, + QXmlStreamAttributes *attributes) const { + type->setSourceLocation(SourceLocation(m_currentFile, + reader.lineNumber())); type->setCodeGeneration(m_generate); const int revisionIndex = indexOfAttribute(*attributes, u"revision"); @@ -1119,7 +1126,7 @@ void TypeSystemParser::applyCommonAttributes(TypeEntry *type, QXmlStreamAttribut } FlagsTypeEntry * - TypeSystemParser::parseFlagsEntry(const QXmlStreamReader &, + TypeSystemParser::parseFlagsEntry(const QXmlStreamReader &reader, EnumTypeEntry *enumEntry, QString flagName, const QVersionNumber &since, QXmlStreamAttributes *attributes) @@ -1140,7 +1147,7 @@ FlagsTypeEntry * } ftype->setOriginalName(flagName); - applyCommonAttributes(ftype, attributes); + applyCommonAttributes(reader, ftype, attributes); QStringList lst = flagName.split(colonColon()); const QString targetLangFlagName = QStringList(lst.mid(0, lst.size() - 1)).join(QLatin1Char('.')); @@ -1166,7 +1173,7 @@ FlagsTypeEntry * } SmartPointerTypeEntry * - TypeSystemParser::parseSmartPointerEntry(const QXmlStreamReader &, + TypeSystemParser::parseSmartPointerEntry(const QXmlStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { @@ -1219,7 +1226,7 @@ SmartPointerTypeEntry * auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, refCountMethodName, since, currentParentTypeEntry()); - applyCommonAttributes(type, attributes); + applyCommonAttributes(reader, type, attributes); m_smartPointerInstantiations.insert(type, instantiations); return type; } @@ -1232,7 +1239,7 @@ PrimitiveTypeEntry * if (!checkRootElement()) return nullptr; auto *type = new PrimitiveTypeEntry(name, since, currentParentTypeEntry()); - applyCommonAttributes(type, attributes); + applyCommonAttributes(reader, type, attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); if (name == targetLangNameAttribute()) { @@ -1258,7 +1265,7 @@ PrimitiveTypeEntry * } ContainerTypeEntry * - TypeSystemParser::parseContainerTypeEntry(const QXmlStreamReader &, + TypeSystemParser::parseContainerTypeEntry(const QXmlStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { @@ -1276,7 +1283,7 @@ ContainerTypeEntry * return nullptr; } auto *type = new ContainerTypeEntry(name, containerType, since, currentParentTypeEntry()); - applyCommonAttributes(type, attributes); + applyCommonAttributes(reader, type, attributes); return type; } @@ -1288,7 +1295,7 @@ EnumTypeEntry * if (!checkRootElement()) return nullptr; auto *entry = new EnumTypeEntry(name, since, currentParentTypeEntry()); - applyCommonAttributes(entry, attributes); + applyCommonAttributes(reader, entry, attributes); entry->setTargetLangPackage(m_defaultPackage); QString flagNames; @@ -1330,7 +1337,7 @@ NamespaceTypeEntry * return nullptr; QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); auto visibility = TypeSystem::Visibility::Unspecified; - applyCommonAttributes(result.data(), attributes); + applyCommonAttributes(reader, result.data(), attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef attributeName = attributes->at(i).qualifiedName(); if (attributeName == QLatin1String("files")) { @@ -1380,14 +1387,14 @@ NamespaceTypeEntry * } ValueTypeEntry * - TypeSystemParser::parseValueTypeEntry(const QXmlStreamReader &, + TypeSystemParser::parseValueTypeEntry(const QXmlStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; auto *typeEntry = new ValueTypeEntry(name, since, currentParentTypeEntry()); - applyCommonAttributes(typeEntry, attributes); + applyCommonAttributes(reader, typeEntry, attributes); const int defaultCtIndex = indexOfAttribute(*attributes, u"default-constructor"); if (defaultCtIndex != -1) @@ -1396,7 +1403,7 @@ ValueTypeEntry * } FunctionTypeEntry * - TypeSystemParser::parseFunctionTypeEntry(const QXmlStreamReader &, + TypeSystemParser::parseFunctionTypeEntry(const QXmlStreamReader &reader, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { @@ -1414,7 +1421,7 @@ FunctionTypeEntry * if (!existingType) { auto *result = new FunctionTypeEntry(name, signature, since, currentParentTypeEntry()); - applyCommonAttributes(result, attributes); + applyCommonAttributes(reader, result, attributes); return result; } @@ -1430,9 +1437,10 @@ FunctionTypeEntry * } TypedefEntry * - TypeSystemParser::parseTypedefEntry(const QXmlStreamReader &, const QString &name, - const QVersionNumber &since, - QXmlStreamAttributes *attributes) + TypeSystemParser::parseTypedefEntry(const QXmlStreamReader &reader, + const QString &name, + const QVersionNumber &since, + QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; @@ -1448,7 +1456,7 @@ TypedefEntry * } const QString sourceType = attributes->takeAt(sourceIndex).value().toString(); auto result = new TypedefEntry(name, sourceType, since, currentParentTypeEntry()); - applyCommonAttributes(result, attributes); + applyCommonAttributes(reader, result, attributes); return result; } @@ -2824,7 +2832,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) if (!checkRootElement()) return false; element->entry = new ObjectTypeEntry(name, versionRange.since, currentParentTypeEntry()); - applyCommonAttributes(element->entry, &attributes); + applyCommonAttributes(reader, element->entry, &attributes); applyComplexTypeAttributes(reader, static_cast<ComplexTypeEntry *>(element->entry), &attributes); break; case StackElement::FunctionTypeEntry: diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h index b4be2765c..66d61f4a1 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.h +++ b/sources/shiboken2/ApiExtractor/typesystemparser.h @@ -168,7 +168,8 @@ private: const TypeEntry *currentParentTypeEntry() const; bool checkRootElement(); - void applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const; + void applyCommonAttributes(const QXmlStreamReader &reader, TypeEntry *type, + QXmlStreamAttributes *attributes) const; PrimitiveTypeEntry * parsePrimitiveTypeEntry(const QXmlStreamReader &, const QString &name, const QVersionNumber &since, QXmlStreamAttributes *); @@ -272,6 +273,7 @@ private: QString m_currentSignature; QString m_currentPath; + QString m_currentFile; QScopedPointer<TypeSystemEntityResolver> m_entityResolver; QHash<SmartPointerTypeEntry *, QString> m_smartPointerInstantiations; }; diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index edd24aa23..d0c144358 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -2265,7 +2265,8 @@ static void checkTypeViability(const AbstractMetaFunction *func, const AbstractM return; QString message; QTextStream str(&message); - str << "There's no user provided way (conversion rule, argument" + str << func->sourceLocation() + << "There's no user provided way (conversion rule, argument" " removal, custom code, etc) to handle the primitive "; if (argIdx == 0) str << "return type '" << type->cppSignature() << '\''; |